First implementation of simple BB Client

Bulletin-Board-Client-phase_1
Arbel Deutsch Peled 2015-12-05 14:25:02 +02:00
parent b6b234891a
commit a31d88bd12
3 changed files with 178 additions and 7 deletions

View File

@ -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));
}
}

View File

@ -8,7 +8,14 @@ import java.util.List;
/**
* 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
* @param msg
@ -27,22 +34,21 @@ public interface BulletinBoard {
* 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
* are guaranteed to be included.
* @param filter return only messages that match the filter (null means no filtering).
* @param max maximum number of messages to return (0=no limit)
* @param filterList return only messages that match the filters (null means no filtering).
* @return
*/
List<BulletinBoardMessage> readMessages(MessageFilter filter, int max);
List<BulletinBoardMessage> readMessages(MessageFilterList filterList);
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.
* The callback will be called only once for each message.
* @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);
}

View File

@ -3,3 +3,5 @@ include 'voting-booth'
include 'bulletin-board-server'
include 'polling-station'
include 'restful-api-common'
include 'bulletin-board-client'