@Override public void writeTo(GatheringByteChannel channel) throws IOException { ByteBuffer[] buffers; ByteBuffer currentBuffer = null; BytesRef ref = new BytesRef(); int pos = 0; // are we a slice? if (offset != 0) { // remaining size of page fragment at offset int fragmentSize = Math.min(length, PAGE_SIZE - (offset % PAGE_SIZE)); bytearray.get(offset, fragmentSize, ref); currentBuffer = ByteBuffer.wrap(ref.bytes, ref.offset, fragmentSize); pos += fragmentSize; } // we only have a single page if (pos == length && currentBuffer != null) { channel.write(currentBuffer); return; } // a slice > pagesize will likely require extra buffers for initial/trailing fragments int numBuffers = countRequiredBuffers((currentBuffer != null ? 1 : 0), length - pos); buffers = new ByteBuffer[numBuffers]; int bufferSlot = 0; if (currentBuffer != null) { buffers[bufferSlot] = currentBuffer; bufferSlot++; } // handle remainder of pages + trailing fragment while (pos < length) { int remaining = length - pos; int bulkSize = (remaining > PAGE_SIZE) ? PAGE_SIZE : remaining; bytearray.get(offset + pos, bulkSize, ref); currentBuffer = ByteBuffer.wrap(ref.bytes, ref.offset, bulkSize); buffers[bufferSlot] = currentBuffer; bufferSlot++; pos += bulkSize; } // this would indicate that our numBuffer calculation is off by one. assert (numBuffers == bufferSlot); // finally write all buffers channel.write(buffers); }
@Override public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { if (PlatformDependent.javaVersion() < 7) { // XXX Gathering write is not supported because of a known issue. // See http://bugs.sun.com/view_bug.do?bug_id=6210541 return out.write(copiedNioBuffer(index, length)); } else { long writtenBytes = out.write(nioBuffers(index, length)); if (writtenBytes > Integer.MAX_VALUE) { return Integer.MAX_VALUE; } else { return (int) writtenBytes; } } }
/** {@inheritDoc} */ @Override public void write(GatheringByteChannel outputchannel) { try { int numimages = numImages(); // Encode each image ByteBuffer[] images = new ByteBuffer[numimages]; for (int i = 0; i < images.length; i++) { ByteBuffer image = com.mikeduvall.redhorizon.util.ByteBufferFactory.createLittleEndianByteBuffer( shpimages[i].capacity()); CodecUtility.encodeFormat80(shpimages[i], image); images[i] = image; } // Construct image offset headers for each image ByteBuffer[] offsets = new ByteBuffer[numimages + 2]; int offsettotal = ShpFileHeaderCNC.HEADER_SIZE + (ShpImageOffsetCNC.OFFSET_SIZE * offsets.length); for (int i = 0; i < numImages(); i++) { offsets[i] = new ShpImageOffsetCNC(offsettotal, FORMAT80, 0, (byte) 0).toByteBuffer(); offsettotal += images[i].limit(); } // The 2 special image offsets at the end of the offset array offsets[numimages] = new ShpImageOffsetCNC(offsettotal, (byte) 0, 0, (byte) 0).toByteBuffer(); offsets[numimages + 1] = new ShpImageOffsetCNC(0, (byte) 0, 0, (byte) 0).toByteBuffer(); // Build header ByteBuffer header = shpfileheader.toByteBuffer(); // Write file try { outputchannel.write(header); outputchannel.write(offsets); outputchannel.write(images); } catch (IOException e) { throw new RuntimeException(e); } } finally { try { outputchannel.close(); } catch (IOException e) { throw new RuntimeException(e); } } }
@Override public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { checkIndex(index, length); index = idx(index); return out.write( (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length)); }
public static void main(String[] args) throws Exception { int reps = 10; if (args.length > 0) { reps = Integer.parseInt(args[0]); } FileOutputStream fos = new FileOutputStream(DEMOGRAPHIC); GatheringByteChannel gatherChannel = fos.getChannel(); ByteBuffer[] bs = utterBS(reps); while (gatherChannel.write(bs) > 0) {} System.out.println("Mindshare paradigms sysnergized to " + DEMOGRAPHIC); fos.close(); }
@Override public int readBytes(GatheringByteChannel out, int length) throws IOException { byte[] array = new byte[length]; try { delegate.get(array, length); return out.write(ByteBuffer.wrap(array)); } catch (ReadPastEndException e) { throw outOfBounds(e); } }
@Override public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { ensureAccessible(); if (length == 0) { return 0; } ByteBuffer tmpBuf = internalNioBuffer(); tmpBuf.clear().position(index).limit(index + length); return out.write(tmpBuf); }
private int getBytes(int var1, GatheringByteChannel var2, int var3, boolean var4) throws IOException { this.checkIndex(var1, var3); if (var3 == 0) { return 0; } else { ByteBuffer var5; if (var4) { var5 = this.internalNioBuffer(); } else { var5 = ((ByteBuffer) this.memory).duplicate(); } var1 = this.idx(var1); var5.clear().position(var1).limit(var1 + var3); return var2.write(var5); } }
/** * Write out our chain of buffers in chunks * * @param channel Where to write * @param chunkSize Size of chunks to write. * @return Amount written. * @throws IOException */ long write(GatheringByteChannel channel, int chunkSize) throws IOException { int chunkRemaining = chunkSize; ByteBuffer lastBuffer = null; int bufCount = 0; int restoreLimit = -1; while (chunkRemaining > 0 && bufferOffset + bufCount < buffers.length) { lastBuffer = buffers[bufferOffset + bufCount]; if (!lastBuffer.hasRemaining()) { bufferOffset++; continue; } bufCount++; if (lastBuffer.remaining() > chunkRemaining) { restoreLimit = lastBuffer.limit(); lastBuffer.limit(lastBuffer.position() + chunkRemaining); chunkRemaining = 0; break; } else { chunkRemaining -= lastBuffer.remaining(); } } assert lastBuffer != null; if (chunkRemaining == chunkSize) { assert !hasRemaining(); // no data left to write return 0; } try { long ret = channel.write(buffers, bufferOffset, bufCount); if (ret > 0) { remaining -= ret; } return ret; } finally { if (restoreLimit >= 0) { lastBuffer.limit(restoreLimit); } } }
public void getBox(WritableByteChannel writableByteChannel) throws IOException { ByteBuffer bb = ByteBuffer.allocate(16); long size = getSize(); if (isSmallBox(size)) { IsoTypeWriter.writeUInt32(bb, size); } else { IsoTypeWriter.writeUInt32(bb, 1); } bb.put(IsoFile.fourCCtoBytes("mdat")); if (isSmallBox(size)) { bb.put(new byte[8]); } else { IsoTypeWriter.writeUInt64(bb, size); } bb.rewind(); writableByteChannel.write(bb); if (writableByteChannel instanceof GatheringByteChannel) { List<ByteBuffer> nuSamples = unifyAdjacentBuffers(samples); int STEPSIZE = 1024; for (int i = 0; i < Math.ceil((double) nuSamples.size() / STEPSIZE); i++) { List<ByteBuffer> sublist = nuSamples.subList( i * STEPSIZE, // start (i + 1) * STEPSIZE < nuSamples.size() ? (i + 1) * STEPSIZE : nuSamples.size()); // end ByteBuffer sampleArray[] = sublist.toArray(new ByteBuffer[sublist.size()]); do { ((GatheringByteChannel) writableByteChannel).write(sampleArray); } while (sampleArray[sampleArray.length - 1].remaining() > 0); } // System.err.println(bytesWritten); } else { for (ByteBuffer sample : samples) { sample.rewind(); writableByteChannel.write(sample); } } }
/** * Drain pending buffers one at a time into the socket * * @param channel * @return * @throws IOException */ @Override int drainTo(final GatheringByteChannel channel) throws IOException { int bytesWritten = 0; long rc = 0; do { /* * Nothing to write */ if (m_currentWriteBuffer == null && m_queuedBuffers.isEmpty()) { break; } ByteBuffer buffer = null; if (m_currentWriteBuffer == null) { m_currentWriteBuffer = m_queuedBuffers.poll(); buffer = m_currentWriteBuffer.b(); buffer.flip(); } else { buffer = m_currentWriteBuffer.b(); } rc = channel.write(buffer); // Discard the buffer back to a pool if no data remains if (!buffer.hasRemaining()) { m_currentWriteBuffer.discard(); m_currentWriteBuffer = null; m_messagesWritten++; } bytesWritten += rc; } while (rc > 0); m_bytesWritten += bytesWritten; return bytesWritten; }
@Override public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { ensureAccessible(); return out.write( (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length)); }
@Override public void close() throws IOException { if (null != out) { out.close(); } }
@Override protected void doWrite(ChannelOutboundBuffer in) throws Exception { int writeSpinCount = -1; GatheringByteChannel sink = connection().getSinkChannel(); for (; ; ) { // Do gathering write for a non-single buffer case. final int msgCount = in.size(); if (msgCount > 0) { // Ensure the pending writes are made of ByteBufs only. ByteBuffer[] nioBuffers = in.nioBuffers(); if (nioBuffers != null) { int nioBufferCnt = in.nioBufferCount(); long expectedWrittenBytes = in.nioBufferSize(); long writtenBytes = 0; boolean done = false; boolean setOpWrite = false; for (int i = config().getWriteSpinCount() - 1; i >= 0; i--) { final long localWrittenBytes = sink.write(nioBuffers, 0, nioBufferCnt); if (localWrittenBytes == 0) { setOpWrite = true; break; } expectedWrittenBytes -= localWrittenBytes; writtenBytes += localWrittenBytes; if (expectedWrittenBytes == 0) { done = true; break; } } if (done) { // Release all buffers for (int i = msgCount; i > 0; i--) { in.remove(); } // Finish the write loop if no new messages were flushed by in.remove(). if (in.isEmpty()) { connection().getSinkChannel().suspendWrites(); break; } } else { // Did not write all buffers completely. // Release the fully written buffers and update the indexes of the partially written // buffer. for (int i = msgCount; i > 0; i--) { final ByteBuf buf = (ByteBuf) in.current(); final int readerIndex = buf.readerIndex(); final int readableBytes = buf.writerIndex() - readerIndex; if (readableBytes < writtenBytes) { in.progress(readableBytes); in.remove(); writtenBytes -= readableBytes; } else if (readableBytes > writtenBytes) { buf.readerIndex(readerIndex + (int) writtenBytes); in.progress(writtenBytes); break; } else { // readableBytes == writtenBytes in.progress(readableBytes); in.remove(); break; } } incompleteWrite(setOpWrite); break; } continue; } } Object msg = in.current(); if (msg == null) { // Wrote all messages. connection().getSinkChannel().suspendWrites(); break; } if (msg instanceof ByteBuf) { ByteBuf buf = (ByteBuf) msg; int readableBytes = buf.readableBytes(); if (readableBytes == 0) { in.remove(); continue; } if (!buf.isDirect()) { ByteBufAllocator alloc = alloc(); if (alloc.isDirectBufferPooled()) { // Non-direct buffers are copied into JDK's own internal direct buffer on every I/O. // We can do a better job by using our pooled allocator. If the current allocator does // not // pool a direct buffer, we rely on JDK's direct buffer pool. buf = alloc.directBuffer(readableBytes).writeBytes(buf); in.current(buf); } } boolean setOpWrite = false; boolean done = false; long flushedAmount = 0; if (writeSpinCount == -1) { writeSpinCount = config().getWriteSpinCount(); } for (int i = writeSpinCount - 1; i >= 0; i--) { int localFlushedAmount = buf.readBytes(sink, buf.readableBytes()); if (localFlushedAmount == 0) { setOpWrite = true; break; } flushedAmount += localFlushedAmount; if (!buf.isReadable()) { done = true; break; } } in.progress(flushedAmount); if (done) { in.remove(); } else { incompleteWrite(setOpWrite); break; } } else if (msg instanceof FileRegion) { FileRegion region = (FileRegion) msg; boolean setOpWrite = false; boolean done = false; long flushedAmount = 0; if (writeSpinCount == -1) { writeSpinCount = config().getWriteSpinCount(); } for (int i = writeSpinCount - 1; i >= 0; i--) { long localFlushedAmount = region.transferTo(sink, region.transfered()); if (localFlushedAmount == 0) { setOpWrite = true; break; } flushedAmount += localFlushedAmount; if (region.transfered() >= region.count()) { done = true; break; } } in.progress(flushedAmount); if (done) { in.remove(); } else { incompleteWrite(setOpWrite); break; } } else { throw new UnsupportedOperationException( "unsupported message type: " + StringUtil.simpleClassName(msg)); } } }
@Test public void testSendDatagramWithoutCallback() throws Exception { // Single datagram sending Pipe readPipe = Pipe.open(); Pipe writePipe = Pipe.open(); GatheringByteChannel gatheringByteChannel = writePipe.sink(); ScatteringByteChannel scatteringByteChannel = readPipe.source(); SelectionKeyRegistrationReference registrationReference = (SelectionKeyRegistrationReference) _selectorIntraband.registerChannel(writePipe.source(), readPipe.sink()); Thread wakeUpThread = new Thread(new WakeUpRunnable(_selectorIntraband)); wakeUpThread.start(); Selector selector = _selectorIntraband.selector; synchronized (selector) { wakeUpThread.interrupt(); wakeUpThread.join(); Datagram requestDatagram = Datagram.createRequestDatagram(_type, _data); _selectorIntraband.sendDatagram(registrationReference, requestDatagram); SelectionKey writeSelectionKey = registrationReference.writeSelectionKey; ChannelContext channelContext = (ChannelContext) writeSelectionKey.attachment(); Queue<Datagram> sendingQueue = channelContext.getSendingQueue(); Assert.assertEquals(1, sendingQueue.size()); Assert.assertSame(requestDatagram, sendingQueue.peek()); } Datagram receiveDatagram = IntrabandTestUtil.readDatagramFully(scatteringByteChannel); Assert.assertEquals(_type, receiveDatagram.getType()); ByteBuffer dataByteBuffer = receiveDatagram.getDataByteBuffer(); Assert.assertArrayEquals(_data, dataByteBuffer.array()); // Two datagrams continuous sending Datagram requestDatagram1 = Datagram.createRequestDatagram(_type, _data); Datagram requestDatagram2 = Datagram.createRequestDatagram(_type, _data); wakeUpThread = new Thread(new WakeUpRunnable(_selectorIntraband)); wakeUpThread.start(); synchronized (selector) { wakeUpThread.interrupt(); wakeUpThread.join(); _selectorIntraband.sendDatagram(registrationReference, requestDatagram1); _selectorIntraband.sendDatagram(registrationReference, requestDatagram2); SelectionKey writeSelectionKey = registrationReference.writeSelectionKey; ChannelContext channelContext = (ChannelContext) writeSelectionKey.attachment(); Queue<Datagram> sendingQueue = channelContext.getSendingQueue(); Assert.assertEquals(2, sendingQueue.size()); Datagram[] datagrams = sendingQueue.toArray(new Datagram[2]); Assert.assertSame(requestDatagram1, datagrams[0]); Assert.assertSame(requestDatagram2, datagrams[1]); } Datagram receiveDatagram1 = IntrabandTestUtil.readDatagramFully(scatteringByteChannel); Assert.assertEquals(_type, receiveDatagram1.getType()); dataByteBuffer = receiveDatagram1.getDataByteBuffer(); Assert.assertArrayEquals(_data, dataByteBuffer.array()); Datagram receiveDatagram2 = IntrabandTestUtil.readDatagramFully(scatteringByteChannel); Assert.assertEquals(_type, receiveDatagram2.getType()); dataByteBuffer = receiveDatagram2.getDataByteBuffer(); Assert.assertArrayEquals(_data, dataByteBuffer.array()); // Two datagrams delay sending requestDatagram1 = Datagram.createRequestDatagram(_type, _data); requestDatagram2 = Datagram.createRequestDatagram(_type, _data); wakeUpThread = new Thread(new WakeUpRunnable(_selectorIntraband)); wakeUpThread.start(); SelectionKey writeSelectionKey = registrationReference.writeSelectionKey; ChannelContext channelContext = (ChannelContext) writeSelectionKey.attachment(); Queue<Datagram> sendingQueue = channelContext.getSendingQueue(); synchronized (writeSelectionKey) { synchronized (selector) { wakeUpThread.interrupt(); wakeUpThread.join(); _selectorIntraband.sendDatagram(registrationReference, requestDatagram1); Assert.assertEquals(1, sendingQueue.size()); Assert.assertSame(requestDatagram1, sendingQueue.peek()); } receiveDatagram1 = IntrabandTestUtil.readDatagramFully(scatteringByteChannel); Assert.assertEquals(_type, receiveDatagram1.getType()); dataByteBuffer = receiveDatagram1.getDataByteBuffer(); Assert.assertArrayEquals(_data, dataByteBuffer.array()); Thread pollingThread = _selectorIntraband.pollingThread; while (pollingThread.getState() == Thread.State.RUNNABLE) ; _selectorIntraband.sendDatagram(registrationReference, requestDatagram2); Assert.assertEquals(1, sendingQueue.size()); Assert.assertSame(requestDatagram2, sendingQueue.peek()); } receiveDatagram2 = IntrabandTestUtil.readDatagramFully(scatteringByteChannel); Assert.assertEquals(_type, receiveDatagram2.getType()); dataByteBuffer = receiveDatagram2.getDataByteBuffer(); Assert.assertArrayEquals(_data, dataByteBuffer.array()); // Huge datagram sending int hugeBufferSize = 1024 * 1024 * 10; ByteBuffer hugeBuffer = ByteBuffer.allocate(hugeBufferSize); for (int i = 0; i < hugeBufferSize; i++) { hugeBuffer.put(i, (byte) i); } _selectorIntraband.sendDatagram( registrationReference, Datagram.createRequestDatagram(_type, hugeBuffer)); receiveDatagram = DatagramHelper.createReceiveDatagram(); channelContext = (ChannelContext) writeSelectionKey.attachment(); int count = 0; while (!DatagramHelper.readFrom(receiveDatagram, scatteringByteChannel)) { count++; } Assert.assertTrue(count > 0); sendingQueue = channelContext.getSendingQueue(); Assert.assertTrue(sendingQueue.isEmpty()); dataByteBuffer = receiveDatagram.getDataByteBuffer(); Assert.assertArrayEquals(hugeBuffer.array(), dataByteBuffer.array()); unregisterChannels(registrationReference); gatheringByteChannel.close(); scatteringByteChannel.close(); }
@AdviseWith(adviceClasses = {Jdk14LogImplAdvice.class}) @Test public void testSendDatagramWithCallback() throws Exception { // Submitted callback Pipe readPipe = Pipe.open(); Pipe writePipe = Pipe.open(); GatheringByteChannel gatheringByteChannel = writePipe.sink(); ScatteringByteChannel scatteringByteChannel = readPipe.source(); RegistrationReference registrationReference = _selectorIntraband.registerChannel(writePipe.source(), readPipe.sink()); Object attachment = new Object(); RecordCompletionHandler<Object> recordCompletionHandler = new RecordCompletionHandler<Object>(); _selectorIntraband.sendDatagram( registrationReference, Datagram.createRequestDatagram(_type, _data), attachment, EnumSet.of(CompletionType.SUBMITTED), recordCompletionHandler); Datagram receiveDatagram = IntrabandTestUtil.readDatagramFully(scatteringByteChannel); recordCompletionHandler.waitUntilSubmitted(); Assert.assertSame(attachment, recordCompletionHandler.getAttachment()); Assert.assertEquals(_type, receiveDatagram.getType()); ByteBuffer dataByteBuffer = receiveDatagram.getDataByteBuffer(); Assert.assertArrayEquals(_data, dataByteBuffer.array()); CaptureHandler captureHandler = null; try { // Callback timeout, with log captureHandler = JDKLoggerTestUtil.configureJDKLogger(BaseIntraband.class.getName(), Level.WARNING); List<LogRecord> logRecords = captureHandler.getLogRecords(); recordCompletionHandler = new RecordCompletionHandler<Object>(); _selectorIntraband.sendDatagram( registrationReference, Datagram.createRequestDatagram(_type, _data), attachment, EnumSet.of(CompletionType.DELIVERED), recordCompletionHandler, 10, TimeUnit.MILLISECONDS); Selector selector = _selectorIntraband.selector; recordCompletionHandler.waitUntilTimeouted(selector); Assert.assertSame(attachment, recordCompletionHandler.getAttachment()); Assert.assertEquals(1, logRecords.size()); IntrabandTestUtil.assertMessageStartWith( logRecords.get(0), "Removed timeout response waiting datagram"); // Callback timeout, without log logRecords = captureHandler.resetLogLevel(Level.OFF); recordCompletionHandler = new RecordCompletionHandler<Object>(); _selectorIntraband.sendDatagram( registrationReference, Datagram.createRequestDatagram(_type, _data), attachment, EnumSet.of(CompletionType.DELIVERED), recordCompletionHandler, 10, TimeUnit.MILLISECONDS); recordCompletionHandler.waitUntilTimeouted(selector); Assert.assertSame(attachment, recordCompletionHandler.getAttachment()); Assert.assertTrue(logRecords.isEmpty()); } finally { if (captureHandler != null) { captureHandler.close(); } } // Callback timeout, completion handler causes NPE captureHandler = JDKLoggerTestUtil.configureJDKLogger(SelectorIntraband.class.getName(), Level.SEVERE); try { List<LogRecord> logRecords = captureHandler.getLogRecords(); recordCompletionHandler = new RecordCompletionHandler<Object>() { @Override public void timedOut(Object attachment) { super.timedOut(attachment); throw new NullPointerException(); } }; Jdk14LogImplAdvice.reset(); Selector selector = _selectorIntraband.selector; try { _selectorIntraband.sendDatagram( registrationReference, Datagram.createRequestDatagram(_type, _data), attachment, EnumSet.of(CompletionType.DELIVERED), recordCompletionHandler, 10, TimeUnit.MILLISECONDS); } finally { recordCompletionHandler.waitUntilTimeouted(selector); Jdk14LogImplAdvice.waitUntilErrorCalled(); } Assert.assertFalse(selector.isOpen()); Assert.assertEquals(1, logRecords.size()); IntrabandTestUtil.assertMessageStartWith( logRecords.get(0), SelectorIntraband.class + ".threadFactory-1 exiting exceptionally"); gatheringByteChannel.close(); scatteringByteChannel.close(); } finally { captureHandler.close(); } }
@AdviseWith(adviceClasses = {Jdk14LogImplAdvice.class}) @Test public void testReceiveDatagram() throws Exception { Pipe readPipe = Pipe.open(); Pipe writePipe = Pipe.open(); GatheringByteChannel gatheringByteChannel = writePipe.sink(); ScatteringByteChannel scatteringByteChannel = readPipe.source(); SelectionKeyRegistrationReference registrationReference = (SelectionKeyRegistrationReference) _selectorIntraband.registerChannel(writePipe.source(), readPipe.sink()); long sequenceId = 100; CaptureHandler captureHandler = null; try { // Receive ACK response, no ACK request, with log captureHandler = JDKLoggerTestUtil.configureJDKLogger(BaseIntraband.class.getName(), Level.WARNING); List<LogRecord> logRecords = captureHandler.getLogRecords(); Jdk14LogImplAdvice.reset(); try { DatagramHelper.writeTo( DatagramHelper.createACKResponseDatagram(sequenceId), gatheringByteChannel); } finally { Jdk14LogImplAdvice.waitUntilWarnCalled(); } Assert.assertEquals(1, logRecords.size()); IntrabandTestUtil.assertMessageStartWith( logRecords.get(0), "Dropped ownerless ACK response "); // Receive ACK response, no ACK request, without log logRecords = captureHandler.resetLogLevel(Level.OFF); Jdk14LogImplAdvice.reset(); try { DatagramHelper.writeTo( DatagramHelper.createACKResponseDatagram(sequenceId), gatheringByteChannel); } finally { Jdk14LogImplAdvice.waitUntilIsWarnEnableCalled(); } Assert.assertTrue(logRecords.isEmpty()); // Receive ACK response, with ACK request Datagram requestDatagram = Datagram.createRequestDatagram(_type, _data); DatagramHelper.setAttachment(requestDatagram, new Object()); RecordCompletionHandler<Object> recordCompletionHandler = new RecordCompletionHandler<Object>(); DatagramHelper.setCompletionHandler(requestDatagram, recordCompletionHandler); DatagramHelper.setSequenceId(requestDatagram, sequenceId); DatagramHelper.setTimeout(requestDatagram, 10000); BaseIntrabandHelper.addResponseWaitingDatagram(_selectorIntraband, requestDatagram); DatagramHelper.writeTo( DatagramHelper.createACKResponseDatagram(sequenceId), gatheringByteChannel); recordCompletionHandler.waitUntilDelivered(); Assert.assertSame( DatagramHelper.getAttachment(requestDatagram), recordCompletionHandler.getAttachment()); // Receive response, no request, with log logRecords = captureHandler.resetLogLevel(Level.WARNING); Jdk14LogImplAdvice.reset(); try { DatagramHelper.writeTo( Datagram.createResponseDatagram(requestDatagram, _data), gatheringByteChannel); } finally { Jdk14LogImplAdvice.waitUntilWarnCalled(); } Assert.assertEquals(1, logRecords.size()); IntrabandTestUtil.assertMessageStartWith(logRecords.get(0), "Dropped ownerless response "); // Receive response, no request, without log logRecords = captureHandler.resetLogLevel(Level.OFF); Jdk14LogImplAdvice.reset(); try { requestDatagram = Datagram.createRequestDatagram(_type, _data); DatagramHelper.setSequenceId(requestDatagram, sequenceId); DatagramHelper.writeTo( Datagram.createResponseDatagram(requestDatagram, _data), gatheringByteChannel); } finally { Jdk14LogImplAdvice.waitUntilIsWarnEnableCalled(); } Assert.assertTrue(logRecords.isEmpty()); // Receive response, with request, with replied completion handler requestDatagram = Datagram.createRequestDatagram(_type, _data); DatagramHelper.setAttachment(requestDatagram, new Object()); recordCompletionHandler = new RecordCompletionHandler<Object>(); DatagramHelper.setCompletionHandler(requestDatagram, recordCompletionHandler); DatagramHelper.setCompletionTypes(requestDatagram, EnumSet.of(CompletionType.REPLIED)); DatagramHelper.setSequenceId(requestDatagram, sequenceId); DatagramHelper.setTimeout(requestDatagram, 10000); BaseIntrabandHelper.addResponseWaitingDatagram(_selectorIntraband, requestDatagram); DatagramHelper.writeTo( Datagram.createResponseDatagram(requestDatagram, _data), gatheringByteChannel); recordCompletionHandler.waitUntilReplied(); Assert.assertSame( DatagramHelper.getAttachment(requestDatagram), recordCompletionHandler.getAttachment()); // Receive response, with request, without replied completion // handler, with log logRecords = captureHandler.resetLogLevel(Level.WARNING); requestDatagram = Datagram.createRequestDatagram(_type, _data); DatagramHelper.setCompletionTypes(requestDatagram, EnumSet.noneOf(CompletionType.class)); recordCompletionHandler = new RecordCompletionHandler<Object>(); DatagramHelper.setCompletionHandler(requestDatagram, recordCompletionHandler); DatagramHelper.setSequenceId(requestDatagram, sequenceId); DatagramHelper.setTimeout(requestDatagram, 10000); BaseIntrabandHelper.addResponseWaitingDatagram(_selectorIntraband, requestDatagram); Jdk14LogImplAdvice.reset(); try { DatagramHelper.writeTo( Datagram.createResponseDatagram(requestDatagram, _data), gatheringByteChannel); } finally { Jdk14LogImplAdvice.waitUntilWarnCalled(); } Assert.assertEquals(1, logRecords.size()); IntrabandTestUtil.assertMessageStartWith(logRecords.get(0), "Dropped unconcerned response "); // Receive response, with request, without replied completion // handler, without log logRecords = captureHandler.resetLogLevel(Level.OFF); requestDatagram = Datagram.createRequestDatagram(_type, _data); DatagramHelper.setCompletionTypes(requestDatagram, EnumSet.noneOf(CompletionType.class)); recordCompletionHandler = new RecordCompletionHandler<Object>(); DatagramHelper.setCompletionHandler(requestDatagram, recordCompletionHandler); DatagramHelper.setSequenceId(requestDatagram, sequenceId); DatagramHelper.setTimeout(requestDatagram, 10000); BaseIntrabandHelper.addResponseWaitingDatagram(_selectorIntraband, requestDatagram); Jdk14LogImplAdvice.reset(); try { DatagramHelper.writeTo( Datagram.createResponseDatagram(requestDatagram, _data), gatheringByteChannel); } finally { Jdk14LogImplAdvice.waitUntilIsWarnEnableCalled(); } Assert.assertTrue(logRecords.isEmpty()); // Receive request, requires ACK, no datagram receive handler, // with log logRecords = captureHandler.resetLogLevel(Level.WARNING); requestDatagram = Datagram.createRequestDatagram(_type, _data); DatagramHelper.setAckRequest(requestDatagram); DatagramHelper.setSequenceId(requestDatagram, sequenceId); Jdk14LogImplAdvice.reset(); try { DatagramHelper.writeTo(requestDatagram, gatheringByteChannel); } finally { Jdk14LogImplAdvice.waitUntilWarnCalled(); } Datagram ackResponseDatagram = IntrabandTestUtil.readDatagramFully(scatteringByteChannel); Assert.assertEquals(sequenceId, DatagramHelper.getSequenceId(ackResponseDatagram)); Assert.assertTrue(DatagramHelper.isAckResponse(ackResponseDatagram)); ByteBuffer dataByteBuffer = ackResponseDatagram.getDataByteBuffer(); Assert.assertEquals(0, dataByteBuffer.capacity()); Assert.assertEquals(1, logRecords.size()); IntrabandTestUtil.assertMessageStartWith(logRecords.get(0), "Dropped ownerless request "); // Receive request, no datagram receive handler, without log logRecords = captureHandler.resetLogLevel(Level.OFF); requestDatagram = Datagram.createRequestDatagram(_type, _data); DatagramHelper.setSequenceId(requestDatagram, sequenceId); Jdk14LogImplAdvice.reset(); try { DatagramHelper.writeTo(requestDatagram, gatheringByteChannel); } finally { Jdk14LogImplAdvice.waitUntilIsWarnEnableCalled(); } Assert.assertTrue(logRecords.isEmpty()); // Receive request, with datagram receive handler, logRecords = captureHandler.resetLogLevel(Level.SEVERE); requestDatagram = Datagram.createRequestDatagram(_type, _data); DatagramHelper.setSequenceId(requestDatagram, sequenceId); RecordDatagramReceiveHandler recordDatagramReceiveHandler = new RecordDatagramReceiveHandler(); _selectorIntraband.registerDatagramReceiveHandler(_type, recordDatagramReceiveHandler); Jdk14LogImplAdvice.reset(); try { DatagramHelper.writeTo(requestDatagram, gatheringByteChannel); } finally { Jdk14LogImplAdvice.waitUntilErrorCalled(); } Datagram receiveDatagram = recordDatagramReceiveHandler.getReceiveDatagram(); Assert.assertEquals(sequenceId, DatagramHelper.getSequenceId(receiveDatagram)); Assert.assertEquals(_type, receiveDatagram.getType()); dataByteBuffer = receiveDatagram.getDataByteBuffer(); Assert.assertArrayEquals(_data, dataByteBuffer.array()); Assert.assertEquals(1, logRecords.size()); IntrabandTestUtil.assertMessageStartWith(logRecords.get(0), "Unable to dispatch"); unregisterChannels(registrationReference); gatheringByteChannel.close(); scatteringByteChannel.close(); } finally { if (captureHandler != null) { captureHandler.close(); } } }
/** {@inheritDoc} */ @Override public void write(GatheringByteChannel outputchannel) { int numimages = numImages(); // Build header ByteBuffer header = wsaheader.toByteBuffer(); // Build palette ByteBuffer palette = wsapalette.toByteBuffer(); // Encode each frame, construct matching offsets ByteBuffer[] frames = new ByteBuffer[isLooping() ? numimages + 1 : numimages]; ByteBuffer lastbytes = com.mikeduvall.redhorizon.util.ByteBufferFactory.createLittleEndianByteBuffer( width() * height()); ByteBuffer frameoffsets = com.mikeduvall.redhorizon.util.ByteBufferFactory.createLittleEndianByteBuffer( (numimages + 2) * 4); int offsettotal = WsaFileHeaderCNC.HEADER_SIZE + ((numimages + 2) * 4); for (int i = 0; i < frames.length; i++) { ByteBuffer framebytes = wsaframes[i]; ByteBuffer frameint = com.mikeduvall.redhorizon.util.ByteBufferFactory.createLittleEndianByteBuffer( (int) (framebytes.capacity() * 1.5)); ByteBuffer frame = com.mikeduvall.redhorizon.util.ByteBufferFactory.createLittleEndianByteBuffer( (int) (framebytes.capacity() * 1.5)); // First encode in Format40, then Format80 CodecUtility.encodeFormat40(framebytes, frameint, lastbytes); CodecUtility.encodeFormat80(frameint, frame); frames[i] = frame; lastbytes = framebytes; frameoffsets.putInt(offsettotal); offsettotal += frame.limit(); } // Last offset for EOF frameoffsets.putInt(offsettotal); frameoffsets.rewind(); // Write file to disk try { outputchannel.write(header); outputchannel.write(frameoffsets); outputchannel.write(palette); outputchannel.write(frames); } catch (IOException e) { throw new RuntimeException(e); } // Generate high-res colour lookup table if (!srcnohires) { // Figure-out the appropriate file name String lookupname = filename.contains(".") ? filename.substring(0, filename.lastIndexOf('.')) + ".pal" : filename + ".pal"; // Write the index of the closest interpolated palette colour // TODO: Perform proper colour interpolation ByteBuffer lookup = com.mikeduvall.redhorizon.util.ByteBufferFactory.createLittleEndianByteBuffer(256); for (int i = 0; i < 256; i++) { lookup.put((byte) i); } lookup.rewind(); try (FileChannel lookupfile = FileChannel.open(Paths.get(lookupname), WRITE)) { for (int i = 0; i < 256; i++) { lookupfile.write(lookup); } } // TODO: Should be able to soften the auto-close without needing this catch (IOException ex) { throw new RuntimeException(ex); } } }