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;
+            }
         }
     }
 

Reply via email to