diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java index 6005e17..f06cfa0 100644 --- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java +++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java @@ -833,7 +833,7 @@ public class FileStore implements SegmentStore, Closeable { long reclaimedSize = initialSize - afterCleanupSize; stats.reclaimed(reclaimedSize); - gcJournal.persist(finalSize); + gcJournal.persist(reclaimedSize, finalSize); gcListener.cleaned(reclaimedSize, finalSize); gcListener.info("TarMK GC #{}: cleanup completed in {} ({} ms). Post cleanup size is {} ({} bytes)" + " and space reclaimed {} ({} bytes).", diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStoreGCMonitor.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStoreGCMonitor.java index 923bb03..d36f9ab 100644 --- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStoreGCMonitor.java +++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStoreGCMonitor.java @@ -54,6 +54,9 @@ public class FileStoreGCMonitor extends AnnotatedStandardMBean private long lastCompaction; private long lastCleanup; + private long lastRepositorySize; + private long lastReclaimedSize; + private String lastError; private String status = "NA"; @@ -104,6 +107,9 @@ public class FileStoreGCMonitor extends AnnotatedStandardMBean @Override public void cleaned(long reclaimed, long current) { lastCleanup = clock.getTime(); + lastReclaimedSize = reclaimed; + lastRepositorySize = current; + gcCount.getCounter().addAndGet(1); repositorySize.getCounter().set(current); reclaimedSize.getCounter().addAndGet(reclaimed); @@ -120,7 +126,17 @@ public class FileStoreGCMonitor extends AnnotatedStandardMBean public String getLastCleanup() { return toString(lastCleanup); } - + + @Override + public long getLastRepositorySize() { + return lastRepositorySize; + } + + @Override + public long getLastReclaimedSize() { + return lastReclaimedSize; + } + private static String toString(long timestamp) { if (timestamp != 0) { return getDateTimeInstance().format(new Date(timestamp)); diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCJournal.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCJournal.java index 6c3f5e4..7d83c92 100644 --- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCJournal.java +++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCJournal.java @@ -41,8 +41,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Persists the repository size following a cleanup operation in the - * {@link #GC_JOURNAL gc journal} file with the format: 'size, timestamp'. + * Persists the repository size and the reclaimed size following a cleanup operation in the + * {@link #GC_JOURNAL gc journal} file with the format: 'repoSize, reclaimedSize, timestamp'. */ public class GCJournal { @@ -59,8 +59,8 @@ public class GCJournal { this.directory = checkNotNull(directory); } - public synchronized void persist(long size) { - latest = new GCJournalEntry(size, System.currentTimeMillis()); + public synchronized void persist(long reclaimedSize, long repoSize) { + latest = new GCJournalEntry(repoSize, reclaimedSize, System.currentTimeMillis()); Path path = new File(directory, GC_JOURNAL).toPath(); try { try (BufferedWriter w = newBufferedWriter(path, UTF_8, WRITE, @@ -108,27 +108,30 @@ public class GCJournal { static class GCJournalEntry { - static GCJournalEntry EMPTY = new GCJournalEntry(-1, -1); + static GCJournalEntry EMPTY = new GCJournalEntry(-1, -1, -1); - private final long size; + private final long repoSize; + private final long reclaimedSize; private final long ts; - public GCJournalEntry(long size, long ts) { + public GCJournalEntry(long repoSize, long reclaimedSize, long ts) { + this.repoSize = repoSize; + this.reclaimedSize = reclaimedSize; this.ts = ts; - this.size = size; } @Override public String toString() { - return size + "," + ts; + return repoSize + "," + reclaimedSize + "," + ts; } static GCJournalEntry fromString(String in) { String[] items = in.split(","); - if (items.length == 2) { - long size = safeParse(items[0]); - long ts = safeParse(items[1]); - return new GCJournalEntry(size, ts); + if (items.length == 3) { + long repoSize = safeParse(items[0]); + long reclaimedSize = safeParse(items[1]); + long ts = safeParse(items[2]); + return new GCJournalEntry(repoSize, reclaimedSize, ts); } return GCJournalEntry.EMPTY; } @@ -142,10 +145,14 @@ public class GCJournal { return -1; } - public long getSize() { - return size; + public long getRepoSize() { + return repoSize; } - + + public long getReclaimedSize() { + return reclaimedSize; + } + public long getTs() { return ts; } @@ -154,7 +161,8 @@ public class GCJournal { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + (int) (size ^ (size >>> 32)); + result = prime * result + (int) (reclaimedSize ^ (reclaimedSize >>> 32)); + result = prime * result + (int) (repoSize ^ (repoSize >>> 32)); result = prime * result + (int) (ts ^ (ts >>> 32)); return result; } @@ -168,7 +176,9 @@ public class GCJournal { if (getClass() != obj.getClass()) return false; GCJournalEntry other = (GCJournalEntry) obj; - if (size != other.size) + if (reclaimedSize != other.reclaimedSize) + return false; + if (repoSize != other.repoSize) return false; if (ts != other.ts) return false; diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCMonitorMBean.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCMonitorMBean.java index a53a6c1..f01bf13 100644 --- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCMonitorMBean.java +++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCMonitorMBean.java @@ -42,6 +42,16 @@ public interface GCMonitorMBean { */ @CheckForNull String getLastCleanup(); + + /** + * @return repository size after the last cleanup. + */ + long getLastRepositorySize(); + + /** + * @return reclaimed size during the last cleanup. + */ + long getLastReclaimedSize(); /** * @return last error or {@code null} if none. diff --git oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGcEstimation.java oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGcEstimation.java index ac05076..44c1a61 100644 --- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGcEstimation.java +++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGcEstimation.java @@ -97,6 +97,6 @@ public class SizeDeltaGcEstimation implements GCEstimation { } private long getPreviousCleanupSize() { - return gcJournal.read().getSize(); + return gcJournal.read().getRepoSize(); } } diff --git oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/CompactionAndCleanupIT.java oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/CompactionAndCleanupIT.java index 42ade59..cbe9f14 100644 --- oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/CompactionAndCleanupIT.java +++ oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/CompactionAndCleanupIT.java @@ -930,4 +930,4 @@ public class CompactionAndCleanupIT { builder.setProperty(UUID.randomUUID().toString(), UUID.randomUUID().toString()); } } -} +} \ No newline at end of file diff --git oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/GcJournalTest.java oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/GcJournalTest.java index 37b1081..cfce239 100644 --- oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/GcJournalTest.java +++ oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/GcJournalTest.java @@ -44,20 +44,27 @@ public class GcJournalTest { File directory = segmentFolder.newFolder(); GCJournal gc = new GCJournal(directory); - gc.persist(100); + gc.persist(0, 100); GCJournalEntry e0 = gc.read(); - assertEquals(100, e0.getSize()); + assertEquals(100, e0.getRepoSize()); + assertEquals(0, e0.getReclaimedSize()); - gc.persist(250); + gc.persist(0, 250); GCJournalEntry e1 = gc.read(); - assertEquals(250, e1.getSize()); + assertEquals(250, e1.getRepoSize()); + assertEquals(0, e1.getReclaimedSize()); + + gc.persist(50, 200); + GCJournalEntry e2 = gc.read(); + assertEquals(200, e2.getRepoSize()); + assertEquals(50, e2.getReclaimedSize()); Collection all = gc.readAll(); - assertEquals(all.size(), 2); + assertEquals(all.size(), 3); File file = new File(directory, GCJournal.GC_JOURNAL); assertTrue(file.exists()); List allLines = Files.readAllLines(file.toPath(), UTF_8); - assertEquals(allLines.size(), 2); + assertEquals(allLines.size(), 3); } }