Index: src/main/java/org/apache/jackrabbit/oak/segment/compaction/SegmentGCOptions.java =================================================================== --- src/main/java/org/apache/jackrabbit/oak/segment/compaction/SegmentGCOptions.java (revision 1761539) +++ src/main/java/org/apache/jackrabbit/oak/segment/compaction/SegmentGCOptions.java (working copy) @@ -79,6 +79,8 @@ "oak.segment.compaction.gcSizeDeltaEstimation", SIZE_DELTA_ESTIMATION_DEFAULT); + private volatile boolean stopCompaction; + public SegmentGCOptions(boolean paused, int gainThreshold, int retryCount, int forceTimeout) { this.paused = paused; this.gainThreshold = gainThreshold; @@ -293,4 +295,14 @@ this.gcSizeDeltaEstimation = gcSizeDeltaEstimation; return this; } + + public boolean isStopCompaction() { + return stopCompaction; + } + + public boolean setStopCompaction(boolean stop) { + this.stopCompaction = stop; + return stop; + } + } Index: src/main/java/org/apache/jackrabbit/oak/segment/compaction/SegmentRevisionGC.java =================================================================== --- src/main/java/org/apache/jackrabbit/oak/segment/compaction/SegmentRevisionGC.java (revision 1761539) +++ src/main/java/org/apache/jackrabbit/oak/segment/compaction/SegmentRevisionGC.java (working copy) @@ -101,4 +101,8 @@ void setGcSizeDeltaEstimation(long gcSizeDeltaEstimation); + /** + * Raise the flag to signal compaction to stop as soon as possible. + */ + void stopCompaction(); } Index: src/main/java/org/apache/jackrabbit/oak/segment/compaction/SegmentRevisionGCMBean.java =================================================================== --- src/main/java/org/apache/jackrabbit/oak/segment/compaction/SegmentRevisionGCMBean.java (revision 1761539) +++ src/main/java/org/apache/jackrabbit/oak/segment/compaction/SegmentRevisionGCMBean.java (working copy) @@ -93,4 +93,9 @@ gcOptions.setGcSizeDeltaEstimation(gcSizeDeltaEstimation); } + @Override + public void stopCompaction() { + gcOptions.setStopCompaction(true); + } + } Index: src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java =================================================================== --- src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java (revision 1761539) +++ src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java (working copy) @@ -516,9 +516,9 @@ gcListener.info("TarMK GC #{}: estimation skipped because compaction is paused", GC_COUNT); } else { gcListener.info("TarMK GC #{}: estimation started", GC_COUNT); - Supplier shutdown = newShutdownSignal(); - GCEstimation estimate = estimateCompactionGain(shutdown); - if (shutdown.get()) { + Supplier cancel = newCancelCompactionCondition(); + GCEstimation estimate = estimateCompactionGain(cancel); + if (cancel.get()) { gcListener.info("TarMK GC #{}: estimation interrupted. Skipping compaction.", GC_COUNT); } @@ -941,10 +941,10 @@ * @return a flag indicating if compaction should be canceled. */ private Supplier newCancelCompactionCondition() { + FileStore.this.gcOptions.setStopCompaction(false); return new Supplier() { - private boolean outOfDiskSpace; - private boolean shutdown; + private byte reason; @Override public Boolean get() { @@ -952,22 +952,31 @@ // The outOfDiskSpace and shutdown flags can only transition from false (their initial // values), to true. Once true, there should be no way to go back. if (!sufficientDiskSpace.get()) { - outOfDiskSpace = true; + reason = 1; + return true; } if (FileStore.this.shutdown) { - this.shutdown = true; + reason = 2; + return true; + } + if (FileStore.this.gcOptions.isStopCompaction()) { + reason = 3; + return true; } - return shutdown || outOfDiskSpace; + return false; } @Override public String toString() { - if (outOfDiskSpace) { + switch (reason) { + case 1: return "Not enough disk space available"; - } else if (shutdown) { + case 2: return "FileStore shutdown request received"; - } else { + case 3: + return "GC stop request received"; + default: return ""; } } @@ -1007,19 +1016,6 @@ } /** - * Returns a signal indication the file store shutting down. - * @return a shutdown signal - */ - private Supplier newShutdownSignal() { - return new Supplier() { - @Override - public Boolean get() { - return shutdown; - } - }; - } - - /** * Copy every referenced record in data (non-bulk) segments. Bulk segments * are fully kept (they are only removed in cleanup, if there is no * reference to them).