package at.ac.ait.archistar.engine.distributor;
import io.netty.channel.nio.NioEventLoopGroup;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import at.ac.ait.archistar.backendserver.fragments.Fragment;
import at.ac.ait.archistar.engine.messages.ReadCommand;
import at.ac.ait.archistar.engine.messages.WriteCommand;
import at.ac.ait.archistar.engine.serverinterface.OzymandiasClient;
import at.archistar.bft.client.ClientResult;
import at.archistar.bft.messages.ClientCommand;
/**
* ]
* Implements the Distributor interface via a simple BFT protocol. For test
* purposes this actually starts f+1 BFT servers on the local machine and wires
* it up to a BFT network.
*
* @author andy
*/
public class BFTDistributor implements Distributor {
protected OzymandiasClient client;
private boolean alreadyConnected = false;
private int clientSequence = 0;
private final int clientId = 0;
private final int f = 1;
private final ServerConfiguration config;
public BFTDistributor(ServerConfiguration config, NioEventLoopGroup loopGroup) {
this.config = config;
this.client = new OzymandiasClient(config.getBFTServerNetworkPortMap(), f, loopGroup);
}
@Override
public boolean putFragmentSet(Set<Fragment> fragments) {
Map<Integer, ClientCommand> msg = new HashMap<Integer, ClientCommand>();
for (Fragment f : fragments) {
msg.put(f.getStorageServer().getBFTId(), new WriteCommand(clientId, clientSequence, f.getFragmentId(), f.getData()));
}
this.client.sendRoundtripMessage(msg);
clientSequence++;
return fragments.size() >= (2 * f + 1);
}
@Override
public boolean getFragmentSet(Set<Fragment> fragments) {
Map<Integer, ClientCommand> msg = new HashMap<>();
for (Fragment f : fragments) {
msg.put(f.getStorageServer().getBFTId(), new ReadCommand(clientId, clientSequence, f.getFragmentId()));
}
ClientResult result = this.client.sendRoundtripMessage(msg);
/* merge fragment results */
for (Fragment f : fragments) {
int bftid = f.getStorageServer().getBFTId();
if (result.containsDataForServer(bftid)) {
f.setData(result.getDataForServer(bftid));
f.setSynchronized(true);
} else {
f.setSynchronized(false);
}
}
clientSequence++;
return fragments.size() >= (2 * f + 1);
}
/* starts up virtual servers */
@Override
public int connectServers() {
if (alreadyConnected == true) {
return config.getOnlineStorageServerCount();
}
/* create and connect client */
try {
this.client.connect();
alreadyConnected = true;
} catch (Exception e) {
e.printStackTrace();
assert (false);
return -1;
}
return config.getOnlineStorageServerCount();
}
@Override
public int disconnectServers() {
/* TODO: how to disconnect servers? */
return 0;
}
}