diff --git oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java index 5574a0a..77abf78 100644 --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java @@ -16,6 +16,7 @@ */ package org.apache.jackrabbit.oak.plugins.segment; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static java.util.Collections.emptyMap; import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toBoolean; @@ -87,6 +88,9 @@ import org.osgi.service.component.ComponentContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + /** * An OSGi wrapper for the segment node store. */ @@ -263,44 +267,97 @@ public class SegmentNodeStoreService extends ProxyNodeStore ) public static final String PROP_BLOB_GC_MAX_AGE = "blobGcMaxAgeInSecs"; + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + @Override - protected synchronized SegmentNodeStore getNodeStore() { - checkState(delegate != null, "service must be activated when used"); - return delegate; + protected SegmentNodeStore getNodeStore() { + lock.readLock().lock(); + + try { + return checkNotNull(delegate, "service must be activated when used"); + } finally { + lock.readLock().unlock(); + } + } @Activate private void activate(ComponentContext context) throws IOException { + lock.writeLock().lock(); + + try { + safeActivate(context); + } finally { + lock.writeLock().unlock(); + } + } + + @Deactivate + private void deactivate() { + lock.writeLock().lock(); + + try { + safeDeactivate(); + } finally { + lock.writeLock().unlock(); + } + } + + protected void bindBlobStore(BlobStore blobStore) throws IOException { + lock.writeLock().lock(); + + try { + safeBindBlobStore(blobStore); + } finally { + lock.writeLock().unlock(); + } + } + + protected void unbindBlobStore(BlobStore blobStore) { + lock.writeLock().lock(); + + try { + safeUnbindBlobStore(blobStore); + } finally { + lock.writeLock().unlock(); + } + } + + private void safeActivate(ComponentContext context) throws IOException { this.context = context; this.customBlobStore = Boolean.parseBoolean(lookup(context, CUSTOM_BLOB_STORE)); - if (blobStore == null && customBlobStore) { - log.info("BlobStore use enabled. SegmentNodeStore would be initialized when BlobStore would be available"); - } else { - registerNodeStore(); - } + registerNodeStore(); } - public void registerNodeStore() throws IOException { - if (registerSegmentStore()) { - boolean standby = toBoolean(lookup(context, STANDBY), false); - providerRegistration = context.getBundleContext().registerService( - SegmentStoreProvider.class.getName(), this, null); - if (!standby) { - Dictionary props = new Hashtable(); - props.put(Constants.SERVICE_PID, SegmentNodeStore.class.getName()); - props.put("oak.nodestore.description", new String[]{"nodeStoreType=segment"}); - storeRegistration = context.getBundleContext().registerService( - NodeStore.class.getName(), this, props); - } + private void safeDeactivate() { + unregisterNodeStore(); + } + + private void safeBindBlobStore(BlobStore blobStore) throws IOException { + unregisterNodeStore(); + this.blobStore = blobStore; + registerNodeStore(); + } + + private void safeUnbindBlobStore(BlobStore blobStore) { + if (this.blobStore == blobStore) { + unregisterNodeStore(); + this.blobStore = null; } } - public synchronized boolean registerSegmentStore() throws IOException { + private void registerNodeStore() throws IOException { if (context == null) { log.info("Component still not activated. Ignoring the initialization call"); - return false; + return; } + + if (blobStore == null && customBlobStore) { + log.info("BlobStore use enabled. SegmentNodeStore would be initialized when BlobStore would be available"); + return; + } + Dictionary properties = context.getProperties(); name = String.valueOf(properties.get(NAME)); @@ -440,79 +497,86 @@ public class SegmentNodeStoreService extends ProxyNodeStore "Segment node store compaction strategy settings"); log.info("SegmentNodeStore initialized"); - return true; - } - private static String lookup(ComponentContext context, String property) { - if (context.getProperties().get(property) != null) { - return context.getProperties().get(property).toString(); - } - if (context.getBundleContext().getProperty(property) != null) { - return context.getBundleContext().getProperty(property); + boolean standby = toBoolean(lookup(context, STANDBY), false); + providerRegistration = context.getBundleContext().registerService( + SegmentStoreProvider.class.getName(), this, null); + if (!standby) { + Dictionary props = new Hashtable(); + props.put(Constants.SERVICE_PID, SegmentNodeStore.class.getName()); + props.put("oak.nodestore.description", new String[]{"nodeStoreType=segment"}); + storeRegistration = context.getBundleContext().registerService( + NodeStore.class.getName(), this, props); } - return null; } - @Deactivate - public synchronized void deactivate() { - unregisterNodeStore(); - - if (observerTracker != null) { - observerTracker.stop(); - } - if (gcMonitor != null) { - gcMonitor.stop(); - } - delegate = null; - if (store != null) { - store.close(); - store = null; + private void unregisterNodeStore() { + if (storeRegistration != null) { + storeRegistration.unregister(); + storeRegistration = null; } - } - protected void bindBlobStore(BlobStore blobStore) throws IOException { - this.blobStore = blobStore; - registerNodeStore(); - } - - protected void unbindBlobStore(BlobStore blobStore){ - this.blobStore = null; - unregisterNodeStore(); - } - - private void unregisterNodeStore() { - if(providerRegistration != null){ + if (providerRegistration != null) { providerRegistration.unregister(); providerRegistration = null; } - if(storeRegistration != null){ - storeRegistration.unregister(); - storeRegistration = null; + + if (compactionStrategyRegistration != null) { + compactionStrategyRegistration.unregister(); + compactionStrategyRegistration = null; } - if (checkpointRegistration != null) { - checkpointRegistration.unregister(); - checkpointRegistration = null; + + if (blobGCRegistration != null) { + blobGCRegistration.unregister(); + blobGCRegistration = null; } + if (revisionGCRegistration != null) { revisionGCRegistration.unregister(); revisionGCRegistration = null; } - if (blobGCRegistration != null) { - blobGCRegistration.unregister(); - blobGCRegistration = null; + + if (checkpointRegistration != null) { + checkpointRegistration.unregister(); + checkpointRegistration = null; } - if (compactionStrategyRegistration != null) { - compactionStrategyRegistration.unregister(); - compactionStrategyRegistration = null; + + if (executor != null) { + executor.stop(); + executor = null; } + + if (observerTracker != null) { + observerTracker.stop(); + observerTracker = null; + } + if (fsgcMonitorMBean != null) { fsgcMonitorMBean.unregister(); fsgcMonitorMBean = null; } - if (executor != null) { - executor.stop(); - executor = null; + + delegate = null; + + if (store != null) { + store.close(); + store = null; } + + if (gcMonitor != null) { + gcMonitor.stop(); + gcMonitor = null; + } + } + + private static String lookup(ComponentContext context, String property) { + if (context.getProperties().get(property) != null) { + return context.getProperties().get(property).toString(); + } + if (context.getBundleContext().getProperty(property) != null) { + return context.getBundleContext().getProperty(property); + } + return null; } /** @@ -521,7 +585,13 @@ public class SegmentNodeStoreService extends ProxyNodeStore */ @Override public SegmentStore getSegmentStore() { - return store; + lock.readLock().lock(); + + try { + return checkNotNull(store, "Segment store not activated"); + } finally { + lock.readLock().unlock(); + } } //------------------------------------------------------------< Observable >---