/*******************************************************************************
* Copyright (c) 2013 Imperial College London.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Raul Castro Fernandez - initial design and implementation
******************************************************************************/
package uk.ac.imperial.lsds.seep.runtimeengine;
import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.util.ArrayList;
import uk.ac.imperial.lsds.seep.GLOBALS;
import uk.ac.imperial.lsds.seep.buffer.Buffer;
import uk.ac.imperial.lsds.seep.comm.serialization.DataTuple;
import uk.ac.imperial.lsds.seep.comm.serialization.messages.Payload;
import uk.ac.imperial.lsds.seep.comm.serialization.messages.TuplePayload;
import uk.ac.imperial.lsds.seep.comm.serialization.serializers.ArrayListSerializer;
import uk.ac.imperial.lsds.seep.operator.EndPoint;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Output;
public class AsynchronousCommunicationChannel implements EndPoint{
private int opId;
private Buffer buf;
private Selector s;
//Serialization tools
private Kryo k;
private Output o;
//Native buffer
private ByteBuffer nativeBuffer;
//Batching variables
private int batchSize = new Integer(GLOBALS.valueFor("batchLimit"));
int currentBatchSize = 0;
public AsynchronousCommunicationChannel(int opId, Buffer buf, Output o, ByteBuffer nativeBuffer){
this.opId = opId;
this.buf = buf;
this.o = o;
this.k = this.initializeKryo();
this.nativeBuffer = nativeBuffer;
}
private Kryo initializeKryo(){
//optimize here kryo
Kryo k = new Kryo();
k.register(ArrayList.class, new ArrayListSerializer());
k.register(Payload.class);
k.register(TuplePayload.class);
// k.register(BatchTuplePayload.class);
return k;
}
public void setSelector(Selector s){
this.s = s;
}
@Override
public int getOperatorId() {
return opId;
}
public Output getOutput(){
return o;
}
public ByteBuffer getNativeBuffer(){
return nativeBuffer;
}
public Kryo getKryo(){
return k;
}
public void resetBatch(){
currentBatchSize = 0;
readyToWrite = false;
}
boolean readyToWrite = false;
public boolean isBatchAvailable(){
return readyToWrite;
}
public void writeDataToOutputBuffer(DataTuple dt){
///\fixme{Handle timestamps for fault tolerance}
// This writes the serialized message to the byte[] that output is backing up
// if(currentBatchSize < batchSize){
// System.out.println("curren: "+currentBatchSize+" < totallimit: "+batchSize);
k.writeObject(o, dt.getPayload());
currentBatchSize++;
if(currentBatchSize == batchSize){
// System.out.println("current: "+currentBatchSize+" == batchlimit "+batchSize);
// System.out.println("o.position: "+ o.position());
// Write to buffer
o.flush();
synchronized(this){
readyToWrite = true;
try {
// System.out.println("Waiting...");
this.wait();
// System.out.println("Unblocked!");
// Reset the batch
currentBatchSize = 0;
// System.out.println("After flushing");
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// }
}
}
/**
*
public void sendToDownstream(DataTuple tuple, EndPoint dest, boolean now, boolean beacon) {
SynchronousCommunicationChannel channelRecord = (SynchronousCommunicationChannel) dest;
Buffer buffer = channelRecord.getBuffer();
AtomicBoolean replay = channelRecord.getReplay();
AtomicBoolean stop = channelRecord.getStop();
//Output for this socket
Output output = channelRecord.getOutput();
try{
//To send tuple
if(replay.compareAndSet(true, false)){
replay(channelRecord);
replay.set(false);
stop.set(false);
//At this point, this operator has finished replaying the tuples
NodeManager.setSystemStable();
}
if(!stop.get()){
if(!beacon){
channelRecord.addDataToBatch(tuple.getPayload());
}
//If it is mandated to send the tuple now (URGENT), then channelBatchSize is put to 0
if(now) channelRecord.resetChannelBatchSize();
long currentTime = System.currentTimeMillis();
/// \todo{Add the following line for include the batch timing mechanism}
// if(channelRecord.channelBatchSize == 0 || (currentTime - channelRecord.getTick) > ExecutionConfiguration.maxLatencyAllowed ){
if(channelRecord.getChannelBatchSize() == 0){
// BatchDataTuple msg = channelRecord.getBatch();
BatchTuplePayload msg = channelRecord.getBatch();
channelRecord.setTick(currentTime);
k.writeObject(output, msg);
//Flush the buffer to the stream
output.flush();
channelRecord.cleanBatch();
if(P.valueFor("eftMechanismEnabled").equals("true")){
// buffer.save(msg);
}
}
}
else if (!beacon){
//Is there any thread replaying?
while(replaySemaphore.get() >= 1){
//If so, wait.
synchronized(this){
this.wait();
}
}
}
}
catch(InterruptedException ie){
NodeManager.nLogger.severe("-> Dispatcher. While trying to do wait() "+ie.getMessage());
ie.printStackTrace();
}
}
*/