You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by am...@apache.org on 2022/12/02 05:47:37 UTC
[jackrabbit-oak] branch trunk updated: OAK-9975: [DSGC] Report cummulative size of referenced blobs during Mark phase (#771)
This is an automated email from the ASF dual-hosted git repository.
amitj pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/trunk by this push:
new 146ea2e604 OAK-9975: [DSGC] Report cummulative size of referenced blobs during Mark phase (#771)
146ea2e604 is described below
commit 146ea2e604927215d4cdb9137e60c752bd8c3393
Author: Amit Jain <am...@apache.org>
AuthorDate: Fri Dec 2 11:17:30 2022 +0530
OAK-9975: [DSGC] Report cummulative size of referenced blobs during Mark phase (#771)
- Update size metrics in checkConsistency & mark
---
.../plugins/blob/MarkSweepGarbageCollector.java | 86 +++++++++++++++--
.../oak/plugins/blob/OperationStatsCollector.java | 20 ++++
.../oak/plugins/blob/OperationsStatsMBean.java | 12 +++
.../jackrabbit/oak/plugins/blob/BlobGCTest.java | 102 ++++++++++++++++-----
4 files changed, 190 insertions(+), 30 deletions(-)
diff --git a/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/MarkSweepGarbageCollector.java b/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/MarkSweepGarbageCollector.java
index 085f156c46..d1361e0b52 100644
--- a/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/MarkSweepGarbageCollector.java
+++ b/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/MarkSweepGarbageCollector.java
@@ -405,13 +405,35 @@ public class MarkSweepGarbageCollector implements BlobGarbageCollector {
// Mark all used references
iterateNodeTree(fs, false);
-
+
+ // Get size
+ getBlobReferencesSize(fs, stats);
+
// Move the marked references file to the data store meta area if applicable
GarbageCollectionType.get(blobStore).addMarked(blobStore, fs, repoId, uniqueSuffix);
LOG.debug("Ending mark phase of the garbage collector");
}
+ private static void getBlobReferencesSize(GarbageCollectorFileState fs, GarbageCollectionOperationStats stats)
+ throws IOException {
+ try (LineIterator lineIterator = new LineIterator(new FileReader(fs.getMarkedRefs()))) {
+ lineIterator.forEachRemaining(line -> {
+ String id = line.split(DELIM)[0];
+ long length = DataStoreBlobStore.BlobId.of(id).getLength();
+ LOG.info("Blob {} has size {}", id, length);
+
+ stats.getCollector().updateNumBlobReferences(1);
+
+ if (length != -1) {
+ stats.getCollector().updateBlobReferencesSize(length);
+ }
+ });
+ }
+ LOG.info("Blob references found : {} with size : {}", stats.getNumBlobReferences(),
+ stats.getBlobReferencesSize());
+ }
+
/**
* Difference phase where the GC candidates are identified.
*
@@ -526,7 +548,7 @@ public class MarkSweepGarbageCollector implements BlobGarbageCollector {
}
if (checkConsistencyAfterGc) {
- BlobCollectionType.get(blobStore).checkConsistencyAfterGC(blobStore, fs, consistencyStatsCollector, new File(root));
+ BlobCollectionType.get(blobStore).checkConsistencyAfterGC(blobStore, fs, consistencyStats);
}
BlobCollectionType.get(blobStore).handleRemoves(blobStore, fs.getGarbage(), fs.getMarkedRefs());
@@ -689,6 +711,9 @@ public class MarkSweepGarbageCollector implements BlobGarbageCollector {
// Mark all used blob references
iterateNodeTree(fs, true);
+ // Move the marked references file to the data store meta area if applicable
+ String uniqueSuffix = UUID.randomUUID().toString();
+ GarbageCollectionType.get(blobStore).addMarked(blobStore, fs, repoId, uniqueSuffix);
consistencyStatsCollector.updateMarkDuration(sw.elapsed(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);
try {
@@ -703,6 +728,21 @@ public class MarkSweepGarbageCollector implements BlobGarbageCollector {
// Retrieve all other marked present in the datastore
List<DataRecord> refFiles =
((SharedDataStore) blobStore).getAllMetadataRecords(SharedStoreRecordType.REFERENCES.getType());
+
+ // Get all the repositories registered
+ List<DataRecord> repoFiles =
+ ((SharedDataStore) blobStore).getAllMetadataRecords(SharedStoreRecordType.REPOSITORY.getType());
+ LOG.info("Repositories registered {}", repoFiles);
+
+ // Retrieve repos for which reference files have not been created
+ Set<String> unAvailRepos =
+ SharedDataStoreUtils.refsNotAvailableFromRepos(repoFiles, refFiles);
+ LOG.info("Repositories with unavailable references {}", unAvailRepos);
+
+ if (!unAvailRepos.isEmpty()) {
+ throw new NotAllRepositoryMarkedException("Not all repositories have marked references available");
+ }
+
if (refFiles.size() > 0) {
File temp = new File(root, repoId + UUID.randomUUID().toString());
copyFile(fs.getMarkedRefs(), temp);
@@ -718,6 +758,9 @@ public class MarkSweepGarbageCollector implements BlobGarbageCollector {
}
}
+ // Get size
+ getBlobReferencesSize(fs, consistencyStats);
+
LOG.trace("Starting difference phase of the consistency check");
FileLineDifferenceIterator iter = new FileLineDifferenceIterator(
fs.getAvailableRefs(),
@@ -1076,8 +1119,8 @@ public class MarkSweepGarbageCollector implements BlobGarbageCollector {
}
void checkConsistencyAfterGC(GarbageCollectableBlobStore blobStore, GarbageCollectorFileState fs,
- OperationStatsCollector consistencyStatsCollector, File root) throws IOException {
- consistencyStatsCollector.start();
+ GarbageCollectionOperationStats stats) throws IOException {
+ stats.getCollector().start();
Stopwatch sw = Stopwatch.createStarted();
try {
@@ -1111,12 +1154,15 @@ public class MarkSweepGarbageCollector implements BlobGarbageCollector {
}
LOG.warn(
"Consistency check failure in the the blob store after GC : {}", blobStore);
- consistencyStatsCollector.finishFailure();
- consistencyStatsCollector.updateNumDeleted(candidates);
+ stats.getCollector().finishFailure();
+ stats.getCollector().updateNumDeleted(candidates);
}
+
+ // Update the size of the referenced blobs
+ getBlobReferencesSize(fs, stats);
} finally {
sw.stop();
- consistencyStatsCollector.updateDuration(sw.elapsed(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);
+ stats.getCollector().updateDuration(sw.elapsed(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);
}
}
@@ -1156,6 +1202,10 @@ public class MarkSweepGarbageCollector implements BlobGarbageCollector {
static final String NUM_BLOBS_DELETED = "NUM_BLOBS_DELETED";
static final String TOTAL_SIZE_DELETED = "TOTAL_SIZE_DELETED";
static final String NUM_CANDIDATES = "NUM_CANDIDATES";
+
+ static final String NUM_BLOB_REFERENCES = "NUM_BLOB_REFERENCES";
+
+ static final String BLOB_REFERENCES_SIZE = "BLOB_REFERENCES_SIZE";
private final String typeName;
@@ -1164,6 +1214,8 @@ public class MarkSweepGarbageCollector implements BlobGarbageCollector {
private CounterStats numDeletedCounter;
private CounterStats totalSizeDeletedCounter;
private CounterStats numCandidatesCounter;
+ private CounterStats numBlobReferencesCounter;
+ private CounterStats blobReferencesSizeCounter;
private TimerStats duration;
private final TimerStats markDuration;
private final TimerStats sweepDuration;
@@ -1177,6 +1229,8 @@ public class MarkSweepGarbageCollector implements BlobGarbageCollector {
this.numDeletedCounter = sp.getCounterStats(getMetricName(NUM_BLOBS_DELETED), StatsOptions.METRICS_ONLY);
this.totalSizeDeletedCounter = sp.getCounterStats(getMetricName(TOTAL_SIZE_DELETED), StatsOptions.METRICS_ONLY);
this.numCandidatesCounter = sp.getCounterStats(getMetricName(NUM_CANDIDATES), StatsOptions.METRICS_ONLY);
+ this.numBlobReferencesCounter = sp.getCounterStats(getMetricName(NUM_BLOB_REFERENCES), StatsOptions.METRICS_ONLY);
+ this.blobReferencesSizeCounter = sp.getCounterStats(getMetricName(BLOB_REFERENCES_SIZE), StatsOptions.METRICS_ONLY);
this.duration = sp.getTimer(getMetricName(DURATION), StatsOptions.METRICS_ONLY);
this.markDuration = sp.getTimer(getMetricName(MARK_DURATION), StatsOptions.METRICS_ONLY);
this.sweepDuration = sp.getTimer(getMetricName(SWEEP_DURATION), StatsOptions.METRICS_ONLY);
@@ -1207,6 +1261,16 @@ public class MarkSweepGarbageCollector implements BlobGarbageCollector {
totalSizeDeletedCounter.inc(size);
}
+ @Override
+ public void updateNumBlobReferences(long num) {
+ numBlobReferencesCounter.inc(num);
+ }
+
+ @Override
+ public void updateBlobReferencesSize(long size) {
+ blobReferencesSizeCounter.inc(size);
+ }
+
@Override
public void updateDuration(long time, TimeUnit timeUnit) {
duration.update(time, timeUnit);
@@ -1262,6 +1326,14 @@ public class MarkSweepGarbageCollector implements BlobGarbageCollector {
@Override public long sizeDeleted() {
return totalSizeDeletedCounter.getCount();
}
+
+ @Override public long getNumBlobReferences() {
+ return numBlobReferencesCounter.getCount();
+ }
+
+ @Override public long getBlobReferencesSize() {
+ return blobReferencesSizeCounter.getCount();
+ }
}
diff --git a/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationStatsCollector.java b/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationStatsCollector.java
index 677c0b8413..1998bbac2a 100644
--- a/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationStatsCollector.java
+++ b/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationStatsCollector.java
@@ -41,6 +41,14 @@ public interface OperationStatsCollector {
@Override public void updateTotalSizeDeleted(long size) {
}
+ @Override
+ public void updateNumBlobReferences(long num) {
+ }
+
+ @Override
+ public void updateBlobReferencesSize(long size) {
+ }
+
@Override public void updateDuration(long time, TimeUnit timeUnit) {
}
@@ -79,6 +87,18 @@ public interface OperationStatsCollector {
*/
void updateTotalSizeDeleted(long size);
+ /**
+ * Update the number of blob references
+ * @param num
+ */
+ public void updateNumBlobReferences(long num);
+
+ /**
+ * Update the size of blob references
+ * @param size
+ */
+ public void updateBlobReferencesSize(long size);
+
/**
* Increment the duration timer
*
diff --git a/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationsStatsMBean.java b/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationsStatsMBean.java
index 5d6796bbbc..2669dabd00 100644
--- a/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationsStatsMBean.java
+++ b/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/OperationsStatsMBean.java
@@ -65,4 +65,16 @@ public interface OperationsStatsMBean {
* @return
*/
long sizeDeleted();
+
+ /**
+ * Returns the number of blob references
+ * @return
+ */
+ long getNumBlobReferences();
+
+ /**
+ * Returns the cumulative size of the blob references
+ * @return
+ */
+ long getBlobReferencesSize();
}
diff --git a/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java b/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java
index 2dc54a3ebd..41127c2fe9 100644
--- a/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java
+++ b/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/BlobGCTest.java
@@ -19,10 +19,12 @@
package org.apache.jackrabbit.oak.plugins.blob;
+import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.BLOB_REFERENCES_SIZE;
import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.CONSISTENCY_NAME;
import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.FINISH_FAILURE;
import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.NAME;
import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.NUM_BLOBS_DELETED;
+import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.NUM_BLOB_REFERENCES;
import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.NUM_CANDIDATES;
import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.START;
import static org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.GarbageCollectionOperationStats.TOTAL_SIZE_DELETED;
@@ -61,6 +63,7 @@ import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider;
import org.apache.jackrabbit.oak.api.blob.BlobUpload;
import org.apache.jackrabbit.oak.commons.concurrent.ExecutorCloser;
import org.apache.jackrabbit.oak.commons.junit.LogCustomizer;
+import org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector.NotAllRepositoryMarkedException;
import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore;
import org.apache.jackrabbit.oak.plugins.blob.datastore.SharedDataStoreUtils;
import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore;
@@ -79,6 +82,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.mockito.internal.util.collections.Iterables;
import org.slf4j.Logger;
@@ -92,6 +96,9 @@ public class BlobGCTest {
@Rule
public TemporaryFolder folder = new TemporaryFolder(new File("target"));
+
+ @Rule
+ public ExpectedException expectedEx = ExpectedException.none();
protected Whiteboard wb;
@@ -150,7 +157,9 @@ public class BlobGCTest {
protected ThreadPoolExecutor executor;
protected DefaultStatisticsProvider statsProvider;
protected long startReferenceTime;
-
+
+ protected int blobSize = 100;
+
public Cluster(File root, GarbageCollectableBlobStore blobStore, NodeStore nodeStore, int seed) throws Exception {
this.root = root;
this.nodeStore = nodeStore;
@@ -167,9 +176,8 @@ public class BlobGCTest {
log.info("Reference time {}", startReferenceTime);
scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
- statsProvider = new DefaultStatisticsProvider(scheduledExecutor);
- blobStoreState = setUp(nodeStore, blobStore, 10, 5, 100, seed);
+ blobStoreState = setUp(nodeStore, blobStore, 10, 5, blobSize, seed);
}
public void setRepoId(String id) {
@@ -182,6 +190,7 @@ public class BlobGCTest {
public MarkSweepGarbageCollector getCollector(long blobGcMaxAgeInSecs, boolean checkConsistency,
boolean sweepIfRefsPastRetention) throws Exception {
+ statsProvider = new DefaultStatisticsProvider(scheduledExecutor);
collector =
new MarkSweepGarbageCollector(referenceRetriever, blobStore, executor, root.getAbsolutePath(), 2048,
@@ -216,7 +225,8 @@ public class BlobGCTest {
assertTrue(Sets.symmetricDifference(totalPresent, existingAfterGC).isEmpty());
assertStats(secondCluster.statsProvider, 1, 0, totalAdded.size() - totalPresent.size(),
- totalAdded.size() - totalPresent.size(), NAME);
+ totalAdded.size() - totalPresent.size(), secondCluster.blobStoreState.blobsPresent.size(),
+ cluster.blobSize, NAME);
}
@Test
@@ -234,7 +244,8 @@ public class BlobGCTest {
Set<String> existingAfterGC = executeGarbageCollection(secondCluster, secondCluster.getCollector(0), false);
assertEquals(totalAdded, existingAfterGC);
- assertStats(secondCluster.statsProvider, 1, 1, 0, 0, NAME);
+ assertStats(secondCluster.statsProvider, 1, 1, 0, 0, secondCluster.blobStoreState.blobsPresent.size(),
+ secondCluster.blobSize, NAME);
}
@Test
@@ -284,8 +295,9 @@ public class BlobGCTest {
Set<String> existingAfterGC = executeGarbageCollection(secondCluster, secondCluster.getCollector(5, false, true), false);
assertTrue(Sets.symmetricDifference(totalPresent, existingAfterGC).isEmpty());
- assertStats(secondCluster.statsProvider, 2, 0, totalAdded.size() - totalPresent.size(),
- totalAdded.size() - totalPresent.size(), NAME);
+ assertStats(secondCluster.statsProvider, 1, 0, totalAdded.size() - totalPresent.size(),
+ totalAdded.size() - totalPresent.size(), secondCluster.blobStoreState.blobsPresent.size(),
+ secondCluster.blobSize, NAME);
}
@Test
@@ -313,7 +325,8 @@ public class BlobGCTest {
Set<String> existingAfterGC = executeGarbageCollection(secondCluster, secondCluster.getCollector(6, false, true), false);
assertTrue(Sets.symmetricDifference(totalAdded, existingAfterGC).isEmpty());
- assertStats(secondCluster.statsProvider, 2, 1, 0,0, NAME);
+ assertStats(secondCluster.statsProvider, 1, 1, 0,0, secondCluster.blobStoreState.blobsPresent.size(),
+ secondCluster.blobSize, NAME);
}
@Test
@@ -324,20 +337,24 @@ public class BlobGCTest {
assertTrue(Sets.symmetricDifference(cluster.blobStoreState.blobsPresent, existingAfterGC).isEmpty());
assertStats(cluster.statsProvider, 1, 0,
cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(),
- cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(), NAME);
+ cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(),
+ cluster.blobStoreState.blobsPresent.size(), cluster.blobSize, NAME);
}
@Test
public void gcWithConsistencyCheck() throws Exception {
log.info("Starting gcWithConsistencyCheck()");
- ((MemoryBlobStoreNodeStore) cluster.nodeStore).getReferencedBlobs().add("SPURIOUS");
+ ((MemoryBlobStoreNodeStore) cluster.nodeStore).getReferencedBlobs().add("SPURIOUS#100");
MarkSweepGarbageCollector collector = cluster.getCollector(0, true, false);
Set<String> existingAfterGC = executeGarbageCollection(cluster, collector, false);
assertFalse(Sets.symmetricDifference(cluster.blobStoreState.blobsPresent, existingAfterGC).isEmpty());
assertStats(cluster.statsProvider, 1, 0,
cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size() + 1,
- cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size() + 1, NAME);
+ cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size() + 1,
+ cluster.blobStoreState.blobsPresent.size(), cluster.blobSize, NAME);
+ assertStats(cluster.statsProvider, 1, 1, 1, 0,
+ cluster.blobStoreState.blobsPresent.size(), cluster.blobSize, CONSISTENCY_NAME);
assertStatsBean(collector.getConsistencyOperationStats(), 1, 1, 1);
}
@@ -350,7 +367,8 @@ public class BlobGCTest {
assertTrue(Sets.symmetricDifference(cluster.blobStoreState.blobsPresent, existingAfterGC).isEmpty());
assertStats(cluster.statsProvider, 1, 0,
cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(),
- cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(), NAME);
+ cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(),
+ cluster.blobStoreState.blobsPresent.size(), cluster.blobSize, NAME);
}
@Test
@@ -362,7 +380,8 @@ public class BlobGCTest {
assertTrue(Sets.symmetricDifference(cluster.blobStoreState.blobsPresent, existingAfterGC).isEmpty());
assertStats(cluster.statsProvider, 1, 0,
cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(),
- cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(), NAME);
+ cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(),
+ cluster.blobStoreState.blobsPresent.size(), cluster.blobSize, NAME);
}
@Test
@@ -377,7 +396,8 @@ public class BlobGCTest {
false);
assertTrue(Sets.symmetricDifference(cluster.blobStoreState.blobsAdded, existingAfterGC).isEmpty());
assertStats(cluster.statsProvider, 1, 0, 0,
- cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(), NAME);
+ cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(),
+ cluster.blobStoreState.blobsPresent.size(), cluster.blobSize, NAME);
}
@Test
@@ -391,7 +411,8 @@ public class BlobGCTest {
long missing = collector.checkConsistency();
assertEquals(0, missing);
- assertStats(cluster.statsProvider, 1, 0, 0, 0, CONSISTENCY_NAME);
+ assertStats(cluster.statsProvider, 1, 0, 0, 0, cluster.blobStoreState.blobsPresent.size(), cluster.blobSize,
+ CONSISTENCY_NAME);
assertStatsBean(collector.getConsistencyOperationStats(), 1, 0, 0);
}
@@ -409,7 +430,8 @@ public class BlobGCTest {
long missing = collector.checkConsistency();
assertEquals(1, missing);
- assertStats(cluster.statsProvider, 1, 1, 1, 0, CONSISTENCY_NAME);
+ assertStats(cluster.statsProvider, 1, 1, 1, 0, cluster.blobStoreState.blobsPresent.size(), cluster.blobSize,
+ CONSISTENCY_NAME);
assertStatsBean(collector.getConsistencyOperationStats(), 1, 1, 1);
}
@@ -421,14 +443,16 @@ public class BlobGCTest {
MemoryBlobStoreNodeStore secondClusterNodeStore = new MemoryBlobStoreNodeStore(cluster.blobStore, true);
Cluster secondCluster = new Cluster(folder.newFolder(), cluster.blobStore, secondClusterNodeStore, 100);
closer.register(secondCluster);
-
+
+ int totalPresent = secondCluster.blobStoreState.blobsPresent.size() + cluster.blobStoreState.blobsPresent.size();
secondCluster.blobStoreState.blobsPresent.add(Iterables.firstOf(cluster.blobStoreState.blobsPresent));
// Execute mark on the default cluster
executeGarbageCollection(cluster, cluster.getCollector(0), true);
MarkSweepGarbageCollector globalCollector = secondCluster.getCollector(0, true, false);
long missing = globalCollector.checkConsistency();
assertEquals(0, missing);
- assertStats(secondCluster.statsProvider, 1, 0, 0, 0, CONSISTENCY_NAME);
+ assertStats(secondCluster.statsProvider, 1, 0, 0, 0, totalPresent,
+ cluster.blobSize, CONSISTENCY_NAME);
assertStatsBean(globalCollector.getConsistencyOperationStats(), 1, 0, 0);
}
@@ -450,7 +474,10 @@ public class BlobGCTest {
MarkSweepGarbageCollector globalCollector = secondCluster.getCollector(0, true, false);
long missing = globalCollector.checkConsistency();
assertEquals(1, missing);
- assertStats(secondCluster.statsProvider, 1, 1, 1, 0, CONSISTENCY_NAME);
+ int totalPresent =
+ secondCluster.blobStoreState.blobsPresent.size() + cluster.blobStoreState.blobsPresent.size();
+ assertStats(secondCluster.statsProvider, 1, 1, 1, 0, totalPresent,
+ cluster.blobSize, CONSISTENCY_NAME);
assertStatsBean(globalCollector.getConsistencyOperationStats(), 1, 1, 1);
}
@@ -472,10 +499,28 @@ public class BlobGCTest {
MarkSweepGarbageCollector globalCollector = secondCluster.getCollector(0, true, false);
long missing = globalCollector.checkConsistency();
assertEquals(1, missing);
- assertStats(secondCluster.statsProvider, 1, 1, 1, 0, CONSISTENCY_NAME);
+ int totalPresent =
+ secondCluster.blobStoreState.blobsPresent.size() + cluster.blobStoreState.blobsPresent.size();
+ assertStats(secondCluster.statsProvider, 1, 1, 1, 0, totalPresent,
+ cluster.blobSize, CONSISTENCY_NAME);
assertStatsBean(globalCollector.getConsistencyOperationStats(), 1, 1, 1);
}
+ @Test
+ public void checkConsistencyFailureNotAllMarked() throws Exception {
+ log.info("Staring checkConsistencyFailureNotAllMarked()");
+ expectedEx.expect(NotAllRepositoryMarkedException.class);
+
+ // Setup a different cluster/repository sharing the blob store
+ MemoryBlobStoreNodeStore secondClusterNodeStore = new MemoryBlobStoreNodeStore(cluster.blobStore);
+ Cluster secondCluster = new Cluster(folder.newFolder(), cluster.blobStore, secondClusterNodeStore, 100);
+ closer.register(secondCluster);
+
+ // Execute mark on the default cluster
+ MarkSweepGarbageCollector globalCollector = cluster.getCollector(0, true, false);
+ globalCollector.checkConsistency();
+ }
+
@Test
public void gcCheckDeletedSize() throws Exception {
log.info("Starting gcCheckDeletedSize()");
@@ -496,7 +541,8 @@ public class BlobGCTest {
assertTrue(customLogs.getLogs().get(0).contains(String.valueOf(deletedSize)));
assertStats(cluster.statsProvider, 1, 0,
cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(),
- cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(), NAME);
+ cluster.blobStoreState.blobsAdded.size() - cluster.blobStoreState.blobsPresent.size(),
+ cluster.blobStoreState.blobsPresent.size(), cluster.blobSize, NAME);
assertEquals(deletedSize, getStatCount(cluster.statsProvider, NAME, TOTAL_SIZE_DELETED));
customLogs.finished();
assertTrue(Sets.symmetricDifference(cluster.blobStoreState.blobsPresent, existingAfterGC).isEmpty());
@@ -509,7 +555,12 @@ public class BlobGCTest {
Set<String> existingAfterGC =
executeGarbageCollection(cluster, cluster.getCollector(0),true);
assertTrue(Sets.symmetricDifference(cluster.blobStoreState.blobsAdded, existingAfterGC).isEmpty());
- assertStats(cluster.statsProvider, 1, 0, 0, 0, NAME);
+ assertStats(cluster.statsProvider, 1, 0, 0, 0, cluster.blobStoreState.blobsPresent.size(), cluster.blobSize,
+ NAME);
+ assertEquals(cluster.blobStoreState.blobsPresent.size(), getStatCount(cluster.statsProvider, NAME,
+ NUM_BLOB_REFERENCES));
+ assertEquals(cluster.blobStoreState.blobsPresent.size() * cluster.blobSize, getStatCount(cluster.statsProvider, NAME,
+ BLOB_REFERENCES_SIZE));
}
protected Set<String> executeGarbageCollection(Cluster cluster, MarkSweepGarbageCollector collector, boolean markOnly)
@@ -524,12 +575,17 @@ public class BlobGCTest {
}
private void assertStats(StatisticsProvider statsProvider, int start, int failure, long deleted, long candidates,
- String typeName) {
+ long blobsPresent, long blobsPresentSize, String typeName) {
assertEquals("Start counter mismatch", start, getStatCount(statsProvider, typeName, START));
assertEquals("Finish error mismatch", failure, getStatCount(statsProvider, typeName, FINISH_FAILURE));
assertEquals("Num deleted mismatch", deleted, getStatCount(statsProvider, typeName, NUM_BLOBS_DELETED));
assertEquals("Num candidates mismatch", candidates, getStatCount(statsProvider, typeName, NUM_CANDIDATES));
+ assertEquals("Num references mismatch", blobsPresent, getStatCount(statsProvider, typeName,
+ NUM_BLOB_REFERENCES));
+ assertEquals("Blob reference size mismatch", blobsPresent * blobsPresentSize, getStatCount(statsProvider,
+ typeName,
+ BLOB_REFERENCES_SIZE));
}