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 2018/07/13 13:23:24 UTC
svn commit: r1835837 [1/3] - in /jackrabbit/oak/trunk:
oak-it/src/test/java/org/apache/jackrabbit/oak/segment/ oak-segment-tar/
oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/
oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/seg...
Author: frm
Date: Fri Jul 13 13:23:24 2018
New Revision: 1835837
URL: http://svn.apache.org/viewvc?rev=1835837&view=rev
Log:
OAK-6770 - Convert oak-segment-tar to OSGi R6 annotations
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreRegistrar.java (with props)
Removed:
jackrabbit/oak/trunk/oak-segment-tar/src/main/resources/OSGI-INF/l10n/metatype.properties
Modified:
jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCachingDataStoreStatsTest.java
jackrabbit/oak/trunk/oak-segment-tar/pom.xml
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreMonitorService.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreServiceDeprecationError.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/osgi/StandbyStoreServiceDeprecationError.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/store/StandbyStoreService.java
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactoryTest.java
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/ComponentDescriptor.java
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreFactoryTest.java
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreMonitorServiceTest.java
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/SegmentNodeStoreServiceTest.java
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/osgi/StandbyStoreServiceTest.java
Modified: jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCachingDataStoreStatsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCachingDataStoreStatsTest.java?rev=1835837&r1=1835836&r2=1835837&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCachingDataStoreStatsTest.java (original)
+++ jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/segment/SegmentCachingDataStoreStatsTest.java Fri Jul 13 13:23:24 2018
@@ -18,6 +18,14 @@
*/
package org.apache.jackrabbit.oak.segment;
+import static com.google.common.collect.Maps.newHashMap;
+import static org.apache.jackrabbit.oak.segment.SegmentNodeStoreService.CUSTOM_BLOB_STORE;
+import static org.apache.jackrabbit.oak.segment.SegmentNodeStoreService.REPOSITORY_HOME_DIRECTORY;
+import static org.apache.sling.testing.mock.osgi.MockOsgi.deactivate;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+
import java.io.File;
import java.util.Map;
@@ -30,21 +38,12 @@ import org.apache.jackrabbit.oak.stats.S
import org.apache.sling.testing.mock.osgi.ReferenceViolationException;
import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.osgi.framework.ServiceRegistration;
-import static com.google.common.collect.Maps.newHashMap;
-import static org.apache.jackrabbit.oak.segment.SegmentNodeStoreService.CUSTOM_BLOB_STORE;
-import static org.apache.jackrabbit.oak.segment.SegmentNodeStoreService.REPOSITORY_HOME_DIRECTORY;
-import static org.apache.sling.testing.mock.osgi.MockOsgi.deactivate;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.mockito.Mockito.mock;
-
/**
* Tests the registration of the {@link ConsolidatedDataStoreCacheStatsMBean}.
*/
Modified: jackrabbit/oak/trunk/oak-segment-tar/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/pom.xml?rev=1835837&r1=1835836&r2=1835837&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/pom.xml Fri Jul 13 13:23:24 2018
@@ -253,8 +253,13 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.scr.annotations</artifactId>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.component.annotations</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.metatype.annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java?rev=1835837&r1=1835836&r2=1835837&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java Fri Jul 13 13:23:24 2018
@@ -16,40 +16,60 @@
*/
package org.apache.jackrabbit.oak.segment;
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.apache.jackrabbit.oak.commons.IOUtils.closeQuietly;
import static org.apache.jackrabbit.oak.osgi.OsgiUtil.lookupConfigurationThenFramework;
+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;
+import static org.apache.jackrabbit.oak.segment.WriterCacheManager.DEFAULT_NODE_CACHE_SIZE_OSGi;
+import static org.apache.jackrabbit.oak.segment.WriterCacheManager.DEFAULT_STRING_CACHE_SIZE_OSGi;
+import static org.apache.jackrabbit.oak.segment.WriterCacheManager.DEFAULT_TEMPLATE_CACHE_SIZE_OSGi;
+import static org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.DISABLE_ESTIMATION_DEFAULT;
+import static org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.FORCE_TIMEOUT_DEFAULT;
+import static org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.GC_PROGRESS_LOG_DEFAULT;
+import static org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.MEMORY_THRESHOLD_DEFAULT;
+import static org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.PAUSE_DEFAULT;
+import static org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.RETAINED_GENERATIONS_DEFAULT;
+import static org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.RETRY_COUNT_DEFAULT;
+import static org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.SIZE_DELTA_ESTIMATION_DEFAULT;
+import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.DEFAULT_MAX_FILE_SIZE;
import static org.apache.jackrabbit.oak.spi.blob.osgi.SplitBlobStoreService.ONLY_STANDALONE_TARGET;
import java.io.Closeable;
+import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import com.google.common.io.Closer;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.ConfigurationPolicy;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
-import org.apache.felix.scr.annotations.ReferencePolicyOption;
import org.apache.jackrabbit.api.stats.RepositoryStatistics;
import org.apache.jackrabbit.api.stats.TimeSeries;
-import org.apache.jackrabbit.oak.commons.IOUtils;
import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentNodeStorePersistence;
import org.apache.jackrabbit.oak.spi.blob.BlobStore;
-import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.apache.jackrabbit.oak.spi.state.NodeStoreProvider;
import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
import org.apache.jackrabbit.oak.stats.CounterStats;
import org.apache.jackrabbit.oak.stats.HistogramStats;
import org.apache.jackrabbit.oak.stats.MeterStats;
import org.apache.jackrabbit.oak.stats.StatisticsProvider;
import org.apache.jackrabbit.oak.stats.StatsOptions;
import org.apache.jackrabbit.oak.stats.TimerStats;
+import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ConfigurationPolicy;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,111 +78,272 @@ import org.slf4j.LoggerFactory;
* <p>
* The different secondaries are distinguished by their role attribute.
*/
-@Component(policy = ConfigurationPolicy.REQUIRE,
- name="org.apache.jackrabbit.oak.segment.SegmentNodeStoreFactory",
- configurationFactory=true,
- metatype = true,
- label = "Apache Jackrabbit Oak Segment-Tar NodeStore Factory",
- description = "Factory allowing configuration of adjacent instances of " +
- "NodeStore implementation based on Segment model besides a default SegmentNodeStore in same setup."
+@Component(
+ configurationPolicy = ConfigurationPolicy.REQUIRE,
+ factory = "org.apache.jackrabbit.oak.segment.SegmentNodeStoreFactory"
)
+@Designate(factory = true, ocd = SegmentNodeStoreFactory.Configuration.class)
public class SegmentNodeStoreFactory {
- @Property(
- label = "Role",
- description="As multiple SegmentNodeStores can be configured, this parameter defines the role " +
- "of 'this' SegmentNodeStore."
- )
- public static final String ROLE = "role";
+ private final Logger log = LoggerFactory.getLogger(getClass());
- @Property(boolValue = false,
- label = "Custom BlobStore",
- description = "Boolean value indicating that a custom BlobStore is to be used. " +
- "By default large binary content would be stored within segment tar files"
- )
- public static final String CUSTOM_BLOB_STORE = "customBlobStore";
+ private static final long DEFAULT_BLOB_SNAPSHOT_INTERVAL = 12 * 60 * 60;
- @Property(boolValue = false,
- label = "Custom segment store",
- description = "Boolean value indicating that a custom (non-tar) segment store is used"
+ private static final long DEFAULT_BLOB_GC_MAX_AGE = 24 * 60 * 60;
+
+ @ObjectClassDefinition(
+ name = "Apache Jackrabbit Oak Segment-Tar NodeStore Factory",
+ description = "Factory allowing configuration of adjacent instances of " +
+ "NodeStore implementation based on Segment model besides a default SegmentNodeStore in same setup."
)
- public static final String CUSTOM_SEGMENT_STORE = "customSegmentStore";
+ @interface Configuration {
- @Property(boolValue = false,
- label = "Register JCR descriptors as OSGi services",
- description="Should only be done for one factory instance")
- public static final String REGISTER_DESCRIPTORS = "registerDescriptors";
+ @AttributeDefinition(
+ name = "Repository Home Directory",
+ description = "Path on the file system where repository data will be stored. "
+ + "Defaults to the value of the framework property 'repository.home' or to 'repository' "
+ + "if that is neither specified."
+ )
+ String repository_home() default "repository";
+
+ @AttributeDefinition(
+ name = "Mode",
+ description = "TarMK mode (64 for memory mapped file access, 32 for normal file access). " +
+ "Default value is taken from the 'sun.arch.data.model' system property."
+ )
+ String tarmk_mode() default "";
+
+ @AttributeDefinition(
+ name = "Maximum tar file size (MB)",
+ description = "The maximum size of the tar files in megabytes. " +
+ "Default value is '" + DEFAULT_MAX_FILE_SIZE + "'."
+ )
+ int tarmk_size() default DEFAULT_MAX_FILE_SIZE;
+
+ @AttributeDefinition(
+ name = "Segment cache size (MB)",
+ description = "Cache size for storing most recently used segments in megabytes. " +
+ "Default value is '" + DEFAULT_SEGMENT_CACHE_MB + "'."
+ )
+ int segmentCache_size() default DEFAULT_SEGMENT_CACHE_MB;
+
+ @AttributeDefinition(
+ name = "String cache size (MB)",
+ description = "Cache size for storing most recently used strings in megabytes. " +
+ "Default value is '" + DEFAULT_STRING_CACHE_MB + "'."
+ )
+ int stringCache_size() default DEFAULT_STRING_CACHE_MB;
+
+ @AttributeDefinition(
+ name = "Template cache size (MB)",
+ description = "Cache size for storing most recently used templates in megabytes. " +
+ "Default value is '" + DEFAULT_TEMPLATE_CACHE_MB + "'."
+ )
+ int templateCache_size() default DEFAULT_TEMPLATE_CACHE_MB;
+
+ @AttributeDefinition(
+ name = "String deduplication cache size (#items)",
+ description = "Maximum number of strings to keep in the deduplication cache. " +
+ "Default value is '" + DEFAULT_STRING_CACHE_SIZE_OSGi + "'."
+ )
+ int stringDeduplicationCache_size() default DEFAULT_STRING_CACHE_SIZE_OSGi;
+
+ @AttributeDefinition(
+ name = "Template deduplication cache size (#items)",
+ description = "Maximum number of templates to keep in the deduplication cache. " +
+ "Default value is '" + DEFAULT_TEMPLATE_CACHE_SIZE_OSGi + "'."
+ )
+ int templateDeduplicationCache_size() default DEFAULT_TEMPLATE_CACHE_SIZE_OSGi;
+
+ @AttributeDefinition(
+ name = "Node deduplication cache size (#items)",
+ description = "Maximum number of node to keep in the deduplication cache. If the supplied " +
+ "value is not a power of 2, it will be rounded up to the next power of 2. " +
+ "Default value is '" + DEFAULT_NODE_CACHE_SIZE_OSGi + "'."
+ )
+ int nodeDeduplicationCache_size() default DEFAULT_NODE_CACHE_SIZE_OSGi;
+
+ @AttributeDefinition(
+ name = "Pause compaction",
+ description = "When set to true the compaction phase is skipped during garbage collection. " +
+ "Default value is '" + PAUSE_DEFAULT + "'."
+ )
+ boolean pauseCompaction() default PAUSE_DEFAULT;
+
+ @AttributeDefinition(
+ name = "Compaction retries",
+ description = "Number of tries to compact concurrent commits on top of already " +
+ "compacted commits. " +
+ "Default value is '" + RETRY_COUNT_DEFAULT + "'."
+ )
+ int compaction_retryCount() default RETRY_COUNT_DEFAULT;
+
+ @AttributeDefinition(
+ name = "Force compaction timeout",
+ description = "Number of seconds to attempt to force compact concurrent commits on top " +
+ "of already compacted commits after the maximum number of retries has been " +
+ "reached. Forced compaction tries to acquire an exclusive write lock on the " +
+ "node store, blocking concurrent write access as long as the lock is held. " +
+ "Default value is '" + FORCE_TIMEOUT_DEFAULT + "'."
+ )
+ int compaction_force_timeout() default FORCE_TIMEOUT_DEFAULT;
+
+ @AttributeDefinition(
+ name = "Garbage collection repository size threshold",
+ description = "Garbage collection will be skipped unless the repository grew at least by " +
+ "the number of bytes specified. " +
+ "Default value is '" + SIZE_DELTA_ESTIMATION_DEFAULT + "'."
+ )
+ long compaction_sizeDeltaEstimation() default SIZE_DELTA_ESTIMATION_DEFAULT;
+
+ @AttributeDefinition(
+ name = "Disable estimation phase",
+ description = "Disables the estimation phase allowing garbage collection to run unconditionally. " +
+ "Default value is '" + DISABLE_ESTIMATION_DEFAULT + "'."
+ )
+ boolean compaction_disableEstimation() default DISABLE_ESTIMATION_DEFAULT;
+
+ @AttributeDefinition(
+ name = "Compaction retained generations",
+ description = "Number of segment generations to retain during garbage collection. " +
+ "The number of generations defaults to " + RETAINED_GENERATIONS_DEFAULT + " and " +
+ "can't be changed. This configuration option is considered deprecated " +
+ "and will be removed in the future."
+ )
+ int compaction_retainedGenerations() default RETAINED_GENERATIONS_DEFAULT;
+
+ @AttributeDefinition(
+ name = "Compaction memory threshold",
+ description = "Threshold of available heap memory in percent of total heap memory below " +
+ "which the compaction phase is canceled. 0 disables heap memory monitoring. " +
+ "Default value is '" + MEMORY_THRESHOLD_DEFAULT + "'."
+ )
+ int compaction_memoryThreshold() default MEMORY_THRESHOLD_DEFAULT;
+
+ @AttributeDefinition(
+ name = "Compaction progress log",
+ description = "The number of nodes compacted after which a status message is logged. " +
+ "-1 disables progress logging. " +
+ "Default value is '" + GC_PROGRESS_LOG_DEFAULT + "'."
+ )
+ long compaction_progressLog() default GC_PROGRESS_LOG_DEFAULT;
+
+ @AttributeDefinition(
+ name = "Standby mode",
+ description = "Flag indicating this component will not register as a NodeStore but as a " +
+ "NodeStoreProvider instead. " +
+ "Default value is 'false'."
+ )
+ boolean standby() default false;
+
+ @AttributeDefinition(
+ name = "Custom blob store",
+ description = "Boolean value indicating that a custom BlobStore is used for storing " +
+ "large binary values."
+ )
+ boolean customBlobStore() default false;
- private final Logger log = LoggerFactory.getLogger(getClass());
+ @AttributeDefinition(
+ name = "Custom segment store",
+ description = "Boolean value indicating that a custom (non-tar) segment store is used"
+ )
+ boolean customSegmentStore() default false;
+
+ @AttributeDefinition(
+ name = "Backup directory",
+ description = "Directory (relative to current working directory) for storing repository backups. " +
+ "Defaults to 'repository.home/segmentstore-backup'."
+ )
+ String repository_backup_dir() default "";
+
+ @AttributeDefinition(
+ name = "Blob gc max age (in secs)",
+ description = "The blob garbage collection logic will only consider those blobs which " +
+ "are not accessed recently (currentTime - lastModifiedTime > blobGcMaxAgeInSecs). " +
+ "For example with the default setting only those blobs which have been created " +
+ "at least 24 hours ago will be considered for garbage collection. " +
+ "Default value is '" + DEFAULT_BLOB_GC_MAX_AGE + "'."
+ )
+ long blobGcMaxAgeInSecs() default DEFAULT_BLOB_GC_MAX_AGE;
+
+ @AttributeDefinition(
+ name = "Blob tracking snapshot interval",
+ description = "Interval in seconds in which snapshots of locally tracked blob ids are " +
+ "taken and synchronized with the blob store. This should be configured to be " +
+ "less than the frequency of blob garbage collection so that deletions during blob " +
+ "garbage collection can be accounted for in the next garbage collection execution. " +
+ "Default value is '" + DEFAULT_BLOB_SNAPSHOT_INTERVAL + "'."
+ )
+ long blobTrackSnapshotIntervalInSecs() default DEFAULT_BLOB_SNAPSHOT_INTERVAL;
+
+ @AttributeDefinition(
+ name = "Role",
+ description = "As multiple SegmentNodeStores can be configured, this parameter defines the role " +
+ "of 'this' SegmentNodeStore."
+ )
+ String role() default "";
+
+ @AttributeDefinition(
+ name = "Register JCR descriptors as OSGi services",
+ description = "Should only be done for one factory instance"
+ )
+ boolean registerDescriptors() default false;
+ }
@Reference(
- cardinality = ReferenceCardinality.OPTIONAL_UNARY,
- policy = ReferencePolicy.STATIC,
- policyOption = ReferencePolicyOption.GREEDY,
- target = ONLY_STANDALONE_TARGET
+ cardinality = ReferenceCardinality.OPTIONAL,
+ policy = ReferencePolicy.STATIC,
+ policyOption = ReferencePolicyOption.GREEDY,
+ target = ONLY_STANDALONE_TARGET
)
private volatile BlobStore blobStore;
@Reference(
- cardinality = ReferenceCardinality.OPTIONAL_UNARY,
- policy = ReferencePolicy.STATIC,
- policyOption = ReferencePolicyOption.GREEDY
+ cardinality = ReferenceCardinality.OPTIONAL,
+ policy = ReferencePolicy.STATIC,
+ policyOption = ReferencePolicyOption.GREEDY
)
private volatile SegmentNodeStorePersistence segmentStore;
@Reference
private StatisticsProvider statisticsProvider = StatisticsProvider.NOOP;
- private Closer registrations = Closer.create();
+ private final Closer registrations = Closer.create();
@Activate
- public void activate(ComponentContext context) throws IOException {
- String role = property(ROLE, context);
- // In secondaryNodeStore mode customBlobStore is always enabled
- boolean isSecondaryStoreMode = "secondary".equals(role);
- boolean customBlobStore = Boolean.parseBoolean(property(CUSTOM_BLOB_STORE, context)) || isSecondaryStoreMode;
- boolean customSegmentStore = Boolean.parseBoolean(property(CUSTOM_SEGMENT_STORE, context));
- boolean registerRepositoryDescriptors = Boolean.parseBoolean(property(REGISTER_DESCRIPTORS, context));
- log.info("activate: SegmentNodeStore '" + role + "' starting.");
+ public void activate(ComponentContext context, Configuration configuration) throws IOException {
+ log.info("activate: SegmentNodeStore '" + configuration.role() + "' starting.");
- if (blobStore == null && customBlobStore) {
- log.info("BlobStore use enabled. SegmentNodeStore would be initialized when BlobStore would be available");
+ if (configuration.role().isEmpty()) {
return;
}
- if (segmentStore == null && customSegmentStore) {
- log.info("customSegmentStore enabled. SegmentNodeStore will be initialized once the custom segment store becomes available");
+ OsgiWhiteboard whiteboard = new OsgiWhiteboard(context.getBundleContext());
+ SegmentNodeStore store = registerSegmentStore(
+ context,
+ configuration,
+ blobStore,
+ segmentStore,
+ getRoleStatisticsProvider(statisticsProvider, configuration.role()),
+ registrations,
+ whiteboard,
+ configuration.role(),
+ log
+ );
+
+ if (store == null) {
return;
}
- if (role != null) {
- registrations = Closer.create();
- OsgiWhiteboard whiteboard = new OsgiWhiteboard(context.getBundleContext());
- final SegmentNodeStore store = SegmentNodeStoreService.registerSegmentStore(context, blobStore, segmentStore,
- getRoleStatisticsProvider(statisticsProvider, role), registrations, whiteboard, role, registerRepositoryDescriptors);
- if (store != null) {
- Map<String, Object> props = new HashMap<String, Object>();
- props.put(NodeStoreProvider.ROLE, role);
-
- registrations
- .register(asCloseable(whiteboard.register(NodeStoreProvider.class, new NodeStoreProvider() {
-
- @Override
- public NodeStore getNodeStore() {
- return store;
- }
- }, props)));
- log.info("Registered NodeStoreProvider backed by SegmentNodeStore of type '{}'", role);
- }
- }
+ Map<String, Object> props = new HashMap<String, Object>();
+ props.put(NodeStoreProvider.ROLE, configuration.role());
+ registrations.register(asCloseable(whiteboard.register(NodeStoreProvider.class, () -> store, props)));
+ log.info("Registered NodeStoreProvider backed by SegmentNodeStore of type '{}'", configuration.role());
}
@Deactivate
public void deactivate() {
- if (registrations != null) {
- IOUtils.closeQuietly(registrations);
- registrations = null;
- }
+ closeQuietly(registrations);
}
private static Closeable asCloseable(final Registration r) {
@@ -180,20 +361,246 @@ public class SegmentNodeStoreFactory {
return lookupConfigurationThenFramework(context, name);
}
- private static StatisticsProvider getRoleStatisticsProvider(StatisticsProvider delegate, String role) {
- RepositoryStatistics repositoryStatistics = new RepositoryStatistics() {
- @Override
- public TimeSeries getTimeSeries(Type type) {
- return getTimeSeries(type.name(), type.isResetValueEachSecond());
+ private static SegmentNodeStore registerSegmentStore(
+ ComponentContext context,
+ Configuration configuration,
+ BlobStore blobStore,
+ SegmentNodeStorePersistence segmentStore,
+ StatisticsProvider statisticsProvider,
+ Closer closer,
+ Whiteboard whiteboard,
+ String role,
+ Logger logger
+ ) throws IOException {
+ return SegmentNodeStoreRegistrar.registerSegmentNodeStore(new SegmentNodeStoreRegistrar.Configuration() {
+
+ String appendRole(String name) {
+ return name + "-" + role;
+ }
+
+ int roundToNextPowerOfTwo(int size) {
+ return 1 << (32 - Integer.numberOfLeadingZeros(Math.max(0, size - 1)));
+ }
+
+ String getMode() {
+ String mode = configuration.tarmk_mode();
+ if (isNullOrEmpty(mode)) {
+ return System.getProperty("tarmk.mode", System.getProperty("sun.arch.data.model", "32"));
}
+ return mode;
+ }
- @Override
- public TimeSeries getTimeSeries(String type, boolean resetValueEachSecond) {
- return delegate.getStats().getTimeSeries(addRoleToName(type, role), resetValueEachSecond);
+ int getCacheSize(String name, int otherwise) {
+ Integer size = Integer.getInteger(name);
+ if (size != null) {
+ return size;
}
+ return otherwise;
+ }
+
+ @Override
+ public boolean isPrimarySegmentStore() {
+ return false;
+ }
+
+ @Override
+ public boolean isSecondarySegmentStore() {
+ return "secondary".equals(role);
+ }
+
+ @Override
+ public boolean isStandbyInstance() {
+ return configuration.standby();
+ }
+
+ @Override
+ public String getRole() {
+ return role;
+ }
+
+ @Override
+ public int getRetainedGenerations() {
+ return configuration.compaction_retainedGenerations();
+ }
+
+ @Override
+ public int getDefaultRetainedGenerations() {
+ return RETAINED_GENERATIONS_DEFAULT;
+ }
+
+ @Override
+ public boolean getPauseCompaction() {
+ return configuration.pauseCompaction();
+ }
+
+ @Override
+ public int getRetryCount() {
+ return configuration.compaction_retryCount();
+ }
+
+ @Override
+ public int getForceCompactionTimeout() {
+ return configuration.compaction_force_timeout();
+ }
+
+ @Override
+ public long getSizeDeltaEstimation() {
+ return configuration.compaction_sizeDeltaEstimation();
+ }
+
+ @Override
+ public int getMemoryThreshold() {
+ return configuration.compaction_memoryThreshold();
+ }
+
+ @Override
+ public boolean getDisableEstimation() {
+ return configuration.compaction_disableEstimation();
+ }
+
+ @Override
+ public long getGCProcessLog() {
+ return configuration.compaction_progressLog();
+ }
+
+ @Override
+ public File getSegmentDirectory() {
+ return new File(getRepositoryHome(), appendRole("segmentstore"));
+ }
+
+ @Override
+ public int getSegmentCacheSize() {
+ return getCacheSize("segmentCache.size", configuration.segmentCache_size());
+ }
+
+ @Override
+ public int getStringCacheSize() {
+ return getCacheSize("stringCache.size", configuration.stringCache_size());
+ }
+
+ @Override
+ public int getTemplateCacheSize() {
+ return getCacheSize("templateCache.size", configuration.templateCache_size());
+ }
+
+ @Override
+ public int getStringDeduplicationCacheSize() {
+ return getCacheSize("stringDeduplicationCache.size", configuration.stringDeduplicationCache_size());
+ }
+
+ @Override
+ public int getTemplateDeduplicationCacheSize() {
+ return getCacheSize("templateDeduplicationCache.size", configuration.templateDeduplicationCache_size());
+ }
+
+ @Override
+ public int getNodeDeduplicationCacheSize() {
+ return roundToNextPowerOfTwo(getCacheSize("nodeDeduplicationCache.size", configuration.nodeDeduplicationCache_size()));
+ }
+
+ @Override
+ public int getMaxFileSize() {
+ return configuration.tarmk_size();
+ }
+
+ @Override
+ public boolean getMemoryMapping() {
+ return getMode().equals("64");
+ }
+
+ @Override
+ public boolean hasCustomBlobStore() {
+ return configuration.customBlobStore();
+ }
+
+ @Override
+ public boolean hasCustomSegmentStore() {
+ return configuration.customSegmentStore();
+ }
+
+ @Override
+ public boolean registerDescriptors() {
+ return configuration.registerDescriptors();
+ }
+
+ @Override
+ public String getRepositoryHome() {
+ return configuration.repository_home();
+ }
+
+ @Override
+ public long getBlobSnapshotInterval() {
+ return configuration.blobTrackSnapshotIntervalInSecs();
+ }
+
+ @Override
+ public long getBlobGcMaxAge() {
+ return configuration.blobGcMaxAgeInSecs();
+ }
+
+ @Override
+ public File getBackupDirectory() {
+ String backupDirectory = configuration.repository_backup_dir();
+ if (isNullOrEmpty(backupDirectory)) {
+ return new File(getRepositoryHome(), appendRole("segmentstore-backup"));
+ }
+ return new File(backupDirectory);
+ }
+
+ @Override
+ public Whiteboard getWhiteboard() {
+ return whiteboard;
+ }
+
+ @Override
+ public Closer getCloser() {
+ return closer;
+ }
+
+ @Override
+ public Logger getLogger() {
+ return logger;
+ }
+
+ @Override
+ public StatisticsProvider getStatisticsProvider() {
+ return statisticsProvider;
+ }
+
+ @Override
+ public BlobStore getBlobStore() {
+ return blobStore;
+ }
+
+ @Override
+ public SegmentNodeStorePersistence getSegmentNodeStorePersistence() {
+ return segmentStore;
+ }
+
+ @Override
+ public BundleContext getBundleContext() {
+ return context.getBundleContext();
+ }
+
+ });
+ }
+
+ private static StatisticsProvider getRoleStatisticsProvider(StatisticsProvider delegate, String role) {
+ RepositoryStatistics repositoryStatistics = new RepositoryStatistics() {
+
+ @Override
+ public TimeSeries getTimeSeries(Type type) {
+ return getTimeSeries(type.name(), type.isResetValueEachSecond());
+ }
+
+ @Override
+ public TimeSeries getTimeSeries(String type, boolean resetValueEachSecond) {
+ return delegate.getStats().getTimeSeries(addRoleToName(type, role), resetValueEachSecond);
+ }
};
return new StatisticsProvider() {
+
@Override
public RepositoryStatistics getStats() {
return repositoryStatistics;
@@ -218,12 +625,12 @@ public class SegmentNodeStoreFactory {
public HistogramStats getHistogram(String name, StatsOptions options) {
return delegate.getHistogram(addRoleToName(name, role), options);
}
+
};
}
private static String addRoleToName(String name, String role) {
- return new StringBuilder(role).append('.').append(name).toString();
+ return role + '.' + name;
}
-
}
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreMonitorService.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreMonitorService.java?rev=1835837&r1=1835836&r2=1835837&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreMonitorService.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreMonitorService.java Fri Jul 13 13:23:24 2018
@@ -19,45 +19,44 @@
package org.apache.jackrabbit.oak.segment;
-import java.io.IOException;
-import java.util.Map;
-
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.ConfigurationPolicy;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.PropertyUnbounded;
-import org.apache.felix.scr.annotations.Reference;
import org.apache.jackrabbit.oak.commons.PropertiesUtil;
-import org.osgi.service.component.ComponentContext;
+import org.apache.jackrabbit.oak.segment.SegmentNodeStoreMonitorService.Configuration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ConfigurationPolicy;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
/**
* An OSGi wrapper for segment node store monitoring configurations.
*/
-@Component(policy = ConfigurationPolicy.REQUIRE,
- metatype = true,
- label = "Oak Segment Tar Monitoring service",
- description = "This service is responsible for different configurations related to " +
- "Oak Segment Tar read/write monitoring."
-)
+@Component(configurationPolicy = ConfigurationPolicy.REQUIRE)
+@Designate(ocd = Configuration.class)
public class SegmentNodeStoreMonitorService {
-
- @Property(label = "Writer groups",
- unbounded = PropertyUnbounded.ARRAY,
- description = "Writer groups for which commits are tracked individually"
+
+ @ObjectClassDefinition(
+ name = "Oak Segment Tar Monitoring service",
+ description = "This service is responsible for different configurations related to " +
+ "Oak Segment Tar read/write monitoring."
)
- private static final String COMMITS_TRACKER_WRITER_GROUPS = "commitsTrackerWriterGroups";
+ @interface Configuration {
+
+ @AttributeDefinition(
+ name = "Writer groups",
+ description = "Writer groups for which commits are tracked individually"
+ )
+ String[] commitsTrackerWriterGroups() default {};
+
+ }
@Reference
private SegmentNodeStoreStatsMBean snsStatsMBean;
-
+
@Activate
- public void activate(ComponentContext context, Map<String, ?> config) throws IOException {
- augmentSegmentNodeStoreStatsMBean(config);
+ public void activate(Configuration config) {
+ snsStatsMBean.setWriterGroupsForLastMinuteCounts(PropertiesUtil.toStringArray(config.commitsTrackerWriterGroups(), null));
}
- private void augmentSegmentNodeStoreStatsMBean(Map<String, ?> config) {
- snsStatsMBean.setWriterGroupsForLastMinuteCounts(
- PropertiesUtil.toStringArray(config.get(COMMITS_TRACKER_WRITER_GROUPS), null));
- }
}
Added: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreRegistrar.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreRegistrar.java?rev=1835837&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreRegistrar.java (added)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreRegistrar.java Fri Jul 13 13:23:24 2018
@@ -0,0 +1,525 @@
+/*
+ * 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.segment;
+
+import static org.apache.jackrabbit.oak.plugins.blob.datastore.SharedDataStoreUtils.isShared;
+import static org.apache.jackrabbit.oak.segment.SegmentNotFoundExceptionListener.IGNORE_SNFE;
+import static org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.RETAINED_GENERATIONS_DEFAULT;
+import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
+import static org.apache.jackrabbit.oak.spi.cluster.ClusterRepositoryInfo.getOrCreateId;
+
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import com.google.common.io.Closer;
+import org.apache.jackrabbit.commons.SimpleValueFactory;
+import org.apache.jackrabbit.oak.api.Descriptors;
+import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean;
+import org.apache.jackrabbit.oak.api.jmx.CheckpointMBean;
+import org.apache.jackrabbit.oak.api.jmx.FileStoreBackupRestoreMBean;
+import org.apache.jackrabbit.oak.backup.impl.FileStoreBackupRestoreImpl;
+import org.apache.jackrabbit.oak.cache.CacheStats;
+import org.apache.jackrabbit.oak.plugins.blob.BlobGC;
+import org.apache.jackrabbit.oak.plugins.blob.BlobGCMBean;
+import org.apache.jackrabbit.oak.plugins.blob.BlobGarbageCollector;
+import org.apache.jackrabbit.oak.plugins.blob.BlobTrackingStore;
+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.segment.compaction.SegmentGCOptions;
+import org.apache.jackrabbit.oak.segment.compaction.SegmentRevisionGC;
+import org.apache.jackrabbit.oak.segment.compaction.SegmentRevisionGCMBean;
+import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder;
+import org.apache.jackrabbit.oak.segment.file.FileStoreGCMonitor;
+import org.apache.jackrabbit.oak.segment.file.FileStoreStatsMBean;
+import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
+import org.apache.jackrabbit.oak.segment.file.MetricsIOMonitor;
+import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentNodeStorePersistence;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore;
+import org.apache.jackrabbit.oak.spi.cluster.ClusterRepositoryInfo;
+import org.apache.jackrabbit.oak.spi.commit.ObserverTracker;
+import org.apache.jackrabbit.oak.spi.descriptors.GenericDescriptors;
+import org.apache.jackrabbit.oak.spi.gc.GCMonitor;
+import org.apache.jackrabbit.oak.spi.gc.GCMonitorTracker;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.spi.state.RevisionGC;
+import org.apache.jackrabbit.oak.spi.state.RevisionGCMBean;
+import org.apache.jackrabbit.oak.spi.whiteboard.AbstractServiceTracker;
+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.spi.whiteboard.WhiteboardUtils;
+import org.apache.jackrabbit.oak.stats.Clock;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+
+class SegmentNodeStoreRegistrar {
+
+ static SegmentNodeStore registerSegmentNodeStore(Configuration cfg) throws IOException {
+ return new SegmentNodeStoreRegistrar(cfg).register();
+ }
+
+ interface Configuration {
+
+ boolean isPrimarySegmentStore();
+
+ boolean isSecondarySegmentStore();
+
+ boolean isStandbyInstance();
+
+ String getRole();
+
+ int getRetainedGenerations();
+
+ int getDefaultRetainedGenerations();
+
+ boolean getPauseCompaction();
+
+ int getRetryCount();
+
+ int getForceCompactionTimeout();
+
+ long getSizeDeltaEstimation();
+
+ int getMemoryThreshold();
+
+ boolean getDisableEstimation();
+
+ long getGCProcessLog();
+
+ File getSegmentDirectory();
+
+ int getSegmentCacheSize();
+
+ int getStringCacheSize();
+
+ int getTemplateCacheSize();
+
+ int getStringDeduplicationCacheSize();
+
+ int getTemplateDeduplicationCacheSize();
+
+ int getNodeDeduplicationCacheSize();
+
+ int getMaxFileSize();
+
+ boolean getMemoryMapping();
+
+ boolean hasCustomBlobStore();
+
+ boolean hasCustomSegmentStore();
+
+ boolean registerDescriptors();
+
+ String getRepositoryHome();
+
+ long getBlobSnapshotInterval();
+
+ long getBlobGcMaxAge();
+
+ File getBackupDirectory();
+
+ Whiteboard getWhiteboard();
+
+ Closer getCloser();
+
+ Logger getLogger();
+
+ StatisticsProvider getStatisticsProvider();
+
+ BlobStore getBlobStore();
+
+ SegmentNodeStorePersistence getSegmentNodeStorePersistence();
+
+ BundleContext getBundleContext();
+
+ }
+
+ private final Configuration cfg;
+
+ private SegmentNodeStoreRegistrar(Configuration cfg) {
+ this.cfg = cfg;
+ }
+
+ private SegmentNodeStore register() throws IOException {
+ if (cfg.getBlobStore() == null && (cfg.hasCustomBlobStore() || cfg.isSecondarySegmentStore())) {
+ cfg.getLogger().info("BlobStore enabled. SegmentNodeStore will be initialized once the blob store becomes available");
+ return null;
+ }
+
+ if (cfg.getSegmentNodeStorePersistence() == null && cfg.hasCustomSegmentStore()) {
+ cfg.getLogger().info("customSegmentStore enabled. SegmentNodeStore will be initialized once the custom segment store becomes available");
+ return null;
+ }
+
+ // Listen for GCMonitor services
+ GCMonitor gcMonitor = GCMonitor.EMPTY;
+
+ if (cfg.isPrimarySegmentStore()) {
+ GCMonitorTracker tracker = new GCMonitorTracker();
+ tracker.start(cfg.getWhiteboard());
+ registerCloseable(tracker);
+ gcMonitor = tracker;
+ }
+
+ // Create the gc options
+ if (cfg.getRetainedGenerations() != cfg.getDefaultRetainedGenerations()) {
+ cfg.getLogger().warn(
+ "The number of retained generations defaults to {} and can't be " +
+ "changed. This configuration option is considered deprecated " +
+ "and will be removed in the future.",
+ RETAINED_GENERATIONS_DEFAULT
+ );
+ }
+ SegmentGCOptions gcOptions = new SegmentGCOptions(cfg.getPauseCompaction(), cfg.getRetryCount(), cfg.getForceCompactionTimeout())
+ .setGcSizeDeltaEstimation(cfg.getSizeDeltaEstimation())
+ .setMemoryThreshold(cfg.getMemoryThreshold())
+ .setEstimationDisabled(cfg.getDisableEstimation())
+ .setGCLogInterval(cfg.getGCProcessLog());
+ if (cfg.isStandbyInstance()) {
+ gcOptions.setRetainedGenerations(1);
+ }
+
+ // Build the FileStore
+ FileStoreBuilder builder = fileStoreBuilder(cfg.getSegmentDirectory())
+ .withSegmentCacheSize(cfg.getSegmentCacheSize())
+ .withStringCacheSize(cfg.getStringCacheSize())
+ .withTemplateCacheSize(cfg.getTemplateCacheSize())
+ .withStringDeduplicationCacheSize(cfg.getStringDeduplicationCacheSize())
+ .withTemplateDeduplicationCacheSize(cfg.getTemplateDeduplicationCacheSize())
+ .withNodeDeduplicationCacheSize(cfg.getNodeDeduplicationCacheSize())
+ .withMaxFileSize(cfg.getMaxFileSize())
+ .withMemoryMapping(cfg.getMemoryMapping())
+ .withGCMonitor(gcMonitor)
+ .withIOMonitor(new MetricsIOMonitor(cfg.getStatisticsProvider()))
+ .withStatisticsProvider(cfg.getStatisticsProvider())
+ .withGCOptions(gcOptions);
+
+ if (cfg.hasCustomBlobStore() && cfg.getBlobStore() != null) {
+ cfg.getLogger().info("Initializing SegmentNodeStore with BlobStore [{}]", cfg.getBlobStore());
+ builder.withBlobStore(cfg.getBlobStore());
+ }
+
+ if (cfg.hasCustomSegmentStore() && cfg.getSegmentNodeStorePersistence() != null) {
+ cfg.getLogger().info("Initializing SegmentNodeStore with custom persistence [{}]", cfg.getSegmentNodeStorePersistence());
+ builder.withCustomPersistence(cfg.getSegmentNodeStorePersistence());
+ }
+
+ if (cfg.isStandbyInstance()) {
+ builder.withSnfeListener(IGNORE_SNFE);
+ }
+
+ FileStore store;
+ try {
+ store = builder.build();
+ } catch (InvalidFileStoreVersionException e) {
+ cfg.getLogger().error("The storage format is not compatible with this version of Oak Segment Tar", e);
+ return null;
+ }
+ registerCloseable(store);
+
+ // Listen for Executor services on the whiteboard
+
+ WhiteboardExecutor executor = new WhiteboardExecutor();
+ executor.start(cfg.getWhiteboard());
+ registerCloseable(executor);
+
+ // Expose stats about the segment cache
+
+ CacheStatsMBean segmentCacheStats = store.getSegmentCacheStats();
+ registerCloseable(registerMBean(
+ CacheStatsMBean.class,
+ segmentCacheStats,
+ CacheStats.TYPE,
+ segmentCacheStats.getName()
+ ));
+
+ // Expose stats about the string and template caches
+
+ CacheStatsMBean stringCacheStats = store.getStringCacheStats();
+ registerCloseable(registerMBean(
+ CacheStatsMBean.class,
+ stringCacheStats,
+ CacheStats.TYPE,
+ stringCacheStats.getName()
+ ));
+
+ CacheStatsMBean templateCacheStats = store.getTemplateCacheStats();
+ registerCloseable(registerMBean(
+ CacheStatsMBean.class,
+ templateCacheStats,
+ CacheStats.TYPE,
+ templateCacheStats.getName()
+ ));
+
+ WriterCacheManager cacheManager = builder.getCacheManager();
+ CacheStatsMBean stringDeduplicationCacheStats = cacheManager.getStringCacheStats();
+ if (stringDeduplicationCacheStats != null) {
+ registerCloseable(registerMBean(
+ CacheStatsMBean.class,
+ stringDeduplicationCacheStats,
+ CacheStats.TYPE,
+ stringDeduplicationCacheStats.getName()
+ ));
+ }
+
+ CacheStatsMBean templateDeduplicationCacheStats = cacheManager.getTemplateCacheStats();
+ if (templateDeduplicationCacheStats != null) {
+ registerCloseable(registerMBean(
+ CacheStatsMBean.class,
+ templateDeduplicationCacheStats,
+ CacheStats.TYPE,
+ templateDeduplicationCacheStats.getName()
+ ));
+ }
+
+ CacheStatsMBean nodeDeduplicationCacheStats = cacheManager.getNodeCacheStats();
+ if (nodeDeduplicationCacheStats != null) {
+ registerCloseable(registerMBean(
+ CacheStatsMBean.class,
+ nodeDeduplicationCacheStats,
+ CacheStats.TYPE,
+ nodeDeduplicationCacheStats.getName()
+ ));
+ }
+
+ // Expose an MBean to managing and monitoring garbage collection
+
+ FileStoreGCMonitor monitor = new FileStoreGCMonitor(Clock.SIMPLE);
+ registerCloseable(register(
+ GCMonitor.class,
+ monitor
+ ));
+ if (!cfg.isStandbyInstance()) {
+ registerCloseable(registerMBean(
+ SegmentRevisionGC.class,
+ new SegmentRevisionGCMBean(store, gcOptions, monitor),
+ SegmentRevisionGC.TYPE,
+ "Segment node store revision garbage collection"
+ ));
+ }
+
+ registerCloseable(registerMBean(
+ RevisionGCMBean.class,
+ new RevisionGC(store.getGCRunner(), store::cancelGC, monitor::getStatus, executor),
+ RevisionGCMBean.TYPE,
+ "Revision garbage collection"
+ ));
+
+ // Expose statistics about the FileStore
+
+ registerCloseable(registerMBean(
+ FileStoreStatsMBean.class,
+ store.getStats(),
+ FileStoreStatsMBean.TYPE,
+ "FileStore statistics"
+ ));
+
+ // register segment node store
+
+ SegmentNodeStore.SegmentNodeStoreBuilder segmentNodeStoreBuilder = SegmentNodeStoreBuilders.builder(store).withStatisticsProvider(cfg.getStatisticsProvider());
+ if (cfg.isStandbyInstance() || !cfg.isPrimarySegmentStore()) {
+ segmentNodeStoreBuilder.dispatchChanges(false);
+ }
+ SegmentNodeStore segmentNodeStore = segmentNodeStoreBuilder.build();
+
+ if (cfg.isPrimarySegmentStore()) {
+ ObserverTracker observerTracker = new ObserverTracker(segmentNodeStore);
+ observerTracker.start(cfg.getBundleContext());
+ registerCloseable(observerTracker);
+ }
+
+ if (cfg.isPrimarySegmentStore()) {
+ registerCloseable(registerMBean(
+ CheckpointMBean.class,
+ new SegmentCheckpointMBean(segmentNodeStore),
+ CheckpointMBean.TYPE,
+ "Segment node store checkpoint management"
+ ));
+ }
+
+ if (cfg.registerDescriptors()) {
+ // 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(getOrCreateId(segmentNodeStore)),
+ true,
+ false
+ );
+ registerCloseable(register(Descriptors.class, clusterIdDesc));
+ // Register "discovery lite" descriptors
+ registerCloseable(register(Descriptors.class, new SegmentDiscoveryLiteDescriptors(segmentNodeStore)));
+ }
+
+ // If a shared data store register the repo id in the data store
+ if (cfg.isPrimarySegmentStore() && isShared(cfg.getBlobStore())) {
+ SharedDataStore sharedDataStore = (SharedDataStore) cfg.getBlobStore();
+ try {
+ sharedDataStore.addMetadataRecord(new ByteArrayInputStream(new byte[0]), SharedDataStoreUtils.SharedStoreRecordType.REPOSITORY.getNameFromId(getOrCreateId(segmentNodeStore)));
+ } catch (Exception e) {
+ throw new IOException("Could not register a unique repositoryId", e);
+ }
+ if (cfg.getBlobStore() instanceof BlobTrackingStore) {
+ BlobTrackingStore trackingStore = (BlobTrackingStore) cfg.getBlobStore();
+ if (trackingStore.getTracker() != null) {
+ trackingStore.getTracker().close();
+ }
+ trackingStore.addTracker(new BlobIdTracker(cfg.getRepositoryHome(), getOrCreateId(segmentNodeStore), cfg.getBlobSnapshotInterval(), sharedDataStore));
+ }
+ }
+
+ if (cfg.isPrimarySegmentStore() && cfg.getBlobStore() instanceof GarbageCollectableBlobStore) {
+ BlobGarbageCollector gc = new MarkSweepGarbageCollector(
+ new SegmentBlobReferenceRetriever(store),
+ (GarbageCollectableBlobStore) cfg.getBlobStore(),
+ executor,
+ TimeUnit.SECONDS.toMillis(cfg.getBlobGcMaxAge()),
+ getOrCreateId(segmentNodeStore),
+ cfg.getWhiteboard(),
+ cfg.getStatisticsProvider()
+ );
+ registerCloseable(registerMBean(
+ BlobGCMBean.class,
+ new BlobGC(gc, executor),
+ BlobGCMBean.TYPE,
+ "Segment node store blob garbage collection"
+ ));
+ }
+
+ // Expose an MBean for backup/restore operations
+
+ registerCloseable(registerMBean(
+ FileStoreBackupRestoreMBean.class,
+ new FileStoreBackupRestoreImpl(
+ segmentNodeStore,
+ store.getRevisions(),
+ store.getReader(),
+ cfg.getBackupDirectory(),
+ executor
+ ),
+ FileStoreBackupRestoreMBean.TYPE,
+ "Segment node store backup/restore"
+ ));
+
+ // Expose statistics about the SegmentNodeStore
+
+ registerCloseable(registerMBean(
+ SegmentNodeStoreStatsMBean.class,
+ segmentNodeStore.getStats(),
+ SegmentNodeStoreStatsMBean.TYPE,
+ "SegmentNodeStore statistics"
+ ));
+
+ if (cfg.isPrimarySegmentStore()) {
+ cfg.getLogger().info("Primary SegmentNodeStore initialized");
+ } else {
+ cfg.getLogger().info("Secondary SegmentNodeStore initialized, role={}", cfg.getRole());
+ }
+
+ // Register a factory service to expose the FileStore
+ registerCloseable(register(
+ SegmentStoreProvider.class,
+ new DefaultSegmentStoreProvider(store)
+ ));
+
+ if (cfg.isStandbyInstance()) {
+ return segmentNodeStore;
+ }
+
+ if (cfg.isPrimarySegmentStore()) {
+ Map<String, Object> props = new HashMap<>();
+ props.put(Constants.SERVICE_PID, SegmentNodeStore.class.getName());
+ props.put("oak.nodestore.description", new String[] {"nodeStoreType=segment"});
+ registerCloseable(register(NodeStore.class, segmentNodeStore, props));
+ }
+
+ return segmentNodeStore;
+ }
+
+ private <T> Registration registerMBean(Class<T> clazz, T bean, String type, String name) {
+ return registerMBean(clazz, bean, type, name, new HashMap<>());
+ }
+
+ private <T> Registration registerMBean(Class<T> clazz, T bean, String type, String name, Map<String, String> attributes) {
+ return WhiteboardUtils.registerMBean(cfg.getWhiteboard(), clazz, bean, type, maybeAppendRole(name), maybePutRoleAttribute(attributes));
+ }
+
+ private <T> Registration register(Class<T> clazz, T service) {
+ return register(clazz, service, new HashMap<>());
+ }
+
+ private <T> Registration register(Class<T> clazz, T service, Map<String, Object> properties) {
+ return cfg.getWhiteboard().register(clazz, service, maybePutRoleProperty(properties));
+ }
+
+ private String maybeAppendRole(String name) {
+ if (cfg.getRole() != null) {
+ return name + " - " + cfg.getRole();
+ }
+ return name;
+ }
+
+ private String jmxRole() {
+ return cfg.getRole().replaceAll(":", "-");
+ }
+
+ private Map<String, String> maybePutRoleAttribute(Map<String, String> attributes) {
+ if (cfg.getRole() != null) {
+ attributes.put("role", jmxRole());
+ }
+ return attributes;
+ }
+
+ private Map<String, Object> maybePutRoleProperty(Map<String, Object> attributes) {
+ if (cfg.getRole() != null) {
+ attributes.put("role", cfg.getRole());
+ }
+ return attributes;
+ }
+
+ private void registerCloseable(Closeable c) {
+ cfg.getCloser().register(c);
+ }
+
+ private void registerCloseable(final AbstractServiceTracker<?> t) {
+ registerCloseable((Closeable) t::stop);
+ }
+
+ private void registerCloseable(final Registration r) {
+ registerCloseable((Closeable) r::unregister);
+ }
+
+ private void registerCloseable(final ObserverTracker t) {
+ registerCloseable((Closeable) t::stop);
+ }
+
+}
Propchange: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreRegistrar.java
------------------------------------------------------------------------------
svn:eol-style = native