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 fr...@apache.org on 2016/12/14 13:08:01 UTC

svn commit: r1774209 - /jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java

Author: frm
Date: Wed Dec 14 13:08:01 2016
New Revision: 1774209

URL: http://svn.apache.org/viewvc?rev=1774209&view=rev
Log:
OAK-4978 - Expose maintainence related MBeans for Segment NodeStores created via factory

Disable change dispatching unless registering the primary SegmentNodeStore.
Don't setup the cluster ID on a SharedDataStore unless registering the primary
SegmentNodeStore. Include a 'role' registration property to most of the
registered services and MBeans. Print more detailed log messages based on the
role of the SegmentNodeStore.

Modified:
    jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java

Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java?rev=1774209&r1=1774208&r2=1774209&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java Wed Dec 14 13:08:01 2016
@@ -23,6 +23,8 @@ import static org.apache.jackrabbit.oak.
 import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toInteger;
 import static org.apache.jackrabbit.oak.commons.PropertiesUtil.toLong;
 import static org.apache.jackrabbit.oak.osgi.OsgiUtil.lookupConfigurationThenFramework;
+import static org.apache.jackrabbit.oak.plugins.blob.datastore.SharedDataStoreUtils.isShared;
+import static org.apache.jackrabbit.oak.plugins.identifier.ClusterRepositoryInfo.getOrCreateId;
 import static org.apache.jackrabbit.oak.segment.CachingSegmentReader.DEFAULT_STRING_CACHE_MB;
 import static org.apache.jackrabbit.oak.segment.CachingSegmentReader.DEFAULT_TEMPLATE_CACHE_MB;
 import static org.apache.jackrabbit.oak.segment.SegmentCache.DEFAULT_SEGMENT_CACHE_MB;
@@ -58,6 +60,7 @@ import javax.annotation.Nullable;
 
 import com.google.common.base.Strings;
 import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import com.google.common.io.Closer;
 import org.apache.felix.scr.annotations.Activate;
@@ -86,7 +89,6 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector;
 import org.apache.jackrabbit.oak.plugins.blob.SharedDataStore;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.BlobIdTracker;
-import org.apache.jackrabbit.oak.plugins.blob.datastore.SharedDataStoreUtils;
 import org.apache.jackrabbit.oak.plugins.blob.datastore.SharedDataStoreUtils.SharedStoreRecordType;
 import org.apache.jackrabbit.oak.plugins.identifier.ClusterRepositoryInfo;
 import org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions;
@@ -107,6 +109,7 @@ import org.apache.jackrabbit.oak.spi.sta
 import org.apache.jackrabbit.oak.spi.whiteboard.AbstractServiceTracker;
 import org.apache.jackrabbit.oak.spi.whiteboard.CompositeRegistration;
 import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
 import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardExecutor;
 import org.apache.jackrabbit.oak.stats.Clock;
 import org.apache.jackrabbit.oak.stats.StatisticsProvider;
@@ -420,7 +423,8 @@ public class SegmentNodeStoreService {
                 CacheStatsMBean.class,
                 segmentCacheStats,
                 CacheStats.TYPE,
-                appendRole(segmentCacheStats.getName(), role)
+                appendRole(segmentCacheStats.getName(), role),
+                withRole(properties(), role)
         ));
 
         // Expose stats about the string and template caches
@@ -430,7 +434,8 @@ public class SegmentNodeStoreService {
                 whiteboard,
                 CacheStatsMBean.class,
                 stringCacheStats, CacheStats.TYPE,
-                appendRole(stringCacheStats.getName(), role)
+                appendRole(stringCacheStats.getName(), role),
+                withRole(properties(), role)
         ));
 
         CacheStatsMBean templateCacheStats = store.getTemplateCacheStats();
@@ -438,7 +443,8 @@ public class SegmentNodeStoreService {
                 whiteboard,
                 CacheStatsMBean.class,
                 templateCacheStats, CacheStats.TYPE,
-                appendRole(templateCacheStats.getName(), role)
+                appendRole(templateCacheStats.getName(), role),
+                withRole(properties(), role)
         ));
 
         CacheStatsMBean stringDeduplicationCacheStats = store.getStringDeduplicationCacheStats();
@@ -447,7 +453,9 @@ public class SegmentNodeStoreService {
                     whiteboard,
                     CacheStatsMBean.class,
                     stringDeduplicationCacheStats, CacheStats.TYPE,
-                    appendRole(stringDeduplicationCacheStats.getName(), role)));
+                    appendRole(stringDeduplicationCacheStats.getName(), role),
+                    withRole(properties(), role)
+            ));
         }
 
         CacheStatsMBean templateDeduplicationCacheStats = store.getTemplateDeduplicationCacheStats();
@@ -456,7 +464,9 @@ public class SegmentNodeStoreService {
                     whiteboard,
                     CacheStatsMBean.class,
                     templateDeduplicationCacheStats, CacheStats.TYPE,
-                    appendRole(templateDeduplicationCacheStats.getName(), role)));
+                    appendRole(templateDeduplicationCacheStats.getName(), role),
+                    withRole(properties(), role)
+            ));
         }
 
         CacheStatsMBean nodeDeduplicationCacheStats = store.getNodeDeduplicationCacheStats();
@@ -465,7 +475,9 @@ public class SegmentNodeStoreService {
                     whiteboard,
                     CacheStatsMBean.class,
                     nodeDeduplicationCacheStats, CacheStats.TYPE,
-                    appendRole(nodeDeduplicationCacheStats.getName(), role)));
+                    appendRole(nodeDeduplicationCacheStats.getName(), role),
+                    withRole(properties(), role)
+            ));
         }
 
         // Expose an MBean to managing and monitoring garbage collection
@@ -478,7 +490,8 @@ public class SegmentNodeStoreService {
                         SegmentRevisionGC.class,
                         new SegmentRevisionGCMBean(store, gcOptions, fsgcm),
                         SegmentRevisionGC.TYPE,
-                        appendRole("Segment node store revision garbage collection", role)
+                        appendRole("Segment node store revision garbage collection", role),
+                        withRole(properties(), role)
                 )));
 
         Runnable cancelGC = new Runnable() {
@@ -500,7 +513,8 @@ public class SegmentNodeStoreService {
                 RevisionGCMBean.class,
                 new RevisionGC(store.getGCRunner(), cancelGC, statusMessage, executor),
                 RevisionGCMBean.TYPE,
-                appendRole("Revision garbage collection", role)
+                appendRole("Revision garbage collection", role),
+                withRole(properties(), role)
         ));
 
         // Expose statistics about the FileStore
@@ -510,95 +524,94 @@ public class SegmentNodeStoreService {
                 FileStoreStatsMBean.class,
                 store.getStats(),
                 FileStoreStatsMBean.TYPE,
-                appendRole("FileStore statistics", role)
+                appendRole("FileStore statistics", role),
+                withRole(properties(), role)
         ));
 
         // register segment node store
 
-        SegmentNodeStore.SegmentNodeStoreBuilder segmentNodeStoreBuilder =
-                SegmentNodeStoreBuilders.builder(store)
+        SegmentNodeStore.SegmentNodeStoreBuilder segmentNodeStoreBuilder = SegmentNodeStoreBuilders.builder(store)
                         .withStatisticsProvider(statisticsProvider);
-        if (isStandbyInstance(context)) {
+        if (isStandbyInstance(context) || !isPrimarySegmentStore(role)) {
             segmentNodeStoreBuilder.dispatchChanges(false);
         }
         SegmentNodeStore segmentNodeStore = segmentNodeStoreBuilder.build();
 
-        ObserverTracker observerTracker = new ObserverTracker(segmentNodeStore);
-        observerTracker.start(context.getBundleContext());
-        registrations.register(asCloseable(observerTracker));
+        if (isPrimarySegmentStore(role)) {
+            ObserverTracker observerTracker = new ObserverTracker(segmentNodeStore);
+            observerTracker.start(context.getBundleContext());
+            registrations.register(asCloseable(observerTracker));
+        }
 
-        mbeans.add(registerMBean(
-                whiteboard,
-                CheckpointMBean.class,
-                new SegmentCheckpointMBean(segmentNodeStore), CheckpointMBean.TYPE,
-                appendRole("Segment node store checkpoint management", role)));
+        if (isPrimarySegmentStore(role)) {
+            mbeans.add(registerMBean(
+                    whiteboard,
+                    CheckpointMBean.class,
+                    new SegmentCheckpointMBean(segmentNodeStore), CheckpointMBean.TYPE,
+                    "Segment node store checkpoint management"
+            ));
+        }
 
         if (descriptors) {
             // ensure a clusterId is initialized
             // and expose it as 'oak.clusterid' repository descriptor
             GenericDescriptors clusterIdDesc = new GenericDescriptors();
-            clusterIdDesc.put(ClusterRepositoryInfo.OAK_CLUSTERID_REPOSITORY_DESCRIPTOR_KEY,
-                    new SimpleValueFactory().createValue(
-                            ClusterRepositoryInfo.getOrCreateId(segmentNodeStore)), true, false);
+            clusterIdDesc.put(
+                    ClusterRepositoryInfo.OAK_CLUSTERID_REPOSITORY_DESCRIPTOR_KEY,
+                    new SimpleValueFactory().createValue(getOrCreateId(segmentNodeStore)),
+                    true,
+                    false
+            );
             mbeans.add(whiteboard.register(
                     Descriptors.class,
                     clusterIdDesc,
-                    Collections.emptyMap()
+                    withRole(properties(), role)
             ));
 
             // Register "discovery lite" descriptors
             mbeans.add(whiteboard.register(
                     Descriptors.class,
                     new SegmentDiscoveryLiteDescriptors(segmentNodeStore),
-                    Collections.emptyMap()
+                    withRole(properties(), role)
             ));
         }
 
         // If a shared data store register the repo id in the data store
-        String repoId = "";
-        if (SharedDataStoreUtils.isShared(blobStore)) {
+        if (isPrimarySegmentStore(role) && isShared(blobStore)) {
+            SharedDataStore sharedDataStore = (SharedDataStore) blobStore;
             try {
-                repoId = ClusterRepositoryInfo.getOrCreateId(segmentNodeStore);
-                ((SharedDataStore) blobStore).addMetadataRecord(new ByteArrayInputStream(new byte[0]),
-                        SharedStoreRecordType.REPOSITORY.getNameFromId(repoId));
+                sharedDataStore.addMetadataRecord(new ByteArrayInputStream(new byte[0]), SharedStoreRecordType.REPOSITORY.getNameFromId(getOrCreateId(segmentNodeStore)));
             } catch (Exception e) {
                 throw new IOException("Could not register a unique repositoryId", e);
             }
-
             if (blobStore instanceof BlobTrackingStore) {
-                final long trackSnapshotInterval = toLong(property(PROP_BLOB_SNAPSHOT_INTERVAL, context),
-                        DEFAULT_BLOB_SNAPSHOT_INTERVAL);
+                long trackSnapshotInterval = toLong(property(PROP_BLOB_SNAPSHOT_INTERVAL, context), DEFAULT_BLOB_SNAPSHOT_INTERVAL);
                 String root = property(DIRECTORY, context);
                 if (Strings.isNullOrEmpty(root)) {
                     root = "repository";
                 }
-
                 BlobTrackingStore trackingStore = (BlobTrackingStore) blobStore;
                 if (trackingStore.getTracker() != null) {
                     trackingStore.getTracker().close();
                 }
-                ((BlobTrackingStore) blobStore).addTracker(
-                        new BlobIdTracker(root, repoId, trackSnapshotInterval, (SharedDataStore)
-                                blobStore));
+                trackingStore.addTracker(new BlobIdTracker(root, getOrCreateId(segmentNodeStore), trackSnapshotInterval, sharedDataStore));
             }
         }
 
-        if (store.getBlobStore() instanceof GarbageCollectableBlobStore) {
-            final long blobGcMaxAgeInSecs = toLong(property(PROP_BLOB_GC_MAX_AGE, context), DEFAULT_BLOB_GC_MAX_AGE);
+        if (isPrimarySegmentStore(role) && isGarbageCollectable(blobStore)) {
             BlobGarbageCollector gc = new MarkSweepGarbageCollector(
                     new SegmentBlobReferenceRetriever(store),
-                    (GarbageCollectableBlobStore) store.getBlobStore(),
+                    (GarbageCollectableBlobStore) blobStore,
                     executor,
-                    TimeUnit.SECONDS.toMillis(blobGcMaxAgeInSecs),
-                    repoId
+                    TimeUnit.SECONDS.toMillis(getBlobGcMaxAge(context)),
+                    getOrCreateId(segmentNodeStore)
             );
-
             mbeans.add(registerMBean(
                     whiteboard,
                     BlobGCMBean.class,
                     new BlobGC(gc, executor),
                     BlobGCMBean.TYPE,
-                    appendRole("Segment node store blob garbage collection", role)
+                    "Segment node store blob garbage collection"
             ));
         }
 
@@ -607,10 +620,16 @@ public class SegmentNodeStoreService {
         mbeans.add(registerMBean(
                 whiteboard,
                 FileStoreBackupRestoreMBean.class,
-                new FileStoreBackupRestoreImpl(segmentNodeStore, store.getRevisions(), store.getReader(),
-                        getBackupDirectory(context, role), executor),
+                new FileStoreBackupRestoreImpl(
+                        segmentNodeStore,
+                        store.getRevisions(),
+                        store.getReader(),
+                        getBackupDirectory(context, role),
+                        executor
+                ),
                 FileStoreBackupRestoreMBean.TYPE,
-                appendRole("Segment node store backup/restore", role)
+                appendRole("Segment node store backup/restore", role),
+                withRole(properties(), role)
         ));
 
         // Expose statistics about the SegmentNodeStore
@@ -620,17 +639,21 @@ public class SegmentNodeStoreService {
                 SegmentNodeStoreStatsMBean.class,
                 segmentNodeStore.getStats(),
                 SegmentNodeStoreStatsMBean.TYPE,
-                appendRole("SegmentNodeStore statistics", role)
+                appendRole("SegmentNodeStore statistics", role),
+                withRole(properties(), role)
         ));
 
-        log.info("SegmentNodeStore initialized");
+        if (isPrimarySegmentStore(role)) {
+            log.info("Primary SegmentNodeStore initialized");
+        } else {
+            log.info("Secondary SegmentNodeStore initialized, role={}", role);
+        }
 
         // Register a factory service to expose the FileStore
-
         registrations.register(asCloseable(whiteboard.register(
                 SegmentStoreProvider.class,
                 new DefaultSegmentStoreProvider(store),
-                Collections.emptyMap()
+                withRole(properties(), role)
         )));
 
         registrations.register(asCloseable(new CompositeRegistration(mbeans)));
@@ -639,10 +662,12 @@ public class SegmentNodeStoreService {
             return segmentNodeStore;
         }
 
-        Map<String, Object> props = new HashMap<String, Object>();
-        props.put(Constants.SERVICE_PID, SegmentNodeStore.class.getName());
-        props.put("oak.nodestore.description", new String[] {"nodeStoreType=segment"});
-        registrations.register(asCloseable(whiteboard.register(NodeStore.class, segmentNodeStore, props)));
+        if (isPrimarySegmentStore(role)) {
+            Map<String, Object> props = new HashMap<String, Object>();
+            props.put(Constants.SERVICE_PID, SegmentNodeStore.class.getName());
+            props.put("oak.nodestore.description", new String[] {"nodeStoreType=segment"});
+            registrations.register(asCloseable(whiteboard.register(NodeStore.class, segmentNodeStore, props)));
+        }
 
         return segmentNodeStore;
     }
@@ -655,6 +680,21 @@ public class SegmentNodeStoreService {
         }
     }
 
+    private static Map<String, String> properties() {
+        return new HashMap<>();
+    }
+
+    private static Map<String, String> withRole(Map<String, String> map, String role) {
+        if (role != null) {
+            map.put("role", role);
+        }
+        return map;
+    }
+
+    private static boolean isGarbageCollectable(BlobStore store) {
+        return store instanceof GarbageCollectableBlobStore;
+    }
+
     private static SegmentGCOptions newGCOptions(ComponentContext context) {
         boolean pauseCompaction = toBoolean(property(PAUSE_COMPACTION, context), PAUSE_DEFAULT);
         int retryCount = toInteger(property(COMPACTION_RETRY_COUNT, context), RETRY_COUNT_DEFAULT);
@@ -729,6 +769,10 @@ public class SegmentNodeStoreService {
         return System.getProperty(propertyName);
     }
 
+    private static long getBlobGcMaxAge(ComponentContext context) {
+        return toLong(property(PROP_BLOB_GC_MAX_AGE, context), DEFAULT_BLOB_GC_MAX_AGE);
+    }
+
     private static int getSegmentCacheSize(ComponentContext context) {
         return toInteger(getCacheSize(SEGMENT_CACHE_SIZE, context), DEFAULT_SEGMENT_CACHE_MB);
     }
@@ -779,6 +823,7 @@ public class SegmentNodeStoreService {
             public void close() {
                 r.unregister();
             }
+
         };
     }
 
@@ -789,6 +834,7 @@ public class SegmentNodeStoreService {
             public void close() {
                 t.stop();
             }
+
         };
     }
 
@@ -799,7 +845,12 @@ public class SegmentNodeStoreService {
             public void close() {
                 t.stop();
             }
+
         };
     }
 
+    private static boolean isPrimarySegmentStore(String role) {
+        return role == null;
+    }
+
 }