@Test public void simpleWriteRead() { byte primaryRingSizeInBits = 9; byte byteRingSizeInBits = 18; Pipe ring = new Pipe(new PipeConfig(primaryRingSizeInBits, byteRingSizeInBits, null, FROM)); ring.initBuffers(); int messageSize = FROM.fragDataSize[FRAG_LOC]; int varDataMax = (ring.byteMask / (ring.mask >> 1)) / messageSize; int testSize = ((1 << primaryRingSizeInBits) / messageSize) - 1; // room for EOF writeTestValue(ring, varDataMax, testSize); // now read the data back int FIELD_LOC = FieldReferenceOffsetManager.lookupFieldLocator(SINGLE_MESSAGE_NAMES[0], FRAG_LOC, FROM); int k = testSize; while (PipeReader.tryReadFragment(ring)) { --k; assertTrue(PipeReader.isNewMessage(ring)); int messageIdx = PipeReader.getMsgIdx(ring); if (messageIdx < 0) { return; } testReadValue(ring, varDataMax, testSize, FIELD_LOC, k, messageIdx); } }
@Test public void simpleWriteReadThreaded() { final byte primaryRingSizeInBits = 7; // this ring is 2^7 eg 128 final byte byteRingSizeInBits = 16; final Pipe ring = new Pipe(new PipeConfig(primaryRingSizeInBits, byteRingSizeInBits, null, FROM)); ring.initBuffers(); final int messageSize = FROM.fragDataSize[FRAG_LOC]; final int varDataMax = (ring.byteMask / (ring.mask >> 1)) / messageSize; final int testSize = (1 << primaryRingSizeInBits) / messageSize; Thread t = new Thread( new Runnable() { @Override public void run() { writeTestValue(ring, varDataMax, testSize); } }); t.start(); // now read the data back int FIELD_LOC = FieldReferenceOffsetManager.lookupFieldLocator(SINGLE_MESSAGE_NAMES[0], FRAG_LOC, FROM); int k = testSize; while (k > 0) { // This is the example code that one would normally use. // System.err.println("content "+ring.contentRemaining(ring)); if (PipeReader.tryReadFragment( ring)) { // this method releases old messages as needed and moves pointer up to the next // fragment k--; // count down all the expected messages so we stop this test at the right time assertTrue(PipeReader.isNewMessage(ring)); int messageIdx = PipeReader.getMsgIdx(ring); if (messageIdx < 0) { return; } testReadValue(ring, varDataMax, testSize, FIELD_LOC, k, messageIdx); } else { // unable to read so at this point // we can do other work and try again soon Thread.yield(); } } }
private void writeTestValue(Pipe ring, int blockSize, int testSize) { int FIELD_LOC = FieldReferenceOffsetManager.lookupFieldLocator(SINGLE_MESSAGE_NAMES[0], FRAG_LOC, FROM); assertTrue(0 == Pipe.contentRemaining(ring)); int j = testSize; while (true) { if (j == 0) { PipeWriter.publishEOF(ring); return; // done } if (PipeWriter.tryWriteFragment( ring, FRAG_LOC)) { // returns true if there is room to write this fragment int value = (--j * blockSize) / testSize; PipeWriter.writeFloatAsIntBits(ring, FIELD_LOC, 1f / (float) value); PipeWriter.publishWrites(ring); // must always publish the writes if message or fragment } else { // Unable to write because there is no room so do something else while we are waiting. Thread.yield(); } } }
public OutputPipeInvocationHandler(Pipe outputRing, int msgIdx, Class<?> clazz) { super(clazz.getMethods()); FieldReferenceOffsetManager from = Pipe.from(outputRing); final Method[] methods = clazz.getMethods(); writers = new OutputPipeWriterMethod[MAX_METHODS]; int j = methods.length; while (--j >= 0) { final Method method = methods[j]; ProngTemplateField fieldAnnonation = method.getAnnotation(ProngTemplateField.class); if (null != fieldAnnonation) { int fieldLoc = FieldReferenceOffsetManager.lookupFieldLocator(fieldAnnonation.fieldId(), msgIdx, from); int key = buildKey(this, method.getName()); if (null != writers[key]) { throw new UnsupportedOperationException(); } writers[key] = OutputPipeWriterMethod.buildWriteForYourType( outputRing, fieldAnnonation.decimalPlaces(), fieldLoc, (fieldLoc >> FieldReferenceOffsetManager.RW_FIELD_OFF_BITS) & TokenBuilder.MASK_TYPE, from); } } }
@Before public void createTestFile() { rb = new Pipe(new PipeConfig((byte) 21, (byte) 7, null, FieldReferenceOffsetManager.RAW_BYTES)); rb.initBuffers(); try { // build a bunch of data int i = 1 << 26; byte[] temp = new byte[i]; while (--i >= 0) { if ((i & 0x3F) == 0) { temp[i] = '\n'; } else { if ((((i + 1) & 0x7) == 0) && (((i + 9) & 0x1F) == 0)) { temp[i] = '\\'; } else { if ((i & 0x7) == 0) { temp[i] = ','; } else { temp[i] = (byte) ('0' + (int) (0x1F & i)); } } } } // System.err.println(new String(temp)); // write the data to the file File f = File.createTempFile(this.getClass().getSimpleName(), "test"); f.deleteOnExit(); // but do keep it arround while we do our test FileOutputStream out = new FileOutputStream(f); out.write(temp); out.close(); testFile = f; } catch (IOException e) { e.printStackTrace(); fail(); } }
/** * Experimental parser built to leverage multiple cores and keep up with the speed of modern SSDs * * @param fileChannel * @throws IOException */ public void extract(FileChannel fileChannel) throws IOException { MappedByteBuffer mappedBuffer; long fileSize = fileChannel.size(); long position = 0; int tailPadding = 8; // needed to cover the transition long blockSize = 1 << 25; TypeExtractor typeExtractor = new TypeExtractor(true /* force ASCII */); RecordFieldExtractor rfe = new RecordFieldExtractor(); mappedBuffer = fileChannel.map( FileChannel.MapMode.READ_ONLY, position, Math.min(blockSize, fileSize - position)); int padding = tailPadding; do { if (mappedBuffer.limit() + position == fileSize) { padding = 0; } int pos = 0; Pipe.setValue( rb.structuredLayoutRingBuffer, rb.mask, Pipe.getWorkingHeadPositionObject(rb).value++, pos); int tokenCount = 0; int c = 0; int j = mappedBuffer.remaining() - padding; do { // walk over the data while we have this section mapped. c++; byte b = (byte) mappedBuffer.get(); // RecordFieldExtractor.appendContent(rfe, b); //TOO much work here must do on reading // thread. // TODO: check the field type sums // TODO: zero copy but we need to discover tokens // splits on returns, commas, dots and many other punctuation if (b < 48) { // System.err.println("char :"+b); // what mask can be built to combine the byte we are after. // allTheBits++; //do something pos = mappedBuffer.position(); Pipe.setValue( rb.structuredLayoutRingBuffer, rb.mask, Pipe.getWorkingHeadPositionObject(rb).value++, pos); if ((++tokenCount & 0xF) == 0) { Pipe.publishWrites(rb); } // rb.reset(); } } while (--j > 0); // this tokenizer assumes that the file ends with a field delimiter so the last record gets // flushed. // TODO: need to wait for threads to finish before swapping to new page or have multiple pages // to swap in/out // only increment by exactly how many bytes were read assuming we started at zero // can only cut at the last known record start position += c; System.out.println("bytes read so far:" + position); mappedBuffer = fileChannel.map( FileChannel.MapMode.READ_ONLY, position, Math.min(blockSize, fileSize - position)); } while (position < fileSize); }