Skip to content

Commit 17af78c

Browse files
daniancuDaniel Iancu
authored and
Daniel Iancu
committed
OAK-11525 Update fullGC configuration for audit logging into Mongo collection
* OAK-11525 Update fullGC configuration for audit logging into Mongo collection
1 parent e303df3 commit 17af78c

13 files changed

+109
-27
lines changed

oak-run/src/main/java/org/apache/jackrabbit/oak/run/RevisionsCommand.java

+9
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ private static class RevisionsOptions extends Utils.NodeStoreOptions {
134134
final OptionSpec<Boolean> dryRun;
135135
final OptionSpec<Boolean> embeddedVerification;
136136
final OptionSpec<Integer> fullGcMode;
137+
final OptionSpec<Boolean> fullGCAuditLoggingEnabled;
137138

138139
RevisionsOptions(String usage) {
139140
super(usage);
@@ -195,6 +196,8 @@ private static class RevisionsOptions extends Utils.NodeStoreOptions {
195196
"to be considered for Full GC i.e. Version Garbage Collector (Full GC) logic will only consider those " +
196197
"nodes for Full GC which are not accessed recently (currentTime - lastModifiedTime > fullGcMaxAge). Default: 86400 (one day)")
197198
.withOptionalArg().ofType(Long.class).defaultsTo(TimeUnit.DAYS.toSeconds(1));
199+
fullGCAuditLoggingEnabled = parser.accepts("fullGCAuditLoggingEnabled", "Enable audit logging for Full GC")
200+
.withOptionalArg().ofType(Boolean.class).defaultsTo(FALSE);
198201
}
199202

200203
public RevisionsOptions parse(String[] args) {
@@ -293,6 +296,10 @@ boolean isEntireRepo() {
293296
boolean doCompaction() {
294297
return options.has(compact);
295298
}
299+
300+
Boolean isFullGCAuditLoggingEnabled() {
301+
return options.has(fullGCAuditLoggingEnabled);
302+
}
296303
}
297304

298305
@Override
@@ -358,6 +365,7 @@ private VersionGarbageCollector bootstrapVGC(RevisionsOptions options, Closer cl
358365
builder.setFullGCBatchSize(options.getFullGcBatchSize());
359366
builder.setFullGCProgressSize(options.getFullGcProgressSize());
360367
builder.setFullGcMaxAgeMillis(SECONDS.toMillis(options.getFullGcMaxAge()));
368+
builder.setFullGCAuditLoggingEnabled(options.isFullGCAuditLoggingEnabled());
361369

362370
// create a VersionGCSupport while builder is read-write
363371
VersionGCSupport gcSupport = builder.createVersionGCSupport();
@@ -391,6 +399,7 @@ private VersionGarbageCollector bootstrapVGC(RevisionsOptions options, Closer cl
391399
System.out.println("FullGcProgressSize is : " + options.getFullGcProgressSize());
392400
System.out.println("FullGcMaxAgeInSecs is : " + options.getFullGcMaxAge());
393401
System.out.println("FullGcMaxAgeMillis is : " + builder.getFullGcMaxAgeMillis());
402+
System.out.println("FullGCAuditLoggingEnabled is : " + options.isFullGCAuditLoggingEnabled());
394403
VersionGarbageCollector gc = createVersionGC(builder.build(), gcSupport, options.isDryRun(), builder);
395404

396405
VersionGCOptions gcOptions = gc.getOptions();

oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Configuration.java

+5
Original file line numberDiff line numberDiff line change
@@ -400,4 +400,9 @@
400400
name = "Invisible for discovery",
401401
description = "Boolean value indicating whether the instance should be discoverable by the cluster. The default value is " + DocumentNodeStoreService.DEFAULT_INVISIBLE_FOR_DISCOVERY)
402402
boolean invisibleForDiscovery() default DocumentNodeStoreService.DEFAULT_INVISIBLE_FOR_DISCOVERY;
403+
404+
@AttributeDefinition(
405+
name = "Enable Full GC Persistent Audit Logging",
406+
description = "This parameter will enable/disable the saving of deleted document IDs and properties during FullGC into a persistent storage, e.g Mongo collection")
407+
boolean fullGCAuditLoggingEnabled() default false;
403408
}

oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBuilder.java

+10
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ public class DocumentNodeStoreBuilder<T extends DocumentNodeStoreBuilder<T>> {
185185
private int fullGCBatchSize = DocumentNodeStoreService.DEFAULT_FGC_BATCH_SIZE;
186186
private int fullGCProgressSize = DocumentNodeStoreService.DEFAULT_FGC_PROGRESS_SIZE;
187187
private double fullGCDelayFactor = DocumentNodeStoreService.DEFAULT_FGC_DELAY_FACTOR;
188+
private boolean fullGCAuditLoggingEnabled;
188189
private long suspendTimeoutMillis = DEFAULT_SUSPEND_TIMEOUT;
189190

190191
/**
@@ -317,6 +318,15 @@ public boolean isFullGCEnabled() {
317318
return this.fullGCEnabled;
318319
}
319320

321+
public T setFullGCAuditLoggingEnabled(boolean b) {
322+
this.fullGCAuditLoggingEnabled = b;
323+
return thisBuilder();
324+
}
325+
326+
public boolean isFullGCAuditLoggingEnabled() {
327+
return this.fullGCAuditLoggingEnabled;
328+
}
329+
320330
public T setFullGCIncludePaths(@Nullable String[] includePaths) {
321331
if (isNull(includePaths) || includePaths.length == 0 || Arrays.equals(includePaths, new String[]{"/"})) {
322332
this.fullGCIncludePaths = Set.of();

oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java

+1
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ private void configureBuilder(DocumentNodeStoreBuilder<?> builder) {
534534
setFullGCBatchSize(config.fullGCBatchSize()).
535535
setFullGCProgressSize(config.fullGCProgressSize()).
536536
setFullGCDelayFactor(config.fullGCDelayFactor()).
537+
setFullGCAuditLoggingEnabled(config.fullGCAuditLoggingEnabled()).
537538
setSuspendTimeoutMillis(config.suspendTimeoutMillis()).
538539
setClusterIdReuseDelayAfterRecovery(config.clusterIdReuseDelayAfterRecoveryMillis()).
539540
setRecoveryDelayMillis(config.recoveryDelayMillis()).

oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentNodeStoreBuilderBase.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public T setCollectionCompressionType(String compressionType) {
172172
public VersionGCSupport createVersionGCSupport() {
173173
DocumentStore store = getDocumentStore();
174174
if (store instanceof MongoDocumentStore) {
175-
return new MongoVersionGCSupport((MongoDocumentStore) store);
175+
return new MongoVersionGCSupport((MongoDocumentStore) store, isFullGCAuditLoggingEnabled());
176176
} else {
177177
return super.createVersionGCSupport();
178178
}

oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@ public MongoDocumentStore(MongoClient connection, MongoDatabase db,
351351

352352
if (!readOnly) {
353353
ensureIndexes(db, status);
354+
if (builder.isFullGCAuditLoggingEnabled()) {
355+
ensureFullGcTTLIndex();
356+
}
354357
}
355358

356359
this.nodeLocks = new StripedNodeDocumentLocks();
@@ -466,10 +469,12 @@ private void ensureIndexes(@NotNull MongoDatabase db, @NotNull MongoStatus mongo
466469

467470
// index on _modified for journal entries
468471
createIndex(journal, JournalEntry.MODIFIED, true, false, false);
472+
}
469473

474+
private void ensureFullGcTTLIndex() {
470475
//TTL index for full GC bin documents to expire after 90 days
471476
//see https://issues.apache.org/jira/browse/OAK-11444
472-
IndexOptions indexOptions = new IndexOptions().expireAfter(TimeUnit.DAYS.toSeconds(90), java.util.concurrent.TimeUnit.SECONDS);
477+
IndexOptions indexOptions = new IndexOptions().expireAfter(TimeUnit.DAYS.toSeconds(90), TimeUnit.SECONDS);
473478
connection.getCollection(BIN_COLLECTION).createIndex(new org.bson.Document(MongoFullGcNodeBin.GC_COLLECTED_AT, 1), indexOptions);
474479
}
475480

oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoFullGcNodeBin.java

+16-18
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.apache.jackrabbit.oak.plugins.document.mongo;
1818

1919
import com.mongodb.BasicDBObject;
20-
import org.apache.jackrabbit.oak.commons.properties.SystemPropertySupplier;
2120
import org.apache.jackrabbit.oak.plugins.document.Collection;
2221
import org.apache.jackrabbit.oak.plugins.document.Document;
2322
import org.apache.jackrabbit.oak.plugins.document.DocumentStore;
@@ -46,13 +45,19 @@
4645
* Each method delegates directly to DocumentStore
4746
*/
4847
public class MongoFullGcNodeBin implements FullGcNodeBin {
49-
private static final Logger LOG = LoggerFactory.getLogger(MongoFullGcNodeBin.class);
5048
public static final String GC_COLLECTED_AT = "_gcCollectedAt";
49+
private static final Logger LOG = LoggerFactory.getLogger(MongoFullGcNodeBin.class);
50+
5151
private final MongoDocumentStore mongoDocumentStore;
52-
private boolean enabled = SystemPropertySupplier.create("oak.document.fullGcBin.enabled", false).get();
52+
private boolean enabled;
5353

5454
public MongoFullGcNodeBin(MongoDocumentStore ds) {
55-
mongoDocumentStore = ds;
55+
this(ds, false);
56+
}
57+
58+
public MongoFullGcNodeBin(MongoDocumentStore store, boolean fullGcBinEnabled) {
59+
mongoDocumentStore = store;
60+
enabled = fullGcBinEnabled;
5661
}
5762

5863
/**
@@ -100,15 +105,9 @@ public List<NodeDocument> findAndUpdate(List<UpdateOp> updateOpList) {
100105
return mongoDocumentStore.findAndUpdate(Collection.NODES, updateOpList);
101106
}
102107

103-
/**
104-
* Saves the name of properties that will be removed in the BIN collection
105-
*
106-
* @param orphanOrDeletedRemovalMap the keys of the documents to remove with the corresponding timestamps
107-
* @return true if the documents were successfully added to the bin
108-
*/
109108
private boolean addToBin(Map<String, Long> orphanOrDeletedRemovalMap) {
110109
if (!enabled) {
111-
LOG.info("Bin is disabled, skip adding delete candidate documents to bin");
110+
LOG.info("Bin is disabled, skipping adding delete candidate documents to bin");
112111
return true;
113112
}
114113
LOG.info("Adding {} delete candidate documents to bin", orphanOrDeletedRemovalMap.size());
@@ -124,15 +123,9 @@ private boolean addToBin(Map<String, Long> orphanOrDeletedRemovalMap) {
124123
return false;
125124
}
126125

127-
/**
128-
* Saves the ID of documents that will be removed in the BIN collection
129-
*
130-
* @param updateOpList the update operation list for removing the documents
131-
* @return true if the documents were successfully added to the bin
132-
*/
133126
private boolean addToBin(List<UpdateOp> updateOpList) {
134127
if (!enabled) {
135-
LOG.info("Bin is disabled, skip adding removed properties to bin");
128+
LOG.info("Bin is disabled, skipping adding removed properties to bin");
136129
return true;
137130
}
138131
LOG.info("Adding {} removed properties to bin", updateOpList.size());
@@ -169,5 +162,10 @@ private BasicDBObject toBasicDBObject(UpdateOp op) {
169162
@Override
170163
public void setEnabled(boolean value) {
171164
this.enabled = value;
165+
LOG.info("Full GC Bin changed to {}", enabled ? "enabled" : "disabled");
166+
}
167+
168+
public boolean isEnabled() {
169+
return enabled;
172170
}
173171
}

oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoVersionGCSupport.java

+10-5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import static com.mongodb.client.model.Filters.and;
3030
import static com.mongodb.client.model.Filters.lt;
3131
import static java.util.Collections.emptyList;
32+
import org.apache.jackrabbit.oak.commons.properties.SystemPropertySupplier;
3233
import static org.apache.jackrabbit.oak.plugins.document.Collection.NODES;
3334
import static org.apache.jackrabbit.oak.plugins.document.Document.ID;
3435
import org.apache.jackrabbit.oak.plugins.document.FullGcNodeBin;
@@ -100,7 +101,6 @@ public class MongoVersionGCSupport extends VersionGCSupport {
100101

101102
/** the hint representing "_modified_1__id_1" - if that index exists, null otherwise */
102103
private final BasicDBObject modifiedIdHint;
103-
private final MongoFullGcNodeBin fullGcNodeBin;
104104

105105
/** timestamp of last time an explain of the 'getModifiedDocs' query was logged */
106106
private long lastExplainLogMs = -1;
@@ -111,10 +111,15 @@ public class MongoVersionGCSupport extends VersionGCSupport {
111111
/**
112112
* The batch size for the query of possibly deleted docs.
113113
*/
114-
private final int batchSize = Integer.getInteger(
115-
"oak.mongo.queryDeletedDocsBatchSize", 1000);
114+
private final int batchSize = SystemPropertySupplier.create(
115+
"oak.mongo.queryDeletedDocsBatchSize", 1000).get();
116+
private final MongoFullGcNodeBin fullGcBin;
116117

117118
public MongoVersionGCSupport(MongoDocumentStore store) {
119+
this(store, false);
120+
}
121+
122+
public MongoVersionGCSupport(MongoDocumentStore store, boolean fullGcBinEnabled) {
118123
super(store);
119124
this.store = store;
120125
if(hasIndex(getNodeCollection(), SD_TYPE, SD_MAX_REV_TIME_IN_SECS)) {
@@ -131,7 +136,7 @@ public MongoVersionGCSupport(MongoDocumentStore store) {
131136
} else {
132137
modifiedIdHint = null;
133138
}
134-
fullGcNodeBin = new MongoFullGcNodeBin(store);
139+
this.fullGcBin = new MongoFullGcNodeBin(store, fullGcBinEnabled);
135140
}
136141

137142
@Override
@@ -485,7 +490,7 @@ private void logSplitDocIdsTobeDeleted(Bson query) {
485490

486491
@Override
487492
public FullGcNodeBin getFullGCBin() {
488-
return fullGcNodeBin;
493+
return fullGcBin;
489494
}
490495

491496
private static String getID(BasicDBObject document) {

oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentNodeStoreBuilder.java

+12
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,18 @@ public RDBDocumentNodeStoreBuilder setFullGCEnabled(boolean b) {
136136
return thisBuilder();
137137
}
138138

139+
@Override
140+
public boolean isFullGCAuditLoggingEnabled() {
141+
// fullGC is non supported for RDB
142+
return false;
143+
}
144+
145+
@Override
146+
public RDBDocumentNodeStoreBuilder setFullGCAuditLoggingEnabled(boolean b) {
147+
// fullGC is non supported for RDB
148+
return thisBuilder();
149+
}
150+
139151
@Override
140152
public Set<String> getFullGCIncludePaths() {
141153
return of();

oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceConfigurationTest.java

+8
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public void defaultValues() throws Exception {
104104
assertEquals(DEFAULT_EMBEDDED_VERIFICATION_ENABLED, config.embeddedVerificationEnabled());
105105
assertEquals(DocumentNodeStoreService.DEFAULT_FULL_GC_MAX_AGE, config.fullGcMaxAgeInSecs());
106106
assertEquals(CommitQueue.DEFAULT_SUSPEND_TIMEOUT, config.suspendTimeoutMillis());
107+
assertFalse(config.fullGCAuditLoggingEnabled());
107108
}
108109

109110
@Test
@@ -170,6 +171,13 @@ public void fullGCBatchSize() throws Exception {
170171
assertEquals(batchSize, config.fullGCBatchSize());
171172
}
172173

174+
@Test
175+
public void fullGCAuditLoggingEnabled() throws Exception {
176+
addConfigurationEntry(preset, "fullGCAuditLoggingEnabled", true);
177+
Configuration config = createConfiguration();
178+
assertTrue(config.fullGCAuditLoggingEnabled());
179+
}
180+
173181
@Test
174182
public void invisibleForDiscoveryFalse() throws Exception {
175183
boolean batchSize = false;

oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentNodeStoreBuilderTest.java

+6
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,10 @@ public void fullGCModeDefaultValue() {
132132
final int fullGcModeNone = 0;
133133
assertEquals(builder.getFullGCMode(), fullGcModeNone);
134134
}
135+
136+
@Test
137+
public void isFullGCAuditLoggingEnabled() {
138+
MongoDocumentNodeStoreBuilder builder = new MongoDocumentNodeStoreBuilder();
139+
assertFalse(builder.isFullGCAuditLoggingEnabled());
140+
}
135141
}

oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoFullGcNodeBinTest.java

+18-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
import com.mongodb.client.MongoCollection;
2222
import org.apache.jackrabbit.oak.plugins.document.Collection;
2323
import org.apache.jackrabbit.oak.plugins.document.Document;
24+
import org.apache.jackrabbit.oak.plugins.document.FullGcNodeBin;
2425
import org.apache.jackrabbit.oak.plugins.document.NodeDocument;
2526
import org.apache.jackrabbit.oak.plugins.document.UpdateOp;
27+
import org.junit.After;
2628
import static org.junit.Assert.assertEquals;
2729
import static org.junit.Assert.assertFalse;
2830
import static org.junit.Assert.assertTrue;
@@ -53,7 +55,7 @@ public class MongoFullGcNodeBinTest {
5355
@Mock
5456
MongoDocumentStore documentStore;
5557

56-
@InjectMocks
58+
5759
MongoFullGcNodeBin fullGcBin;
5860

5961
@Mock MongoCollection<BasicDBObject> mockBinCollection;
@@ -62,6 +64,7 @@ public class MongoFullGcNodeBinTest {
6264
@Before
6365
public void setUp() throws Exception {
6466
MockitoAnnotations.openMocks(this);
67+
fullGcBin = new MongoFullGcNodeBin(documentStore, true);
6568
when(documentStore.remove(eq(Collection.NODES), anyMap())).thenAnswer(invocation -> {
6669
Map<String, Long> map = invocation.getArgument(1);
6770
return map.size();
@@ -72,8 +75,21 @@ public void setUp() throws Exception {
7275
});
7376

7477
when(documentStore.getBinCollection()).thenReturn(mockBinCollection);
78+
}
79+
80+
@After
81+
public void tearDown() {
82+
Mockito.reset(documentStore, mockBinCollection);
83+
}
7584

76-
fullGcBin.setEnabled(true);
85+
@Test
86+
public void defaultDisabled() {
87+
assertFalse(new MongoFullGcNodeBin(this.documentStore).isEnabled());
88+
}
89+
90+
@Test
91+
public void enableWithConstructor() {
92+
assertTrue(new MongoFullGcNodeBin(this.documentStore, true).isEnabled());
7793
}
7894

7995
@Test

oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentNodeStoreBuilderTest.java

+7
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,11 @@ public void fullGcMaxAgeInSecsHasDefaultValue() {
121121
builder.setFullGcMaxAgeMillis(30 * 24 * 60 * 60 * 1000L);
122122
assertEquals(0, builder.getFullGcMaxAgeMillis());
123123
}
124+
125+
@Test
126+
public void fullGcAuditLoggingEnabled() {
127+
RDBDocumentNodeStoreBuilder builder = new RDBDocumentNodeStoreBuilder();
128+
builder.setFullGCAuditLoggingEnabled(true);
129+
assertFalse(builder.isFullGCAuditLoggingEnabled());
130+
}
124131
}

0 commit comments

Comments
 (0)