Author: reschke
Date: Mon Feb 16 16:20:05 2015
New Revision: 1660153

URL: http://svn.apache.org/r1660153
Log:
OAK-2506 - port RDB support back to Oak 1.0

Part 3: add support in DocumentNodeStoreService (back-ports OAK-1708)

Modified:
    
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java

Modified: 
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java?rev=1660153&r1=1660152&r2=1660153&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
 (original)
+++ 
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
 Mon Feb 16 16:20:05 2015
@@ -18,8 +18,6 @@
  */
 package org.apache.jackrabbit.oak.plugins.document;
 
-import static 
org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
-
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Dictionary;
@@ -28,6 +26,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
+import javax.sql.DataSource;
+
 import com.mongodb.DB;
 import com.mongodb.MongoClient;
 import com.mongodb.MongoClientOptions;
@@ -65,6 +65,12 @@ import org.osgi.service.component.Compon
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toBoolean;
+import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toInteger;
+import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toLong;
+import static 
org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
+
 /**
  * The OSGi service to start/stop a DocumentNodeStore instance.
  */
@@ -121,8 +127,25 @@ public class DocumentNodeStoreService {
      */
     public static final String CUSTOM_BLOB_STORE = "customBlobStore";
 
+    /**
+     * Boolean value indicating a different DataSource has to be used for
+     * BlobStore
+     */
+    public static final String CUSTOM_BLOB_DATA_SOURCE = 
"customBlobDataSource";
+
     private static final long MB = 1024 * 1024;
 
+    private static enum DocumentStoreType {
+        MONGO, RDB;
+
+        static DocumentStoreType fromString(String type) {
+            if (type == null) {
+                return MONGO;
+            }
+            return valueOf(type.toUpperCase());
+        }
+    }
+
     private final Logger log = LoggerFactory.getLogger(this.getClass());
 
     private ServiceRegistration reg;
@@ -133,6 +156,18 @@ public class DocumentNodeStoreService {
             policy = ReferencePolicy.DYNAMIC)
     private volatile BlobStore blobStore;
 
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY,
+            policy = ReferencePolicy.DYNAMIC,
+            target = "(datasource.name=oak)"
+    )
+    private volatile DataSource dataSource;
+
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY,
+            policy = ReferencePolicy.DYNAMIC,
+            target = "(datasource.name=oak)"
+    )
+    private volatile DataSource blobDataSource;
+
     private DocumentMK mk;
     private ObserverTracker observerTracker;
     private ComponentContext context;
@@ -159,78 +194,104 @@ public class DocumentNodeStoreService {
     public static final String PROP_REPLICATION_LAG = 
"maxReplicationLagInSecs";
     private long maxReplicationLagInSecs = DEFAULT_MAX_REPLICATION_LAG;
 
+    /**
+     * Specifies the type of DocumentStore MONGO, RDB
+     */
+    public static final String PROP_DS_TYPE = "documentStoreType";
+    private DocumentStoreType documentStoreType;
+
+    private boolean customBlobStore;
+    private boolean customBlobDataSource;
+
     @Activate
     protected void activate(ComponentContext context, Map<String, ?> config) 
throws Exception {
         this.context = context;
-        this.whiteboard = new OsgiWhiteboard(context.getBundleContext());
-        this.executor = new WhiteboardExecutor();
+        whiteboard = new OsgiWhiteboard(context.getBundleContext());
+        executor = new WhiteboardExecutor();
         executor.start(whiteboard);
-        this.maxReplicationLagInSecs = 
PropertiesUtil.toLong(config.get(PROP_REPLICATION_LAG),
-                DEFAULT_MAX_REPLICATION_LAG);
+        maxReplicationLagInSecs = toLong(config.get(PROP_REPLICATION_LAG), 
DEFAULT_MAX_REPLICATION_LAG);
+        customBlobStore = toBoolean(prop(CUSTOM_BLOB_STORE), false);
+        customBlobDataSource = toBoolean(prop(CUSTOM_BLOB_DATA_SOURCE), false);
+        documentStoreType = 
DocumentStoreType.fromString(PropertiesUtil.toString(config.get(PROP_DS_TYPE), 
"MONGO"));
+
+        modified(config);
+        registerNodeStoreIfPossible();
+    }
 
-        if (blobStore == null &&
-                PropertiesUtil.toBoolean(prop(CUSTOM_BLOB_STORE), false)) {
+    private void registerNodeStoreIfPossible() throws IOException {
+        if (context == null) {
+            log.info("Component still not activated. Ignoring the 
initialization call");
+        } else if (customBlobStore && blobStore == null) {
             log.info("BlobStore use enabled. DocumentNodeStoreService would be 
initialized when "
                     + "BlobStore would be available");
+        } else if (documentStoreType == DocumentStoreType.RDB
+                && (dataSource == null || (customBlobDataSource && 
blobDataSource == null))) {
+            log.info("DataSource use enabled. DocumentNodeStoreService would 
be initialized when "
+                    + "DataSource would be available");
         } else {
             registerNodeStore();
         }
-        modified(config);
     }
 
-    protected void registerNodeStore() throws IOException {
-        if (context == null) {
-            log.info("Component still not activated. Ignoring the 
initialization call");
-            return;
-        }
+    private void registerNodeStore() throws IOException {
         String uri = PropertiesUtil.toString(prop(PROP_URI, FWK_PROP_URI), 
DEFAULT_URI);
         String db = PropertiesUtil.toString(prop(PROP_DB, FWK_PROP_DB), 
DEFAULT_DB);
 
-        int offHeapCache = PropertiesUtil.toInteger(prop(PROP_OFF_HEAP_CACHE), 
DEFAULT_OFF_HEAP_CACHE);
-        int cacheSize = PropertiesUtil.toInteger(prop(PROP_CACHE), 
DEFAULT_CACHE);
-        int changesSize = PropertiesUtil.toInteger(prop(PROP_CHANGES_SIZE), 
DEFAULT_CHANGES_SIZE);
-        int blobCacheSize = 
PropertiesUtil.toInteger(prop(PROP_BLOB_CACHE_SIZE), DEFAULT_BLOB_CACHE_SIZE);
-        String persistentCache = 
PropertiesUtil.toString(prop(PROP_PERSISTENT_CACHE), DEFAULT_PERSISTENT_CACHE);
-        boolean useMK = 
PropertiesUtil.toBoolean(context.getProperties().get(PROP_USE_MK), false);
-
-
-        MongoClientOptions.Builder builder = 
MongoConnection.getDefaultBuilder();
-        MongoClientURI mongoURI = new MongoClientURI(uri, builder);
-
-        if (log.isInfoEnabled()) {
-            // Take care around not logging the uri directly as it
-            // might contain passwords
-            String type = useMK ? "MK" : "NodeStore";
-            log.info("Starting Document{} with host={}, db={}, cache size 
(MB)={}, Off Heap Cache size (MB)={}, " +
-                            "'changes' collection size (MB)={}, blobCacheSize 
(MB)={}, maxReplicationLagInSecs={}",
-                    type, mongoURI.getHosts(), db, cacheSize, offHeapCache, 
changesSize, blobCacheSize, maxReplicationLagInSecs);
-            log.info("Mongo Connection details {}", 
MongoConnection.toString(mongoURI.getOptions()));
-        }
-
-        MongoClient client = new MongoClient(mongoURI);
-        DB mongoDB = client.getDB(db);
+        int offHeapCache = toInteger(prop(PROP_OFF_HEAP_CACHE), 
DEFAULT_OFF_HEAP_CACHE);
+        int cacheSize = toInteger(prop(PROP_CACHE), DEFAULT_CACHE);
+        int changesSize = toInteger(prop(PROP_CHANGES_SIZE), 
DEFAULT_CHANGES_SIZE);
+        int blobCacheSize = toInteger(prop(PROP_BLOB_CACHE_SIZE), 
DEFAULT_BLOB_CACHE_SIZE);
+        boolean useMK = toBoolean(context.getProperties().get(PROP_USE_MK), 
false);
 
         DocumentMK.Builder mkBuilder =
                 new DocumentMK.Builder().
                 memoryCacheSize(cacheSize * MB).
                 offHeapCacheSize(offHeapCache * MB);
-        
-        if (persistentCache != null && persistentCache.length() > 0) {
-            mkBuilder.setPersistentCache(persistentCache);
-        }
 
         //Set blobstore before setting the DB
-        if (blobStore != null) {
+        if (customBlobStore) {
+            checkNotNull(blobStore, "Use of custom BlobStore enabled via  [%s] 
but blobStore reference not " +
+                    "initialized", CUSTOM_BLOB_STORE);
             mkBuilder.setBlobStore(blobStore);
         }
 
-        mkBuilder.setMaxReplicationLag(maxReplicationLagInSecs, 
TimeUnit.SECONDS);
-        mkBuilder.setMongoDB(mongoDB, changesSize, blobCacheSize);
+        if (documentStoreType == DocumentStoreType.RDB){
+            checkNotNull(dataSource, "DataStore type set [%s] but DataSource 
reference not initialized", PROP_DS_TYPE);
+            if(customBlobDataSource){
+                checkNotNull(blobDataSource, "DataStore type set [%s] and 
BlobStore is configured to use different " +
+                        "DataSource via [%s] but BlobDataSource reference not 
initialized", PROP_DS_TYPE, CUSTOM_BLOB_DATA_SOURCE);
+                mkBuilder.setRDBConnection(dataSource, blobDataSource);
+                log.info("Connected to datasources {} {}", dataSource, 
blobDataSource);
+            } else {
+                mkBuilder.setRDBConnection(dataSource);
+                log.info("Connected to datasource {}", dataSource);
+            }
+        } else {
+            MongoClientOptions.Builder builder = 
MongoConnection.getDefaultBuilder();
+            MongoClientURI mongoURI = new MongoClientURI(uri, builder);
+
+            if (log.isInfoEnabled()) {
+                // Take care around not logging the uri directly as it
+                // might contain passwords
+                String type = useMK ? "MK" : "NodeStore";
+                log.info("Starting Document{} with host={}, db={}, cache size 
(MB)={}, Off Heap Cache size (MB)={}, " +
+                                "'changes' collection size (MB)={}, 
blobCacheSize (MB)={}, maxReplicationLagInSecs={}",
+                        type, mongoURI.getHosts(), db, cacheSize, 
offHeapCache, changesSize, blobCacheSize, maxReplicationLagInSecs);
+                log.info("Mongo Connection details {}", 
MongoConnection.toString(mongoURI.getOptions()));
+            }
+
+            MongoClient client = new MongoClient(mongoURI);
+            DB mongoDB = client.getDB(db);
+
+            mkBuilder.setMaxReplicationLag(maxReplicationLagInSecs, 
TimeUnit.SECONDS);
+            mkBuilder.setMongoDB(mongoDB, changesSize, blobCacheSize);
+
+            log.info("Connected to database {}", mongoDB);
+        }
+
         mkBuilder.setExecutor(executor);
         mk = mkBuilder.open();
 
-        log.info("Connected to database {}", mongoDB);
-
         registerJMXBeans(mk.getNodeStore());
         registerLastRevRecoveryJob(mk.getNodeStore());
 
@@ -257,8 +318,8 @@ public class DocumentNodeStoreService {
      */
     @Modified
     protected void modified(Map<String, ?> config){
-        versionGcMaxAgeInSecs = 
PropertiesUtil.toLong(config.get(PROP_VER_GC_MAX_AGE), DEFAULT_VER_GC_MAX_AGE);
-        blobGcMaxAgeInSecs = 
PropertiesUtil.toLong(config.get(PROP_BLOB_GC_MAX_AGE), 
DEFAULT_BLOB_GC_MAX_AGE);
+        versionGcMaxAgeInSecs = toLong(config.get(PROP_VER_GC_MAX_AGE), 
DEFAULT_VER_GC_MAX_AGE);
+        blobGcMaxAgeInSecs = toLong(config.get(PROP_BLOB_GC_MAX_AGE), 
DEFAULT_BLOB_GC_MAX_AGE);
     }
 
     @Deactivate
@@ -274,7 +335,7 @@ public class DocumentNodeStoreService {
     protected void bindBlobStore(BlobStore blobStore) throws IOException {
         log.info("Initializing DocumentNodeStore with BlobStore [{}]", 
blobStore);
         this.blobStore = blobStore;
-        registerNodeStore();
+        registerNodeStoreIfPossible();
     }
 
     @SuppressWarnings("UnusedDeclaration")
@@ -283,6 +344,30 @@ public class DocumentNodeStoreService {
         unregisterNodeStore();
     }
 
+    @SuppressWarnings("UnusedDeclaration")
+    protected void bindDataSource(DataSource dataSource) throws IOException {
+        this.dataSource = dataSource;
+        registerNodeStoreIfPossible();
+    }
+
+    @SuppressWarnings("UnusedDeclaration")
+    protected void unbindDataSource(DataSource dataSource) {
+        this.dataSource = null;
+        unregisterNodeStore();
+    }
+
+    @SuppressWarnings("UnusedDeclaration")
+    protected void bindBlobDataSource(DataSource dataSource) throws 
IOException {
+        this.blobDataSource = dataSource;
+        registerNodeStoreIfPossible();
+    }
+
+    @SuppressWarnings("UnusedDeclaration")
+    protected void unbindBlobDataSource(DataSource dataSource) {
+        this.blobDataSource = null;
+        unregisterNodeStore();
+    }
+
     private void unregisterNodeStore() {
         for (Registration r : registrations) {
             r.unregister();
@@ -323,15 +408,6 @@ public class DocumentNodeStoreService {
                         CacheStatsMBean.TYPE,
                         store.getDocChildrenCacheStats().getName())
         );
-
-        registrations.add(
-                registerMBean(whiteboard,
-                        DocumentNodeStoreMBean.class,
-                        store.getMBean(),
-                        DocumentNodeStoreMBean.TYPE,
-                        "Document node store management")
-        );
-
         DiffCache cl = store.getDiffCache();
         if (cl instanceof MemoryDiffCache) {
             MemoryDiffCache mcl = (MemoryDiffCache) cl;
@@ -341,7 +417,6 @@ public class DocumentNodeStoreService {
                             mcl.getDiffCacheStats(),
                             CacheStatsMBean.TYPE,
                             mcl.getDiffCacheStats().getName()));
-            
         }
 
         DocumentStore ds = store.getDocumentStore();
@@ -379,7 +454,7 @@ public class DocumentNodeStoreService {
     }
 
     private void registerLastRevRecoveryJob(final DocumentNodeStore nodeStore) 
{
-        long leaseTime = 
PropertiesUtil.toLong(context.getProperties().get(PROP_REV_RECOVERY_INTERVAL),
+        long leaseTime = 
toLong(context.getProperties().get(PROP_REV_RECOVERY_INTERVAL),
                 ClusterNodeInfo.DEFAULT_LEASE_DURATION_MILLIS);
         Runnable recoverJob = new Runnable() {
             @Override


Reply via email to