package br.ufms.dct.simplerep.kernels;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import org.apache.log4j.Logger;
import seqSamoa.Callback;
import seqSamoa.SamoaFlowControl;
import seqSamoa.SamoaScheduler;
import seqSamoa.SequentialManager;
import seqSamoa.api.ApiSamoaAbcastStack;
import seqSamoa.exceptions.AlreadyBoundServiceException;
import framework.PID;
import framework.libraries.serialization.TLinkedList;
import br.ufms.dct.simplerep.Host;
import br.ufms.dct.simplerep.SimpleRepConfiguration;
import br.ufms.dct.simplerep.ar.MessageContext;
import br.ufms.dct.simplerep.ar.SequencedEnvelope;
import br.ufms.dct.simplerep.ar.SystemContext;
import br.ufms.dct.simplerep.proxies.http.ThirdPartyRequestsRunner;
import br.ufms.dct.simplerep.samoa.Pt2Pt2Parameter;
import br.ufms.dct.simplerep.samoa.SimpleRepABCastCallback;
import br.ufms.dct.simplerep.samoa.runners.ABCastRunner;
import br.ufms.dct.simplerep.samoa.runners.Pt2PtRunner;
public class SamoaKernel extends AbstractKernel {
static Logger logger = Logger.getLogger(SamoaKernel.class.getName());
public static final String SAMOA_IN_QUEUE = "simplerep_in_queue";
public static final String SAMOA_OUT_QUEUE = "simplerep_out_queue";
public static final String SAMOA_ABCAST_IN_QUEUE = "simplerep_abcast_in_queue";
public static final String SAMOA_ABCAST_OUT_QUEUE = "simplerep_abcast_out_queue";
public static final String ORIGINAL_PID = "simplerep_samoa_original_pid";
private static ApiSamoaAbcastStack stack;
private SimpleRepConfiguration conf;
SynchronousQueue<MessageContext> inQueue;
SynchronousQueue<MessageContext> outQueue;
HashMap<String, SynchronousQueue<String>> transportOutQueues;
HashMap<String, SequencedEnvelope> lastEnvelopesOutQueue;
BlockingQueue<Pt2Pt2Parameter> udpOutQueue;
BlockingQueue<MessageContext> thirdPartyQueue;
ExecutorService abcastExecutor;
ExecutorService pt2ptExecutor;
ExecutorService thirdPartyExecutor;
public void init(SimpleRepConfiguration configuration) {
conf = configuration;
SystemContext sysContext = conf.getSystemContext();
inQueue = new SynchronousQueue<MessageContext>();
outQueue = new SynchronousQueue<MessageContext>();
udpOutQueue = new LinkedBlockingQueue<Pt2Pt2Parameter>();
thirdPartyQueue = new LinkedBlockingQueue<MessageContext>();
transportOutQueues = new HashMap<String, SynchronousQueue<String>>();
// host / <seqId,Envelope>
lastEnvelopesOutQueue = new HashMap<String, SequencedEnvelope>();
sysContext.set(SAMOA_ABCAST_IN_QUEUE, inQueue);
sysContext.set(SAMOA_OUT_QUEUE, outQueue);
sysContext.set(TRANSPORT_OUT_QUEUES, transportOutQueues);
sysContext.set(LAST_ENVELOPES_OUT_QUEUE, lastEnvelopesOutQueue);
stack = getSamoaStack();
ABCastRunner samoaRunner = new ABCastRunner(stack, inQueue);
abcastExecutor = Executors.newSingleThreadExecutor();
abcastExecutor.execute(samoaRunner);
Pt2PtRunner pt2ptRunner = new Pt2PtRunner(stack, udpOutQueue);
pt2ptExecutor = Executors.newSingleThreadExecutor();
pt2ptExecutor.execute(pt2ptRunner);
if (conf.getReplicationStyle().equals("active")) {
// sends requests to the local appServer in the active replication
ThirdPartyRequestsRunner thirdPartyRunner = new ThirdPartyRequestsRunner(thirdPartyQueue, udpOutQueue);
thirdPartyExecutor = Executors.newSingleThreadExecutor();
thirdPartyExecutor.execute(thirdPartyRunner);
}
}
public void shutdown(){
stack.close();
// killing the thread created in the init method
abcastExecutor.shutdown();
pt2ptExecutor.shutdown();
if (conf.getReplicationStyle() == "active") {
thirdPartyExecutor.shutdown();
}
}
/**
* This method is the responsible for the actual instantiation of the
* samoa stack
*
* @param localPort
* @param frameworkProcesses
* @return
*/
public synchronized ApiSamoaAbcastStack getSamoaStack() {
if (stack == null) {
logger.trace("Loading Samoa... ");
PID myself;
try {
try {
myself = new PID(InetAddress.getByName("127.0.0.1"), conf
.getFrameworkLocalPort(), 0);
} catch (UnknownHostException e1) {
logger.fatal("Localhost is down!? Port: " + conf.getFrameworkLocalPort());
return null;
}
SimpleRepABCastCallback callback = new SimpleRepABCastCallback(udpOutQueue, thirdPartyQueue);
Callback udpCallback = new br.ufms.dct.simplerep.samoa.SimpleRepUdpCallback(this.transportOutQueues);
TLinkedList processes = new TLinkedList();
for (Host host : conf.getFrameworkProcesses()) {
try {
PID pid = new PID(InetAddress.getByName(host
.getHost()), host.getPort(), 0);
processes.addLast(pid);
logger.debug("Host " + pid + " added.");
} catch (UnknownHostException e) {
logger.error("The host " + host.getHost() + " does not exist.");
}
}
// running the thread?
stack = new ApiSamoaAbcastStack(myself, processes,
new SamoaScheduler(new SequentialManager()),
new SamoaFlowControl(1000), callback, udpCallback, null, conf);
// we need the stack object to send direct messages in the callback
callback.setStack(stack);
stack.init();
logger.trace("Samoa Stack up and running!");
}
catch (AlreadyBoundServiceException e) {
logger.fatal("Samoa Stack não pôde ser instanciada.");
return null;
}
}
else {
logger.trace("Samoa has already been started.");
}
return stack;
}
}