q.add(w); writes.add(w);
@Override public CompletableFuture<LogAddress> append(ArrayView data, Duration timeout) { ensurePreconditions(); long traceId = LoggerHelpers.traceEnterWithContext(log, this.traceObjectId, "append", data.getLength()); if (data.getLength() > getMaxAppendLength()) { return Futures.failedFuture(new WriteTooLongException(data.getLength(), getMaxAppendLength())); } Timer timer = new Timer(); // Queue up the write. CompletableFuture<LogAddress> result = new CompletableFuture<>(); this.writes.add(new Write(data, getWriteLedger(), result)); // Trigger Write Processor. this.writeProcessor.runAsync(); // Post append tasks. We do not need to wait for these to happen before returning the call. result.whenCompleteAsync((address, ex) -> { if (ex != null) { handleWriteException(ex); } else { // Update metrics and take care of other logging tasks. this.metrics.writeCompleted(timer.getElapsed()); LoggerHelpers.traceLeave(log, this.traceObjectId, "append", traceId, data.getLength(), address); } }, this.executorService); return result; }
for (int i = 0; i < ITEM_COUNT; i++) { val w = new Write(new ByteArraySegment(new byte[i]), new TestWriteLedger(i), CompletableFuture.completedFuture(null)); q.add(w); expectedWrites.add(w); () -> q.add(new Write(new ByteArraySegment(new byte[1]), new TestWriteLedger(0), CompletableFuture.completedFuture(null))), ex -> ex instanceof ObjectClosedException); AssertExtensions.assertThrows(
/** * Tests the basic functionality of the add() method. */ @Test public void testAdd() { final int timeIncrement = 1234 * 1000; // Just over 1ms. AtomicLong time = new AtomicLong(); val q = new WriteQueue(time::get); val initialStats = q.getStatistics(); Assert.assertEquals("Unexpected getSize on empty queue.", 0, initialStats.getSize()); Assert.assertEquals("Unexpected getAverageFillRate on empty queue.", 0, initialStats.getAverageItemFillRatio(), 0); Assert.assertEquals("Unexpected getExpectedProcessingTimeMillis on empty queue.", 0, initialStats.getExpectedProcessingTimeMillis()); int expectedSize = 0; long firstItemTime = 0; for (int i = 0; i < ITEM_COUNT; i++) { time.addAndGet(timeIncrement); if (i == 0) { firstItemTime = time.get(); } int writeSize = i * 10000; q.add(new Write(new ByteArraySegment(new byte[writeSize]), new TestWriteLedger(i), CompletableFuture.completedFuture(null))); expectedSize += writeSize; val stats = q.getStatistics(); val expectedFillRatio = (double) expectedSize / stats.getSize() / BookKeeperConfig.MAX_APPEND_LENGTH; val expectedProcTime = (time.get() - firstItemTime) / AbstractTimer.NANOS_TO_MILLIS; Assert.assertEquals("Unexpected getSize.", i + 1, stats.getSize()); Assert.assertEquals("Unexpected getAverageFillRate.", expectedFillRatio, stats.getAverageItemFillRatio(), 0.01); Assert.assertEquals("Unexpected getExpectedProcessingTimeMillis.", expectedProcTime, stats.getExpectedProcessingTimeMillis()); } }