package uk.ac.imperial.lsds.seepworker.core; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.Iterator; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import uk.ac.imperial.lsds.seep.api.API; import uk.ac.imperial.lsds.seep.api.SeepTask; import uk.ac.imperial.lsds.seep.api.data.ITuple; import uk.ac.imperial.lsds.seep.api.data.OTuple; import uk.ac.imperial.lsds.seep.api.data.Schema; import uk.ac.imperial.lsds.seep.api.data.TransporterITuple; import uk.ac.imperial.lsds.seep.api.operator.LogicalOperator; import uk.ac.imperial.lsds.seep.scheduler.ScheduleDescription; import uk.ac.imperial.lsds.seep.scheduler.Stage; import uk.ac.imperial.lsds.seep.util.Utils; public class ScheduleTask implements SeepTask { final private static Logger LOG = LoggerFactory.getLogger(ScheduleTask.class.getName()); private int stageId; private int euId; private List<LogicalOperator> operators; private Iterator<LogicalOperator> opIt; private List<SeepTask> tasks; private Iterator<SeepTask> taskIterator; private API scApi = new SimpleCollector(); // Optimizing for same schema private boolean sameSchema = true; private Schema schema = null; private ITuple data = null; private TransporterITuple d = null; private ScheduleTask(int euId, int stageId, List<LogicalOperator> operators) { this.stageId = stageId; this.euId = euId; this.operators = operators; this.tasks = new ArrayList<>(); this.opIt = operators.iterator(); while(opIt.hasNext()) { tasks.add(opIt.next().getSeepTask()); } this.taskIterator = tasks.iterator(); // TODO: initialize sameSchema here by actually checking if the schema is the same if(sameSchema && opIt.hasNext()) { schema = opIt.next().downstreamConnections().get(0).getSchema(); data = new ITuple(schema); d = new TransporterITuple(schema); opIt = operators.iterator(); // reset } } public static ScheduleTask buildTaskFor(int id, Stage s, ScheduleDescription sd) { Deque<Integer> wrappedOps = s.getWrappedOperators(); LOG.info("Building stage {}. Wraps {} operators", s.getStageId(), wrappedOps.size()); // Deque<LogicalOperator> operators = new ArrayDeque<>(); List<LogicalOperator> operators = new ArrayList<>(); while(! wrappedOps.isEmpty()) { LogicalOperator lo = sd.getOperatorWithId(wrappedOps.poll()); LOG.debug("op {} is part of stage {}", lo.getOperatorId(), s.getStageId()); operators.add(lo); } return new ScheduleTask(id, s.getStageId(), operators); } public int getStageId() { return stageId; } public int getEuId() { return euId; } @Override public void setUp() { if(! taskIterator.hasNext()) { taskIterator = tasks.iterator(); } if(! opIt.hasNext()) { opIt = operators.iterator(); } } // @Override @Deprecated public void _processData(ITuple data, API api) { API scApi = new SimpleCollector(); SeepTask next = taskIterator.next(); // Get first, and possibly only task here // Check whether there are tasks ahead while(taskIterator.hasNext()) { // There is a next OP, we simply need to collect output next.processData(data, scApi); byte[] o = ((SimpleCollector)scApi).collectMem(); LogicalOperator nextOp = opIt.next(); if(! sameSchema) { Schema schema = nextOp.downstreamConnections().get(0).getSchema(); // 0 cause there's only 1 data = new ITuple(schema); } data.setData(o); // Otherwise we simply forward the data next = taskIterator.next(); } // Finally use real API for real forwarding next.processData(data, api); // Then reset iterators for more processing taskIterator = tasks.iterator(); opIt = operators.iterator(); } @Override public void processData(ITuple data, API api) { for(int i = 0; i < tasks.size() - 1; i++) { SeepTask next = tasks.get(i); next.processData(data, scApi); OTuple o = ((SimpleCollector)scApi).collect(); LogicalOperator nextOp = operators.get(i); if(! sameSchema) { Schema schema = nextOp.downstreamConnections().get(0).getSchema(); // 0 cause there's only 1 data = new ITuple(schema); d = new TransporterITuple(schema); // FIXME: can we get schema from OTuple } if(d == null) { Schema schema = nextOp.downstreamConnections().get(0).getSchema(); d = new TransporterITuple(schema); } Object[] values = o.getValues(); d.setValues(values); } SeepTask next = tasks.get(tasks.size() -1); next.processData(data, api); // SeepTask next = taskIterator.next(); // Get first, and possibly only task here // // Check whether there are tasks ahead // while(taskIterator.hasNext()) { // // There is a next OP, we simply need to collect output // next.processData(data, scApi); //// byte[] o = ((SimpleCollector)scApi).collect(); // OTuple o = ((SimpleCollector)scApi).collect(); // LogicalOperator nextOp = opIt.next(); // if(! sameSchema) { // Schema schema = nextOp.downstreamConnections().get(0).getSchema(); // 0 cause there's only 1 // data = new ITuple(schema); // d = new TransporterITuple(schema); // FIXME: can we get schema from OTuple // } // if(d == null) { // Schema schema = nextOp.downstreamConnections().get(0).getSchema(); // d = new TransporterITuple(schema); // } // Object[] values = o.getValues(); // d.setValues(values); // // Otherwise we simply forward the data // next = taskIterator.next(); // } // // // Finally use real API for real forwarding // next.processData(data, api); // // Then reset iterators for more processing // taskIterator = tasks.iterator(); // opIt = operators.iterator(); } public void __processData(ITuple data, API api) { SeepTask next = taskIterator.next(); // Get first, and possibly only task here // Check whether there are tasks ahead while(taskIterator.hasNext()) { // There is a next OP, we simply need to collect output next.processData(data, scApi); // byte[] o = ((SimpleCollector)scApi).collect(); OTuple o = ((SimpleCollector)scApi).collect(); LogicalOperator nextOp = opIt.next(); if(! sameSchema) { Schema schema = nextOp.downstreamConnections().get(0).getSchema(); // 0 cause there's only 1 data = new ITuple(schema); d = new TransporterITuple(schema); // FIXME: can we get schema from OTuple } if(d == null) { Schema schema = nextOp.downstreamConnections().get(0).getSchema(); d = new TransporterITuple(schema); } Object[] values = o.getValues(); d.setValues(values); // Otherwise we simply forward the data next = taskIterator.next(); } // Finally use real API for real forwarding next.processData(data, api); // Then reset iterators for more processing taskIterator = tasks.iterator(); opIt = operators.iterator(); } public boolean hasMoreTasks() { return taskIterator.hasNext(); } @Override public void processDataGroup(List<ITuple> dataBatch, API api) { // TODO Auto-generated method stub } @Override public void close() { if(taskIterator.hasNext()){ taskIterator.next().close(); } else{ taskIterator = tasks.iterator(); } } @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("Stage: " + this.stageId + ", running on: " + this.euId); sb.append(Utils.NL); StringBuffer tasksDescr = new StringBuffer(); for(LogicalOperator lo : operators) { tasksDescr.append(" t: " + lo.getOperatorId() + "-> " + lo.getSeepTask().toString()); tasksDescr.append(Utils.NL); } sb.append(tasksDescr.toString()); return sb.toString(); } }