First implementation of simple BB Client
parent
b6b234891a
commit
a31d88bd12
|
@ -0,0 +1,163 @@
|
||||||
|
package meerkat.bulletinboard;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
import meerkat.comm.CommunicationException;
|
||||||
|
import meerkat.crypto.Digest;
|
||||||
|
import meerkat.crypto.concrete.SHA256Digest;
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||||
|
import meerkat.rest.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.ws.rs.client.Client;
|
||||||
|
import javax.ws.rs.client.ClientBuilder;
|
||||||
|
import javax.ws.rs.client.Entity;
|
||||||
|
import javax.ws.rs.client.WebTarget;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Arbel Deutsch Peled on 05-Dec-15.
|
||||||
|
*/
|
||||||
|
public class SimpleBulletinBoardClient implements BulletinBoardClient {
|
||||||
|
|
||||||
|
//TODO: Make this general
|
||||||
|
private static String SQL_SERVER_POST = "sqlserver/postmessage";
|
||||||
|
private static String SQL_SERVER_GET = "sqlserver/readmessages";
|
||||||
|
|
||||||
|
private List<String> meerkatDBs;
|
||||||
|
|
||||||
|
private Client client;
|
||||||
|
|
||||||
|
private Digest digest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores database locations and initializes the web Client
|
||||||
|
* @param meerkatDBs is the list of database locations
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void init(List<String> meerkatDBs) {
|
||||||
|
|
||||||
|
this.meerkatDBs = meerkatDBs;
|
||||||
|
|
||||||
|
client = ClientBuilder.newClient();
|
||||||
|
client.register(ProtobufMessageBodyReader.class);
|
||||||
|
client.register(ProtobufMessageBodyWriter.class);
|
||||||
|
|
||||||
|
digest = new SHA256Digest();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post message to all DBs
|
||||||
|
* Make only one try per DB.
|
||||||
|
* @param msg is the message,
|
||||||
|
* @return the message ID for later retrieval
|
||||||
|
* @throws CommunicationException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MessageID postMessage(BulletinBoardMessage msg) throws CommunicationException {
|
||||||
|
|
||||||
|
WebTarget webTarget;
|
||||||
|
Response response;
|
||||||
|
|
||||||
|
// Post message to all databases
|
||||||
|
try {
|
||||||
|
for (String db : meerkatDBs) {
|
||||||
|
webTarget = client.target(db).path(SQL_SERVER_POST);
|
||||||
|
response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(msg, Constants.MEDIATYPE_PROTOBUF));
|
||||||
|
|
||||||
|
// Only consider valid responses
|
||||||
|
if (response.getStatusInfo() == Response.Status.OK
|
||||||
|
|| response.getStatusInfo() == Response.Status.CREATED) {
|
||||||
|
response.readEntity(BoolMsg.class).getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) { // Occurs only when server replies with valid status but invalid data
|
||||||
|
throw new CommunicationException("Error accessing database: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the correct message ID and return it
|
||||||
|
digest.reset();
|
||||||
|
digest.update(msg.getMsg());
|
||||||
|
return MessageID.newBuilder().setID(ByteString.copyFrom(digest.digest())).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access each database and search for a given message ID
|
||||||
|
* Return the number of databases in which the message was found
|
||||||
|
* Only try once per DB
|
||||||
|
* Ignore communication exceptions in specific databases
|
||||||
|
* @param id is the requested message ID
|
||||||
|
* @return the number of DBs in which retrieval was successful
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public float getRedundancy(MessageID id) {
|
||||||
|
WebTarget webTarget;
|
||||||
|
Response response;
|
||||||
|
|
||||||
|
MessageFilterList filterList = MessageFilterList.newBuilder()
|
||||||
|
.addFilter(MessageFilter.newBuilder()
|
||||||
|
.setType(FilterType.MSG_ID)
|
||||||
|
.setId(id.getID())
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (String db : meerkatDBs) {
|
||||||
|
try {
|
||||||
|
webTarget = client.target(db).path(SQL_SERVER_GET);
|
||||||
|
|
||||||
|
response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(filterList, Constants.MEDIATYPE_PROTOBUF));
|
||||||
|
|
||||||
|
if (response.readEntity(BulletinBoardMessageList.class).getMessageCount() > 0){
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go through the DBs and try to retrieve messages according to the specified filter
|
||||||
|
* If at the operation is successful for some DB: return the results and stop iterating
|
||||||
|
* If no operation is successful: return null (NOT blank list)
|
||||||
|
* @param filterList return only messages that match the filters (null means no filtering).
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<BulletinBoardMessage> readMessages(MessageFilterList filterList) {
|
||||||
|
WebTarget webTarget;
|
||||||
|
Response response;
|
||||||
|
BulletinBoardMessageList messageList;
|
||||||
|
|
||||||
|
// Replace null filter list with blank one.
|
||||||
|
if (filterList == null){
|
||||||
|
filterList = MessageFilterList.newBuilder().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String db : meerkatDBs) {
|
||||||
|
try {
|
||||||
|
webTarget = client.target(db).path(SQL_SERVER_GET);
|
||||||
|
|
||||||
|
response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(filterList, Constants.MEDIATYPE_PROTOBUF));
|
||||||
|
|
||||||
|
messageList =response.readEntity(BulletinBoardMessageList.class);
|
||||||
|
|
||||||
|
if (messageList != null){
|
||||||
|
return messageList.getMessageList();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerNewMessageCallback(MessageCallback callback, MessageFilterList filterList) {
|
||||||
|
callback.handleNewMessage(readMessages(filterList));
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,14 @@ import java.util.List;
|
||||||
/**
|
/**
|
||||||
* Created by talm on 24/10/15.
|
* Created by talm on 24/10/15.
|
||||||
*/
|
*/
|
||||||
public interface BulletinBoard {
|
public interface BulletinBoardClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the client to use some specified servers
|
||||||
|
* @param meerkatDBs is the list of database locations
|
||||||
|
*/
|
||||||
|
void init(List<String> meerkatDBs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post a message to the bulletin board
|
* Post a message to the bulletin board
|
||||||
* @param msg
|
* @param msg
|
||||||
|
@ -27,22 +34,21 @@ public interface BulletinBoard {
|
||||||
* Note that if messages haven't been "fully posted", this might return a different
|
* Note that if messages haven't been "fully posted", this might return a different
|
||||||
* set of messages in different calls. However, messages that are fully posted
|
* set of messages in different calls. However, messages that are fully posted
|
||||||
* are guaranteed to be included.
|
* are guaranteed to be included.
|
||||||
* @param filter return only messages that match the filter (null means no filtering).
|
* @param filterList return only messages that match the filters (null means no filtering).
|
||||||
* @param max maximum number of messages to return (0=no limit)
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<BulletinBoardMessage> readMessages(MessageFilter filter, int max);
|
List<BulletinBoardMessage> readMessages(MessageFilterList filterList);
|
||||||
|
|
||||||
interface MessageCallback {
|
interface MessageCallback {
|
||||||
void handleNewMessage(BulletinBoardMessage msg);
|
void handleNewMessage(List<BulletinBoardMessage> msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a callback that will be called with each new message that is posted.
|
* Register a callback that will be called with each new message that is posted.
|
||||||
* The callback will be called only once for each message.
|
* The callback will be called only once for each message.
|
||||||
* @param callback
|
* @param callback
|
||||||
* @param filter only call back for messages that match the filter.
|
* @param filterList only call back for messages that match the filter.
|
||||||
*/
|
*/
|
||||||
void registerNewMessageCallback(MessageCallback callback, MessageFilter filter);
|
void registerNewMessageCallback(MessageCallback callback, MessageFilterList filterList);
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,3 +3,5 @@ include 'voting-booth'
|
||||||
include 'bulletin-board-server'
|
include 'bulletin-board-server'
|
||||||
include 'polling-station'
|
include 'polling-station'
|
||||||
include 'restful-api-common'
|
include 'restful-api-common'
|
||||||
|
include 'bulletin-board-client'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue