/*******************************************************************************
* 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.buffer;
import java.io.Serializable;
import java.util.Deque;
import java.util.Iterator;
import java.util.concurrent.LinkedBlockingDeque;
import uk.ac.imperial.lsds.seep.comm.serialization.controlhelpers.BackupOperatorState;
import uk.ac.imperial.lsds.seep.comm.serialization.controlhelpers.RawData;
import uk.ac.imperial.lsds.seep.comm.serialization.messages.BatchTuplePayload;
import uk.ac.imperial.lsds.seep.runtimeengine.TimestampTracker;
/**
* Buffer class models the buffers for the connections between operators in our system
*/
public class Buffer implements Serializable{
private static final long serialVersionUID = 1L;
// private Deque<BatchTuplePayload> buff = new LinkedBlockingDeque<BatchTuplePayload>();
private Deque<OutputLogEntry> log = new LinkedBlockingDeque<OutputLogEntry>();
private BackupOperatorState bs = null;
private RawData rw = null;
// public Iterator<BatchTuplePayload> iterator() {
// return buff.iterator();
// }
public Iterator<OutputLogEntry> iterator() {
return log.iterator();
}
public Buffer(){
BackupOperatorState initState = new BackupOperatorState();
bs = initState;
}
public int size(){
return log.size();
}
public BackupOperatorState getBackupState(){
return bs;
}
// public void saveStateAndTrim(BackupOperatorState bs){
// //Save state
// this.bs = bs;
// long ts_e = bs.getState().getData_ts();
// //Trim buffer, eliminating those tuples that are represented by this state
// trim(ts_e);
// }
public void replaceBackupOperatorState(BackupOperatorState bs) {
// In-memory
long smem = System.currentTimeMillis();
this.bs = bs;
long emem = System.currentTimeMillis();
// On-disk
// try {
// // Write the object out to a byte array
// FileOutputStream fos = new FileOutputStream("tempBackup");
// ExtendedObjectOutputStream out = new ExtendedObjectOutputStream(fos);
//
// out.writeObject(bs);
// out.flush();
// out.close();
// }
// catch(IOException e) {
// e.printStackTrace();
// }
// long enddisk = System.currentTimeMillis();
// System.out.println("MEM: "+(emem-smem)+" DISK: "+(enddisk-emem));
}
public void replaceRawData(RawData rw){
System.out.println("Storing: "+rw.getData().length+" bytes");
this.rw = rw;
}
public void save(BatchTuplePayload batch, long outputTs, TimestampTracker inputTs){
log.add(new OutputLogEntry(outputTs, inputTs, batch));
}
public TimestampTracker trim(long ts){
// System.out.println("ACK: "+ts);
TimestampTracker oldest = null;
boolean matchFirstEntryToRemove = true;
long startTrim = System.currentTimeMillis();
Iterator<OutputLogEntry> iter = log.iterator();
while (iter.hasNext()) {
OutputLogEntry next = iter.next();
BatchTuplePayload batch = next.batch;
long timeStamp = 0;
timeStamp = next.outputTs; // the newest ts in the entry
if (timeStamp <= ts) {
//Detect first entry to remove and store the inputVTs
if(matchFirstEntryToRemove){
///\todo{are we iterating from the tail or the head?}
matchFirstEntryToRemove = false;
oldest = next.inputVTs;
}
// System.out.println("Remove tuple with ts: "+timeStamp);
iter.remove();
}
else {
break;
}
}
// if(!log.isEmpty()){
// oldest = log.getFirst().inputVTs;
// }
long endTrim = System.currentTimeMillis();
System.out.println("TOTAL-TRIM: "+(endTrim-startTrim));
return oldest;
}
///fixme{just for testing, do binary search on structure}
public TimestampTracker getInputVTsForOutputTs(long output_ts){
for(OutputLogEntry l : log){
if(l.outputTs == output_ts){
return l.inputVTs;
}
}
return null;
}
}