Author: amitj
Date: Wed Sep 14 09:03:33 2016
New Revision: 1760661
URL: http://svn.apache.org/viewvc?rev=1760661&view=rev
Log:
OAK-4712: Publish S3DataStore stats in JMX MBean
Modified patch from Matt Ryan
Added:
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/aws/s3/stats/
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/aws/s3/stats/S3DataStoreStatsMBean.java
(with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreStats.java
(with props)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreStatsTest.java
(with props)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentS3DataStoreStatsTest.java
(with props)
jackrabbit/oak/trunk/oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentS3DataStoreStatsTest.java
(with props)
Modified:
jackrabbit/oak/trunk/oak-blob-cloud/pom.xml
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/aws/s3/S3DataStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreService.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/SharedS3DataStoreService.java
Modified: jackrabbit/oak/trunk/oak-blob-cloud/pom.xml
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud/pom.xml?rev=1760661&r1=1760660&r2=1760661&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-cloud/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-blob-cloud/pom.xml Wed Sep 14 09:03:33 2016
@@ -41,7 +41,7 @@
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
-
<Export-Package>org.apache.jackrabbit.oak.blob.cloud.aws.s3</Export-Package>
+
<Export-Package>org.apache.jackrabbit.oak.blob.cloud.aws.s3,org.apache.jackrabbit.oak.blob.cloud.aws.s3.stats</Export-Package>
<DynamicImport-Package>sun.io</DynamicImport-Package>
</instructions>
</configuration>
@@ -101,6 +101,13 @@
<version>${jackrabbit.version}</version>
</dependency>
+ <!-- Dependencies to other Oak components -->
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>oak-commons</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
<!-- Amazon AWS dependency -->
<dependency>
<groupId>com.amazonaws</groupId>
Modified:
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/aws/s3/S3DataStore.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/aws/s3/S3DataStore.java?rev=1760661&r1=1760660&r2=1760661&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/aws/s3/S3DataStore.java
(original)
+++
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/aws/s3/S3DataStore.java
Wed Sep 14 09:03:33 2016
@@ -17,14 +17,26 @@
package org.apache.jackrabbit.oak.blob.cloud.aws.s3;
import java.util.Properties;
+
+import com.google.common.base.Strings;
import org.apache.jackrabbit.core.data.Backend;
import org.apache.jackrabbit.core.data.CachingDataStore;
+import org.apache.jackrabbit.core.data.DataIdentifier;
+import org.apache.jackrabbit.core.data.DataStoreException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* An Amazon S3 data store.
*/
public class S3DataStore extends CachingDataStore {
+
+ /**
+ * Logger instance.
+ */
+ private static final Logger LOG =
LoggerFactory.getLogger(S3DataStore.class);
+
protected Properties properties;
@Override
@@ -47,4 +59,24 @@ public class S3DataStore extends Caching
public void setProperties(Properties properties) {
this.properties = properties;
}
+
+ /**
+ * Look in the backend for a record matching the given identifier.
Returns true
+ * if such a record exists.
+ *
+ * @param identifier - An identifier for the record.
+ * @return true if a record for the provided identifier can be found.
+ */
+ public boolean haveRecordForIdentifier(final String identifier) {
+ try {
+ if (!Strings.isNullOrEmpty(identifier)) {
+ return this.getBackend().exists(new
DataIdentifier(identifier));
+ }
+ }
+ catch (DataStoreException e) {
+ LOG.warn(String.format("Data Store Exception caught checking for
%s in pending uploads",
+ identifier), e);
+ }
+ return false;
+ }
}
Added:
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/aws/s3/stats/S3DataStoreStatsMBean.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/aws/s3/stats/S3DataStoreStatsMBean.java?rev=1760661&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/aws/s3/stats/S3DataStoreStatsMBean.java
(added)
+++
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/aws/s3/stats/S3DataStoreStatsMBean.java
Wed Sep 14 09:03:33 2016
@@ -0,0 +1,44 @@
+/*
+ * 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.blob.cloud.aws.s3.stats;
+
+/**
+ * MBean for JMX statistics pertaining to an S3DataStore.
+ */
+public interface S3DataStoreStatsMBean {
+ String TYPE = "S3DataStoreStats";
+
+ /**
+ * Obtains the number of records that are in the process
+ * of being "synced", meaning they are either scheduled to
+ * be copied to S3 or are actively being copied to S3
+ * but the copy of these files has not yet completed.
+ *
+ * @return number of syncs in progress (active).
+ */
+ long getActiveSyncs();
+
+ /**
+ * Determines whether a file-like entity with the given name
+ * has been "synced" (completely copied) to S3.
+ *
+ * @param nodePathName - Path to the entity to check. This is
+ * the repository node path, not an external file
path.
+ * @return true if the file is synced to S3.
+ */
+ boolean isFileSynced(final String nodePathName);
+}
Propchange:
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/aws/s3/stats/S3DataStoreStatsMBean.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreService.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreService.java?rev=1760661&r1=1760660&r2=1760661&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreService.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreService.java
Wed Sep 14 09:03:33 2016
@@ -19,18 +19,25 @@
package org.apache.jackrabbit.oak.plugins.blob.datastore;
+import java.util.Dictionary;
+import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.jackrabbit.core.data.DataStore;
-import org.apache.jackrabbit.oak.blob.cloud.aws.s3.S3DataStore;
+import org.apache.jackrabbit.core.data.DataStoreException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
@Component(policy = ConfigurationPolicy.REQUIRE, name =
S3DataStoreService.NAME)
public class S3DataStoreService extends AbstractDataStoreService{
public static final String NAME =
"org.apache.jackrabbit.oak.plugins.blob.datastore.S3DataStore";
+ private static final String DESCRIPTION = "oak.datastore.description";
+
+ private ServiceRegistration delegateReg;
@Override
protected DataStore createDataStore(ComponentContext context, Map<String,
Object> config) {
@@ -40,9 +47,26 @@ public class S3DataStoreService extends
properties.putAll(config);
dataStore.setProperties(properties);
+
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put(Constants.SERVICE_PID, dataStore.getClass().getName());
+ props.put(DESCRIPTION, getDescription());
+
+ delegateReg = context.getBundleContext().registerService(new String[] {
+ SharedS3DataStore.class.getName(),
+ SharedS3DataStore.class.getName()
+ }, dataStore , props);
+
return dataStore;
}
+ protected void deactivate() throws DataStoreException {
+ if (delegateReg != null) {
+ delegateReg.unregister();
+ }
+ super.deactivate();
+ }
+
@Override
protected String[] getDescription() {
return new String[] {"type=S3"};
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreStats.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreStats.java?rev=1760661&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreStats.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreStats.java
Wed Sep 14 09:03:33 2016
@@ -0,0 +1,174 @@
+/*
+ * 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.blob.datastore;
+
+import com.google.common.base.Strings;
+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.jackrabbit.oak.api.Blob;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.blob.cloud.aws.s3.stats.S3DataStoreStatsMBean;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.osgi.framework.BundleContext;
+
+import java.util.List;
+
+import static
org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
+
+@Component
+public class S3DataStoreStats implements S3DataStoreStatsMBean {
+
+ private Registration mbeanReg;
+
+ @Reference
+ protected SharedS3DataStore s3ds;
+
+ @Reference
+ protected NodeStore nodeStore;
+
+ @Activate
+ private void activate(BundleContext context){
+ Whiteboard wb = new OsgiWhiteboard(context);
+ mbeanReg = registerMBean(wb,
+ S3DataStoreStatsMBean.class,
+ this,
+ S3DataStoreStatsMBean.TYPE,
+ "S3 DataStore statistics");
+ }
+
+ @Deactivate
+ private void deactivate(){
+ if(mbeanReg != null){
+ mbeanReg.unregister();
+ }
+ }
+
+ /**
+ * Obtains the number of records that are in the process
+ * of being "synced", meaning they are either scheduled to
+ * be copied to S3 or are actively being copied to S3
+ * but the copy of these files has not yet completed.
+ *
+ * @return number of syncs in progress (active).
+ */
+ @Override
+ public long getActiveSyncs() {
+ return s3ds.getPendingUploads().size();
+ }
+
+ /**
+ * Determines whether a file-like entity with the given name
+ * has been "synced" (completely copied) to S3.
+ *
+ * Determination of "synced":
+ * - A nodeName of null or "" is always "not synced".
+ * - A nodeName that does not map to a valid node is always "not synced".
+ * - If the node for this nodeName does not have a binary property,
+ * this node is always "not synced" since such a node would never be
+ * copied to S3.
+ * - If the node for this nodeName is not in the nodeStore, this node is
+ * always "not synced".
+ * - Otherwise, the state is "synced" if the corresponding blob is
+ * completely stored in S3.
+ *
+ * @param nodePathName - Path to the entity to check. This is
+ * a node path, not an external file path.
+ * @return true if the file is synced to S3.
+ */
+ @Override
+ public boolean isFileSynced(final String nodePathName) {
+ if (Strings.isNullOrEmpty(nodePathName)) {
+ return false;
+ }
+
+ if (null == nodeStore) {
+ return false;
+ }
+
+ final NodeState leafNode = findLeafNode(nodePathName);
+ if (!leafNode.exists()) {
+ return false;
+ }
+
+ boolean nodeHasBinaryProperties = false;
+ for (final PropertyState propertyState : leafNode.getProperties()) {
+ nodeHasBinaryProperties |= (propertyState.getType() == Type.BINARY
|| propertyState.getType() == Type.BINARIES);
+ try {
+ if (propertyState.getType() == Type.BINARY) {
+ final Blob blob = (Blob)
propertyState.getValue(propertyState.getType());
+ if (null == blob || !haveRecordForBlob(blob)) {
+ return false;
+ }
+ } else if (propertyState.getType() == Type.BINARIES) {
+ final List<Blob> blobs = (List<Blob>)
propertyState.getValue(propertyState.getType());
+ if (null == blobs) {
+ return false;
+ }
+ for (final Blob blob : blobs) {
+ if (!haveRecordForBlob(blob)) {
+ return false;
+ }
+ }
+ }
+ }
+ catch (ClassCastException e) {
+ return false;
+ }
+ }
+
+ // If we got here and nodeHasBinaryProperties is true,
+ // it means at least one binary property was found for
+ // the leaf node and that we were able to locate a
+ // records for binaries found.
+ return nodeHasBinaryProperties;
+ }
+
+ private NodeState findLeafNode(final String nodePathName) {
+ final Iterable<String> pathNodes =
PathUtils.elements(PathUtils.getParentPath(nodePathName));
+ final String leafNodeName = PathUtils.getName(nodePathName);
+
+ NodeState currentNode = nodeStore.getRoot();
+ for (String pathNodeName : pathNodes) {
+ if (pathNodeName.length() > 0) {
+ NodeState childNode = currentNode.getChildNode(pathNodeName);
+ if (!childNode.exists()) {
+ break;
+ }
+ currentNode = childNode;
+ }
+ }
+ return currentNode.getChildNode(leafNodeName);
+ }
+
+ private boolean haveRecordForBlob(final Blob blob) {
+ final String fullBlobId = blob.getContentIdentity();
+ if (!Strings.isNullOrEmpty(fullBlobId)
+ && !InMemoryDataRecord.isInstance(fullBlobId)) {
+ String blobId = DataStoreBlobStore.BlobId.of(fullBlobId).blobId;
+ return s3ds.haveRecordForIdentifier(blobId);
+ }
+ return false;
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreStats.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/SharedS3DataStoreService.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/SharedS3DataStoreService.java?rev=1760661&r1=1760660&r2=1760661&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/SharedS3DataStoreService.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/SharedS3DataStoreService.java
Wed Sep 14 09:03:33 2016
@@ -22,14 +22,22 @@ package org.apache.jackrabbit.oak.plugin
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.jackrabbit.core.data.DataStore;
+import org.apache.jackrabbit.core.data.DataStoreException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
+import java.util.Dictionary;
+import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
@Component(policy = ConfigurationPolicy.REQUIRE, name =
SharedS3DataStoreService.NAME)
public class SharedS3DataStoreService extends AbstractDataStoreService{
public static final String NAME =
"org.apache.jackrabbit.oak.plugins.blob.datastore.SharedS3DataStore";
+ private static final String DESCRIPTION = "oak.datastore.description";
+
+ private ServiceRegistration delegateReg;
@Override
protected DataStore createDataStore(ComponentContext context, Map<String,
Object> config) {
@@ -39,9 +47,26 @@ public class SharedS3DataStoreService ex
properties.putAll(config);
dataStore.setProperties(properties);
+
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put(Constants.SERVICE_PID, dataStore.getClass().getName());
+ props.put(DESCRIPTION, getDescription());
+
+ delegateReg = context.getBundleContext().registerService(new String[] {
+ SharedS3DataStore.class.getName(),
+ SharedS3DataStore.class.getName()
+ }, dataStore , props);
+
return dataStore;
}
+ protected void deactivate() throws DataStoreException {
+ if (delegateReg != null) {
+ delegateReg.unregister();
+ }
+ super.deactivate();
+ }
+
@Override
protected String[] getDescription() {
return new String[] {"type=SharedS3"};
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreStatsTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreStatsTest.java?rev=1760661&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreStatsTest.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreStatsTest.java
Wed Sep 14 09:03:33 2016
@@ -0,0 +1,438 @@
+/*
+ * 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.blob.datastore;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.DigestOutputStream;
+import java.security.MessageDigest;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import com.amazonaws.util.StringInputStream;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.core.data.AsyncTouchCallback;
+import org.apache.jackrabbit.core.data.AsyncTouchResult;
+import org.apache.jackrabbit.core.data.AsyncUploadCallback;
+import org.apache.jackrabbit.core.data.AsyncUploadResult;
+import org.apache.jackrabbit.core.data.Backend;
+import org.apache.jackrabbit.core.data.CachingDataStore;
+import org.apache.jackrabbit.core.data.DataIdentifier;
+import org.apache.jackrabbit.core.data.DataRecord;
+import org.apache.jackrabbit.core.data.DataStoreException;
+import org.apache.jackrabbit.oak.api.Blob;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.joda.time.DateTime;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static org.apache.commons.codec.binary.Hex.encodeHexString;
+import static org.apache.commons.io.FileUtils.copyInputStreamToFile;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class S3DataStoreStatsTest {
+ @Rule public TemporaryFolder folder = new TemporaryFolder(new
File("target")) {
+ @Override public void delete() {
+ }
+ };
+
+ private NodeStore mockNodeStore;
+
+ private static String testNodePathName = "test/node/path/name";
+ private File testFile;
+
+ private SharedS3DataStore defaultS3ds;
+ private SharedS3DataStore autoSyncMockS3ds;
+ private SharedS3DataStore manualSyncMockS3ds;
+ private S3DataStoreStats mBean;
+
+ @Before
+ public void setup() throws Exception {
+ testFile = folder.newFile();
+ copyInputStreamToFile(randomStream(0, 16384), testFile);
+ mockNodeStore = mock(NodeStore.class);
+ MessageDigest digest = MessageDigest.getInstance("SHA-1");
+ OutputStream output = new DigestOutputStream(new
FileOutputStream(testFile), digest);
+ FileInputStream inputStream = null;
+ try {
+ inputStream = new FileInputStream(testFile);
+ IOUtils.copyLarge(inputStream, output);
+ } finally {
+ IOUtils.closeQuietly(output);
+ IOUtils.closeQuietly(inputStream);
+ }
+ String testNodeId = encodeHexString(digest.digest());
+
+ mockNodeStore = mock(NodeStore.class);
+ final NodeState mockRootState = mock(NodeState.class);
+ final NodeState mockLeafState = mock(NodeState.class);
+ final PropertyState mockLeafPropertyState = mock(PropertyState.class);
+ final Blob mockBlob = mock(Blob.class);
+ when(mockNodeStore.getRoot()).thenReturn(mockRootState);
+
when(mockRootState.getChildNode(anyString())).thenReturn(mockLeafState);
+
when(mockLeafState.getChildNode(anyString())).thenReturn(mockLeafState);
+ when(mockLeafState.exists()).thenReturn(true);
+
when(mockLeafState.getProperty(anyString())).thenReturn(mockLeafPropertyState);
+
doReturn(Lists.newArrayList(mockLeafPropertyState)).when(mockLeafState).getProperties();
+ doReturn(Type.BINARY).when(mockLeafPropertyState).getType();
+ when(mockLeafPropertyState.getValue(Type.BINARY)).thenReturn(mockBlob);
+ when(mockBlob.getContentIdentity()).thenReturn(testNodeId);
+
+ defaultS3ds = mock(SharedS3DataStore.class);
+ defaultS3ds.init(folder.newFolder().getAbsolutePath());
+ autoSyncMockS3ds = new CustomBackendS3DataStore(new
TestMemoryBackend());
+ autoSyncMockS3ds.init(folder.newFolder().getAbsolutePath());
+ manualSyncMockS3ds = new CustomBackendS3DataStore(new
ManuallySyncingInMemoryBackend());
+ manualSyncMockS3ds.init(folder.newFolder().getAbsolutePath());
+ }
+
+ @After
+ public void teardown() throws Exception {
+ }
+
+ @Test public void testGetActiveS3FileSyncMetricExists()
+ throws Exception {
+
+ mBean = new S3DataStoreStats();
+ mBean.nodeStore = mockNodeStore;
+ mBean.s3ds = defaultS3ds;
+
+ assertTrue(0 == mBean.getActiveSyncs());
+ }
+
+ @Test
+ public void testGetSingleActiveS3FileSyncMetric()
+ throws Exception {
+
+ mBean = new S3DataStoreStats();
+ mBean.nodeStore = mockNodeStore;
+ mBean.s3ds = manualSyncMockS3ds;
+
+ DataRecord record = null;
+ try {
+ record = manualSyncMockS3ds.addRecord(new
StringInputStream("test"));
+ assertTrue(1 == mBean.getActiveSyncs());
+ } finally {
+ if (null != record) {
+ manualSyncMockS3ds.deleteRecord(record.getIdentifier());
+ }
+ }
+
+ ((ManuallySyncingInMemoryBackend)
manualSyncMockS3ds.getBackend()).clearInProgressWrites();
+
+ assertTrue(0 == mBean.getActiveSyncs());
+ }
+
+ @Test
+ public void testGetMultilpleActiveS3FileSyncMetric()
+ throws Exception {
+
+ mBean = new S3DataStoreStats();
+ mBean.nodeStore = mockNodeStore;
+ mBean.s3ds = manualSyncMockS3ds;
+
+ final Set<DataRecord> records = Sets.newHashSet();
+ try {
+ records.add(manualSyncMockS3ds.addRecord(new
StringInputStream("test1")));
+ records.add(manualSyncMockS3ds.addRecord(new
StringInputStream("test2")));
+ records.add(manualSyncMockS3ds.addRecord(new
StringInputStream("test3")));
+
+ assertTrue(3 == mBean.getActiveSyncs());
+ } finally {
+ for (final DataRecord record : records) {
+ manualSyncMockS3ds.deleteRecord(record.getIdentifier());
+ }
+ }
+
+ ((ManuallySyncingInMemoryBackend)
manualSyncMockS3ds.getBackend()).clearInProgressWrites();
+
+ assertTrue(0 == mBean.getActiveSyncs());
+ }
+
+ @Test
+ public void testIsFileSyncedMetricExists()
+ throws Exception {
+
+ mBean = new S3DataStoreStats();
+ mBean.nodeStore = mockNodeStore;
+ mBean.s3ds = defaultS3ds;
+
+ assertFalse(mBean.isFileSynced(testNodePathName));
+ }
+
+ @Test
+ public void testIsFileSyncedNullFileReturnsFalse()
+ throws Exception {
+ mBean = new S3DataStoreStats();
+ mBean.nodeStore = mockNodeStore;
+ mBean.s3ds = defaultS3ds;
+
+ assertFalse(mBean.isFileSynced(null));
+ }
+
+ @Test
+ public void testIsFileSyncedEmptyStringReturnsFalse()
+ throws Exception {
+ mBean = new S3DataStoreStats();
+ mBean.nodeStore = mockNodeStore;
+ mBean.s3ds = defaultS3ds;
+
+ assertFalse(mBean.isFileSynced(""));
+ }
+
+ @Test
+ public void testIsFileSyncedInvalidFilenameReturnsFalse()
+ throws Exception {
+ mBean = new S3DataStoreStats();
+ mBean.nodeStore = mockNodeStore;
+ mBean.s3ds = defaultS3ds;
+
+ assertFalse(mBean.isFileSynced("invalid"));
+ }
+
+ @Test
+ public void testIsFileSyncedFileNotAddedReturnsFalse()
+ throws Exception {
+ mBean = new S3DataStoreStats();
+ mBean.nodeStore = mockNodeStore;
+ mBean.s3ds = autoSyncMockS3ds;
+
+ assertFalse(mBean.isFileSynced(testNodePathName));
+ }
+
+ @Test
+ public void testIsFileSyncedSyncIncompleteReturnsFalse()
+ throws Exception {
+ mBean = new S3DataStoreStats();
+ mBean.nodeStore = mockNodeStore;
+ mBean.s3ds = manualSyncMockS3ds;
+
+ DataRecord record = null;
+ FileInputStream stream = null;
+ try {
+ stream = new FileInputStream(testFile);
+ record = manualSyncMockS3ds.addRecord(stream);
+ assertFalse(mBean.isFileSynced(testNodePathName));
+ } finally {
+ IOUtils.closeQuietly(stream);
+ if (null != record) {
+ manualSyncMockS3ds.deleteRecord(record.getIdentifier());
+ }
+ }
+ }
+
+ @Test
+ public void testIsFileSyncedSyncCompleteReturnsTrue()
+ throws Exception {
+
+ mBean = new S3DataStoreStats();
+ mBean.nodeStore = mockNodeStore;
+ mBean.s3ds = autoSyncMockS3ds;
+
+ DataRecord record = null;
+ FileInputStream stream = null;
+ try {
+ stream = new FileInputStream(testFile);
+ record = autoSyncMockS3ds.addRecord(stream);
+ assertTrue(mBean.isFileSynced(testNodePathName));
+ } finally {
+ IOUtils.closeQuietly(stream);
+ if (null != record) {
+ autoSyncMockS3ds.deleteRecord(record.getIdentifier());
+ }
+ }
+ }
+
+ @Test
+ public void testIsFileSyncedFileDeletedReturnsFalse()
+ throws Exception {
+ mBean = new S3DataStoreStats();
+ mBean.nodeStore = mockNodeStore;
+ mBean.s3ds = autoSyncMockS3ds;
+
+ DataRecord record = null;
+ FileInputStream stream = null;
+ try {
+ stream = new FileInputStream(testFile);
+ record = autoSyncMockS3ds.addRecord(stream);
+ } finally {
+ IOUtils.closeQuietly(stream);
+ if (null != record) {
+ autoSyncMockS3ds.deleteRecord(record.getIdentifier());
+ }
+ }
+
+ assertFalse(mBean.isFileSynced(testNodePathName));
+ }
+
+
+ // A mock S3DataStore that allows us to replace the default
+ // S3Backend with our own backend, for test purposes only.
+ private class CustomBackendS3DataStore extends SharedS3DataStore {
+ private Backend _localBackend;
+
+ CustomBackendS3DataStore(final Backend backend) {
+ _localBackend = backend;
+ }
+
+ @Override protected Backend createBackend() {
+ return _localBackend;
+ }
+ }
+
+
+ // A mock Backend implementation that uses a Map to keep track of what
+ // records have been added and removed, for test purposes only.
+ private class TestMemoryBackend implements Backend {
+ final Map<DataIdentifier, File> _backend = Maps.newHashMap();
+
+ @Override public void init(CachingDataStore store, String homeDir,
String config)
+ throws DataStoreException {
+
+ }
+
+ @Override public InputStream read(DataIdentifier identifier) throws
DataStoreException {
+ try {
+ return new FileInputStream(_backend.get(identifier));
+ } catch (FileNotFoundException e) {
+ throw new DataStoreException(e);
+ }
+ }
+
+ @Override public long getLength(DataIdentifier identifier) throws
DataStoreException {
+ return _backend.get(identifier).length();
+ }
+
+ @Override public long getLastModified(DataIdentifier identifier)
throws DataStoreException {
+ return _backend.get(identifier).lastModified();
+ }
+
+ @Override public void write(DataIdentifier identifier, File file)
+ throws DataStoreException {
+ _backend.put(identifier, file);
+ }
+
+ @Override public void writeAsync(final DataIdentifier identifier,
final File file,
+ AsyncUploadCallback callback) throws DataStoreException {
+ write(identifier, file);
+ callback.onSuccess(new AsyncUploadResult(identifier, file));
+ }
+
+ @Override public Iterator<DataIdentifier> getAllIdentifiers() throws
DataStoreException {
+ return _backend.keySet().iterator();
+ }
+
+ @Override public boolean exists(DataIdentifier identifier, boolean
touch)
+ throws DataStoreException {
+ if (_backend.containsKey(identifier) && touch) {
+ touch(identifier, new DateTime().getMillis());
+ }
+ return exists(identifier);
+ }
+
+ @Override public boolean exists(DataIdentifier identifier) throws
DataStoreException {
+ return _backend.containsKey(identifier);
+ }
+
+ @Override public void touch(DataIdentifier identifier, long
minModifiedDate)
+ throws DataStoreException {
+
+ }
+
+ @Override public void touchAsync(DataIdentifier identifier, long
minModifiedDate,
+ AsyncTouchCallback callback) throws DataStoreException {
+ callback.onSuccess(new AsyncTouchResult(identifier));
+ }
+
+ @Override public void close() throws DataStoreException {
+
+ }
+
+ @Override public Set<DataIdentifier> deleteAllOlderThan(long timestamp)
+ throws DataStoreException {
+ final Set<DataIdentifier> toDelete = Sets.newHashSet();
+ for (final DataIdentifier identifier : _backend.keySet()) {
+ if (_backend.get(identifier).lastModified() < timestamp) {
+ toDelete.add(identifier);
+ }
+ }
+ for (final DataIdentifier identifier : toDelete) {
+ _backend.remove(identifier);
+ }
+ return toDelete;
+ }
+
+ @Override public void deleteRecord(DataIdentifier identifier) throws
DataStoreException {
+ if (_backend.containsKey(identifier)) {
+ _backend.remove(identifier);
+ }
+ }
+ }
+
+
+ // A modified InMemoryBackend that, when writeAsync() is called, does not
+ // actually store the record but keeps track that it was intended to be
+ // stored, and allows the test to tell it when it expects the record
+ // to be "synced".
+ private class ManuallySyncingInMemoryBackend extends TestMemoryBackend {
+ final Map<DataIdentifier, File> inProgessWrites = Maps.newHashMap();
+ final Map<DataIdentifier, AsyncUploadCallback> asyncCallbacks =
Maps.newHashMap();
+
+ @Override public void writeAsync(final DataIdentifier identifier,
final File file,
+ AsyncUploadCallback callback) throws DataStoreException {
+ inProgessWrites.put(identifier, file);
+ asyncCallbacks.put(identifier, callback);
+ }
+
+ void clearInProgressWrites() throws DataStoreException {
+ for (final DataIdentifier identifier : inProgessWrites.keySet()) {
+ final File file = inProgessWrites.get(identifier);
+ asyncCallbacks.get(identifier).onSuccess(new
AsyncUploadResult(identifier, file));
+ write(identifier, file);
+ }
+ inProgessWrites.clear();
+ }
+ }
+
+ private static InputStream randomStream(int seed, int size) {
+ Random r = new Random(seed);
+ byte[] data = new byte[size];
+ r.nextBytes(data);
+ return new ByteArrayInputStream(data);
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/S3DataStoreStatsTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentS3DataStoreStatsTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentS3DataStoreStatsTest.java?rev=1760661&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentS3DataStoreStatsTest.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentS3DataStoreStatsTest.java
Wed Sep 14 09:03:33 2016
@@ -0,0 +1,134 @@
+/*
+ * 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.document;
+
+import java.util.Map;
+
+import org.apache.jackrabbit.oak.blob.cloud.aws.s3.stats.S3DataStoreStatsMBean;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.S3DataStoreStats;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.SharedS3DataStore;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.apache.sling.testing.mock.osgi.ReferenceViolationException;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.osgi.framework.ServiceRegistration;
+
+import static com.google.common.collect.Maps.newHashMap;
+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 S3DataStoreStatsMbean.
+ */
+public class DocumentS3DataStoreStatsTest {
+
+ @Rule
+ public OsgiContext context = new OsgiContext();
+
+ @Rule
+ public ExpectedException expectedEx = ExpectedException.none();
+
+ @BeforeClass
+ public static void checkMongoDbAvailable() {
+ Assume.assumeTrue(MongoUtils.isAvailable());
+ }
+
+ @Before
+ public void setUp() {
+ context.registerService(StatisticsProvider.class,
StatisticsProvider.NOOP);
+ }
+
+ @Test
+ public void testUseS3BlobStore() {
+ ServiceRegistration delegateReg =
+
context.bundleContext().registerService(SharedS3DataStore.class.getName(),
+ mock(SharedS3DataStore.class), null);
+ assertNotNull(context.getService(SharedS3DataStore.class));
+ registerBlobStore();
+
+ registerDocumentNodeStoreService(true);
+ assertServiceActivated();
+
+ S3DataStoreStats s3DataStoreStats =
+ context.registerInjectActivateService(new S3DataStoreStats(),
null);
+ assertNotNull(context.getService(S3DataStoreStatsMBean.class));
+
+ deactivate(s3DataStoreStats);
+ unregisterDocumentNodeStoreService();
+ unregisterBlobStore();
+ delegateReg.unregister();
+ }
+
+ @Test
+ public void testNoS3BlobStore() {
+ expectedEx.expect(ReferenceViolationException.class);
+
+ registerBlobStore();
+
+ registerDocumentNodeStoreService(true);
+ assertServiceActivated();
+
+ S3DataStoreStats s3DataStoreStats =
+ context.registerInjectActivateService(new S3DataStoreStats(),
null);
+ assertNull(context.getService(S3DataStoreStatsMBean.class));
+
+ unregisterDocumentNodeStoreService();
+ unregisterBlobStore();
+ }
+
+ private DocumentNodeStoreService documentNodeStoreService;
+
+ private void registerDocumentNodeStoreService(boolean customBlobStore) {
+ Map<String, Object> properties = newHashMap();
+
+ properties.put("mongouri", MongoUtils.URL);
+ properties.put("db", MongoUtils.DB);
+ properties.put(DocumentNodeStoreService.CUSTOM_BLOB_STORE,
customBlobStore);
+ documentNodeStoreService =
+ context.registerInjectActivateService(new
DocumentNodeStoreService(), properties);
+ }
+
+ private void unregisterDocumentNodeStoreService() {
+ deactivate(documentNodeStoreService);
+ }
+
+ private ServiceRegistration blobStore;
+
+ private void registerBlobStore() {
+ blobStore = context.bundleContext()
+ .registerService(BlobStore.class.getName(), mock(BlobStore.class),
null);
+ }
+
+ private void unregisterBlobStore() {
+ blobStore.unregister();
+ }
+
+ private void assertServiceActivated() {
+ assertNotNull(context.getService(NodeStore.class));
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentS3DataStoreStatsTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentS3DataStoreStatsTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentS3DataStoreStatsTest.java?rev=1760661&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentS3DataStoreStatsTest.java
(added)
+++
jackrabbit/oak/trunk/oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentS3DataStoreStatsTest.java
Wed Sep 14 09:03:33 2016
@@ -0,0 +1,131 @@
+/*
+ * 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 java.io.File;
+import java.util.Map;
+
+import org.apache.jackrabbit.oak.blob.cloud.aws.s3.stats.S3DataStoreStatsMBean;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.S3DataStoreStats;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.SharedS3DataStore;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.apache.sling.testing.mock.osgi.ReferenceViolationException;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.junit.Before;
+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.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 S3DataStoreStatsMbean.
+ */
+public class SegmentS3DataStoreStatsTest {
+
+ @Rule
+ public OsgiContext context = new OsgiContext();
+
+ @Rule
+ public TemporaryFolder folder = new TemporaryFolder(new File("target"));
+
+ @Rule
+ public ExpectedException expectedEx = ExpectedException.none();
+
+ @Before
+ public void setUp() {
+ context.registerService(StatisticsProvider.class,
StatisticsProvider.NOOP);
+ }
+
+ @Test
+ public void testUseS3BlobStore() {
+ ServiceRegistration delegateReg =
+
context.bundleContext().registerService(SharedS3DataStore.class.getName(),
+ mock(SharedS3DataStore.class), null);
+ assertNotNull(context.getService(SharedS3DataStore.class));
+ registerBlobStore();
+
+ registerSegmentNodeStoreService(true);
+ assertServiceActivated();
+
+ S3DataStoreStats s3DataStoreStats =
+ context.registerInjectActivateService(new S3DataStoreStats(),
null);
+ assertNotNull(context.getService(S3DataStoreStatsMBean.class));
+
+ deactivate(s3DataStoreStats);
+ unregisterSegmentNodeStoreService();
+ unregisterBlobStore();
+ delegateReg.unregister();
+ }
+
+ @Test
+ public void testNoS3BlobStore() {
+ expectedEx.expect(ReferenceViolationException.class);
+
+ registerBlobStore();
+
+ registerSegmentNodeStoreService(true);
+ assertServiceActivated();
+
+ S3DataStoreStats s3DataStoreStats =
+ context.registerInjectActivateService(new S3DataStoreStats(),
null);
+ assertNull(context.getService(S3DataStoreStatsMBean.class));
+
+ unregisterSegmentNodeStoreService();
+ unregisterBlobStore();
+ }
+
+ private SegmentNodeStoreService segmentNodeStoreService;
+
+ private void registerSegmentNodeStoreService(boolean customBlobStore) {
+ Map<String, Object> properties = newHashMap();
+
+ properties.put(SegmentNodeStoreService.CUSTOM_BLOB_STORE,
customBlobStore);
+ properties.put(SegmentNodeStoreService.DIRECTORY,
folder.getRoot().getAbsolutePath());
+
+ segmentNodeStoreService = context.registerInjectActivateService(new
SegmentNodeStoreService(), properties);
+ }
+
+ private void unregisterSegmentNodeStoreService() {
+ deactivate(segmentNodeStoreService);
+ }
+
+ private ServiceRegistration blobStore;
+
+ private void registerBlobStore() {
+ blobStore =
context.bundleContext().registerService(BlobStore.class.getName(),
mock(BlobStore.class), null);
+ }
+
+ private void unregisterBlobStore() {
+ blobStore.unregister();
+ }
+
+ private void assertServiceActivated() {
+ assertNotNull(context.getService(NodeStore.class));
+ assertNotNull(context.getService(SegmentStoreProvider.class));
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentS3DataStoreStatsTest.java
------------------------------------------------------------------------------
svn:eol-style = native