Iterator<Entry> iterator() { ensureEnabled(); return this.entries.read(Long.MIN_VALUE, Integer.MAX_VALUE); }
private void triggerTailReads() { this.executor.execute(() -> { // Gather all the eligible tail reads. List<TailRead> toTrigger; synchronized (this.tailReads) { Operation lastOp = this.inMemoryOperationLog.getLast(); if (lastOp != null) { long seqNo = lastOp.getSequenceNumber(); toTrigger = this.tailReads.stream().filter(e -> e.afterSequenceNumber < seqNo).collect(Collectors.toList()); } else { toTrigger = Collections.emptyList(); } } // Trigger all of them (no need to unregister them; the unregister handle is already wired up). for (TailRead tr : toTrigger) { tr.future.complete(Futures.runOrFail( () -> this.inMemoryOperationLog.read(tr.afterSequenceNumber, tr.maxCount), tr.future)); } }); }
ensureRunning(); log.debug("{}: Read (AfterSequenceNumber = {}, MaxCount = {}).", this.traceObjectId, afterSequenceNumber, maxCount); Iterator<Operation> logReadResult = this.inMemoryOperationLog.read(afterSequenceNumber, maxCount); if (logReadResult.hasNext()) { logReadResult = this.inMemoryOperationLog.read(afterSequenceNumber, maxCount); assert logReadResult.hasNext() : String.format("Unable to read anything after SeqNo %d, even though last operation SeqNo == %d",
/** * Tests the combination of the basic append() method and read(). */ @Test public void testAddRead() { SequencedItemList<Item> list = new SequencedItemList<>(); for (int i = 0; i < ITEM_COUNT; i++) { list.add(new Item(i)); } //Read 1/2 items Iterator<Item> readResult = list.read(START, ITEM_COUNT / 2); checkRange("Read first 50%", 0, ITEM_COUNT / 2 - 1, readResult); // Read all items readResult = list.read(START, ITEM_COUNT); checkRange("Read all items", 0, ITEM_COUNT - 1, readResult); // Try to read more items. readResult = list.read(START, ITEM_COUNT * 2); checkRange("Read more items than list has", 0, ITEM_COUNT - 1, readResult); // Read 25% of items, starting at the middle point. readResult = list.read(ITEM_COUNT / 2 - 1, ITEM_COUNT / 4); checkRange("Read 25% starting at 50%", ITEM_COUNT / 2, ITEM_COUNT / 2 + ITEM_COUNT / 4 - 1, readResult); }
/** * Tests the functionality of the truncate() method. */ @Test public void testTruncate() { SequencedItemList<Item> list = new SequencedItemList<>(); for (int i = 0; i < ITEM_COUNT; i++) { list.add(new Item(i)); } // Truncate 25% of items. list.truncate(ITEM_COUNT / 4 - 1); checkRange("Truncate 25%", ITEM_COUNT / 4, ITEM_COUNT - 1, list.read(START, ITEM_COUNT)); // Truncate the same 25% of items - verify no change. list.truncate(ITEM_COUNT / 4 - 1); checkRange("Re-truncate 25%", ITEM_COUNT / 4, ITEM_COUNT - 1, list.read(START, ITEM_COUNT)); // Truncate all items. list.truncate(END); Iterator<Item> readResult = list.read(START, ITEM_COUNT * 2); Assert.assertFalse("List should be empty.", readResult.hasNext()); }
@Override public CompletableFuture<Iterator<Operation>> read(long afterSequenceNumber, int maxCount, Duration timeout) { Exceptions.checkNotClosed(this.closed.get(), this); ErrorInjector<Exception> asyncErrorInjector; synchronized (this.lock) { ErrorInjector.throwSyncExceptionIfNeeded(this.readSyncErrorInjector); asyncErrorInjector = this.readAsyncErrorInjector; } return ErrorInjector .throwAsyncExceptionIfNeeded(asyncErrorInjector, () -> { Iterator<Operation> logReadResult = this.log.read(afterSequenceNumber, maxCount); if (logReadResult.hasNext()) { // Result is readily available; return it. return CompletableFuture.completedFuture(logReadResult); } else { // Result is not yet available; wait for an add and then retry the read. return waitForAdd(afterSequenceNumber, timeout) .thenComposeAsync(v1 -> this.read(afterSequenceNumber, maxCount, timeout), this.executor); } }); }
/** * Tests the functionality of the clear() method. */ @Test public void testClear() { SequencedItemList<Item> list = new SequencedItemList<>(); for (int i = 0; i < ITEM_COUNT; i++) { list.add(new Item(i)); } list.clear(); Iterator<Item> readResult = list.read(START, ITEM_COUNT * 2); Assert.assertFalse("List should be empty.", readResult.hasNext()); }
Iterator<Item> addIterator = list.read(START, ITEM_COUNT * 2); Item firstValue = addIterator.next(); Assert.assertEquals("Unexpected first value, pre-modification.", 0, firstValue.getSequenceNumber()); Iterator<Item> truncateIterator = list.read(START, ITEM_COUNT * 2); Iterator<Item> midTruncateIterator = list.read(START, ITEM_COUNT * 2); Assert.assertTrue("Unexpected value from hasNext when not been truncated.", midTruncateIterator.hasNext()); list.truncate(20);
Iterator<Operation> logIterator = opLog.read(-1, operations.size()); int currentIndex = -1; int currentReadIndex = -1;
TestUtils.await(() -> memoryLog.read(successfulOps.get(successfulOps.size() - 1).getSequenceNumber() - 1, 1).hasNext(), 10, TIMEOUT.toMillis()); Iterator<Operation> memoryLogIterator = memoryLog.read(-1, operations.size() + 1); OperationComparer memoryLogComparer = new OperationComparer(true); for (Operation expectedOp : successfulOps) {
/** * Tests the functionality of the addIf() method. */ @Test public void testAddIf() { SequencedItemList<Item> list = new SequencedItemList<>(); for (int i = 0; i < ITEM_COUNT; i++) { final Item currentValue = new Item(i); // Happy case. boolean resultValue = list.add(currentValue); Assert.assertTrue("Unexpected return value from addIf for successful append.", resultValue); // Unhappy case resultValue = list.add(currentValue); Assert.assertFalse("Unexpected return value from addIf for unsuccessful append.", resultValue); } Iterator<Item> readResult = list.read(START, ITEM_COUNT * 2); checkRange("AddIf", 0, ITEM_COUNT - 1, readResult); }