void truncate(long upToSequence, String clientId) throws DataLogWriterNotPrimaryException { ensureLock(clientId); ensureEnabled(); this.entries.truncate(upToSequence); }
/** * 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<Void> truncate(long upToSequenceNumber, Duration timeout) { ensureRunning(); Preconditions.checkArgument(this.metadata.isValidTruncationPoint(upToSequenceNumber), "Invalid Truncation Point. Must refer to a MetadataCheckpointOperation."); // The SequenceNumber we were given points directly to a MetadataCheckpointOperation. We must not remove it! // Instead, it must be the first operation that does survive, so we need to adjust our SeqNo to the one just // before it. long actualTruncationSequenceNumber = upToSequenceNumber - 1; // Find the closest Truncation Marker (that does not exceed it). LogAddress truncationFrameAddress = this.metadata.getClosestTruncationMarker(actualTruncationSequenceNumber); if (truncationFrameAddress == null) { // Nothing to truncate. return CompletableFuture.completedFuture(null); } TimeoutTimer timer = new TimeoutTimer(timeout); log.info("{}: Truncate (OperationSequenceNumber = {}, DataFrameAddress = {}).", this.traceObjectId, upToSequenceNumber, truncationFrameAddress); // Before we do any real truncation, we need to mini-snapshot the metadata with only those fields that are updated // asynchronously for us (i.e., not via normal Log Operations) such as the Storage State. That ensures that this // info will be readily available upon recovery without delay. return add(new StorageMetadataCheckpointOperation(), timer.getRemaining()) .thenComposeAsync(v -> this.durableDataLog.truncate(truncationFrameAddress, timer.getRemaining()), this.executor) .thenRunAsync(() -> { // Truncate InMemory Transaction Log. int count = this.inMemoryOperationLog.truncate(actualTruncationSequenceNumber); // Remove old truncation markers. this.metadata.removeTruncationMarkers(actualTruncationSequenceNumber); this.operationProcessor.getMetrics().operationLogTruncate(count); }, this.executor); }
if (this.ackEffective.get()) { this.log.truncate(upToSequenceNumber); this.metadata.removeTruncationMarkers(upToSequenceNumber);
list.truncate(10); Assert.assertFalse("Unexpected value from hasNext when list has been truncated.", truncateIterator.hasNext()); AssertExtensions.assertThrows( list.truncate(20); AssertExtensions.assertThrows( "Unexpected behavior from next() when current element has been truncated (after hasNext() and before next()).",