diff --git a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLogCache.java b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLogCache.java index 631cbf9513..6d5aa6d411 100644 --- a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLogCache.java +++ b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLogCache.java @@ -51,6 +51,20 @@ public class SegmentedRaftLogCache { public static final Logger LOG = LoggerFactory.getLogger(SegmentedRaftLogCache.class); static final class SegmentFileInfo { + static final SegmentFileInfo[] EMPTY_ARRAY = {}; + static final Comparator REVERSED_ORDER = Comparator.comparingLong(SegmentFileInfo::getStartIndex) + .thenComparingLong(SegmentFileInfo::getEndIndex) + .reversed(); + + static SegmentFileInfo[] toSortedArray(List list) { + if (list == null) { + return EMPTY_ARRAY; + } + final SegmentFileInfo[] array = list.toArray(EMPTY_ARRAY); + Arrays.sort(array, REVERSED_ORDER); + return array; + } + static SegmentFileInfo newClosedSegmentFileInfo(LogSegment ls) { Objects.requireNonNull(ls, "ls == null"); Preconditions.assertTrue(!ls.isOpen(), () -> ls + " is OPEN"); @@ -121,8 +135,7 @@ public SegmentFileInfo[] getToDelete() { TruncationSegments(SegmentFileInfo toTruncate, List toDelete) { - this.toDelete = toDelete == null ? null : - toDelete.toArray(new SegmentFileInfo[toDelete.size()]); + this.toDelete = SegmentFileInfo.toSortedArray(toDelete); this.toTruncate = toTruncate; } diff --git a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLogWorker.java b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLogWorker.java index 7928f2297b..9f34f29170 100644 --- a/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLogWorker.java +++ b/ratis-server/src/main/java/org/apache/ratis/server/raftlog/segmented/SegmentedRaftLogWorker.java @@ -657,6 +657,21 @@ private class TruncateLog extends Task { void execute() throws IOException { freeSegmentedRaftLogOutputStream(); + if (segments.getToDelete() != null && segments.getToDelete().length > 0) { + long minStart = segments.getToDelete()[0].getStartIndex(); + for (SegmentFileInfo del : segments.getToDelete()) { + final File delFile = del.getFile(storage); + Preconditions.assertTrue(delFile.exists(), + "File %s to be deleted does not exist", delFile); + FileUtils.deleteFile(delFile); + LOG.info("{}: Deleted log file {}", name, delFile); + minStart = Math.min(minStart, del.getStartIndex()); + } + if (segments.getToTruncate() == null) { + lastWrittenIndex = minStart - 1; + } + } + if (segments.getToTruncate() != null) { final File fileToTruncate = segments.getToTruncate().getFile(storage); Preconditions.assertTrue(fileToTruncate.exists(), @@ -674,20 +689,7 @@ void execute() throws IOException { // update lastWrittenIndex lastWrittenIndex = segments.getToTruncate().getNewEndIndex(); } - if (segments.getToDelete() != null && segments.getToDelete().length > 0) { - long minStart = segments.getToDelete()[0].getStartIndex(); - for (SegmentFileInfo del : segments.getToDelete()) { - final File delFile = del.getFile(storage); - Preconditions.assertTrue(delFile.exists(), - "File %s to be deleted does not exist", delFile); - FileUtils.deleteFile(delFile); - LOG.info("{}: Deleted log file {}", name, delFile); - minStart = Math.min(minStart, del.getStartIndex()); - } - if (segments.getToTruncate() == null) { - lastWrittenIndex = minStart - 1; - } - } + if (stateMachineFuture != null) { IOUtils.getFromFuture(stateMachineFuture, () -> this + "-truncateStateMachineData"); }