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 da...@apache.org on 2023/08/03 10:03:11 UTC
[jackrabbit-oak] 24/24: OAK-10199 : added unit cases for bundled properties getting garbaged collected as well
This is an automated email from the ASF dual-hosted git repository.
daim pushed a commit to branch OAK-10199
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
commit 6f640e9ae5c4534b860a6654e361c34a6b52ee34
Author: Rishabh Kumar <di...@adobe.com>
AuthorDate: Thu Aug 3 15:32:24 2023 +0530
OAK-10199 : added unit cases for bundled properties getting garbaged collected as well
---
.../document/VersionGarbageCollectorIT.java | 133 +++++++++++++++++++--
1 file changed, 125 insertions(+), 8 deletions(-)
diff --git a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollectorIT.java b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollectorIT.java
index 4e5360e2c3..56f8b3f77b 100644
--- a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollectorIT.java
+++ b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollectorIT.java
@@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
+import static java.util.List.of;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.stream.Collectors.toList;
@@ -43,7 +44,9 @@ import static org.apache.jackrabbit.guava.common.collect.Iterables.filter;
import static org.apache.jackrabbit.guava.common.collect.Iterables.size;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.apache.jackrabbit.oak.api.Type.NAME;
import static org.apache.jackrabbit.oak.api.Type.STRING;
+import static org.apache.jackrabbit.oak.api.Type.STRINGS;
import static org.apache.jackrabbit.oak.plugins.document.Collection.NODES;
import static org.apache.jackrabbit.oak.plugins.document.Collection.SETTINGS;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.MIN_ID_VALUE;
@@ -51,12 +54,14 @@ import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.NUM_REVS_T
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.PREV_SPLIT_FACTOR;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.SplitDocType;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.setModified;
+import static org.apache.jackrabbit.oak.plugins.document.Revision.getCurrentTimestamp;
import static org.apache.jackrabbit.oak.plugins.document.Revision.newRevision;
import static org.apache.jackrabbit.oak.plugins.document.TestUtils.NO_BINARY;
import static org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.SETTINGS_COLLECTION_DETAILED_GC_DOCUMENT_ID_PROP;
import static org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.SETTINGS_COLLECTION_DETAILED_GC_TIMESTAMP_PROP;
import static org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.SETTINGS_COLLECTION_ID;
import static org.apache.jackrabbit.oak.plugins.document.VersionGarbageCollector.VersionGCStats;
+import static org.apache.jackrabbit.oak.plugins.document.bundlor.DocumentBundlor.META_PROP_PATTERN;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -79,10 +84,12 @@ import org.apache.jackrabbit.guava.common.io.Closer;
import org.apache.jackrabbit.guava.common.util.concurrent.Atomics;
import com.mongodb.ReadPreference;
+import org.apache.jackrabbit.oak.InitialContent;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.document.DocumentStoreFixture.RDBFixture;
+import org.apache.jackrabbit.oak.plugins.document.bundlor.BundlingConfigInitializer;
import org.apache.jackrabbit.oak.plugins.document.mongo.MongoTestUtils;
import org.apache.jackrabbit.oak.plugins.document.rdb.RDBOptions;
import org.apache.jackrabbit.oak.plugins.document.util.Utils;
@@ -316,7 +323,7 @@ public class VersionGarbageCollectorIT {
assertEquals(1, stats.updatedDetailedGCDocsCount);
assertTrue(stats.ignoredGCDueToCheckPoint);
assertFalse(stats.ignoredDetailedGCDueToCheckPoint);
- assertFalse(stats.canceled);
+ assertTrue(stats.canceled);
}
@Test
@@ -344,7 +351,7 @@ public class VersionGarbageCollectorIT {
long maxAge = 1; //hours
long delta = MINUTES.toMillis(10);
//1. Go past GC age and check no GC done as nothing deleted
- clock.waitUntil(Revision.getCurrentTimestamp() + maxAge);
+ clock.waitUntil(getCurrentTimestamp() + maxAge);
VersionGCStats stats = gc.gc(maxAge, HOURS);
assertEquals(0, stats.deletedPropsGCCount);
assertEquals(0, stats.updatedDetailedGCDocsCount);
@@ -455,7 +462,7 @@ public class VersionGarbageCollectorIT {
}
store.merge(b2, EmptyHook.INSTANCE, CommitInfo.EMPTY);
// increase the clock to create new revision for next batch
- clock.waitUntil(Revision.getCurrentTimestamp() + (k * 5));
+ clock.waitUntil(getCurrentTimestamp() + (k * 5));
}
store.runBackgroundOperations();
@@ -482,7 +489,7 @@ public class VersionGarbageCollectorIT {
}
store.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
// increase the clock to create new revision for next batch
- clock.waitUntil(Revision.getCurrentTimestamp() + (k * 5));
+ clock.waitUntil(getCurrentTimestamp() + (k * 5));
}
store.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
@@ -524,7 +531,7 @@ public class VersionGarbageCollectorIT {
long maxAge = 1; //hours
long delta = MINUTES.toMillis(10);
//1. Go past GC age and check no GC done as nothing deleted
- clock.waitUntil(Revision.getCurrentTimestamp() + maxAge);
+ clock.waitUntil(getCurrentTimestamp() + maxAge);
VersionGCStats stats = gc.gc(maxAge, HOURS);
assertEquals(0, stats.deletedPropsGCCount);
@@ -654,7 +661,7 @@ public class VersionGarbageCollectorIT {
long maxAge = 1; //hours
long delta = MINUTES.toMillis(10);
//1. Go past GC age and check no GC done as nothing deleted
- clock.waitUntil(Revision.getCurrentTimestamp() + maxAge);
+ clock.waitUntil(getCurrentTimestamp() + maxAge);
VersionGCStats stats = gc.gc(maxAge, HOURS);
assertEquals(0, stats.deletedPropsGCCount);
assertEquals(0, stats.updatedDetailedGCDocsCount);
@@ -694,6 +701,116 @@ public class VersionGarbageCollectorIT {
assertEquals(0, stats.updatedDetailedGCDocsCount);
}
+ @Test
+ public void testGCDeletedNonBundledProps() throws Exception {
+
+ //0. Initialize bundling configs
+ final NodeBuilder builder = store.getRoot().builder();
+ new InitialContent().initialize(builder);
+ BundlingConfigInitializer.INSTANCE.initialize(builder);
+ merge(store, builder);
+ store.runBackgroundOperations();
+
+ //1. Create nodes with properties
+ NodeBuilder b1 = store.getRoot().builder();
+ b1.child("x").setProperty("jcr:primaryType", "nt:file", NAME);
+
+ // Add property to node & save
+ for (int i = 0; i < 10; i++) {
+ b1.child("x").child("jcr:content").setProperty("prop"+i, "t", STRING);
+ b1.child("x").setProperty(META_PROP_PATTERN, of("jcr:content"), STRINGS);
+ b1.child("x").setProperty("prop"+i, "bar", STRING);
+ }
+ store.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ // enable the detailed gc flag
+ writeField(gc, "detailedGCEnabled", true, true);
+ long maxAge = 1; //hours
+ long delta = MINUTES.toMillis(10);
+ //1. Go past GC age and check no GC done as nothing deleted
+ clock.waitUntil(getCurrentTimestamp() + maxAge);
+ VersionGCStats stats = gc.gc(maxAge, HOURS);
+ assertEquals(0, stats.deletedPropsGCCount);
+ assertEquals(0, stats.updatedDetailedGCDocsCount);
+
+ //Remove property
+ NodeBuilder b2 = store.getRoot().builder();
+ for (int i = 0; i < 10; i++) {
+ b2.getChildNode("x").removeProperty("prop"+i);
+ }
+ store.merge(b2, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ store.runBackgroundOperations();
+
+ //2. Check that a deleted property 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.deletedPropsGCCount);
+ assertEquals(0, stats.updatedDetailedGCDocsCount);
+
+ //3. Check that deleted property does get collected post maxAge
+ clock.waitUntil(clock.getTime() + HOURS.toMillis(maxAge*2) + delta);
+
+ stats = gc.gc(maxAge*2, HOURS);
+ assertEquals(10, stats.deletedPropsGCCount);
+ }
+
+ @Test
+ public void testGCDeletedBundledProps() throws Exception {
+
+ //0. Initialize bundling configs
+ final NodeBuilder builder = store.getRoot().builder();
+ new InitialContent().initialize(builder);
+ BundlingConfigInitializer.INSTANCE.initialize(builder);
+ merge(store, builder);
+ store.runBackgroundOperations();
+
+ //1. Create nodes with properties
+ NodeBuilder b1 = store.getRoot().builder();
+ b1.child("x").setProperty("jcr:primaryType", "nt:file", NAME);
+
+ // Add property to node & save
+ for (int i = 0; i < 10; i++) {
+ b1.child("x").child("jcr:content").setProperty("prop"+i, "t", STRING);
+ b1.child("x").setProperty(META_PROP_PATTERN, of("jcr:content"), STRINGS);
+ b1.child("x").setProperty("prop"+i, "bar", STRING);
+ }
+ store.merge(b1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ // enable the detailed gc flag
+ writeField(gc, "detailedGCEnabled", true, true);
+ long maxAge = 1; //hours
+ long delta = MINUTES.toMillis(10);
+ //1. Go past GC age and check no GC done as nothing deleted
+ clock.waitUntil(getCurrentTimestamp() + maxAge);
+ VersionGCStats stats = gc.gc(maxAge, HOURS);
+ assertEquals(0, stats.deletedPropsGCCount);
+ assertEquals(0, stats.updatedDetailedGCDocsCount);
+
+ //Remove property
+ NodeBuilder b2 = store.getRoot().builder();
+ for (int i = 0; i < 10; i++) {
+ b2.getChildNode("x").getChildNode("jcr:content").removeProperty("prop"+i);
+ }
+ store.merge(b2, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ store.runBackgroundOperations();
+
+ //2. Check that a deleted property 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.deletedPropsGCCount);
+ assertEquals(0, stats.updatedDetailedGCDocsCount);
+
+ //3. Check that deleted property does get collected post maxAge
+ clock.waitUntil(clock.getTime() + HOURS.toMillis(maxAge*2) + delta);
+
+ stats = gc.gc(maxAge*2, HOURS);
+ assertEquals(10, stats.deletedPropsGCCount);
+ }
+
@Test
public void testGCDeletedPropsWhenModifiedConcurrently() throws Exception {
//1. Create nodes with properties
@@ -710,7 +827,7 @@ public class VersionGarbageCollectorIT {
long maxAge = 1; //hours
long delta = MINUTES.toMillis(10);
//1. Go past GC age and check no GC done as nothing deleted
- clock.waitUntil(Revision.getCurrentTimestamp() + maxAge);
+ clock.waitUntil(getCurrentTimestamp() + maxAge);
VersionGCStats stats = gc.gc(maxAge, HOURS);
assertEquals(0, stats.deletedPropsGCCount);
assertEquals(0, stats.updatedDetailedGCDocsCount);
@@ -779,7 +896,7 @@ public class VersionGarbageCollectorIT {
long maxAge = 1; //hours
long delta = MINUTES.toMillis(10);
//1. Go past GC age and check no GC done as nothing deleted
- clock.waitUntil(Revision.getCurrentTimestamp() + maxAge);
+ clock.waitUntil(getCurrentTimestamp() + maxAge);
VersionGCStats stats = gc.gc(maxAge, HOURS);
assertEquals(0, stats.deletedPropsGCCount);
assertEquals(0, stats.updatedDetailedGCDocsCount);