package uk.ac.imperial.lsds.seepworker.core;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Properties;
import org.junit.Test;
import uk.ac.imperial.lsds.seep.api.API;
import uk.ac.imperial.lsds.seep.api.DataReference;
import uk.ac.imperial.lsds.seep.api.DataReference.ServeMode;
import uk.ac.imperial.lsds.seep.api.RuntimeEvent;
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.Schema;
import uk.ac.imperial.lsds.seep.api.data.Schema.SchemaBuilder;
import uk.ac.imperial.lsds.seep.api.data.TupleInfo;
import uk.ac.imperial.lsds.seep.api.data.Type;
import uk.ac.imperial.lsds.seep.testutils.WriterOfTrash;
import uk.ac.imperial.lsds.seepworker.WorkerConfig;
import uk.ac.imperial.lsds.seepworker.core.output.CoreOutput;
import uk.ac.imperial.lsds.seepworker.core.output.CoreOutputFactory;
public class OutOfMemoryEventTest {
public SeepTask createFakeSeepTask(Schema schema) {
WriterOfTrash wot = new WriterOfTrash(schema);
return wot;
}
// @Test
// public void testRunOutOfMemoryAndSpillToDisk() {
//
// // Configure test execution
// final int numBytesWritten = 256;//1048576;
// final int tupleSize = 4 + TupleInfo.TUPLE_SIZE_OVERHEAD;
// final int numTuples = numBytesWritten / tupleSize;
// final int maxBufferSize = 2046;
// final int minBufferAllocation = 128;
// // false if im writing less, true if Im writing more than memory size
// final boolean eventPositive = ((numTuples*tupleSize) > maxBufferSize);
//
//
// Schema schema = SchemaBuilder.getInstance().newField(Type.INT, "4bytes").build();
// // Get the fake task, passing a schema
// SeepTask wot = createFakeSeepTask(schema);
//
// // Configure properties of data reference manager
// Properties p = new Properties();
// p.put("bufferpool.max.memory.available", maxBufferSize);
// p.put("bufferpool.min.buffer.size", minBufferAllocation);
// p.put("master.ip", ""); // mandatory config
// p.put("worker.ip", ""); // mandatory config
// p.put("properties.file", ""); // mandatory config
// WorkerConfig wc = new WorkerConfig(p);
// DataReferenceManager drm = DataReferenceManager.makeDataReferenceManager(wc);
// CoreOutput coreOutput = CoreOutputFactory.buildCoreOutputForTestingOneDatasetOutput(wc, drm);
// API api = new Collector(0, coreOutput);
//
// ITuple d = new ITuple(schema); // same input schema than output, who cares
//
// for(int i = 0; i < numTuples; i++) {
// // create data
// byte[] data = new byte[] {0,1,2,3};
// d.setData(data);
//
// // call the task
// wot.processData(d, api);
// }
//
// List<RuntimeEvent> evs = api.getRuntimeEvents();
//
// for(RuntimeEvent ev : evs) {
// if (eventPositive){
// assert(ev.getSpillToDiskRuntimeEvent() != null);
// }
// else if (! eventPositive) {
// assert(ev.getSpillToDiskRuntimeEvent() == null);
// }
// }
// }
@Test
public void testReadFromSpilledFile() {
// First write something to the dataset -> REUSE method above, maybe changing the payload to ease debugging
// Then read data back and make sure size is the same and payload is correct
// Configure test execution
final int tupleSize = 4 + TupleInfo.TUPLE_SIZE_OVERHEAD;
final int numTuples = 10;
//Basing the buffer sizes on the tuple size lets us control running out of memory
final int maxBufferSize = 8 * tupleSize;
final int minBufferAllocation = 2 * tupleSize;
Schema schema = SchemaBuilder.getInstance().newField(Type.INT, "4bytes").build();
// Get the fake task, passing a schema
SeepTask wot = createFakeSeepTask(schema);
// Configure properties of data reference manager
Properties p = new Properties();
p.put("bufferpool.max.memory.available", maxBufferSize);
p.put("bufferpool.min.buffer.size", minBufferAllocation);
p.put("master.ip", ""); // mandatory config
p.put("worker.ip", ""); // mandatory config
p.put("properties.file", ""); // mandatory config
WorkerConfig wc = new WorkerConfig(p);
DataReferenceManager drm = DataReferenceManager.makeDataReferenceManager(wc);
CoreOutput coreOutput = CoreOutputFactory.buildCoreOutputForTestingOneDatasetOutput(null, drm);
API api = new Collector(0, coreOutput);
DataReference dataRef = DataReference.makeManagedDataReferenceWithOwner(((int)System.currentTimeMillis()%Integer.MAX_VALUE), null, null, ServeMode.STORE);
Dataset testDataset = (Dataset) drm.manageNewDataReference(dataRef);
ITuple d = new ITuple(schema); // same input schema than output, who cares
//create an output Dataset which is larger than our buffer
int tuplesWritten = 0;
for(int i = 0; i < numTuples; i++) {
// create data
ByteBuffer writeData = ByteBuffer.allocate(tupleSize);
writeData.putInt((new Integer(Integer.BYTES)));
writeData.putInt(i);
byte[] data = writeData.array();
d.setData(data);
testDataset.write(writeData.array(), api);
tuplesWritten++;
// call the task
//wot.processData(d, api);
}
//TODO: Grab output Dataset and check it for numbers 1-25.
System.out.println("done writing");
System.out.println("tuples written: " + tuplesWritten);
int tuplesRead = 0;
for (int x = 0; x < numTuples; x++) {
byte[] content = testDataset.consumeData();
if(content == null) {
System.out.println("why is content null");
break;
}
tuplesRead++;
ByteBuffer readData = ByteBuffer.allocate(content.length);
readData.put(content);
readData.flip();
readData.getInt();
assert(readData.getInt() == x):"The order of the Dataset appears to have been altered by the cache/return process";
}
System.out.println("Tuples read: " + tuplesRead);
System.out.println("Dataset size: " + testDataset.size());
System.out.println("Dataset cost: " + testDataset.creationCost());
//TODO: Assert that the Dataset has been fully consumed.
assert(testDataset.consumeData() == null):"New data was generated during the cache/return process";
}
}