package gameengine;
import PBFT.ClientMessage;
import PBFT.PBFTCohort;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import common.CryptoUtil;
import common.Transaction;
import config.GroupConfigProvider;
import config.GroupMember;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import statemachine.InvalidStateMachineOperationException;
import statemachine.Operation;
import java.nio.ByteBuffer;
import java.util.Collection;
/**
* Created by leo on 12/3/14.
*/
public class ChineseCheckersGameEngine implements GameEngine<ChineseCheckersState> {
Logger LOG = LogManager.getLogger(ChineseCheckersGameEngine.class);
protected final GroupConfigProvider configProvider;
private ChineseCheckersStateMachine stateMachine;
private Collection<GameEngineListener<ChineseCheckersState>> listeners = Lists.newArrayList();
public ChineseCheckersGameEngine(GroupConfigProvider<PBFTCohort.Client> configProvider){
this.configProvider = configProvider;
this.stateMachine = new ChineseCheckersStateMachine(ChineseCheckersState.buildGameForGroupMembers(configProvider.getGroupMembers()));
}
@Override
synchronized public void notifyOnCommit(Transaction<Operation<ChineseCheckersState>> transaction) throws Exception {
this.stateMachine.applyOperation(transaction.getValue());
// if the above does not throw an exception, then:
for (GameEngineListener<ChineseCheckersState> listener : listeners) {
listener.notifyOnSuccessfulApply(transaction.getValue());
}
}
@Override
public ChineseCheckersStateMachine getStateMachine() {
return stateMachine;
}
@Override
public void addListener(GameEngineListener<ChineseCheckersState> listener) {
Preconditions.checkNotNull(listener);
listeners.add(listener);
}
@Override
synchronized public void requestCommit(Operation<ChineseCheckersState> operation) {
final GroupMember<PBFTCohort.Client> leader = this.configProvider.getLeader();
GroupMember<PBFTCohort.Client> me = this.configProvider.getMe();
final String name = configProvider.getMe().getName();
final ClientMessage message = new ClientMessage();
message.operation = operation.serialize();
message.replicaId = me.getReplicaID();
message.messageSignature = ByteBuffer.wrap(CryptoUtil.computeMessageSignature(message, me.getPrivateKey()).getBytes());
new Thread(new Runnable() {
@Override
public void run() {
PBFTCohort.Client thriftConnection = null;
try {
thriftConnection = leader.getThriftConnection();
thriftConnection.clientMessage(message);
} catch (Exception e) {
LOG.error(name);
e.printStackTrace();
} finally {
leader.returnThriftConnection(thriftConnection);
}
}
}).start();
}
}