use of org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats in project jackrabbit-oak by apache.
the class VersionGarbageCollectorIT method gcDefaultNoBranchSplitDoc.
@Test
public void gcDefaultNoBranchSplitDoc() throws Exception {
// hrs
long maxAge = 1;
long delta = TimeUnit.MINUTES.toMillis(10);
NodeBuilder builder = store.getRoot().builder();
builder.child("foo").child("bar");
merge(store, builder);
String value = "";
for (int i = 0; i < NUM_REVS_THRESHOLD; i++) {
builder = store.getRoot().builder();
value = "v" + i;
builder.child("foo").setProperty("prop", value);
merge(store, builder);
}
store.runBackgroundOperations();
// perform a change to make sure the sweep rev will be newer than
// the split revs, otherwise revision GC won't remove the split doc
clock.waitUntil(clock.getTime() + TimeUnit.SECONDS.toMillis(NodeDocument.MODIFIED_IN_SECS_RESOLUTION * 2));
builder = store.getRoot().builder();
builder.child("qux");
merge(store, builder);
store.runBackgroundOperations();
NodeDocument doc = getDoc("/foo");
assertNotNull(doc);
List<NodeDocument> prevDocs = ImmutableList.copyOf(doc.getAllPreviousDocs());
assertEquals(1, prevDocs.size());
assertEquals(SplitDocType.DEFAULT_NO_BRANCH, prevDocs.get(0).getSplitDocType());
clock.waitUntil(clock.getTime() + HOURS.toMillis(maxAge) + delta);
VersionGCStats stats = gc.gc(maxAge, HOURS);
assertEquals(1, stats.splitDocGCCount);
doc = getDoc("/foo");
assertNotNull(doc);
prevDocs = ImmutableList.copyOf(doc.getAllPreviousDocs());
assertEquals(0, prevDocs.size());
assertEquals(value, store.getRoot().getChildNode("foo").getString("prop"));
}
use of org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats in project jackrabbit-oak by apache.
the class VersionGarbageCollectorIT method gcIgnoredForCheckpoint.
@Test
public void gcIgnoredForCheckpoint() throws Exception {
long expiryTime = 100, maxAge = 20;
Revision cp = Revision.fromString(store.checkpoint(expiryTime));
// Fast forward time to future but before expiry of checkpoint
clock.waitUntil(cp.getTimestamp() + expiryTime - maxAge);
VersionGCStats stats = gc.gc(maxAge, TimeUnit.MILLISECONDS);
assertTrue(stats.ignoredGCDueToCheckPoint);
// Fast forward time to future such that checkpoint get expired
clock.waitUntil(clock.getTime() + expiryTime + 1);
stats = gc.gc(maxAge, TimeUnit.MILLISECONDS);
assertFalse("GC should be performed", stats.ignoredGCDueToCheckPoint);
}
use of org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats in project jackrabbit-oak by apache.
the class VersionGarbageCollectorIT method gcSplitDocsInternal.
private void gcSplitDocsInternal(String subNodeName) throws Exception {
// hrs
long maxAge = 1;
long delta = TimeUnit.MINUTES.toMillis(10);
NodeBuilder b1 = store.getRoot().builder();
b1.child("test").child(subNodeName).child("bar");
b1.child("test2").child(subNodeName);
store.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
// is parent
for (int i = 0; i < NUM_REVS_THRESHOLD; i++) {
b1 = store.getRoot().builder();
// This updates a middle node i.e. one which has child bar
// Should result in SplitDoc of type PROP_COMMIT_ONLY
b1.child("test").child(subNodeName).setProperty("prop", i);
// This should result in SplitDoc of type DEFAULT_NO_CHILD
b1.child("test2").child(subNodeName).setProperty("prop", i);
store.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
}
store.runBackgroundOperations();
// perform a change to make sure the sweep rev will be newer than
// the split revs, otherwise revision GC won't remove the split doc
clock.waitUntil(clock.getTime() + TimeUnit.SECONDS.toMillis(NodeDocument.MODIFIED_IN_SECS_RESOLUTION * 2));
NodeBuilder builder = store.getRoot().builder();
builder.child("qux");
merge(store, builder);
store.runBackgroundOperations();
List<NodeDocument> previousDocTestFoo = ImmutableList.copyOf(getDoc("/test/" + subNodeName).getAllPreviousDocs());
List<NodeDocument> previousDocTestFoo2 = ImmutableList.copyOf(getDoc("/test2/" + subNodeName).getAllPreviousDocs());
List<NodeDocument> previousDocRoot = ImmutableList.copyOf(getDoc("/").getAllPreviousDocs());
assertEquals(1, previousDocTestFoo.size());
assertEquals(1, previousDocTestFoo2.size());
assertEquals(1, previousDocRoot.size());
assertEquals(SplitDocType.COMMIT_ROOT_ONLY, previousDocTestFoo.get(0).getSplitDocType());
assertEquals(SplitDocType.DEFAULT_LEAF, previousDocTestFoo2.get(0).getSplitDocType());
assertEquals(SplitDocType.DEFAULT_NO_BRANCH, previousDocRoot.get(0).getSplitDocType());
clock.waitUntil(clock.getTime() + HOURS.toMillis(maxAge) + delta);
VersionGCStats stats = gc.gc(maxAge, HOURS);
assertEquals(3, stats.splitDocGCCount);
assertEquals(0, stats.deletedLeafDocGCCount);
// Previous doc should be removed
assertNull(getDoc(previousDocTestFoo.get(0).getPath()));
assertNull(getDoc(previousDocTestFoo2.get(0).getPath()));
assertNull(getDoc(previousDocRoot.get(0).getPath()));
// Following would not work for Mongo as the delete happened on the server side
// And entries from cache are not evicted
// assertTrue(ImmutableList.copyOf(getDoc("/test2/foo").getAllPreviousDocs()).isEmpty());
}
use of org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats in project jackrabbit-oak by apache.
the class VersionGarbageCollectorIT method testGCDeletedDocument.
@Test
public void testGCDeletedDocument() throws Exception {
// 1. Create nodes
NodeBuilder b1 = store.getRoot().builder();
b1.child("x").child("y");
b1.child("z");
store.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
// hours
long maxAge = 1;
long delta = TimeUnit.MINUTES.toMillis(10);
// 1. Go past GC age and check no GC done as nothing deleted
clock.waitUntil(Revision.getCurrentTimestamp() + maxAge);
VersionGCStats stats = gc.gc(maxAge, HOURS);
assertEquals(0, stats.deletedDocGCCount);
// Remove x/y
NodeBuilder b2 = store.getRoot().builder();
b2.child("x").child("y").remove();
store.merge(b2, EmptyHook.INSTANCE, CommitInfo.EMPTY);
store.runBackgroundOperations();
// 2. Check that a deleted doc is not collected before
// maxAge
// Clock cannot move back (it moved forward in #1) so double the maxAge
clock.waitUntil(clock.getTime() + delta);
stats = gc.gc(maxAge * 2, HOURS);
assertEquals(0, stats.deletedDocGCCount);
assertEquals(0, stats.deletedLeafDocGCCount);
// 3. Check that deleted doc does get collected post maxAge
clock.waitUntil(clock.getTime() + HOURS.toMillis(maxAge * 2) + delta);
stats = gc.gc(maxAge * 2, HOURS);
assertEquals(1, stats.deletedDocGCCount);
assertEquals(1, stats.deletedLeafDocGCCount);
// 4. Check that a revived doc (deleted and created again) does not get gc
NodeBuilder b3 = store.getRoot().builder();
b3.child("z").remove();
store.merge(b3, EmptyHook.INSTANCE, CommitInfo.EMPTY);
NodeBuilder b4 = store.getRoot().builder();
b4.child("z");
store.merge(b4, EmptyHook.INSTANCE, CommitInfo.EMPTY);
clock.waitUntil(clock.getTime() + HOURS.toMillis(maxAge * 2) + delta);
stats = gc.gc(maxAge * 2, HOURS);
assertEquals(0, stats.deletedDocGCCount);
assertEquals(0, stats.deletedLeafDocGCCount);
assertEquals(1, stats.updateResurrectedGCCount);
}
use of org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats in project jackrabbit-oak by apache.
the class VersionGarbageCollectorIT method cancelGCAfterFirstPhase.
@Test
public void cancelGCAfterFirstPhase() throws Exception {
createTestNode("foo");
NodeBuilder builder = store.getRoot().builder();
builder.child("foo").child("bar");
merge(store, builder);
builder = store.getRoot().builder();
builder.child("foo").remove();
merge(store, builder);
store.runBackgroundOperations();
clock.waitUntil(clock.getTime() + TimeUnit.HOURS.toMillis(1));
final AtomicReference<VersionGarbageCollector> gcRef = Atomics.newReference();
VersionGCSupport gcSupport = new VersionGCSupport(store.getDocumentStore()) {
@Override
public Iterable<NodeDocument> getPossiblyDeletedDocs(final long fromModified, final long toModified) {
return new Iterable<NodeDocument>() {
@Nonnull
@Override
public Iterator<NodeDocument> iterator() {
return new AbstractIterator<NodeDocument>() {
private Iterator<NodeDocument> it = candidates(fromModified, toModified);
@Override
protected NodeDocument computeNext() {
if (it.hasNext()) {
return it.next();
}
// cancel when we reach the end
gcRef.get().cancel();
return endOfData();
}
};
}
};
}
private Iterator<NodeDocument> candidates(long prevLastModifiedTime, long lastModifiedTime) {
return super.getPossiblyDeletedDocs(prevLastModifiedTime, lastModifiedTime).iterator();
}
};
gcRef.set(new VersionGarbageCollector(store, gcSupport));
VersionGCStats stats = gcRef.get().gc(30, TimeUnit.MINUTES);
assertTrue(stats.canceled);
assertEquals(0, stats.deletedDocGCCount);
assertEquals(0, stats.deletedLeafDocGCCount);
assertEquals(0, stats.intermediateSplitDocGCCount);
assertEquals(0, stats.splitDocGCCount);
}
Aggregations