This is an automated email from the ASF dual-hosted git repository.
mbaedke pushed a commit to branch OAK-12309
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/OAK-12309 by this push:
new 799ec5640e OAK-12309: DocumentNodeStoreService may fail to register or
double register the NodeStore due to race conditions
799ec5640e is described below
commit 799ec5640ec785fe008a98038b072926d0a09124
Author: Manfred Baedke <[email protected]>
AuthorDate: Fri Jul 10 13:11:26 2026 +0200
OAK-12309: DocumentNodeStoreService may fail to register or double register
the NodeStore due to race conditions
Added synchronization.
---
.../plugins/document/DocumentNodeStoreService.java | 82 ++++++++++++----------
1 file changed, 45 insertions(+), 37 deletions(-)
diff --git
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
index 5ff80c2634..7dccd2537a 100644
---
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
+++
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
@@ -273,7 +273,7 @@ public class DocumentNodeStoreService {
private Feature cancelInvalidationFeature;
private Feature docStoreAvoidMergeLockFeature;
private Feature prevNoPropCacheFeature;
- private ComponentContext context;
+ private volatile ComponentContext context;
private Whiteboard whiteboard;
private long deactivationTimestamp = 0;
@@ -286,7 +286,7 @@ public class DocumentNodeStoreService {
@Reference(service = Preset.class)
private Preset preset;
- private boolean customBlobStore;
+ private volatile boolean customBlobStore;
private ServiceRegistration blobStoreReg;
@@ -294,6 +294,8 @@ public class DocumentNodeStoreService {
private Configuration config;
+ private final Object registrationLock = new Object();
+
@Activate
protected void activate(ComponentContext context, Configuration config)
throws Exception {
closer = Closer.create();
@@ -316,19 +318,23 @@ public class DocumentNodeStoreService {
}
private void registerNodeStoreIfPossible() throws IOException {
- // disallow attempts to restart (OAK-3420)
- if (deactivationTimestamp != 0) {
- log.info("DocumentNodeStore was already unregistered ({}ms ago)",
System.currentTimeMillis() - deactivationTimestamp);
- } else if (context == null) {
- log.info("Component still not activated. Ignoring the
initialization call");
- } else if (customBlobStore && blobStore == null) {
- log.info("Custom BlobStore use enabled. DocumentNodeStoreService
would be initialized when "
- + "BlobStore would be available");
- } else if (documentStoreType == DocumentStoreType.RDB && (dataSource
== null || blobDataSource == null)) {
- log.info("DataSource use enabled. DocumentNodeStoreService would
be initialized when "
- + "DataSource would be available (currently available:
nodes: {}, blobs: {})", dataSource, blobDataSource);
- } else {
- registerNodeStore();
+ synchronized (registrationLock) {
+ // disallow attempts to restart (OAK-3420)
+ if (deactivationTimestamp != 0) {
+ log.info("DocumentNodeStore was already unregistered ({}ms
ago)", System.currentTimeMillis() - deactivationTimestamp);
+ } else if (nodeStore != null) {
+ log.info("DocumentNodeStore already registered. Ignoring the
initialization call");
+ } else if (context == null) {
+ log.info("Component still not activated. Ignoring the
initialization call");
+ } else if (customBlobStore && blobStore == null) {
+ log.info("Custom BlobStore use enabled.
DocumentNodeStoreService would be initialized when "
+ + "BlobStore would be available");
+ } else if (documentStoreType == DocumentStoreType.RDB &&
(dataSource == null || blobDataSource == null)) {
+ log.info("DataSource use enabled. DocumentNodeStoreService
would be initialized when "
+ + "DataSource would be available (currently available:
nodes: {}, blobs: {})", dataSource, blobDataSource);
+ } else {
+ registerNodeStore();
+ }
}
}
@@ -763,7 +769,7 @@ public class DocumentNodeStoreService {
}
- private DocumentStoreType documentStoreType;
+ private volatile DocumentStoreType documentStoreType;
@Reference(name = "blobDataSource",
cardinality = ReferenceCardinality.OPTIONAL,
@@ -825,32 +831,34 @@ public class DocumentNodeStoreService {
}
private void unregisterNodeStore() {
- deactivationTimestamp = System.currentTimeMillis();
+ synchronized (registrationLock) {
+ deactivationTimestamp = System.currentTimeMillis();
- closeQuietly(closer);
+ closeQuietly(closer);
- if (nodeStoreReg != null) {
- nodeStoreReg.unregister();
- nodeStoreReg = null;
- }
+ if (nodeStoreReg != null) {
+ nodeStoreReg.unregister();
+ nodeStoreReg = null;
+ }
- //If we exposed our BlobStore then unregister it *after*
- //NodeStore service. This ensures that if any other component
- //like SecondaryStoreCache depends on this then it remains active
- //untill DocumentNodeStore get deactivated
- if (blobStoreReg != null){
- blobStoreReg.unregister();
- blobStoreReg = null;
- }
+ //If we exposed our BlobStore then unregister it *after*
+ //NodeStore service. This ensures that if any other component
+ //like SecondaryStoreCache depends on this then it remains active
+ //untill DocumentNodeStore get deactivated
+ if (blobStoreReg != null){
+ blobStoreReg.unregister();
+ blobStoreReg = null;
+ }
- if (nodeStore != null) {
- nodeStore.dispose();
- nodeStore = null;
- }
+ if (nodeStore != null) {
+ nodeStore.dispose();
+ nodeStore = null;
+ }
- if (executor != null) {
- executor.stop();
- executor = null;
+ if (executor != null) {
+ executor.stop();
+ executor = null;
+ }
}
}