You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by sh...@apache.org on 2015/04/06 08:57:51 UTC
svn commit: r1671491 - in /jackrabbit/trunk/jackrabbit-data/src:
main/java/org/apache/jackrabbit/core/data/
test/java/org/apache/jackrabbit/core/data/ test/resources/
Author: shashank
Date: Mon Apr 6 06:57:51 2015
New Revision: 1671491
URL: http://svn.apache.org/r1671491
Log:
JCR-3869 CachingDataStore for SAN or NFS mounted storage
Implemented CachingFDS that leverages caching on datastore hosted on network storage.
18 test cases added.
Tested multi-threaded scenario in my office NFS storage. Multi-threaded test for FileDatastore took 57sec and CachingFDS took 1sec.
Added:
jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/CachingFDS.java (with props)
jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FSBackend.java (with props)
jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCachingFDS.java (with props)
jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCachingFDSCacheOff.java (with props)
jackrabbit/trunk/jackrabbit-data/src/test/resources/fs.properties (with props)
Modified:
jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCaseBase.java
jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestFileDataStore.java
jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestInMemDs.java
Added: jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/CachingFDS.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/CachingFDS.java?rev=1671491&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/CachingFDS.java (added)
+++ jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/CachingFDS.java Mon Apr 6 06:57:51 2015
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+/**
+ * {@link CachingDataStore} with {@link FSBackend}. It is performant
+ * {@link DataStore} when {@link FSBackend} is hosted on network storage
+ * (SAN or NAS). It leverages all caching capabilites of
+ * {@link CachingDataStore}.
+ */
+package org.apache.jackrabbit.core.data;
+
+import java.util.Properties;
+
+public class CachingFDS extends CachingDataStore {
+ private Properties properties;
+
+ @Override
+ protected Backend createBackend() {
+ FSBackend backend = new FSBackend();
+ if (properties != null) {
+ backend.setProperties(properties);
+ }
+ return backend;
+ }
+
+ @Override
+ protected String getMarkerFile() {
+ return "fs.init.done";
+ }
+
+ /**
+ * Properties required to configure the S3Backend
+ */
+ public void setProperties(Properties properties) {
+ this.properties = properties;
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/CachingFDS.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FSBackend.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FSBackend.java?rev=1671491&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FSBackend.java (added)
+++ jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FSBackend.java Mon Apr 6 06:57:51 2015
@@ -0,0 +1,492 @@
+/*
+ * 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.
+ */
+/**
+ * File system {@link Backend} used with {@link CachingDataStore}.
+ * The file system can be network storage.
+ */
+package org.apache.jackrabbit.core.data;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.core.data.util.NamedThreadFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FSBackend implements Backend {
+
+ private Properties properties;
+
+ private String path;
+
+ private CachingDataStore store;
+
+ private String homeDir;
+
+ private String config;
+
+ File pathDir;
+
+ private ThreadPoolExecutor asyncWriteExecuter;
+
+ public static final String PATH = "path";
+
+ /**
+ * Logger instance.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(FSBackend.class);
+
+ /**
+ * The maximum last modified time resolution of the file system.
+ */
+ private static final int ACCESS_TIME_RESOLUTION = 2000;
+
+ @Override
+ public void init(CachingDataStore store, String homeDir, String config)
+ throws DataStoreException {
+ Properties initProps = null;
+ // Check is configuration is already provided. That takes precedence
+ // over config provided via file based config
+ this.config = config;
+ if (this.properties != null) {
+ initProps = this.properties;
+ } else {
+ initProps = new Properties();
+ InputStream in = null;
+ try {
+ in = new FileInputStream(config);
+ initProps.load(in);
+ } catch (IOException e) {
+ throw new DataStoreException(
+ "Could not initialize FSBackend from " + config, e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ this.properties = initProps;
+ }
+ init(store, homeDir, initProps);
+
+ }
+
+ public void init(CachingDataStore store, String homeDir, Properties prop)
+ throws DataStoreException {
+ this.store = store;
+ this.homeDir = homeDir;
+ this.path = prop.getProperty(PATH);
+ if (this.path == null || "".equals(this.path)) {
+ throw new DataStoreException("Could not initialize FSBackend from "
+ + config + ". [" + PATH + "] property not found.");
+ }
+ pathDir = new File(this.path);
+ if (pathDir.exists() && pathDir.isFile()) {
+ throw new DataStoreException("Can not create a directory "
+ + "because a file exists with the same name: " + this.path);
+ }
+ boolean created = pathDir.mkdirs();
+ if (!created) {
+ throw new DataStoreException("Could not create directory: "
+ + pathDir.getAbsolutePath());
+ }
+ asyncWriteExecuter = (ThreadPoolExecutor) Executors.newFixedThreadPool(
+ 10, new NamedThreadFactory("fs-write-worker"));
+
+ }
+
+ @Override
+ public InputStream read(DataIdentifier identifier)
+ throws DataStoreException {
+ File file = getFile(identifier);
+ try {
+ return new LazyFileInputStream(file);
+ } catch (IOException e) {
+ throw new DataStoreException("Error opening input stream of "
+ + file.getAbsolutePath(), e);
+ }
+ }
+
+ @Override
+ public long getLength(DataIdentifier identifier) throws DataStoreException {
+ File file = getFile(identifier);
+ if (file.isFile()) {
+ return file.length();
+ }
+ throw new DataStoreException("Could not length of dataIdentifier ["
+ + identifier + "]");
+ }
+
+ @Override
+ public long getLastModified(DataIdentifier identifier)
+ throws DataStoreException {
+ long start = System.currentTimeMillis();
+ File f = getFile(identifier);
+ if (f.isFile()) {
+ return getLastModified(f);
+ }
+ LOG.info("getLastModified:Identifier [{}] not found. Took [{}] ms.",
+ identifier, (System.currentTimeMillis() - start));
+ throw new DataStoreException("Identifier [" + identifier
+ + "] not found.");
+ }
+
+ @Override
+ public void write(DataIdentifier identifier, File src)
+ throws DataStoreException {
+ File dest = getFile(identifier);
+ synchronized (this) {
+ if (dest.exists()) {
+ long now = System.currentTimeMillis();
+ if (getLastModified(dest) < now + ACCESS_TIME_RESOLUTION) {
+ setLastModified(dest, now + ACCESS_TIME_RESOLUTION);
+ }
+ } else {
+ try {
+ FileUtils.copyFile(src, dest);
+ } catch (IOException ioe) {
+ throw new DataStoreException("Not able to write file ["
+ + identifier + "]");
+ }
+ }
+ }
+
+ }
+
+ @Override
+ public void writeAsync(final DataIdentifier identifier, final File src,
+ final AsyncUploadCallback callback)
+ throws DataStoreException {
+ if (callback == null) {
+ throw new IllegalArgumentException(
+ "callback parameter cannot be null in asyncUpload");
+ }
+ asyncWriteExecuter.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ write(identifier, src);
+ callback.onSuccess(new AsyncUploadResult(identifier, src));
+ } catch (DataStoreException dse) {
+ AsyncUploadResult res = new AsyncUploadResult(identifier,
+ src);
+ res.setException(dse);
+ callback.onFailure(res);
+ }
+
+ }
+ });
+ }
+
+ @Override
+ public Iterator<DataIdentifier> getAllIdentifiers()
+ throws DataStoreException {
+ ArrayList<File> files = new ArrayList<File>();
+ for (File file : pathDir.listFiles()) {
+ if (file.isDirectory()) { // skip top-level files
+ listRecursive(files, file);
+ }
+ }
+
+ ArrayList<DataIdentifier> identifiers = new ArrayList<DataIdentifier>();
+ for (File f : files) {
+ String name = f.getName();
+ identifiers.add(new DataIdentifier(name));
+ }
+ LOG.debug("Found " + identifiers.size() + " identifiers.");
+ return identifiers.iterator();
+ }
+
+ @Override
+ public boolean exists(DataIdentifier identifier, boolean touch)
+ throws DataStoreException {
+ File file = getFile(identifier);
+ if (file.isFile()) {
+ if (touch) {
+ long now = System.currentTimeMillis();
+ setLastModified(file, now + ACCESS_TIME_RESOLUTION);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean exists(DataIdentifier identifier) throws DataStoreException {
+ return exists(identifier, false);
+ }
+
+ @Override
+ public void touch(DataIdentifier identifier, long minModifiedDate)
+ throws DataStoreException {
+ File file = getFile(identifier);
+ long now = System.currentTimeMillis();
+ if (minModifiedDate > 0 && minModifiedDate > getLastModified(file)) {
+ setLastModified(file, now + ACCESS_TIME_RESOLUTION);
+ }
+ }
+
+ @Override
+ public void touchAsync(final DataIdentifier identifier,
+ final long minModifiedDate,
+ final AsyncTouchCallback callback)
+ throws DataStoreException {
+ try {
+ if (callback == null) {
+ throw new IllegalArgumentException(
+ "callback parameter cannot be null in touchAsync");
+ }
+ Thread.currentThread().setContextClassLoader(
+ getClass().getClassLoader());
+
+ asyncWriteExecuter.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ touch(identifier, minModifiedDate);
+ callback.onSuccess(new AsyncTouchResult(identifier));
+ } catch (DataStoreException e) {
+ AsyncTouchResult result = new AsyncTouchResult(
+ identifier);
+ result.setException(e);
+ callback.onFailure(result);
+ }
+ }
+ });
+ } catch (Exception e) {
+ callback.onAbort(new AsyncTouchResult(identifier));
+ throw new DataStoreException("Cannot touch the record "
+ + identifier.toString(), e);
+ }
+
+ }
+
+ @Override
+ public void close() throws DataStoreException {
+ asyncWriteExecuter.shutdownNow();
+
+ }
+
+ @Override
+ public Set<DataIdentifier> deleteAllOlderThan(long min)
+ throws DataStoreException {
+ Set<DataIdentifier> deleteIdSet = new HashSet<DataIdentifier>(30);
+ for (File file : pathDir.listFiles()) {
+ if (file.isDirectory()) { // skip top-level files
+ deleteOlderRecursive(file, min, deleteIdSet);
+ }
+ }
+ return deleteIdSet;
+ }
+
+ @Override
+ public void deleteRecord(DataIdentifier identifier)
+ throws DataStoreException {
+ File file = getFile(identifier);
+ synchronized (this) {
+ if (file.exists()) {
+ if (file.delete()) {
+ deleteEmptyParentDirs(file);
+ } else {
+ LOG.warn("Failed to delete file " + file.getAbsolutePath());
+ }
+ }
+ }
+ }
+
+ /**
+ * Properties used to configure the backend. If provided explicitly before
+ * init is invoked then these take precedence
+ * @param properties to configure S3Backend
+ */
+ public void setProperties(Properties properties) {
+ this.properties = properties;
+ }
+
+ /**
+ * Returns the identified file. This method implements the pattern used to
+ * avoid problems with too many files in a single directory.
+ * <p>
+ * No sanity checks are performed on the given identifier.
+ * @param identifier data identifier
+ * @return identified file
+ */
+ private File getFile(DataIdentifier identifier) {
+ String string = identifier.toString();
+ File file = this.pathDir;
+ file = new File(file, string.substring(0, 2));
+ file = new File(file, string.substring(2, 4));
+ file = new File(file, string.substring(4, 6));
+ return new File(file, string);
+ }
+
+ /**
+ * Set the last modified date of a file, if the file is writable.
+ * @param file the file
+ * @param time the new last modified date
+ * @throws DataStoreException if the file is writable but modifying the date
+ * fails
+ */
+ private static void setLastModified(File file, long time)
+ throws DataStoreException {
+ if (!file.setLastModified(time)) {
+ if (!file.canWrite()) {
+ // if we can't write to the file, so garbage collection will
+ // also not delete it
+ // (read only files or file systems)
+ return;
+ }
+ try {
+ // workaround for Windows: if the file is already open for
+ // reading
+ // (in this or another process), then setting the last modified
+ // date
+ // doesn't work - see also JCR-2872
+ RandomAccessFile r = new RandomAccessFile(file, "rw");
+ try {
+ r.setLength(r.length());
+ } finally {
+ r.close();
+ }
+ } catch (IOException e) {
+ throw new DataStoreException(
+ "An IO Exception occurred while trying to set the last modified date: "
+ + file.getAbsolutePath(), e);
+ }
+ }
+ }
+
+ /**
+ * Get the last modified date of a file.
+ * @param file the file
+ * @return the last modified date
+ * @throws DataStoreException if reading fails
+ */
+ private static long getLastModified(File file) throws DataStoreException {
+ long lastModified = file.lastModified();
+ if (lastModified == 0) {
+ throw new DataStoreException(
+ "Failed to read record modified date: "
+ + file.getAbsolutePath());
+ }
+ return lastModified;
+ }
+
+ private void listRecursive(List<File> list, File file) {
+ File[] files = file.listFiles();
+ if (files != null) {
+ for (File f : files) {
+ if (f.isDirectory()) {
+ listRecursive(list, f);
+ } else {
+ list.add(f);
+ }
+ }
+ }
+ }
+
+ private void deleteEmptyParentDirs(File file) {
+ File parent = file.getParentFile();
+ try {
+ // Only iterate & delete if parent directory of the blob file is
+ // child
+ // of the base directory and if it is empty
+ while (FileUtils.directoryContains(pathDir, parent)) {
+ String[] entries = parent.list();
+ if (entries == null) {
+ LOG.warn("Failed to list directory {}",
+ parent.getAbsolutePath());
+ break;
+ }
+ if (entries.length > 0) {
+ break;
+ }
+ boolean deleted = parent.delete();
+ LOG.debug("Deleted parent [{}] of file [{}]: {}", new Object[] {
+ parent, file.getAbsolutePath(), deleted });
+ parent = parent.getParentFile();
+ }
+ } catch (IOException e) {
+ LOG.warn("Error in parents deletion for " + file.getAbsoluteFile(),
+ e);
+ }
+ }
+
+ private void deleteOlderRecursive(File file, long min,
+ Set<DataIdentifier> deleteIdSet) throws DataStoreException {
+ if (file.isFile() && file.exists() && file.canWrite()) {
+ synchronized (this) {
+ long lastModified;
+ try {
+ lastModified = getLastModified(file);
+ } catch (DataStoreException e) {
+ LOG.warn(
+ "Failed to read modification date; file not deleted", e);
+ // don't delete the file, since the lastModified date is
+ // uncertain
+ lastModified = min;
+ }
+ if (lastModified < min) {
+ DataIdentifier id = new DataIdentifier(file.getName());
+ if (store.confirmDelete(id)) {
+ store.deleteFromCache(id);
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Deleting old file "
+ + file.getAbsolutePath() + " modified: "
+ + new Timestamp(lastModified).toString()
+ + " length: " + file.length());
+ }
+ if (file.delete()) {
+ deleteIdSet.add(id);
+ } else {
+ LOG.warn("Failed to delete old file "
+ + file.getAbsolutePath());
+ }
+ }
+ }
+ }
+ } else if (file.isDirectory()) {
+ File[] list = file.listFiles();
+ if (list != null) {
+ for (File f : list) {
+ deleteOlderRecursive(f, min, deleteIdSet);
+ }
+ }
+
+ // JCR-1396: FileDataStore Garbage Collector and empty directories
+ // Automatic removal of empty directories (but not the root!)
+ synchronized (this) {
+ list = file.listFiles();
+ if (list != null && list.length == 0) {
+ file.delete();
+ }
+ }
+ }
+ }
+
+}
Propchange: jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FSBackend.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCachingFDS.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCachingFDS.java?rev=1671491&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCachingFDS.java (added)
+++ jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCachingFDS.java Mon Apr 6 06:57:51 2015
@@ -0,0 +1,50 @@
+/*
+ * 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.core.data;
+
+import java.util.Properties;
+
+import javax.jcr.RepositoryException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestCachingFDS extends TestFileDataStore {
+
+ protected static final Logger LOG = LoggerFactory.getLogger(TestCachingFDS.class);
+
+ protected DataStore createDataStore() throws RepositoryException {
+ CachingFDS cacheFDS = new CachingFDS();
+ Properties props = loadProperties("/fs.properties");
+ String pathValue = props.getProperty("path");
+ if (props != null && !"".equals(pathValue.trim())) {
+ path = pathValue + "/cachingFds" + "-"
+ + String.valueOf(randomGen.nextInt(100000)) + "-"
+ + String.valueOf(randomGen.nextInt(100000));
+ } else {
+ path = dataStoreDir + "/cachingFds";
+ }
+ props.setProperty("path", path);
+ LOG.info("path [{}] set.", path);
+ cacheFDS.setProperties(props);
+ cacheFDS.setSecret("12345");
+ cacheFDS.init(dataStoreDir);
+ return cacheFDS;
+ }
+
+}
Propchange: jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCachingFDS.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCachingFDSCacheOff.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCachingFDSCacheOff.java?rev=1671491&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCachingFDSCacheOff.java (added)
+++ jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCachingFDSCacheOff.java Mon Apr 6 06:57:51 2015
@@ -0,0 +1,49 @@
+/*
+ * 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.core.data;
+
+import java.util.Properties;
+
+import javax.jcr.RepositoryException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestCachingFDSCacheOff extends TestFileDataStore {
+
+ protected static final Logger LOG = LoggerFactory.getLogger(TestCachingFDS.class);
+
+ protected DataStore createDataStore() throws RepositoryException {
+ CachingFDS cacheFDS = new CachingFDS();
+ Properties props = loadProperties("/fs.properties");
+ String pathValue = props.getProperty("path");
+ if (props != null && !"".equals(pathValue.trim())) {
+ path = pathValue + "/cachingFds" + "-"
+ + String.valueOf(randomGen.nextInt(100000)) + "-"
+ + String.valueOf(randomGen.nextInt(100000));
+ } else {
+ path = dataStoreDir + "/cachingFDS";
+ }
+ props.setProperty("path", path);
+ cacheFDS.setProperties(props);
+ cacheFDS.setSecret("12345");
+ cacheFDS.setCacheSize(0);
+ cacheFDS.init(dataStoreDir);
+ return cacheFDS;
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCachingFDSCacheOff.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCaseBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCaseBase.java?rev=1671491&r1=1671490&r2=1671491&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCaseBase.java (original)
+++ jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestCaseBase.java Mon Apr 6 06:57:51 2015
@@ -22,10 +22,12 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
+import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Properties;
import java.util.Random;
import javax.jcr.RepositoryException;
@@ -663,4 +665,18 @@ public abstract class TestCaseBase exten
}
}
}
+
+ /**
+ * Return {@link Properties} from class resource. Return empty
+ * {@link Properties} if not found.
+ */
+ protected Properties loadProperties(String resource) {
+ Properties configProp = new Properties();
+ try {
+ configProp.load(this.getClass().getResourceAsStream(resource));
+ } catch (Exception ignore) {
+
+ }
+ return configProp;
+ }
}
Modified: jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestFileDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestFileDataStore.java?rev=1671491&r1=1671490&r2=1671491&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestFileDataStore.java (original)
+++ jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestFileDataStore.java Mon Apr 6 06:57:51 2015
@@ -18,6 +18,7 @@
package org.apache.jackrabbit.core.data;
import java.io.File;
+import java.util.Properties;
import javax.jcr.RepositoryException;
@@ -32,12 +33,21 @@ public class TestFileDataStore extends T
protected static final Logger LOG = LoggerFactory.getLogger(TestFileDataStore.class);
- String path;
+ protected String path;
@Override
protected DataStore createDataStore() throws RepositoryException {
FileDataStore fds = new FileDataStore();
- path = dataStoreDir + "/repository/datastore";
+ Properties props = loadProperties("/fs.properties");
+ String pathValue = props.getProperty("path");
+ if (props != null && !"".equals(pathValue.trim())) {
+ path = pathValue + "/fds" + "-"
+ + String.valueOf(randomGen.nextInt(100000)) + "-"
+ + String.valueOf(randomGen.nextInt(100000));
+ } else {
+ path = dataStoreDir + "/repository/datastore";
+ }
+ LOG.info("path [{}] set.", path);
fds.setPath(path);
fds.init(dataStoreDir);
return fds;
@@ -45,6 +55,7 @@ public class TestFileDataStore extends T
@Override
protected void tearDown() {
+ LOG.info("cleaning path [{}]", path);
File f = new File(path);
try {
for (int i = 0; i < 4 && f.exists(); i++) {
@@ -54,6 +65,7 @@ public class TestFileDataStore extends T
} catch (Exception ignore) {
}
+ super.tearDown();
}
}
Modified: jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestInMemDs.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestInMemDs.java?rev=1671491&r1=1671490&r2=1671491&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestInMemDs.java (original)
+++ jackrabbit/trunk/jackrabbit-data/src/test/java/org/apache/jackrabbit/core/data/TestInMemDs.java Mon Apr 6 06:57:51 2015
@@ -28,7 +28,7 @@ public class TestInMemDs extends TestCas
protected static final Logger LOG = LoggerFactory.getLogger(TestInMemDs.class);
-
+ @Override
protected DataStore createDataStore() throws RepositoryException {
InMemoryDataStore inMemDS = new InMemoryDataStore();
inMemDS.setProperties(null);
Added: jackrabbit/trunk/jackrabbit-data/src/test/resources/fs.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-data/src/test/resources/fs.properties?rev=1671491&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-data/src/test/resources/fs.properties (added)
+++ jackrabbit/trunk/jackrabbit-data/src/test/resources/fs.properties Mon Apr 6 06:57:51 2015
@@ -0,0 +1 @@
+path=Y:/ds
Propchange: jackrabbit/trunk/jackrabbit-data/src/test/resources/fs.properties
------------------------------------------------------------------------------
svn:eol-style = native