Modified: jackrabbit/oak/trunk/oak-store-document/pom.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/pom.xml?rev=1810002&r1=1810001&r2=1810002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-store-document/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-store-document/pom.xml Thu Sep 28 14:09:26 2017
@@ -101,8 +101,8 @@
       <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.metatype.annotations</artifactId>
       <scope>provided</scope>
     </dependency>
 

Modified: 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentDiscoveryLiteService.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentDiscoveryLiteService.java?rev=1810002&r1=1810001&r2=1810002&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentDiscoveryLiteService.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentDiscoveryLiteService.java
 Thu Sep 28 14:09:26 2017
@@ -30,13 +30,6 @@ import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.jcr.Value;
 
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-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.Service;
 import org.apache.jackrabbit.commons.SimpleValueFactory;
 import org.apache.jackrabbit.oak.api.Descriptors;
 import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
@@ -46,6 +39,12 @@ import org.apache.jackrabbit.oak.spi.com
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.osgi.framework.Version;
 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.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -136,8 +135,10 @@ import org.slf4j.LoggerFactory;
  * 
  * @see #OAK_DISCOVERYLITE_CLUSTERVIEW
  */
-@Component(immediate = true, name = 
DocumentDiscoveryLiteService.COMPONENT_NAME)
-@Service(value = { DocumentDiscoveryLiteService.class, Observer.class })
+@Component(
+        name = DocumentDiscoveryLiteService.COMPONENT_NAME,
+        immediate = true,
+        service = { DocumentDiscoveryLiteService.class, Observer.class })
 public class DocumentDiscoveryLiteService implements 
ClusterStateChangeListener, Observer {
 
     static final String COMPONENT_NAME = 
"org.apache.jackrabbit.oak.plugins.document.DocumentDiscoveryLiteService";
@@ -287,8 +288,8 @@ public class DocumentDiscoveryLiteServic
      * Require a static reference to the NodeStore. Note that this implies the
      * service is only active for documentNS
      **/
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY, policy = 
ReferencePolicy.STATIC)
-    private volatile DocumentNodeStore nodeStore;
+    @Reference
+    private DocumentNodeStore nodeStore;
 
     /**
      * inactive nodes that have been so for a while, ie they have no backlog

Modified: 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java?rev=1810002&r1=1810001&r2=1810002&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
 Thu Sep 28 14:09:26 2017
@@ -58,15 +58,6 @@ import com.google.common.util.concurrent
 import com.mongodb.MongoClientURI;
 
 import org.apache.commons.io.FilenameUtils;
-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.PropertyOption;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
 import org.apache.jackrabbit.commons.SimpleValueFactory;
 import org.apache.jackrabbit.oak.api.Descriptors;
 import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean;
@@ -116,21 +107,27 @@ import org.osgi.framework.BundleExceptio
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
 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.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.osgi.service.metatype.annotations.Option;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * The OSGi service to start/stop a DocumentNodeStore instance.
  */
-@Component(policy = ConfigurationPolicy.REQUIRE,
-        metatype = true,
-        label = "Apache Jackrabbit Oak Document NodeStore Service",
-        description = "NodeStore implementation based on Document model. For 
configuration option refer " +
-                "to 
http://jackrabbit.apache.org/oak/docs/osgi_config.html#DocumentNodeStore. Note 
that for system " +
-                "stability purpose it is advisable to not change these 
settings at runtime. Instead the config change " +
-                "should be done via file system based config file and this 
view should ONLY be used to determine which " +
-                "options are supported"
-)
+@Component(
+        configurationPolicy = ConfigurationPolicy.REQUIRE,
+        service = {})
+@Designate(ocd = DocumentNodeStoreService.Configuration.class)
 public class DocumentNodeStoreService {
 
     private static final long MB = 1024 * 1024;
@@ -144,6 +141,27 @@ public class DocumentNodeStoreService {
     private static final boolean DEFAULT_CONTINUOUS_RGC = false;
     private static final String PREFIX = "oak.documentstore.";
     private static final String DESCRIPTION = "oak.nodestore.description";
+    private static final long DEFAULT_JOURNAL_GC_INTERVAL_MILLIS = 5*60*1000; 
// default is 5min
+    static final long DEFAULT_JOURNAL_GC_MAX_AGE_MILLIS = 24*60*60*1000; // 
default is 24hours
+    private static final String DEFAULT_PROP_HOME = "./repository";
+    private static final long DEFAULT_MAX_REPLICATION_LAG = 6 * 60 * 60;
+    private static final boolean DEFAULT_BUNDLING_DISABLED = false;
+
+    /**
+     * Revisions older than this time would be garbage collected
+     */
+    private static final long DEFAULT_VER_GC_MAX_AGE = 24 * 60 * 60; 
//TimeUnit.DAYS.toSeconds(1);
+
+
+    /**
+     * Blob modified before this time duration would be considered for Blob GC
+     */
+    private static final long DEFAULT_BLOB_GC_MAX_AGE = 24 * 60 * 60;
+
+    /**
+     * Default interval for taking snapshots of locally tracked blob ids.
+     */
+    private static final long DEFAULT_BLOB_SNAPSHOT_INTERVAL = 12 * 60 * 60;
 
     /**
      * Name of framework property to configure Mongo Connection URI
@@ -161,133 +179,219 @@ public class DocumentNodeStoreService {
      */
     private static final String FWK_PROP_SO_KEEP_ALIVE = 
"oak.mongo.socketKeepAlive";
 
-    @Property(value = DEFAULT_URI,
-            label = "Mongo URI",
-            description = "Mongo connection URI used to connect to Mongo. 
Refer to " +
-                    
"http://docs.mongodb.org/manual/reference/connection-string/ for details. Note 
that this value " +
-                    "can be overridden via framework property 'oak.mongo.uri'"
-    )
-    private static final String PROP_URI = "mongouri";
 
-    @Property(value = DEFAULT_DB,
-            label = "Mongo DB name",
-            description = "Name of the database in Mongo. Note that this value 
" +
-                    "can be overridden via framework property 'oak.mongo.db'"
-    )
+    @ObjectClassDefinition(
+            name = "Apache Jackrabbit Oak Document NodeStore Service",
+            description = "NodeStore implementation based on Document model. 
For configuration option refer " +
+                    "to 
http://jackrabbit.apache.org/oak/docs/osgi_config.html#DocumentNodeStore. Note 
that for system " +
+                    "stability purpose it is advisable to not change these 
settings at runtime. Instead the config change " +
+                    "should be done via file system based config file and this 
view should ONLY be used to determine which " +
+                    "options are supported")
+    @interface Configuration {
+        @AttributeDefinition(
+                name = "Mongo URI",
+                description = "Mongo connection URI used to connect to Mongo. 
Refer to " +
+                        
"http://docs.mongodb.org/manual/reference/connection-string/ for details. Note 
that this value " +
+                        "can be overridden via framework property 
'oak.mongo.uri'")
+        String mongouri() default DEFAULT_URI;
+
+        @AttributeDefinition(
+                name = "Mongo DB name",
+                description = "Name of the database in Mongo. Note that this 
value " +
+                        "can be overridden via framework property 
'oak.mongo.db'")
+        String db() default DEFAULT_DB;
+
+
+        @AttributeDefinition(
+                name = "MongoDB socket keep-alive option",
+                description = "Whether socket keep-alive should be enabled for 
" +
+                        "connections to MongoDB. Note that this value can be " 
+
+                        "overridden via framework property 
'oak.mongo.socketKeepAlive'")
+        boolean socketKeepAlive() default DEFAULT_SO_KEEP_ALIVE;
+
+        @AttributeDefinition(
+                name = "Cache Size (in MB)",
+                description = "Cache size in MB. This is distributed among 
various caches used in DocumentNodeStore")
+        int cache() default DEFAULT_CACHE;
+
+        @AttributeDefinition(
+                name = "NodeState Cache",
+                description = "Percentage of cache to be allocated towards 
Node cache")
+        int nodeCachePercentage() default DEFAULT_NODE_CACHE_PERCENTAGE;
+
+        @AttributeDefinition(
+                name = "PreviousDocument Cache",
+                description = "Percentage of cache to be allocated towards 
Previous Document cache")
+        int prevDocCachePercentage() default DEFAULT_PREV_DOC_CACHE_PERCENTAGE;
+
+        @AttributeDefinition(
+                name = "NodeState Children Cache",
+                description = "Percentage of cache to be allocated towards 
Children cache")
+        int childrenCachePercentage() default 
DEFAULT_CHILDREN_CACHE_PERCENTAGE;
+
+        @AttributeDefinition(
+                name = "Diff Cache",
+                description = "Percentage of cache to be allocated towards 
Diff cache")
+        int diffCachePercentage() default DEFAULT_DIFF_CACHE_PERCENTAGE;
+
+        @AttributeDefinition(
+                name = "LIRS Cache Segment Count",
+                description = "The number of segments in the LIRS cache " +
+                        "(default 16, a higher count means higher concurrency 
" +
+                        "but slightly lower cache hit rate)")
+        int cacheSegmentCount() default DEFAULT_CACHE_SEGMENT_COUNT;
+
+        @AttributeDefinition(
+                name = "LIRS Cache Stack Move Distance",
+                description = "The delay to move entries to the head of the 
queue " +
+                        "in the LIRS cache " +
+                        "(default 16, a higher value means higher concurrency 
" +
+                        "but slightly lower cache hit rate)")
+        int cacheStackMoveDistance() default DEFAULT_CACHE_STACK_MOVE_DISTANCE;
+
+        @AttributeDefinition(
+                name = "Blob Cache Size (in MB)",
+                description = "Cache size to store blobs in memory. Used only 
with default BlobStore " +
+                        "(as per DocumentStore type)")
+        int blobCacheSize() default DEFAULT_BLOB_CACHE_SIZE;
+
+        @AttributeDefinition(
+                name = "Persistent Cache Config",
+                description = "Configuration for persistent cache. Refer to " +
+                        
"http://jackrabbit.apache.org/oak/docs/nodestore/persistent-cache.html for 
various options")
+        String persistentCache() default DEFAULT_PERSISTENT_CACHE;
+
+        @AttributeDefinition(
+                name = "Journal Cache Config",
+                description = "Configuration for journal cache. Refer to " +
+                        
"http://jackrabbit.apache.org/oak/docs/nodestore/persistent-cache.html for 
various options")
+        String journalCache() default DEFAULT_JOURNAL_CACHE;
+
+        @AttributeDefinition(
+                name = "Custom BlobStore",
+                description = "Boolean value indicating that a custom 
BlobStore is to be used. " +
+                        "By default, for MongoDB, MongoBlobStore is used; for 
RDB, RDBBlobStore is used.")
+        boolean customBlobStore() default false;
+
+
+        @AttributeDefinition(
+                name = "Journal Garbage Collection Interval (millis)",
+                description = "Long value indicating interval (in 
milliseconds) with which the "
+                        + "journal (for external changes) is cleaned up. 
Default is " + DEFAULT_JOURNAL_GC_INTERVAL_MILLIS)
+        long journalGCInterval() default DEFAULT_JOURNAL_GC_INTERVAL_MILLIS;
+        
+        @AttributeDefinition(
+                name = "Maximum Age of Journal Entries (millis)",
+                description = "Long value indicating max age (in milliseconds) 
that "
+                        + "journal (for external changes) entries are kept 
(older ones are candidates for gc). "
+                        + "Default is " + DEFAULT_JOURNAL_GC_MAX_AGE_MILLIS)
+        long journalGCMaxAge() default DEFAULT_JOURNAL_GC_MAX_AGE_MILLIS;
+
+        @AttributeDefinition(
+                name = "Pre-fetch external changes",
+                description = "Boolean value indicating if external changes 
should " +
+                        "be pre-fetched in a background thread.")
+        boolean prefetchExternalChanges() default false;
+
+        @AttributeDefinition(
+                name = "NodeStoreProvider role",
+                description = "Property indicating that this component will 
not register as a NodeStore but as a " +
+                        "NodeStoreProvider with given role")
+        String role();
+
+        @AttributeDefinition(
+                name = "Version GC Max Age (in secs)",
+                description = "Version Garbage Collector (GC) logic will only 
consider those deleted for GC which " +
+                        "are not accessed recently (currentTime - 
lastModifiedTime > versionGcMaxAgeInSecs). For " +
+                        "example as per default only those document which have 
been *marked* deleted 24 hrs ago will be " +
+                        "considered for GC. This also applies how older 
revision of live document are GC.")
+        long versionGcMaxAgeInSecs() default DEFAULT_VER_GC_MAX_AGE;
+
+        @AttributeDefinition(
+                name = "Continuous Version GC Mode",
+                description = "Run Version GC continuously as a background 
task.")
+        boolean versionGCContinuous() default DEFAULT_CONTINUOUS_RGC;
+
+        @AttributeDefinition(
+                name = "Blob GC Max Age (in secs)",
+                description = "Blob Garbage Collector (GC) logic will only 
consider those blobs for GC which " +
+                        "are not accessed recently (currentTime - 
lastModifiedTime > blobGcMaxAgeInSecs). For " +
+                        "example as per default only those blobs which have 
been created 24 hrs ago will be " +
+                        "considered for GC")
+        long blobGcMaxAgeInSecs() default DEFAULT_BLOB_GC_MAX_AGE;
+
+        @AttributeDefinition(
+                name = "Blob tracking snapshot interval (in secs)",
+                description = "This is the default interval in which the 
snapshots of locally tracked blob ids will"
+                        + "be taken and synchronized with the blob store. This 
should be configured to be less than the "
+                        + "frequency of blob GC so that deletions during blob 
GC can be accounted for "
+                        + "in the next GC execution.")
+        long blobTrackSnapshotIntervalInSecs() default 
DEFAULT_BLOB_SNAPSHOT_INTERVAL;
+
+        @AttributeDefinition(
+                name = "Root directory",
+                description = "Root directory for local tracking of blob ids. 
This service " +
+                        "will first lookup the 'repository.home' framework 
property and " +
+                        "then a component context property with the same name. 
If none " +
+                        "of them is defined, a sub directory 'repository' 
relative to " +
+                        "the current working directory is used.")
+        String repository_home();
+
+        @AttributeDefinition(
+                name = "Max Replication Lag (in secs)",
+                description = "Value in seconds. Determines the duration 
beyond which it can be safely assumed " +
+                        "that the state on the secondaries is consistent with 
the primary, and it is safe to read from them")
+        long maxReplicationLagInSecs() default DEFAULT_MAX_REPLICATION_LAG;
+
+        @AttributeDefinition(
+                name = "DocumentStore Type",
+                description = "Type of DocumentStore to use for persistence. 
Defaults to MONGO",
+                options = {
+                        @Option(label = "MONGO", value = "MONGO"),
+                        @Option(label = "RDB", value = "RDB")})
+        String documentStoreType() default "MONGO";
+
+        @AttributeDefinition(
+                name = "Bundling Disabled",
+                description = "Boolean value indicating that Node bundling is 
disabled")
+        boolean bundlingDisabled() default DEFAULT_BUNDLING_DISABLED;
+
+        @AttributeDefinition(
+                name = "DocumentNodeStore update.limit",
+                description = "Number of content updates that need to happen 
before " +
+                        "the updates are automatically purged to the private 
branch.")
+        int updateLimit();
+    }
+    
+    // property name constants - values can come from framework properties or 
OSGi config
+    private static final String PROP_URI = "mongouri";
     private static final String PROP_DB = "db";
-
-    @Property(boolValue = DEFAULT_SO_KEEP_ALIVE,
-            label = "MongoDB socket keep-alive option",
-            description = "Whether socket keep-alive should be enabled for " +
-                    "connections to MongoDB. Note that this value can be " +
-                    "overridden via framework property 
'oak.mongo.socketKeepAlive'"
-    )
     static final String PROP_SO_KEEP_ALIVE = "socketKeepAlive";
-
-    @Property(intValue = DEFAULT_CACHE,
-            label = "Cache Size (in MB)",
-            description = "Cache size in MB. This is distributed among various 
caches used in DocumentNodeStore"
-    )
     private static final String PROP_CACHE = "cache";
-
-    @Property(intValue = DEFAULT_NODE_CACHE_PERCENTAGE,
-            label = "NodeState Cache",
-            description = "Percentage of cache to be allocated towards Node 
cache"
-    )
     private static final String PROP_NODE_CACHE_PERCENTAGE = 
"nodeCachePercentage";
-
-    @Property(intValue = DEFAULT_PREV_DOC_CACHE_PERCENTAGE,
-            label = "PreviousDocument Cache",
-            description = "Percentage of cache to be allocated towards 
Previous Document cache"
-    )
     private static final String PROP_PREV_DOC_CACHE_PERCENTAGE = 
"prevDocCachePercentage";
-
-    @Property(intValue = DocumentMK.Builder.DEFAULT_CHILDREN_CACHE_PERCENTAGE,
-            label = "NodeState Children Cache",
-            description = "Percentage of cache to be allocated towards 
Children cache"
-    )
     private static final String PROP_CHILDREN_CACHE_PERCENTAGE = 
"childrenCachePercentage";
-    
-    @Property(intValue = DocumentMK.Builder.DEFAULT_DIFF_CACHE_PERCENTAGE,
-            label = "Diff Cache",
-            description = "Percentage of cache to be allocated towards Diff 
cache"
-    )
     private static final String PROP_DIFF_CACHE_PERCENTAGE = 
"diffCachePercentage";
-    
-    @Property(intValue = DEFAULT_CACHE_SEGMENT_COUNT,
-            label = "LIRS Cache Segment Count",
-            description = "The number of segments in the LIRS cache " + 
-                    "(default 16, a higher count means higher concurrency " + 
-                    "but slightly lower cache hit rate)"
-    )
     private static final String PROP_CACHE_SEGMENT_COUNT = "cacheSegmentCount";
-
-    @Property(intValue = DEFAULT_CACHE_STACK_MOVE_DISTANCE,
-            label = "LIRS Cache Stack Move Distance",
-            description = "The delay to move entries to the head of the queue 
" + 
-                    "in the LIRS cache " +
-                    "(default 16, a higher value means higher concurrency " + 
-                    "but slightly lower cache hit rate)"
-    )
     private static final String PROP_CACHE_STACK_MOVE_DISTANCE = 
"cacheStackMoveDistance";
-
-    @Property(intValue =  DEFAULT_BLOB_CACHE_SIZE,
-            label = "Blob Cache Size (in MB)",
-            description = "Cache size to store blobs in memory. Used only with 
default BlobStore " +
-                    "(as per DocumentStore type)"
-    )
     private static final String PROP_BLOB_CACHE_SIZE = "blobCacheSize";
-
-    @Property(value = DEFAULT_PERSISTENT_CACHE,
-            label = "Persistent Cache Config",
-            description = "Configuration for persistent cache. Refer to " +
-                    
"http://jackrabbit.apache.org/oak/docs/nodestore/persistent-cache.html for 
various options"
-    )
     private static final String PROP_PERSISTENT_CACHE = "persistentCache";
-
-    @Property(value = DEFAULT_JOURNAL_CACHE,
-            label = "Journal Cache Config",
-            description = "Configuration for journal cache. Refer to " +
-                    
"http://jackrabbit.apache.org/oak/docs/nodestore/persistent-cache.html for 
various options"
-    )
     private static final String PROP_JOURNAL_CACHE = "journalCache";
-
-    @Property(boolValue = false,
-            label = "Custom BlobStore",
-            description = "Boolean value indicating that a custom BlobStore is 
to be used. " +
-                    "By default, for MongoDB, MongoBlobStore is used; for RDB, 
RDBBlobStore is used."
-    )
-    public static final String CUSTOM_BLOB_STORE = "customBlobStore";
-
-    private static final long DEFAULT_JOURNAL_GC_INTERVAL_MILLIS = 5*60*1000; 
// default is 5min
-    @Property(longValue = DEFAULT_JOURNAL_GC_INTERVAL_MILLIS,
-            label = "Journal Garbage Collection Interval (millis)",
-            description = "Long value indicating interval (in milliseconds) 
with which the "
-                    + "journal (for external changes) is cleaned up. Default 
is " + DEFAULT_JOURNAL_GC_INTERVAL_MILLIS
-    )
-    private static final String PROP_JOURNAL_GC_INTERVAL_MILLIS = 
"journalGCInterval";
-    
-    static final long DEFAULT_JOURNAL_GC_MAX_AGE_MILLIS = 24*60*60*1000; // 
default is 24hours
-    @Property(longValue = DEFAULT_JOURNAL_GC_MAX_AGE_MILLIS,
-            label = "Maximum Age of Journal Entries (millis)",
-            description = "Long value indicating max age (in milliseconds) 
that "
-                    + "journal (for external changes) entries are kept (older 
ones are candidates for gc). "
-                    + "Default is " + DEFAULT_JOURNAL_GC_MAX_AGE_MILLIS
-    )
-    private static final String PROP_JOURNAL_GC_MAX_AGE_MILLIS = 
"journalGCMaxAge";
-
-    @Property (boolValue = false,
-            label = "Pre-fetch external changes",
-            description = "Boolean value indicating if external changes should 
" +
-                    "be pre-fetched in a background thread."
-    )
     public static final String PROP_PREFETCH_EXTERNAL_CHANGES = 
"prefetchExternalChanges";
-
-    @Property(
-            label = "NodeStoreProvider role",
-            description = "Property indicating that this component will not 
register as a NodeStore but as a NodeStoreProvider with given role"
-    )
+    private static final String PROP_JOURNAL_GC_MAX_AGE_MILLIS = 
"journalGCMaxAge";
+    public static final String CUSTOM_BLOB_STORE = "customBlobStore";
+    public static final String PROP_VER_GC_MAX_AGE = "versionGcMaxAgeInSecs";
+    public static final String PROP_VER_GC_CONTINUOUS = "versionGCContinuous";
+    public static final String PROP_REV_RECOVERY_INTERVAL = 
"lastRevRecoveryJobIntervalInSecs";
+    public static final String PROP_BLOB_GC_MAX_AGE = "blobGcMaxAgeInSecs";
+    public static final String PROP_BLOB_SNAPSHOT_INTERVAL = 
"blobTrackSnapshotIntervalInSecs";
+    private static final String PROP_HOME = "repository.home";
+    public static final String PROP_REPLICATION_LAG = 
"maxReplicationLagInSecs";
+    public static final String PROP_DS_TYPE = "documentStoreType";
+    private static final String PROP_BUNDLING_DISABLED = "bundlingDisabled";
+    public static final String PROP_UPDATE_LIMIT = "updateLimit";
     public static final String PROP_ROLE = "role";
+    private static final String PROP_JOURNAL_GC_INTERVAL_MILLIS = 
"journalGCInterval";
 
     private static enum DocumentStoreType {
         MONGO, RDB;
@@ -306,24 +410,12 @@ public class DocumentNodeStoreService {
     private Closer closer;
     private WhiteboardExecutor executor;
 
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY,
-            policy = ReferencePolicy.DYNAMIC, target = ONLY_STANDALONE_TARGET)
     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;
 
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY,
-            policy = ReferencePolicy.DYNAMIC)
     private volatile DocumentNodeStateCache nodeStateCache;
 
     private DocumentNodeStore nodeStore;
@@ -332,99 +424,7 @@ public class DocumentNodeStoreService {
     private ComponentContext context;
     private Whiteboard whiteboard;
     private long deactivationTimestamp = 0;
-
-
-    /**
-     * Revisions older than this time would be garbage collected
-     */
-    private static final long DEFAULT_VER_GC_MAX_AGE = 24 * 60 * 60; 
//TimeUnit.DAYS.toSeconds(1);
-    @Property (longValue = DEFAULT_VER_GC_MAX_AGE,
-            label = "Version GC Max Age (in secs)",
-            description = "Version Garbage Collector (GC) logic will only 
consider those deleted for GC which " +
-                    "are not accessed recently (currentTime - lastModifiedTime 
> versionGcMaxAgeInSecs). For " +
-                    "example as per default only those document which have 
been *marked* deleted 24 hrs ago will be " +
-                    "considered for GC. This also applies how older revision 
of live document are GC."
-    )
-    public static final String PROP_VER_GC_MAX_AGE = "versionGcMaxAgeInSecs";
-
-    @Property (boolValue = DEFAULT_CONTINUOUS_RGC,
-            label = "Continuous Version GC Mode",
-            description = "Run Version GC continuously as a background task.")
-    public static final String PROP_VER_GC_CONTINUOUS = "versionGCContinuous";
-
-    public static final String PROP_REV_RECOVERY_INTERVAL = 
"lastRevRecoveryJobIntervalInSecs";
-
-    /**
-     * Blob modified before this time duration would be considered for Blob GC
-     */
-    private static final long DEFAULT_BLOB_GC_MAX_AGE = 24 * 60 * 60;
-    @Property (longValue = DEFAULT_BLOB_GC_MAX_AGE,
-            label = "Blob GC Max Age (in secs)",
-            description = "Blob Garbage Collector (GC) logic will only 
consider those blobs for GC which " +
-                    "are not accessed recently (currentTime - lastModifiedTime 
> blobGcMaxAgeInSecs). For " +
-                    "example as per default only those blobs which have been 
created 24 hrs ago will be " +
-                    "considered for GC"
-    )
-    public static final String PROP_BLOB_GC_MAX_AGE = "blobGcMaxAgeInSecs";
-
-    /**
-     * Default interval for taking snapshots of locally tracked blob ids.
-     */
-    private static final long DEFAULT_BLOB_SNAPSHOT_INTERVAL = 12 * 60 * 60;
-    @Property (longValue = DEFAULT_BLOB_SNAPSHOT_INTERVAL,
-        label = "Blob tracking snapshot interval (in secs)",
-        description = "This is the default interval in which the snapshots of 
locally tracked blob ids will"
-            + "be taken and synchronized with the blob store. This should be 
configured to be less than the "
-            + "frequency of blob GC so that deletions during blob GC can be 
accounted for "
-            + "in the next GC execution."
-    )
-    public static final String PROP_BLOB_SNAPSHOT_INTERVAL = 
"blobTrackSnapshotIntervalInSecs";
-
-    private static final String DEFAULT_PROP_HOME = "./repository";
-    @Property(
-        label = "Root directory",
-        description = "Root directory for local tracking of blob ids. This 
service " +
-                "will first lookup the 'repository.home' framework property 
and " +
-                "then a component context property with the same name. If none 
" +
-                "of them is defined, a sub directory 'repository' relative to 
" +
-                "the current working directory is used."
-    )
-    private static final String PROP_HOME = "repository.home";
-
-    private static final long DEFAULT_MAX_REPLICATION_LAG = 6 * 60 * 60;
-    @Property(longValue = DEFAULT_MAX_REPLICATION_LAG,
-            label = "Max Replication Lag (in secs)",
-            description = "Value in seconds. Determines the duration beyond 
which it can be safely assumed " +
-                    "that the state on the secondaries is consistent with the 
primary, and it is safe to read from them"
-    )
-    public static final String PROP_REPLICATION_LAG = 
"maxReplicationLagInSecs";
-    private long maxReplicationLagInSecs = DEFAULT_MAX_REPLICATION_LAG;
-
-    @Property(options = {
-                @PropertyOption(name = "MONGO", value = "MONGO"),
-                @PropertyOption(name = "RDB", value = "RDB")
-            },
-            value = "MONGO",
-            label = "DocumentStore Type",
-            description = "Type of DocumentStore to use for persistence. 
Defaults to MONGO"
-    )
-    public static final String PROP_DS_TYPE = "documentStoreType";
-
-    private static final boolean DEFAULT_BUNDLING_DISABLED = false;
-    @Property(boolValue = DEFAULT_BUNDLING_DISABLED,
-            label = "Bundling Disabled",
-            description = "Boolean value indicating that Node bundling is 
disabled"
-    )
-    private static final String PROP_BUNDLING_DISABLED = "bundlingDisabled";
-
-    @Property(
-            label = "DocumentNodeStore update.limit",
-            description = "Number of content updates that need to happen 
before " +
-                    "the updates are automatically purged to the private 
branch."
-    )
-    public static final String PROP_UPDATE_LIMIT = "updateLimit";
-
-    private DocumentStoreType documentStoreType;
+    private long maxReplicationLagInSecs;
 
     @Reference
     private StatisticsProvider statisticsProvider;
@@ -436,15 +436,15 @@ public class DocumentNodeStoreService {
     private BlobStore defaultBlobStore;
 
     @Activate
-    protected void activate(ComponentContext context, Map<String, ?> config) 
throws Exception {
+    protected void activate(ComponentContext context, Configuration config) 
throws Exception {
         closer = Closer.create();
         this.context = context;
         whiteboard = new OsgiWhiteboard(context.getBundleContext());
         executor = new WhiteboardExecutor();
         executor.start(whiteboard);
-        maxReplicationLagInSecs = toLong(config.get(PROP_REPLICATION_LAG), 
DEFAULT_MAX_REPLICATION_LAG);
+        maxReplicationLagInSecs = config.maxReplicationLagInSecs();
         customBlobStore = toBoolean(prop(CUSTOM_BLOB_STORE), false);
-        documentStoreType = 
DocumentStoreType.fromString(PropertiesUtil.toString(config.get(PROP_DS_TYPE), 
"MONGO"));
+        documentStoreType = 
DocumentStoreType.fromString(config.documentStoreType());
 
         registerNodeStoreIfPossible();
     }
@@ -730,6 +730,11 @@ public class DocumentNodeStoreService {
         unregisterNodeStore();
     }
 
+    @Reference(name = "blobStore",
+            cardinality = ReferenceCardinality.OPTIONAL,
+            policy = ReferencePolicy.DYNAMIC,
+            target = ONLY_STANDALONE_TARGET
+    )
     @SuppressWarnings("UnusedDeclaration")
     protected void bindBlobStore(BlobStore blobStore) throws IOException {
         if (defaultBlobStore == blobStore){
@@ -749,6 +754,11 @@ public class DocumentNodeStoreService {
         unregisterNodeStore();
     }
 
+    @Reference(name = "dataSource",
+            cardinality = ReferenceCardinality.OPTIONAL,
+            policy = ReferencePolicy.DYNAMIC,
+            target = "(datasource.name=oak)"
+    )
     @SuppressWarnings("UnusedDeclaration")
     protected void bindDataSource(DataSource dataSource) throws IOException {
         if (this.dataSource != null) {
@@ -771,6 +781,14 @@ public class DocumentNodeStoreService {
         }
     }
 
+
+    private DocumentStoreType documentStoreType;
+
+    @Reference(name = "blobDataSource",
+            cardinality = ReferenceCardinality.OPTIONAL,
+            policy = ReferencePolicy.DYNAMIC,
+            target = "(datasource.name=oak)"
+    )
     @SuppressWarnings("UnusedDeclaration")
     protected void bindBlobDataSource(DataSource dataSource) throws 
IOException {
         if (this.blobDataSource != null) {
@@ -794,6 +812,10 @@ public class DocumentNodeStoreService {
         }
     }
 
+    @Reference(name = "nodeStateCache",
+            cardinality = ReferenceCardinality.OPTIONAL,
+            policy = ReferencePolicy.DYNAMIC
+    )
     @SuppressWarnings("UnusedDeclaration")
     protected void bindNodeStateCache(DocumentNodeStateCache nodeStateCache) 
throws IOException {
        if (nodeStore != null){

Modified: 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/secondary/SecondaryStoreCacheService.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/secondary/SecondaryStoreCacheService.java?rev=1810002&r1=1810001&r2=1810002&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/secondary/SecondaryStoreCacheService.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/secondary/SecondaryStoreCacheService.java
 Thu Sep 28 14:09:26 2017
@@ -20,28 +20,16 @@
 package org.apache.jackrabbit.oak.plugins.document.secondary;
 
 import static java.util.Arrays.asList;
-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.toStringArray;
 import static 
org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
 
 import java.util.Collections;
 import java.util.Hashtable;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.Executor;
 
 import javax.annotation.Nonnull;
 
 import com.google.common.collect.Lists;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.PropertyUnbounded;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
 import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
 import org.apache.jackrabbit.oak.plugins.document.AbstractDocumentNodeState;
 import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStateCache;
@@ -60,15 +48,47 @@ import org.apache.jackrabbit.oak.stats.S
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+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.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;
 
-@Component(label = "Apache Jackrabbit Oak DocumentNodeStateCache Provider",
-        metatype = true,
-        immediate = true,
-        description = "Configures a DocumentNodeStateCache based on a 
secondary NodeStore"
-)
+@Component
+@Designate(ocd = SecondaryStoreCacheService.Configuration.class)
 public class SecondaryStoreCacheService {
+
+    @ObjectClassDefinition(
+            name = "Apache Jackrabbit Oak DocumentNodeStateCache Provider",
+            description = "Configures a DocumentNodeStateCache based on a 
secondary NodeStore"
+    )
+    @interface Configuration {
+
+        @AttributeDefinition(
+                name = "Included Paths",
+                description = "List of paths which are to be included in the 
secondary store"
+        )
+        String[] includedPaths() default {"/"};
+
+        @AttributeDefinition(
+                name = "Async Observation",
+                description = "Enable async observation processing"
+        )
+        boolean enableAsyncObserver() default true;
+
+        @AttributeDefinition(
+                name = "Observer queue size",
+                description = "Observer queue size. Used if 
'enableAsyncObserver' is set to true"
+        )
+        int observerQueueSize() default BackgroundObserver.DEFAULT_QUEUE_SIZE;
+    }
+
     private final Logger log = LoggerFactory.getLogger(getClass());
     /**
      * Having a reference to BlobStore ensures that DocumentNodeStoreService 
does register a BlobStore
@@ -89,32 +109,9 @@ public class SecondaryStoreCacheService
      * Have an optional dependency on DocumentNodeStore such that we do not 
have hard dependency
      * on it and DocumentNodeStore can make use of this service even after it 
has unregistered
      */
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY,
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL,
             policy = ReferencePolicy.DYNAMIC)
-    private DocumentNodeStore documentNodeStore;
-
-    @Property(unbounded = PropertyUnbounded.ARRAY,
-            label = "Included Paths",
-            description = "List of paths which are to be included in the 
secondary store",
-            value = {"/"}
-    )
-    private static final String PROP_INCLUDES = "includedPaths";
-
-    private static final boolean PROP_ASYNC_OBSERVER_DEFAULT = true;
-    @Property(
-            boolValue = PROP_ASYNC_OBSERVER_DEFAULT,
-            label = "Async Observation",
-            description = "Enable async observation processing"
-    )
-    private static final String PROP_ASYNC_OBSERVER = "enableAsyncObserver";
-
-    private static final int PROP_OBSERVER_QUEUE_SIZE_DEFAULT = 
BackgroundObserver.DEFAULT_QUEUE_SIZE;
-    @Property(
-            intValue = PROP_OBSERVER_QUEUE_SIZE_DEFAULT,
-            label = "Observer queue size",
-            description = "Observer queue size. Used if 'enableAsyncObserver' 
is set to true"
-    )
-    private static final String PROP_OBSERVER_QUEUE_SIZE = "observerQueueSize";
+    private volatile DocumentNodeStore documentNodeStore;
 
     private final List<Registration> oakRegs = Lists.newArrayList();
 
@@ -129,10 +126,10 @@ public class SecondaryStoreCacheService
     private final MultiplexingNodeStateDiffer differ = new 
MultiplexingNodeStateDiffer();
 
     @Activate
-    private void activate(BundleContext context, Map<String, Object> config){
+    private void activate(BundleContext context, Configuration config){
         bundleContext = context;
         whiteboard = new OsgiWhiteboard(context);
-        String[] includedPaths = toStringArray(config.get(PROP_INCLUDES), new 
String[]{"/"});
+        String[] includedPaths = config.includedPaths();
 
         //TODO Support for exclude is not possible as once a NodeState is 
loaded from secondary
         //store it assumes that complete subtree is in same store. With 
exclude it would need to
@@ -180,9 +177,9 @@ public class SecondaryStoreCacheService
 
     //~----------------------------------------------------< internal >
 
-    private void registerObserver(Observer observer, Map<String, Object> 
config) {
-        boolean enableAsyncObserver = 
toBoolean(config.get(PROP_ASYNC_OBSERVER), PROP_ASYNC_OBSERVER_DEFAULT);
-        int  queueSize = toInteger(config.get(PROP_OBSERVER_QUEUE_SIZE), 
PROP_OBSERVER_QUEUE_SIZE_DEFAULT);
+    private void registerObserver(Observer observer, Configuration config) {
+        boolean enableAsyncObserver = config.enableAsyncObserver();
+        int  queueSize = config.observerQueueSize();
         if (enableAsyncObserver){
             BackgroundObserver bgObserver = new BackgroundObserver(observer, 
executor, queueSize);
             oakRegs.add(registerMBean(whiteboard,

Modified: jackrabbit/oak/trunk/oak-store-spi/pom.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-spi/pom.xml?rev=1810002&r1=1810001&r2=1810002&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-store-spi/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-store-spi/pom.xml Thu Sep 28 14:09:26 2017
@@ -91,11 +91,6 @@
       <artifactId>org.osgi.compendium</artifactId>
       <scope>provided</scope>
     </dependency>
-    <dependency>
-      <groupId>org.apache.felix</groupId>
-      <artifactId>org.apache.felix.scr.annotations</artifactId>
-      <scope>provided</scope>
-    </dependency>
 
     <!-- Dependencies to other Oak components -->
     <dependency>


Reply via email to