package com.neverwinterdp.scribengin.dataflow; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import com.neverwinterdp.scribengin.Record; import com.neverwinterdp.scribengin.storage.StreamDescriptor; import com.neverwinterdp.scribengin.storage.sink.Sink; import com.neverwinterdp.scribengin.storage.sink.SinkFactory; import com.neverwinterdp.scribengin.storage.sink.SinkStream; import com.neverwinterdp.scribengin.storage.sink.SinkStreamWriter; import com.neverwinterdp.scribengin.storage.source.Source; import com.neverwinterdp.scribengin.storage.source.SourceFactory; import com.neverwinterdp.scribengin.storage.source.SourceStream; import com.neverwinterdp.scribengin.storage.source.SourceStreamReader; public class DataflowTaskContext { private DataflowTaskReport report ; private SourceContext sourceContext ; private Map<String, SinkContext> sinkContexts = new HashMap<String, SinkContext>(); private DataflowRegistry dataflowRegistry; private DataflowTaskDescriptor dataflowTaskDescriptor; public DataflowTaskContext(DataflowContainer container, DataflowTaskDescriptor descriptor, DataflowTaskReport report) throws Exception { this.sourceContext = new SourceContext(container.getSourceFactory(), descriptor.getSourceStreamDescriptor()); Iterator<Map.Entry<String, StreamDescriptor>> i = descriptor.getSinkStreamDescriptors().entrySet().iterator() ; while(i.hasNext()) { Map.Entry<String, StreamDescriptor> entry = i.next(); SinkContext context = new SinkContext(container.getSinkFactory(), entry.getValue()); sinkContexts.put(entry.getKey(), context) ; } this.report = report ; this.dataflowTaskDescriptor = descriptor; this.dataflowRegistry = container.getDataflowRegistry(); } public DataflowTaskReport getReport() { return this.report ;} public SourceStreamReader getSourceStreamReader() { return sourceContext.assignedSourceStreamReader; } public void append(Record record) throws Exception { SinkContext sinkContext = sinkContexts.get("default") ; sinkContext.assignedSinkStreamWriter.append(record); } public void write(String sinkName, Record record) throws Exception { SinkContext sinkContext = sinkContexts.get(sinkName) ; sinkContext.assignedSinkStreamWriter.append(record); } private void prepareCommit() throws Exception { sourceContext.assignedSourceStreamReader.prepareCommit(); Iterator<SinkContext> i = sinkContexts.values().iterator(); while(i.hasNext()) { SinkContext ctx = i.next(); ctx.prepareCommit() ; } } public boolean commit() throws Exception { //prepareCommit is a vote to make sure both sink, invalidSink, and source //are ready to commit data, otherwise rollback will occur try { prepareCommit() ; completeCommit(); } catch(Exception ex) { rollback(); throw ex; } report.incrCommitProcessCount(); dataflowRegistry.dataflowTaskReport(dataflowTaskDescriptor, report); return false; } private void rollback() throws Exception { //TODO: implement the proper transaction Iterator<SinkContext> i = sinkContexts.values().iterator(); while(i.hasNext()) { SinkContext ctx = i.next(); ctx.rollback(); } sourceContext.rollback(); } public void close() throws Exception { //TODO: implement the proper transaction Iterator<SinkContext> i = sinkContexts.values().iterator(); while(i.hasNext()) { SinkContext ctx = i.next(); ctx.close();; } sourceContext.close(); } private void completeCommit() throws Exception { Iterator<SinkContext> i = sinkContexts.values().iterator(); while(i.hasNext()) { SinkContext ctx = i.next(); ctx.completeCommit(); } //The source should commit after sink commit. In the case the source or sink does not support //2 phases commit, it will cause the data to duplicate only, not loss sourceContext.assignedSourceStreamReader.completeCommit(); } static public class SourceContext { private Source source ; private SourceStream assignedSourceStream ; private SourceStreamReader assignedSourceStreamReader; public SourceContext(SourceFactory factory, StreamDescriptor streamDescriptor) throws Exception { this.source = factory.create(streamDescriptor) ; this.assignedSourceStream = source.getStream(streamDescriptor.getId()); this.assignedSourceStreamReader = assignedSourceStream.getReader("DataflowTask"); } public void prepapreCommit() throws Exception { assignedSourceStreamReader.prepareCommit(); } public void completeCommit() throws Exception { assignedSourceStreamReader.completeCommit(); } public void commit() throws Exception { assignedSourceStreamReader.commit(); } public void rollback() throws Exception { assignedSourceStreamReader.rollback(); } public void close() throws Exception { assignedSourceStreamReader.close(); } } static public class SinkContext { private Sink sink ; private SinkStream assignedSinkStream ; private SinkStreamWriter assignedSinkStreamWriter; public SinkContext(SinkFactory factory, StreamDescriptor streamDescriptor) throws Exception { this.sink = factory.create(streamDescriptor); this.assignedSinkStream = sink.getStream(streamDescriptor); this.assignedSinkStreamWriter = this.assignedSinkStream.getWriter(); } public void prepareCommit() throws Exception{ assignedSinkStreamWriter.prepareCommit(); } public void completeCommit() throws Exception { assignedSinkStreamWriter.completeCommit(); } public void commit() throws Exception { assignedSinkStreamWriter.commit(); } public void rollback() throws Exception { assignedSinkStreamWriter.rollback(); } public void close() throws Exception { assignedSinkStreamWriter.close(); } } }