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 to...@apache.org on 2016/09/21 12:35:02 UTC
svn commit: r1761723 - in /jackrabbit/oak/trunk:
oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java
oak-segment/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreFactory.java
Author: tomekr
Date: Wed Sep 21 12:35:02 2016
New Revision: 1761723
URL: http://svn.apache.org/viewvc?rev=1761723&view=rev
Log:
OAK-4655: Enable configuring multiple segment nodestore instances in same setup
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java
jackrabbit/oak/trunk/oak-segment/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreFactory.java
Added: 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=1761723&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java (added)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreFactory.java Wed Sep 21 12:35:02 2016
@@ -0,0 +1,308 @@
+/*
+ * 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 com.google.common.base.Preconditions.checkState;
+import static org.apache.jackrabbit.oak.osgi.OsgiUtil.lookupConfigurationThenFramework;
+import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
+import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+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.jackrabbit.oak.commons.PropertiesUtil;
+import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
+import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder;
+import org.apache.jackrabbit.oak.segment.file.FileStoreStatsMBean;
+import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.spi.state.NodeStoreProvider;
+import org.apache.jackrabbit.oak.spi.state.ProxyNodeStore;
+import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardExecutor;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A factory allowing creation of secondary segment node stores.
+ * <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."
+)
+public class SegmentNodeStoreFactory extends ProxyNodeStore
+ implements SegmentStoreProvider {
+
+ public static final String NAME = "name";
+
+ @Property(
+ label = "Role",
+ description="As multiple SegmentNodeStores can be configured, this parameter defines the role " +
+ "of 'this' SegmentNodeStore."
+ )
+ public static final String ROLE = "nsProvider.role";
+
+ @Property(
+ label = "Directory",
+ description="Directory location used to store the segment tar files. If not specified then looks " +
+ "for framework property 'repository.home' otherwise use a subdirectory with name 'tarmk'"
+ )
+ public static final String DIRECTORY = "repository.home";
+
+ @Property(
+ label = "Mode",
+ description="TarMK mode (64 for memory mapping, 32 for normal file access)"
+ )
+ public static final String MODE = "tarmk.mode";
+
+ @Property(
+ intValue = 256,
+ label = "Maximum Tar File Size (MB)",
+ description = "TarMK maximum file size (MB)"
+ )
+ public static final String SIZE = "tarmk.size";
+
+ @Property(
+ intValue = 256,
+ label = "Cache size (MB)",
+ description = "Cache size for storing most recently used Segments"
+ )
+ public static final String CACHE = "cache";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private String name;
+
+ private FileStore store;
+
+ private volatile SegmentNodeStore segmentNodeStore;
+
+ private ComponentContext context;
+
+ @Reference
+ private StatisticsProvider statisticsProvider = StatisticsProvider.NOOP;
+
+ private ServiceRegistration storeRegistration;
+ private Registration fileStoreStatsMBean;
+ private WhiteboardExecutor executor;
+
+ @Override
+ protected SegmentNodeStore getNodeStore() {
+ checkState(segmentNodeStore != null, "service must be activated when used");
+ return segmentNodeStore;
+ }
+
+ private String getRole() {
+ String role = PropertiesUtil.toString(property(ROLE), null);
+ return role;
+ }
+
+ @Activate
+ public void activate(ComponentContext context) throws IOException {
+ this.context = context;
+ log.info("activate: SegmentNodeStore '"+getRole()+"' starting.");
+
+ registerNodeStore();
+ }
+
+ @Deactivate
+ public void deactivate() {
+ unregisterNodeStore();
+
+ synchronized (this) {
+ segmentNodeStore = null;
+
+ if (store != null) {
+ store.close();
+ store = null;
+ }
+ }
+ }
+
+ private synchronized void registerNodeStore() throws IOException {
+ if (registerSegmentStore()) {
+
+ if (getRole() != null) {
+ registerNodeStoreProvider();
+ return;
+ }
+
+ }
+ }
+
+ private void registerNodeStoreProvider() {
+ SegmentNodeStore.SegmentNodeStoreBuilder nodeStoreBuilder = SegmentNodeStoreBuilders.builder(store);
+ segmentNodeStore = nodeStoreBuilder.build();
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put(NodeStoreProvider.ROLE, getRole());
+ storeRegistration = context.getBundleContext().registerService(NodeStoreProvider.class.getName(), new NodeStoreProvider() {
+ @Override
+ public NodeStore getNodeStore() {
+ return SegmentNodeStoreFactory.this;
+ }
+ },
+ props);
+ log.info("Registered NodeStoreProvider backed by SegmentNodeStore of type '{}'", getRole());
+ }
+
+ private boolean registerSegmentStore() throws IOException {
+ if (context == null) {
+ log.info("Component still not activated. Ignoring the initialization call");
+ return false;
+ }
+
+ OsgiWhiteboard whiteboard = new OsgiWhiteboard(context.getBundleContext());
+
+ // Build the FileStore
+
+ FileStoreBuilder builder = fileStoreBuilder(getDirectory())
+ .withSegmentCacheSize(getCacheSize())
+ .withMaxFileSize(getMaxFileSize())
+ .withMemoryMapping(getMode().equals("64"))
+ .withStatisticsProvider(statisticsProvider);
+
+ try {
+ store = builder.build();
+ } catch (InvalidFileStoreVersionException e) {
+ log.error("The segment store data is not compatible with the current version. Please use oak-segment-tar or a different version of oak-segment.");
+ return false;
+ }
+
+ // Listen for Executor services on the whiteboard
+
+ executor = new WhiteboardExecutor();
+ executor.start(whiteboard);
+
+ // Expose statistics about the FileStore
+
+ fileStoreStatsMBean = registerMBean(
+ whiteboard,
+ FileStoreStatsMBean.class,
+ store.getStats(),
+ FileStoreStatsMBean.TYPE,
+ "FileStore '" + getRole() + "' statistics"
+ );
+
+ return true;
+ }
+
+ private void unregisterNodeStore() {
+ if (storeRegistration != null) {
+ storeRegistration.unregister();
+ storeRegistration = null;
+ }
+ if (fileStoreStatsMBean != null) {
+ fileStoreStatsMBean.unregister();
+ fileStoreStatsMBean = null;
+ }
+ if (executor != null) {
+ executor.stop();
+ executor = null;
+ }
+ }
+
+ private File getBaseDirectory() {
+ String directory = property(DIRECTORY);
+
+ if (directory != null) {
+ return new File(directory);
+ }
+
+ return new File("tarmk");
+ }
+
+ private File getDirectory() {
+ return new File(getBaseDirectory(), "segmentstore");
+ }
+
+ private String getMode() {
+ String mode = property(MODE);
+
+ if (mode != null) {
+ return mode;
+ }
+
+ return System.getProperty(MODE, System.getProperty("sun.arch.data.model", "32"));
+ }
+
+ private String getCacheSizeProperty() {
+ String cache = property(CACHE);
+
+ if (cache != null) {
+ return cache;
+ }
+
+ return System.getProperty(CACHE);
+ }
+
+ private int getCacheSize() {
+ return Integer.parseInt(getCacheSizeProperty());
+ }
+
+ private String getMaxFileSizeProperty() {
+ String size = property(SIZE);
+
+ if (size != null) {
+ return size;
+ }
+
+ return System.getProperty(SIZE, "256");
+ }
+
+ private int getMaxFileSize() {
+ return Integer.parseInt(getMaxFileSizeProperty());
+ }
+
+ private String property(String name) {
+ return lookupConfigurationThenFramework(context, name);
+ }
+
+ /**
+ * needed for situations where you have to unwrap the
+ * SegmentNodeStoreService, to get the SegmentStore, like the failover
+ */
+ @Override
+ public SegmentStore getSegmentStore() {
+ return store;
+ }
+
+ //------------------------------------------------------------< Object >--
+
+ @Override
+ public String toString() {
+ return name + ": " + segmentNodeStore + "[role:" + getRole() + "]";
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-segment/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreFactory.java?rev=1761723&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-segment/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreFactory.java (added)
+++ jackrabbit/oak/trunk/oak-segment/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreFactory.java Wed Sep 21 12:35:02 2016
@@ -0,0 +1,307 @@
+/*
+ * 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.plugins.segment;
+
+import static com.google.common.base.Preconditions.checkState;
+import static org.apache.jackrabbit.oak.osgi.OsgiUtil.lookupConfigurationThenFramework;
+import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+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.jackrabbit.oak.commons.PropertiesUtil;
+import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore.Builder;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStoreStatsMBean;
+import org.apache.jackrabbit.oak.plugins.segment.file.InvalidFileStoreVersionException;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.spi.state.NodeStoreProvider;
+import org.apache.jackrabbit.oak.spi.state.ProxyNodeStore;
+import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardExecutor;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A factory allowing creation of secondary segment node stores.
+ * <p>
+ * The different secondaries are distinguished by their role attribute.
+ */
+@Component(policy = ConfigurationPolicy.REQUIRE,
+ name="org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStoreFactory",
+ configurationFactory=true,
+ metatype = true,
+ label = "Apache Jackrabbit Oak Segment NodeStore Factory",
+ description = "Factory allowing configuration of adjacent instances of " +
+ "NodeStore implementation based on Segment model besides a default SegmentNodeStore in same setup."
+)
+public class SegmentNodeStoreFactory extends ProxyNodeStore
+ implements SegmentStoreProvider {
+
+ public static final String NAME = "name";
+
+ @Property(
+ label = "Role",
+ description="As multiple SegmentNodeStores can be configured, this parameter defines the role " +
+ "of 'this' SegmentNodeStore."
+ )
+ public static final String ROLE = "nsProvider.role";
+
+ @Property(
+ label = "Directory",
+ description="Directory location used to store the segment tar files. If not specified then looks " +
+ "for framework property 'repository.home' otherwise use a subdirectory with name 'tarmk'"
+ )
+ public static final String DIRECTORY = "repository.home";
+
+ @Property(
+ label = "Mode",
+ description="TarMK mode (64 for memory mapping, 32 for normal file access)"
+ )
+ public static final String MODE = "tarmk.mode";
+
+ @Property(
+ intValue = 256,
+ label = "Maximum Tar File Size (MB)",
+ description = "TarMK maximum file size (MB)"
+ )
+ public static final String SIZE = "tarmk.size";
+
+ @Property(
+ intValue = 256,
+ label = "Cache size (MB)",
+ description = "Cache size for storing most recently used Segments"
+ )
+ public static final String CACHE = "cache";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private String name;
+
+ private FileStore store;
+
+ private volatile SegmentNodeStore segmentNodeStore;
+
+ private ComponentContext context;
+
+ @Reference
+ private StatisticsProvider statisticsProvider = StatisticsProvider.NOOP;
+
+ private ServiceRegistration storeRegistration;
+ private Registration fileStoreStatsMBean;
+ private WhiteboardExecutor executor;
+
+ @Override
+ protected SegmentNodeStore getNodeStore() {
+ checkState(segmentNodeStore != null, "service must be activated when used");
+ return segmentNodeStore;
+ }
+
+ private String getRole() {
+ String role = PropertiesUtil.toString(property(ROLE), null);
+ return role;
+ }
+
+ @Activate
+ public void activate(ComponentContext context) throws IOException {
+ this.context = context;
+ log.info("activate: SegmentNodeStore '"+getRole()+"' starting.");
+
+ registerNodeStore();
+ }
+
+ @Deactivate
+ public void deactivate() {
+ unregisterNodeStore();
+
+ synchronized (this) {
+ segmentNodeStore = null;
+
+ if (store != null) {
+ store.close();
+ store = null;
+ }
+ }
+ }
+
+ private synchronized void registerNodeStore() throws IOException {
+ if (registerSegmentStore()) {
+
+ if (getRole() != null) {
+ registerNodeStoreProvider();
+ return;
+ }
+
+ }
+ }
+
+ private void registerNodeStoreProvider() {
+ SegmentNodeStore.SegmentNodeStoreBuilder nodeStoreBuilder = SegmentNodeStore.builder(store);
+ segmentNodeStore = nodeStoreBuilder.build();
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put(NodeStoreProvider.ROLE, getRole());
+ storeRegistration = context.getBundleContext().registerService(NodeStoreProvider.class.getName(), new NodeStoreProvider() {
+ @Override
+ public NodeStore getNodeStore() {
+ return SegmentNodeStoreFactory.this;
+ }
+ },
+ props);
+ log.info("Registered NodeStoreProvider backed by SegmentNodeStore of type '{}'", getRole());
+ }
+
+ private boolean registerSegmentStore() throws IOException {
+ if (context == null) {
+ log.info("Component still not activated. Ignoring the initialization call");
+ return false;
+ }
+
+ OsgiWhiteboard whiteboard = new OsgiWhiteboard(context.getBundleContext());
+
+ // Build the FileStore
+
+ Builder builder = FileStore.builder(getDirectory())
+ .withCacheSize(getCacheSize())
+ .withMaxFileSize(getMaxFileSize())
+ .withMemoryMapping(getMode().equals("64"))
+ .withStatisticsProvider(statisticsProvider);
+
+ try {
+ store = builder.build();
+ } catch (InvalidFileStoreVersionException e) {
+ log.error("The segment store data is not compatible with the current version. Please use oak-segment-tar or a different version of oak-segment.");
+ return false;
+ }
+
+ // Listen for Executor services on the whiteboard
+
+ executor = new WhiteboardExecutor();
+ executor.start(whiteboard);
+
+ // Expose statistics about the FileStore
+
+ fileStoreStatsMBean = registerMBean(
+ whiteboard,
+ FileStoreStatsMBean.class,
+ store.getStats(),
+ FileStoreStatsMBean.TYPE,
+ "FileStore '" + getRole() + "' statistics"
+ );
+
+ return true;
+ }
+
+ private void unregisterNodeStore() {
+ if (storeRegistration != null) {
+ storeRegistration.unregister();
+ storeRegistration = null;
+ }
+ if (fileStoreStatsMBean != null) {
+ fileStoreStatsMBean.unregister();
+ fileStoreStatsMBean = null;
+ }
+ if (executor != null) {
+ executor.stop();
+ executor = null;
+ }
+ }
+
+ private File getBaseDirectory() {
+ String directory = property(DIRECTORY);
+
+ if (directory != null) {
+ return new File(directory);
+ }
+
+ return new File("tarmk");
+ }
+
+ private File getDirectory() {
+ return new File(getBaseDirectory(), "segmentstore");
+ }
+
+ private String getMode() {
+ String mode = property(MODE);
+
+ if (mode != null) {
+ return mode;
+ }
+
+ return System.getProperty(MODE, System.getProperty("sun.arch.data.model", "32"));
+ }
+
+ private String getCacheSizeProperty() {
+ String cache = property(CACHE);
+
+ if (cache != null) {
+ return cache;
+ }
+
+ return System.getProperty(CACHE);
+ }
+
+ private int getCacheSize() {
+ return Integer.parseInt(getCacheSizeProperty());
+ }
+
+ private String getMaxFileSizeProperty() {
+ String size = property(SIZE);
+
+ if (size != null) {
+ return size;
+ }
+
+ return System.getProperty(SIZE, "256");
+ }
+
+ private int getMaxFileSize() {
+ return Integer.parseInt(getMaxFileSizeProperty());
+ }
+
+ private String property(String name) {
+ return lookupConfigurationThenFramework(context, name);
+ }
+
+ /**
+ * needed for situations where you have to unwrap the
+ * SegmentNodeStoreService, to get the SegmentStore, like the failover
+ */
+ @Override
+ public SegmentStore getSegmentStore() {
+ return store;
+ }
+
+ //------------------------------------------------------------< Object >--
+
+ @Override
+ public String toString() {
+ return name + ": " + segmentNodeStore + "[role:" + getRole() + "]";
+ }
+
+}