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 ch...@apache.org on 2014/06/03 12:41:50 UTC
svn commit: r1599472 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/
oak-pojosr/ oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/
oak-pojosr/src/test/java/org/apache/jackrabbit/oak/run/osgi/
Author: chetanm
Date: Tue Jun 3 10:41:49 2014
New Revision: 1599472
URL: http://svn.apache.org/r1599472
Log:
OAK-1708 - extend DocumentNodeStoreService to support RDBPersistence
Added support for referencing the DataSource via OSGi service and also added relevant testcase in pojosr module
Added:
jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/DocumentNodeStoreConfigTest.groovy
jackrabbit/oak/trunk/oak-pojosr/src/test/java/org/apache/jackrabbit/oak/run/osgi/MongoUtils.java (with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
jackrabbit/oak/trunk/oak-pojosr/pom.xml
jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/AbstractRepositoryFactoryTest.groovy
jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/NodeStoreConfigTest.groovy
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java?rev=1599472&r1=1599471&r2=1599472&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java Tue Jun 3 10:41:49 2014
@@ -516,7 +516,9 @@ public class DocumentMK implements Micro
*/
public Builder setRDBConnection(DataSource ds) {
this.documentStore = new RDBDocumentStore(ds, this);
- this.blobStore = new RDBBlobStore(ds);
+ if(this.blobStore == null) {
+ this.blobStore = new RDBBlobStore(ds);
+ }
return this;
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java?rev=1599472&r1=1599471&r2=1599472&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java Tue Jun 3 10:41:49 2014
@@ -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;
@@ -30,6 +28,10 @@ import java.util.concurrent.TimeUnit;
import javax.sql.DataSource;
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientOptions;
+import com.mongodb.MongoClientURI;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
@@ -65,10 +67,11 @@ import org.osgi.service.component.Compon
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.mongodb.DB;
-import com.mongodb.MongoClient;
-import com.mongodb.MongoClientOptions;
-import com.mongodb.MongoClientURI;
+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.
@@ -118,8 +121,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;
@@ -130,6 +150,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;
@@ -155,39 +187,54 @@ public class DocumentNodeStoreService {
private static final long DEFAULT_MAX_REPLICATION_LAG = TimeUnit.HOURS.toSeconds(6);
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);
- this.customBlobStore = PropertiesUtil.toBoolean(prop(CUSTOM_BLOB_STORE), false);
+ 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 && customBlobStore) {
+ 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);
- boolean useMK = PropertiesUtil.toBoolean(context.getProperties().get(PROP_USE_MK), false);
+ 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);
+ boolean useMK = toBoolean(context.getProperties().get(PROP_USE_MK), false);
DocumentMK.Builder mkBuilder =
new DocumentMK.Builder().
@@ -195,7 +242,9 @@ public class DocumentNodeStoreService {
offHeapCacheSize(offHeapCache * MB);
//Set blobstore before setting the DB
- if (blobStore != null && customBlobStore) {
+ if (customBlobStore) {
+ checkNotNull(blobStore, "Use of custom BlobStore enabled via [%s] but blobStore reference not " +
+ "initialized", CUSTOM_BLOB_STORE);
mkBuilder.setBlobStore(blobStore);
}
@@ -234,6 +283,17 @@ public class DocumentNodeStoreService {
mkBuilder.setRDBConnection(ds, dsbs);
log.info("Connected to datasources {} {}", ds, dsbs);
}
+ } else 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);
@@ -286,8 +346,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
@@ -303,7 +363,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")
@@ -312,6 +372,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();
@@ -399,7 +483,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
Modified: jackrabbit/oak/trunk/oak-pojosr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-pojosr/pom.xml?rev=1599472&r1=1599471&r2=1599472&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-pojosr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-pojosr/pom.xml Tue Jun 3 10:41:49 2014
@@ -178,6 +178,23 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <version>${h2.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <version>4.3.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.gmongo</groupId>
+ <artifactId>gmongo</artifactId>
+ <version>1.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>${groovy.version}</version>
Modified: jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/AbstractRepositoryFactoryTest.groovy
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/AbstractRepositoryFactoryTest.groovy?rev=1599472&r1=1599471&r2=1599472&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/AbstractRepositoryFactoryTest.groovy (original)
+++ jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/AbstractRepositoryFactoryTest.groovy Tue Jun 3 10:41:49 2014
@@ -27,19 +27,18 @@ import org.junit.After
import org.junit.Before
import org.osgi.framework.ServiceReference
import org.osgi.service.cm.ConfigurationAdmin
+import org.osgi.util.tracker.ServiceTracker
-import javax.jcr.Repository
-import javax.jcr.RepositoryException
-import javax.jcr.RepositoryFactory
-import javax.jcr.Session
-import javax.jcr.SimpleCredentials
+import javax.jcr.*
+import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import static org.apache.jackrabbit.oak.run.osgi.OakOSGiRepositoryFactory.REPOSITORY_HOME
import static org.apache.jackrabbit.oak.run.osgi.OakOSGiRepositoryFactory.REPOSITORY_STARTUP_TIMEOUT
-abstract class AbstractRepositoryFactoryTest {
- static AtomicInteger counter = new AtomicInteger()
+abstract class AbstractRepositoryFactoryTest{
+ static final int SVC_WAIT_TIME = Integer.getInteger("pojosr.waitTime", 10)
+ static final AtomicInteger counter = new AtomicInteger()
Map config
File workDir
Repository repository
@@ -47,7 +46,7 @@ abstract class AbstractRepositoryFactory
@Before
void setUp() {
- workDir = new File("target", "repotest-${counter}-${System.currentTimeMillis()}");
+ workDir = new File("target", "repotest-${counter.incrementAndGet()}-${System.currentTimeMillis()}");
config = [
(REPOSITORY_HOME): workDir.absolutePath,
(REPOSITORY_STARTUP_TIMEOUT) : 2
@@ -76,6 +75,14 @@ abstract class AbstractRepositoryFactory
return (T) registry.getService(sr)
}
+ protected <T> T getServiceWithWait(Class<T> clazz) {
+ ServiceTracker st = new ServiceTracker(getRegistry().bundleContext, clazz.name, null)
+ st.open()
+ T sr = (T) st.waitForService(TimeUnit.SECONDS.toMillis(SVC_WAIT_TIME))
+ assert sr , "No service found for ${clazz.name}"
+ return sr
+ }
+
protected File getResource(String path){
File file = new File(FilenameUtils.concat(getBaseDir(), "src/test/resources/$path"))
assert file.exists() : "No file found at ${file.absolutePath}"
Added: jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/DocumentNodeStoreConfigTest.groovy
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/DocumentNodeStoreConfigTest.groovy?rev=1599472&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/DocumentNodeStoreConfigTest.groovy (added)
+++ jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/DocumentNodeStoreConfigTest.groovy Tue Jun 3 10:41:49 2014
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.run.osgi
+
+import de.kalpatec.pojosr.framework.launch.PojoServiceRegistry
+import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore
+import org.apache.jackrabbit.oak.plugins.document.util.MongoConnection
+import org.apache.jackrabbit.oak.spi.blob.BlobStore
+import org.apache.jackrabbit.oak.spi.blob.MemoryBlobStore
+import org.apache.jackrabbit.oak.spi.state.NodeStore
+import org.h2.jdbcx.JdbcDataSource
+import org.junit.After
+import org.junit.Test
+
+import javax.sql.DataSource
+import java.sql.Connection
+import java.sql.ResultSet
+
+import static org.junit.Assume.assumeNotNull
+
+class DocumentNodeStoreConfigTest extends AbstractRepositoryFactoryTest {
+ private PojoServiceRegistry registry
+ private MongoConnection mongoConn = MongoUtils.getConnection()
+
+ @Test
+ public void testRDBDocumentStore() throws Exception {
+ registry = repositoryFactory.initializeServiceRegistry(config)
+
+ //1. Register the DataSource as a service
+ DataSource ds = createDS("jdbc:h2:mem:testRDB;DB_CLOSE_DELAY=-1")
+ registry.registerService(DataSource.class.name, ds, ['datasource.name': 'oak'] as Hashtable)
+
+ //2. Create config for DocumentNodeStore with RDB enabled
+ createConfig([
+ 'org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService': [
+ documentStoreType: 'RDB'
+ ]
+ ])
+
+ DocumentNodeStore ns = getServiceWithWait(NodeStore.class)
+
+ //3. Check that DS contains tables from both RDBBlobStore and RDBDocumentStore
+ assert getExistingTables(ds).containsAll(['NODES', 'DATASTORE_META'])
+ }
+
+ @Test
+ public void testRDBDocumentStore_CustomBlobDataSource() throws Exception {
+ registry = repositoryFactory.initializeServiceRegistry(config)
+
+ //1. Register the DataSource as a service
+ DataSource ds1 = createDS("jdbc:h2:mem:testRDB1;DB_CLOSE_DELAY=-1")
+ registry.registerService(DataSource.class.name, ds1, ['datasource.name': 'oak'] as Hashtable)
+
+ //2. Create config for DocumentNodeStore with RDB enabled
+ createConfig([
+ 'org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService': [
+ documentStoreType : 'RDB',
+ customBlobDataSource : true,
+ 'blobDataSource.target': '(datasource.name=oak-blob)',
+ ]
+ ])
+
+ DataSource ds2 = createDS("jdbc:h2:mem:testRDB2;DB_CLOSE_DELAY=-1")
+ registry.registerService(DataSource.class.name, ds2, ['datasource.name': 'oak-blob'] as Hashtable)
+
+ DocumentNodeStore ns = getServiceWithWait(NodeStore.class)
+
+ //3. Check that DS contains tables from RDBBlobStore and RDBDocumentStore
+ //in there respective DataStores
+ List<String> ds1Tables = getExistingTables(ds1)
+ List<String> ds2Tables = getExistingTables(ds2)
+
+ //DS1 should contain RDBDocumentStore tables
+ assert ds1Tables.contains('NODES')
+ assert !ds1Tables.contains('DATASTORE_META')
+
+ //DS2 should contain only RDBBlobStore tables
+ assert !ds2Tables.contains('NODES')
+ assert ds2Tables.contains('DATASTORE_META')
+ }
+
+ @Test
+ public void testRDBDocumentStore_CustomBlobStore() throws Exception {
+ registry = repositoryFactory.initializeServiceRegistry(config)
+
+ //1. Register the DataSource as a service
+ DataSource ds = createDS("jdbc:h2:mem:testRDB3;DB_CLOSE_DELAY=-1")
+ registry.registerService(DataSource.class.name, ds, ['datasource.name': 'oak'] as Hashtable)
+
+ //2. Create config for DocumentNodeStore with RDB enabled
+ createConfig([
+ 'org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService': [
+ documentStoreType: 'RDB',
+ customBlobStore : true
+ ]
+ ])
+
+ registry.registerService(BlobStore.class.name, new MemoryBlobStore(), null)
+
+ DocumentNodeStore ns = getServiceWithWait(NodeStore.class)
+
+ //3. Check that DS contains tables only from both RDBDocumentStore
+ List<String> dsTables = getExistingTables(ds)
+
+ //DS1 should contain RDBDocumentStore tables
+ assert dsTables.contains('NODES')
+ assert !dsTables.contains('DATASTORE_META')
+ }
+
+ @Test
+ public void testMongoDocumentStore_CustomBlobStore() throws Exception {
+ assumeNotNull(mongoConn)
+
+ registry = repositoryFactory.initializeServiceRegistry(config)
+ createConfig([
+ 'org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService': [
+ mongouri : MongoUtils.mongoURI,
+ db : MongoUtils.mongoDB,
+ customBlobStore: true
+ ]
+ ])
+
+ registry.registerService(BlobStore.class.name, new MemoryBlobStore(), null)
+
+ DocumentNodeStore ns = getServiceWithWait(NodeStore.class)
+
+ Collection<String> colNames = getCollectionNames()
+ assert colNames.containsAll(['NODES'])
+ assert !colNames.contains(['BLOBS'])
+ }
+
+ @Test
+ public void testMongoDocumentStore() throws Exception {
+ assumeNotNull(mongoConn)
+
+ registry = repositoryFactory.initializeServiceRegistry(config)
+ createConfig([
+ 'org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService': [
+ mongouri: MongoUtils.mongoURI,
+ db : MongoUtils.mongoDB
+ ]
+ ])
+
+ DocumentNodeStore ns = getServiceWithWait(NodeStore.class)
+
+ Collection<String> colNames = getCollectionNames()
+ assert colNames.containsAll(['NODES', "BLOBS"])
+ }
+
+ @Override
+ protected PojoServiceRegistry getRegistry() {
+ return registry
+ }
+
+ @After
+ public void tearDown() {
+ if (mongoConn) {
+ MongoUtils.dropCollections(mongoConn.DB)
+ }
+ }
+
+ private Collection<String> getCollectionNames() {
+ return mongoConn.DB.getCollectionNames().collect { it.toUpperCase() }
+ }
+
+ private List<String> getExistingTables(DataSource ds) {
+ Connection con = ds.connection
+ List<String> existing = []
+ try {
+ ResultSet rs = con.metaData.getTables(null, null, "%", null)
+ while (rs.next()) {
+ existing << rs.toRowResult()['TABLE_NAME'].toUpperCase()
+ }
+ } finally {
+ con.close()
+ }
+ return existing
+ }
+
+ private DataSource createDS(String url) {
+ DataSource ds = new JdbcDataSource()
+ ds.url = url
+ return ds
+ }
+}
Modified: jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/NodeStoreConfigTest.groovy
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/NodeStoreConfigTest.groovy?rev=1599472&r1=1599471&r2=1599472&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/NodeStoreConfigTest.groovy (original)
+++ jackrabbit/oak/trunk/oak-pojosr/src/test/groovy/org/apache/jackrabbit/oak/run/osgi/NodeStoreConfigTest.groovy Tue Jun 3 10:41:49 2014
@@ -26,9 +26,6 @@ import org.apache.jackrabbit.oak.spi.blo
import org.apache.jackrabbit.oak.spi.blob.MemoryBlobStore
import org.apache.jackrabbit.oak.spi.state.NodeStore
import org.junit.Test
-import org.osgi.util.tracker.ServiceTracker
-
-import java.util.concurrent.TimeUnit
class NodeStoreConfigTest extends AbstractRepositoryFactoryTest{
private PojoServiceRegistry registry
@@ -41,10 +38,7 @@ class NodeStoreConfigTest extends Abstr
'org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStoreService' : [:]
])
- ServiceTracker st = new ServiceTracker(registry.bundleContext, NodeStore.class.name, null)
- st.open()
-
- SegmentNodeStoreService ns = st.waitForService(TimeUnit.SECONDS.toMillis(10)) as SegmentNodeStoreService
+ SegmentNodeStoreService ns = getServiceWithWait(NodeStore.class)
//NodeStore is of type SegmentNodeStoreService
SegmentStore segStore = ns.getSegmentStore()
assert segStore.blobStore == null , "BlobStore should not be picked up unless 'customBlobStore " +
Added: jackrabbit/oak/trunk/oak-pojosr/src/test/java/org/apache/jackrabbit/oak/run/osgi/MongoUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-pojosr/src/test/java/org/apache/jackrabbit/oak/run/osgi/MongoUtils.java?rev=1599472&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-pojosr/src/test/java/org/apache/jackrabbit/oak/run/osgi/MongoUtils.java (added)
+++ jackrabbit/oak/trunk/oak-pojosr/src/test/java/org/apache/jackrabbit/oak/run/osgi/MongoUtils.java Tue Jun 3 10:41:49 2014
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.oak.run.osgi;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DB;
+import org.apache.jackrabbit.oak.plugins.document.util.MongoConnection;
+
+/**
+ * A utility class to get a {@link MongoConnection} to a local mongo instance
+ * and clean a test database.
+ */
+public class MongoUtils {
+
+ protected static final String HOST =
+ System.getProperty("mongo.host", "127.0.0.1");
+
+ protected static final int PORT =
+ Integer.getInteger("mongo.port", 27017);
+
+ protected static final String DB =
+ System.getProperty("mongo.db", "MongoMKDB");
+
+ protected static Exception exception;
+
+ /**
+ * Get a connection if available. If not available, null is returned.
+ *
+ * @return the connection or null
+ */
+ public static MongoConnection getConnection() {
+ return getConnection(DB);
+ }
+
+ public static String getMongoURI(){
+ return String.format("mongodb://%s:%s", HOST, PORT);
+ }
+
+ public static String getMongoDB(){
+ return DB;
+ }
+
+ /**
+ * Get a connection if available. If not available, null is returned.
+ *
+ * @param dbName the database name
+ * @return the connection or null
+ */
+ public static MongoConnection getConnection(String dbName) {
+ if (exception != null) {
+ return null;
+ }
+ MongoConnection mongoConnection = null;
+ try {
+ mongoConnection = new MongoConnection(HOST, PORT, dbName);
+ mongoConnection.getDB().command(new BasicDBObject("ping", 1));
+ // dropCollections(mongoConnection.getDB());
+ } catch (Exception e) {
+ exception = e;
+ mongoConnection = null;
+ }
+ return mongoConnection;
+ }
+
+ /**
+ * Drop all user defined collections. System collections are not dropped.
+ *
+ * @param db the connection
+ */
+ public static void dropCollections(DB db) {
+ for (String name : db.getCollectionNames()) {
+ if (!name.startsWith("system.")) {
+ db.getCollection(name).drop();
+ }
+ }
+ }
+
+}
Propchange: jackrabbit/oak/trunk/oak-pojosr/src/test/java/org/apache/jackrabbit/oak/run/osgi/MongoUtils.java
------------------------------------------------------------------------------
svn:eol-style = native