### Eclipse Workspace Patch 1.0 #P jackrabbit-core Index: src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java (revision 1241895) +++ src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java (working copy) @@ -20,6 +20,7 @@ import org.apache.jackrabbit.core.cluster.ClusterNode; import org.apache.jackrabbit.core.data.DataStore; import org.apache.jackrabbit.core.data.DataStoreFactory; +import org.apache.jackrabbit.core.data.MultiDataStore; import org.apache.jackrabbit.core.fs.FileSystem; import org.apache.jackrabbit.core.fs.FileSystemException; import org.apache.jackrabbit.core.fs.FileSystemFactory; @@ -966,6 +967,23 @@ * ... * </DataStore> * + * Its also possible to configure a multi data store. The configuration uses following format: + *
+ * <DataStore class="org.apache.jackrabbit.core.data.MultiDataStore"> + * <param name="primary" value="org.apache.jackrabbit.core.data.db.XXDataStore"> + * <DataStore class="org.apache.jackrabbit.core.data.db.XXDataStore"> + * <param name="..." value="..."> + * ... + * </DataStore> + * </param> + * <param name="archive" value="org.apache.jackrabbit.core.data.db.XXDataStore"> + * <DataStore class="org.apache.jackrabbit.core.data.db.XXDataStore"> + * <param name="..." value="..."> + * ... + * </DataStore> + * </param> + * </DataStore> + ** *
DataStore is a {@link #parseBeanConfig(Element,String) bean configuration}
* element.
@@ -985,9 +1003,24 @@
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE
&& DATA_STORE_ELEMENT.equals(child.getNodeName())) {
- BeanConfig bc =
- parseBeanConfig(parent, DATA_STORE_ELEMENT);
+ BeanConfig bc = parseBeanConfig(parent, DATA_STORE_ELEMENT);
+ bc.setValidate(false);
DataStore store = bc.newInstance(DataStore.class);
+ if (store instanceof MultiDataStore) {
+ String msg = "A MultiDataStore must have configured a primary and archive datastore";
+ Node paramNode = child.getChildNodes().item(1);
+ if (paramNode == null) {
+ throw new ConfigurationException(msg);
+ }
+ DataStore subStore = getDataStoreFactory((Element) paramNode, directory).getDataStore();
+ ((MultiDataStore) store).setPrimaryDataStore(subStore);
+ paramNode = child.getChildNodes().item(3);
+ if (paramNode == null) {
+ throw new ConfigurationException(msg);
+ }
+ subStore = getDataStoreFactory((Element) paramNode, directory).getDataStore();
+ ((MultiDataStore) store).setArchiveDataStore(subStore);
+ }
store.init(directory);
return store;
}
Index: src/main/resources/org/apache/jackrabbit/core/config/repository-2.6.dtd
===================================================================
--- src/main/resources/org/apache/jackrabbit/core/config/repository-2.6.dtd (revision 0)
+++ src/main/resources/org/apache/jackrabbit/core/config/repository-2.6.dtd (working copy)
@@ -0,0 +1,64 @@
+
+
+
+%repository-elements;
+
+
+
Index: src/main/resources/org/apache/jackrabbit/core/config/repository-2.6.dtd
===================================================================
--- src/main/resources/org/apache/jackrabbit/core/config/repository-2.6.dtd (revision 0)
+++ src/main/resources/org/apache/jackrabbit/core/config/repository-2.6.dtd (working copy)
Property changes on: src/main/resources/org/apache/jackrabbit/core/config/repository-2.6.dtd
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: src/main/resources/org/apache/jackrabbit/core/config/repository-2.6-elements.dtd
===================================================================
--- src/main/resources/org/apache/jackrabbit/core/config/repository-2.6-elements.dtd (revision 0)
+++ src/main/resources/org/apache/jackrabbit/core/config/repository-2.6-elements.dtd (working copy)
@@ -0,0 +1,254 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: src/main/resources/org/apache/jackrabbit/core/config/repository-2.6-elements.dtd
===================================================================
--- src/main/resources/org/apache/jackrabbit/core/config/repository-2.6-elements.dtd (revision 0)
+++ src/main/resources/org/apache/jackrabbit/core/config/repository-2.6-elements.dtd (working copy)
Property changes on: src/main/resources/org/apache/jackrabbit/core/config/repository-2.6-elements.dtd
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: src/main/java/org/apache/jackrabbit/core/data/MultiDataStore.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/data/MultiDataStore.java (revision 0)
+++ src/main/java/org/apache/jackrabbit/core/data/MultiDataStore.java (working copy)
@@ -0,0 +1,198 @@
+/*
+ * 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.io.InputStream;
+import java.util.Iterator;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * A MultiDataStore can handle to independent DataStores. Attention: You will
+ * lost the global single instance mechanism ! It can be used if you have two
+ * storage systems. One for fast access and a other one like a archive DataStore
+ * on a slower storage system. All Files will be added to the primary DataStore.
+ * On read operations first the primary dataStore will be used and if no Record
+ * is found the archive DataStore will be used. To split up the data between the
+ * two DataStores use the MultiDataStoreJanitor. The GarabageCollector will only
+ * remove files from the archive DataStore.
+ * Configuration:
+ *
+ *
+ * <DataStore class="org.apache.jackrabbit.core.data.MultiDataStore">
+ * <param name="{@link #setPath(String) path}" value="/data/datastore"/>
+ * <param name="{@link #setMinRecordLength(int) minRecordLength}" value="1024"/>
+ * </DataStore>
+ *
+ */
+public class MultiDataStore implements DataStore {
+
+ private DataStore primaryDataStore;
+ private DataStore archiveDataStore;
+
+ /**
+ * Setter for the primary dataStore
+ *
+ * @param dataStore
+ */
+ public void setPrimaryDataStore(DataStore dataStore) {
+ this.primaryDataStore = dataStore;
+ }
+
+ /**
+ * Setter for the archive dataStore
+ *
+ * @param dataStore
+ */
+ public void setArchiveDataStore(DataStore dataStore) {
+ this.archiveDataStore = dataStore;
+ }
+
+ /**
+ * Check if a record for the given identifier exists in the primary data store.
+ * If not found there it will be returned from the archive data store.
+ * If no record exists, this method returns null.
+ *
+ * @param identifier data identifier
+ * @return the record if found, and null if not
+ */
+ public DataRecord getRecordIfStored(DataIdentifier identifier)
+ throws DataStoreException {
+ DataRecord dataRecord = primaryDataStore.getRecordIfStored(identifier);
+ if (dataRecord == null) {
+ dataRecord = archiveDataStore.getRecordIfStored(identifier);
+ }
+ return dataRecord;
+ }
+
+ /**
+ * Returns the identified data record from the primary data store.
+ * If not found there it will be returned from the archive data store. The given identifier should be
+ * the identifier of a previously saved data record. Since records are
+ * never removed, there should never be cases where the identified record
+ * is not found. Abnormal cases like that are treated as errors and
+ * handled by throwing an exception.
+ *
+ * @param identifier data identifier
+ * @return identified data record
+ * @throws DataStoreException if the data store could not be accessed,
+ * or if the given identifier is invalid
+ */
+ public DataRecord getRecord(DataIdentifier identifier)
+ throws DataStoreException {
+ try {
+ return primaryDataStore.getRecord(identifier);
+ } catch (DataStoreException e) {
+ return archiveDataStore.getRecord(identifier);
+ }
+ }
+
+ /**
+ * Creates a new data record in the primary data store. The given binary stream is consumed and
+ * a binary record containing the consumed stream is created and returned.
+ * If the same stream already exists in another record, then that record
+ * is returned instead of creating a new one.
+ * + * The given stream is consumed and not closed by this + * method. It is the responsibility of the caller to close the stream. + * A typical call pattern would be: + *
+ * InputStream stream = ...;
+ * try {
+ * record = store.addRecord(stream);
+ * } finally {
+ * stream.close();
+ * }
+ *
+ *
+ * @param stream binary stream
+ * @return data record that contains the given stream
+ * @throws DataStoreException if the data store could not be accessed
+ */
+ public DataRecord addRecord(InputStream stream) throws DataStoreException {
+ return primaryDataStore.addRecord(stream);
+ }
+
+ /**
+ * From now on, update the modified date of an object even when accessing it in the archive data store.
+ * Usually, the modified date is only updated when creating a new object,
+ * or when a new link is added to an existing object. When this setting is enabled,
+ * even getLength() will update the modified date.
+ *
+ * @param before - update the modified date to the current time if it is older than this value
+ */
+ public void updateModifiedDateOnAccess(long before) {
+ archiveDataStore.updateModifiedDateOnAccess(before);
+ }
+
+ /**
+ * Delete objects that have a modified date older than the specified date from the archive data store.
+ *
+ * @param min the minimum time
+ * @return the number of data records deleted
+ * @throws DataStoreException
+ */
+ public int deleteAllOlderThan(long min) throws DataStoreException {
+ return archiveDataStore.deleteAllOlderThan(min);
+ }
+
+ /**
+ * Get all identifiers from the archive data store.
+ *
+ * @return an iterator over all DataIdentifier objects
+ * @throws DataStoreException if the list could not be read
+ */
+ public Iterator