exo-jcr SVN: r4014 - in jcr/branches/1.12.x: patch/1.12.8-GA/JCR-1581 and 1 other directory.
by do-not-reply@jboss.org
Author: paristote
Date: 2011-02-24 21:48:27 -0500 (Thu, 24 Feb 2011)
New Revision: 4014
Added:
jcr/branches/1.12.x/patch/1.12.8-GA/JCR-1581/readme.txt
Modified:
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
Log:
JCR-1581
What is the problem to fix?
* We are running in a two node cluster sharing a single NFS mount for the data/gatein directory. We are seeing the following exceptions in server.log file
java.io.IOException: Stale NFS file handle
at java.io.RandomAccessFile.readBytes(Native Method)
at java.io.RandomAccessFile.read(RandomAccessFile.java:322)
at org.apache.lucene.store.FSDirectory$FSIndexInput.readInternal(FSDirectory.java:596)
at org.apache.lucene.store.BufferedIndexInput.readBytes(BufferedIndexInput.java:136)
at org.apache.lucene.index.CompoundFileReader$CSIndexInput.readInternal(CompoundFileReader.java:247)
at org.apache.lucene.store.BufferedIndexInput.refill(BufferedIndexInput.java:157)
at org.apache.lucene.store.BufferedIndexInput.readByte(BufferedIndexInput.java:38)
at org.apache.lucene.store.IndexInput.readVInt(IndexInput.java:78)
How is the problem fixed?
* It is fixed by addition IndexInfos.write() call exactly after replaceIndex operations done by IndexMerger
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java 2011-02-24 16:03:02 UTC (rev 4013)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java 2011-02-25 02:48:27 UTC (rev 4014)
@@ -784,6 +784,13 @@
// when reindexing the final commit is done at the very end
executeAndLog(new Commit(getTransactionId()));
}
+ // force IndexInfos (IndexNames) to be written on FS and both be replicated over cluster
+ // for non-coordinator cluster nodes be notified of new index list ASAP. This may avoid race
+ // conditions when coordinator invokes flush() which performs indexNames.write()
+ // and deletes obsolete index just after. Making this list be written now, will notify non-
+ // coordinator node about new merged index and obsolete indexes long time before they will
+ // be deleted.
+ indexNames.write();
}
finally
{
Added: jcr/branches/1.12.x/patch/1.12.8-GA/JCR-1581/readme.txt
===================================================================
--- jcr/branches/1.12.x/patch/1.12.8-GA/JCR-1581/readme.txt (rev 0)
+++ jcr/branches/1.12.x/patch/1.12.8-GA/JCR-1581/readme.txt 2011-02-25 02:48:27 UTC (rev 4014)
@@ -0,0 +1,113 @@
+Summary
+
+ * Status: NFS stale handle
+ * CCP Issue: CCP-766, Product Jira Issue: JCR-1581.
+ * Complexity: high
+
+The Proposal
+Problem description
+
+What is the problem to fix?
+
+ * We are running in a two node cluster sharing a single NFS mount for the data/gatein directory with the following configuration.properties settings:
+
+ Data
+ gatein.data.dir=${jboss.server.data.dir}/gatein
+ DB
+ gatein.db.data.dir=${gatein.data.dir}/db
+
+ # JCR
+ gatein.jcr.config.type=cluster
+ gatein.jcr.datasource.name=java:gatein-jcr
+ gatein.jcr.datasource.dialect=auto
+
+ gatein.jcr.data.dir=${gatein.data.dir}/jcr
+ gatein.jcr.storage.data.dir=${gatein.jcr.data.dir}/values
+ gatein.jcr.cache.config=classpath:/conf/jcr/jbosscache/${gatein.jcr.config.type}/config.xml
+ gatein.jcr.lock.cache.config=classpath:/conf/jcr/jbosscache/${gatein.jcr.config.type}/lock-config.xml
+ gatein.jcr.index.data.dir=${gatein.jcr.data.dir}/lucene
+ gatein.jcr.index.changefilterclass=org.exoplatform.services.jcr.impl.core.query.jbosscache.JBossCacheIndexChangesFilter
+ gatein.jcr.index.cache.config=classpath:/conf/jcr/jbosscache/cluster/indexer-config.xml
+ gatein.jcr.jgroups.config=classpath:/conf/jcr/jbosscache/cluster/udp-mux.xml
+
+ We are seeing the following exceptions in server.log file
+
+ java.io.IOException: Stale NFS file handle
+ at java.io.RandomAccessFile.readBytes(Native Method)
+ at java.io.RandomAccessFile.read(RandomAccessFile.java:322)
+ at org.apache.lucene.store.FSDirectory$FSIndexInput.readInternal(FSDirectory.java:596)
+ at org.apache.lucene.store.BufferedIndexInput.readBytes(BufferedIndexInput.java:136)
+ at org.apache.lucene.index.CompoundFileReader$CSIndexInput.readInternal(CompoundFileReader.java:247)
+ at org.apache.lucene.store.BufferedIndexInput.refill(BufferedIndexInput.java:157)
+ at org.apache.lucene.store.BufferedIndexInput.readByte(BufferedIndexInput.java:38)
+ at org.apache.lucene.store.IndexInput.readVInt(IndexInput.java:78)
+
+Fix description
+
+How is the problem fixed?
+
+ * It is fixed by addition IndexInfos.write() call exactly after replaceIndex operations done by IndexMerger
+
+Patch information:
+Patch files: JCR-1581.patch
+
+Tests to perform
+
+Reproduction test
+
+ * Content manipulation:
+
+ Run 2 nodes, try to
+
+ 1. Go to System Tab
+ 2. Click on Import Node
+ 3. Browse files to add
+ 4. Select Zip option and click on import
+
+ * We also reproduce the problem when we start the fourth node without any content manipulation
+
+Tests performed at DevLevel
+
+ * Run 2 nodes with NFS3 shared folder for lucene indexes. Simultaneously add a huge number of pdf and txt files on both nodes via WebDav or FTP.
+
+Tests performed at QA/Support Level
+*
+
+
+Documentation changes
+
+Documentation changes:
+
+ * none
+
+Configuration changes
+
+Configuration changes:
+
+ * none
+
+Will previous configuration continue to work?
+
+ * yes
+
+Risks and impacts
+
+Can this bug fix have any side effects on current client projects?
+
+ * no
+
+Is there a performance risk/cost?
+
+ * no
+
+Validation (PM/Support/QA)
+
+PM Comment
+*Patch approved by PM
+
+Support Comment
+*Support review : patch validated
+
+QA Feedbacks
+*
+
13 years, 2 months
exo-jcr SVN: r4013 - jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-02-24 11:03:02 -0500 (Thu, 24 Feb 2011)
New Revision: 4013
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java
Log:
EXOJCR-832: implementation
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java 2011-02-24 16:02:07 UTC (rev 4012)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java 2011-02-24 16:03:02 UTC (rev 4013)
@@ -27,6 +27,7 @@
import org.exoplatform.services.jcr.impl.core.query.SearchManager;
import org.exoplatform.services.jcr.impl.core.query.jbosscache.ChangesFilterListsWrapper;
import org.exoplatform.services.jcr.impl.core.query.lucene.ChangesHolder;
+import org.exoplatform.services.jcr.infinispan.ISPNCacheFactory;
import org.exoplatform.services.jcr.infinispan.PrivilegedISPNCacheHelper;
import org.exoplatform.services.jcr.util.IdGenerator;
import org.exoplatform.services.log.ExoLogger;
@@ -85,8 +86,8 @@
// // Long pushStateTimeOut = config.getParameterTime(PARAM_JBOSSCACHE_PUSHSTATE_TIMEOUT, 10000L);
//
// // insert CacheLoaderConfig
- // ISPNCacheFactory<Serializable, Object> factory = new ISPNCacheFactory<Serializable, Object>(cfm);
- // this.cache = factory.createCache("Indexer-" + searchManager.getWsId(), config);
+ ISPNCacheFactory<Serializable, Object> factory = new ISPNCacheFactory<Serializable, Object>(cfm);
+ this.cache = factory.createCache("Indexer-" + searchManager.getWsId(), config);
//
// // Could have change of cache
// CacheLoaderManager cacheLoaderManager =
13 years, 2 months
exo-jcr SVN: r4012 - jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-02-24 11:02:07 -0500 (Thu, 24 Feb 2011)
New Revision: 4012
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java
Log:
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java 2011-02-24 15:58:54 UTC (rev 4011)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java 2011-02-24 16:02:07 UTC (rev 4012)
@@ -27,14 +27,12 @@
import org.exoplatform.services.jcr.impl.core.query.SearchManager;
import org.exoplatform.services.jcr.impl.core.query.jbosscache.ChangesFilterListsWrapper;
import org.exoplatform.services.jcr.impl.core.query.lucene.ChangesHolder;
-import org.exoplatform.services.jcr.infinispan.ISPNCacheFactory;
import org.exoplatform.services.jcr.infinispan.PrivilegedISPNCacheHelper;
import org.exoplatform.services.jcr.util.IdGenerator;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.infinispan.Cache;
import org.infinispan.CacheException;
-import org.infinispan.loaders.CacheLoaderManager;
import java.io.IOException;
import java.io.Serializable;
@@ -80,21 +78,21 @@
this.wsId = searchManager.getWsId().hashCode();
// initialize IndexerCacheLoader
- IndexerCacheStore indexerCacheStore = new IndexerCacheStore();
+ // IndexerCacheStore indexerCacheStore = new IndexerCacheStore();
+ //
+ // // try to get pushState parameters, since they are set programmatically only
+ // // Boolean pushState = config.getParameterBoolean(PARAM_JBOSSCACHE_PUSHSTATE, false);
+ // // Long pushStateTimeOut = config.getParameterTime(PARAM_JBOSSCACHE_PUSHSTATE_TIMEOUT, 10000L);
+ //
+ // // insert CacheLoaderConfig
+ // ISPNCacheFactory<Serializable, Object> factory = new ISPNCacheFactory<Serializable, Object>(cfm);
+ // this.cache = factory.createCache("Indexer-" + searchManager.getWsId(), config);
+ //
+ // // Could have change of cache
+ // CacheLoaderManager cacheLoaderManager =
+ // cache.getAdvancedCache().getComponentRegistry().getComponent(CacheLoaderManager.class);
+ // IndexerCacheStore cacheStore = (IndexerCacheStore)cacheLoaderManager.getCacheLoader();
- // try to get pushState parameters, since they are set programmatically only
- // Boolean pushState = config.getParameterBoolean(PARAM_JBOSSCACHE_PUSHSTATE, false);
- // Long pushStateTimeOut = config.getParameterTime(PARAM_JBOSSCACHE_PUSHSTATE_TIMEOUT, 10000L);
-
- // insert CacheLoaderConfig
- ISPNCacheFactory<Serializable, Object> factory = new ISPNCacheFactory<Serializable, Object>(cfm);
- this.cache = factory.createCache("Indexer-" + searchManager.getWsId(), config);
-
- // Could have change of cache
- CacheLoaderManager cacheLoaderManager =
- cache.getAdvancedCache().getComponentRegistry().getComponent(CacheLoaderManager.class);
- IndexerCacheStore cacheStore = (IndexerCacheStore)cacheLoaderManager.getCacheLoader();
-
// This code make it possible to use the JBossCacheIndexChangesFilter in
// a non-cluster environment
// if (cache.getConfiguration().getCacheMode() == CacheMode.LOCAL)
13 years, 2 months
exo-jcr SVN: r4011 - in jcr/trunk/exo.jcr.component.core/src: test/resources/conf/standalone/cluster and 1 other directory.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-02-24 10:58:54 -0500 (Thu, 24 Feb 2011)
New Revision: 4011
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ChangesKey.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexInfos.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-indexer.xml
Log:
EXOJCR-832: implementation
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ChangesKey.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ChangesKey.java 2011-02-24 15:19:35 UTC (rev 4010)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ChangesKey.java 2011-02-24 15:58:54 UTC (rev 4011)
@@ -30,13 +30,23 @@
*/
public class ChangesKey extends CacheKey
{
+ private final int wsId;
- ChangesKey(String id)
+ ChangesKey(int wsId, String id)
{
super(id);
+ this.wsId = wsId;
}
/**
+ * @return unique workspace identifier
+ */
+ public int getWsId()
+ {
+ return wsId;
+ }
+
+ /**
* {@inheritDoc}
*/
@Override
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java 2011-02-24 15:19:35 UTC (rev 4010)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java 2011-02-24 15:58:54 UTC (rev 4011)
@@ -22,7 +22,6 @@
import org.exoplatform.services.jcr.config.QueryHandlerEntry;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
import org.exoplatform.services.jcr.impl.core.query.IndexerChangesFilter;
-import org.exoplatform.services.jcr.impl.core.query.IndexerIoModeHandler;
import org.exoplatform.services.jcr.impl.core.query.IndexingTree;
import org.exoplatform.services.jcr.impl.core.query.QueryHandler;
import org.exoplatform.services.jcr.impl.core.query.SearchManager;
@@ -35,11 +34,7 @@
import org.exoplatform.services.log.Log;
import org.infinispan.Cache;
import org.infinispan.CacheException;
-import org.infinispan.config.CacheLoaderManagerConfig;
-import org.infinispan.config.Configuration.CacheMode;
-import org.infinispan.loaders.AbstractCacheStoreConfig;
-import org.infinispan.loaders.decorators.AsyncStoreConfig;
-import org.infinispan.loaders.decorators.SingletonStoreConfig;
+import org.infinispan.loaders.CacheLoaderManager;
import java.io.IOException;
import java.io.Serializable;
@@ -58,24 +53,21 @@
public class ISPNIndexChangesFilter extends IndexerChangesFilter
{
/**
- * Logger instance for this class
+ * Logger instance for this class.
*/
private final Log log = ExoLogger.getLogger("exo.jcr.component.core.ISPNIndexChangesFilter");
- public static final String PARAM_INFINISPAN_CONFIGURATION = "infinispan-configuration";
-
- public static final String PARAM_INFINISPAN_PUSHSTATE = "infinispan-sscl-push.state.enabled";
-
- public static final String PARAM_INFINISPAN_PUSHSTATE_TIMEOUT = "infinispan-sscl-push.state.timeout";
-
- // TODO eviction
-
/**
* ISPN cache.
*/
private final Cache<Serializable, Object> cache;
/**
+ * Unique workspace identifier.
+ */
+ private final int wsId;
+
+ /**
* ISPNIndexChangesFilter constructor.
*/
public ISPNIndexChangesFilter(SearchManager searchManager, SearchManager parentSearchManager,
@@ -85,84 +77,57 @@
{
super(searchManager, parentSearchManager, config, indexingTree, parentIndexingTree, handler, parentHandler, cfm);
- // create cache using custom factory
- ISPNCacheFactory<Serializable, Object> factory = new ISPNCacheFactory<Serializable, Object>(cfm);
- cache = factory.createCache("Indexer-" + searchManager.getWsId(), config);
+ this.wsId = searchManager.getWsId().hashCode();
- // singletonStoreConfig.setSingletonStoreClass(IndexerSingletonStoreCacheLoader.class.getName());
- // create SingletonStoreConfig
- SingletonStoreConfig singletonStoreConfig = new SingletonStoreConfig();
-
- Boolean pushState = config.getParameterBoolean(PARAM_INFINISPAN_PUSHSTATE, false);
- Long pushStateTimeOut = config.getParameterTime(PARAM_INFINISPAN_PUSHSTATE_TIMEOUT, 10000L);
-
- singletonStoreConfig.setPushStateWhenCoordinator(pushState);
- singletonStoreConfig.setPushStateTimeout(pushStateTimeOut);
- singletonStoreConfig.setSingletonStoreEnabled(true);
-
// initialize IndexerCacheLoader
IndexerCacheStore indexerCacheStore = new IndexerCacheStore();
- // create CacheLoaderConfig
- AbstractCacheStoreConfig individualCacheStoreConfig = new AbstractCacheStoreConfig();
- individualCacheStoreConfig.setSingletonStoreConfig(singletonStoreConfig);
- individualCacheStoreConfig.setCacheLoaderClassName(IndexerCacheStore.class.getName());
- individualCacheStoreConfig.setFetchPersistentState(false);
- individualCacheStoreConfig.setIgnoreModifications(false);
- individualCacheStoreConfig.setPurgeOnStartup(false);
-
- AsyncStoreConfig asyncStoreConfig = new AsyncStoreConfig();
- asyncStoreConfig.setEnabled(false);
- individualCacheStoreConfig.setAsyncStoreConfig(asyncStoreConfig);
+ // try to get pushState parameters, since they are set programmatically only
+ // Boolean pushState = config.getParameterBoolean(PARAM_JBOSSCACHE_PUSHSTATE, false);
+ // Long pushStateTimeOut = config.getParameterTime(PARAM_JBOSSCACHE_PUSHSTATE_TIMEOUT, 10000L);
- // create CacheLoaderManagerConfig
- CacheLoaderManagerConfig cacheLoaderManagerConfig = new CacheLoaderManagerConfig();
- cacheLoaderManagerConfig.setShared(false);
- cacheLoaderManagerConfig.setPassivation(false);
- cacheLoaderManagerConfig.addCacheLoaderConfig(individualCacheStoreConfig);
+ // insert CacheLoaderConfig
+ ISPNCacheFactory<Serializable, Object> factory = new ISPNCacheFactory<Serializable, Object>(cfm);
+ this.cache = factory.createCache("Indexer-" + searchManager.getWsId(), config);
- // insert CacheLoaderManagerConfig
- cache.getConfiguration().setCacheLoaderManagerConfig(cacheLoaderManagerConfig);
-
// Could have change of cache
- // IndexerSingletonStoreCacheLoader
- // IndexerCacheStore issCacheLoader =
- // (IndexerCacheStore)cache.getConfiguration().getCacheLoaderManagerConfig().getFirstCacheLoaderConfig().g;
+ CacheLoaderManager cacheLoaderManager =
+ cache.getAdvancedCache().getComponentRegistry().getComponent(CacheLoaderManager.class);
+ IndexerCacheStore cacheStore = (IndexerCacheStore)cacheLoaderManager.getCacheLoader();
// This code make it possible to use the JBossCacheIndexChangesFilter in
// a non-cluster environment
- if (cache.getConfiguration().getCacheMode() == CacheMode.LOCAL)
- {
- // Activate the cache loader
- // try
- // {
- // // issCacheLoader.activeStatusChanged(true);
- // }
- // catch (PushStateException e)
- // {
- // // ignore me;
- // }
- }
- // indexerCacheStore = (IndexerCacheStore)issCacheLoader.getCacheLoader();
-
- indexerCacheStore.register(searchManager, parentSearchManager, handler, parentHandler);
- IndexerIoModeHandler modeHandler = indexerCacheStore.getModeHandler();
- handler.setIndexerIoModeHandler(modeHandler);
- parentHandler.setIndexerIoModeHandler(modeHandler);
-
- if (!parentHandler.isInitialized())
- {
- parentHandler.setIndexInfos(new ISPNIndexInfos(searchManager.getWsId(), cache, true, modeHandler));
- parentHandler.setIndexUpdateMonitor(new ISPNIndexUpdateMonitor(searchManager.getWsId(), cache, true,
- modeHandler));
- parentHandler.init();
- }
- if (!handler.isInitialized())
- {
- handler.setIndexInfos(new ISPNIndexInfos(searchManager.getWsId(), cache, false, modeHandler));
- handler.setIndexUpdateMonitor(new ISPNIndexUpdateMonitor(searchManager.getWsId(), cache, false, modeHandler));
- handler.init();
- }
+ // if (cache.getConfiguration().getCacheMode() == CacheMode.LOCAL)
+ // {
+ // // Activate the cache loader
+ // try
+ // {
+ // cacheStore.activeStatusChanged(true);
+ // }
+ // catch (PushStateException e)
+ // {
+ // // ignore me;
+ // }
+ // }
+ // indexerCacheLoader = (IndexerCacheLoader)issCacheLoader.getCacheLoader();
+ //
+ // indexerCacheLoader.register(searchManager, parentSearchManager, handler, parentHandler);
+ // IndexerIoModeHandler modeHandler = indexerCacheLoader.getModeHandler();
+ // handler.setIndexerIoModeHandler(modeHandler);
+ // parentHandler.setIndexerIoModeHandler(modeHandler);
+ //
+ // if (!parentHandler.isInitialized())
+ // {
+ // parentHandler.setIndexInfos(new ISPNIndexInfos(searchManager.getWsId(), cache, true, modeHandler));
+ // parentHandler.setIndexUpdateMonitor(new ISPNIndexUpdateMonitor(searchManager.getWsId(), cache, true, modeHandler));
+ // parentHandler.init();
+ // }
+ // if (!handler.isInitialized())
+ // {
+ // handler.setIndexInfos(new ISPNIndexInfos(searchManager.getWsId(), cache, false, modeHandler));
+ // handler.setIndexUpdateMonitor(new ISPNIndexUpdateMonitor(searchManager.getWsId(), cache, false, modeHandler));
+ // handler.init();
+ // }
}
/**
@@ -180,7 +145,7 @@
return;
}
- ChangesKey changesKey = new ChangesKey(searchManager.getWsId() + IdGenerator.generate());
+ ChangesKey changesKey = new ChangesKey(wsId, IdGenerator.generate());
try
{
PrivilegedISPNCacheHelper.put(cache, changesKey, new ChangesFilterListsWrapper(changes, parentChanges));
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexInfos.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexInfos.java 2011-02-24 15:19:35 UTC (rev 4010)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexInfos.java 2011-02-24 15:58:54 UTC (rev 4011)
@@ -34,7 +34,6 @@
import java.io.IOException;
import java.io.Serializable;
import java.util.Set;
-import java.util.concurrent.TimeUnit;
/**
* Created by The eXo Platform SAS.
@@ -168,7 +167,7 @@
super.write();
// write to cache
- PrivilegedISPNCacheHelper.put(cache, namesKey, getNames(), -1, TimeUnit.SECONDS);
+ PrivilegedISPNCacheHelper.put(cache, namesKey, getNames());
}
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java 2011-02-24 15:19:35 UTC (rev 4010)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java 2011-02-24 15:58:54 UTC (rev 4011)
@@ -35,7 +35,6 @@
import java.io.Serializable;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.TimeUnit;
/**
* Created by The eXo Platform SAS.
@@ -153,7 +152,7 @@
localUpdateInProgress = updateInProgress;
if (persitentUpdate)
{
- PrivilegedISPNCacheHelper.put(cache, updateKey, new Boolean(updateInProgress), -1, TimeUnit.SECONDS);
+ PrivilegedISPNCacheHelper.put(cache, updateKey, new Boolean(updateInProgress));
}
for (IndexUpdateMonitorListener listener : listeners)
{
Modified: jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-indexer.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-indexer.xml 2011-02-24 15:19:35 UTC (rev 4010)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-indexer.xml 2011-02-24 15:58:54 UTC (rev 4011)
@@ -50,6 +50,11 @@
<transaction transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup" syncRollbackPhase="false" syncCommitPhase="false"/>
<jmxStatistics enabled="true"/>
<deadlockDetection enabled="true" spinDuration="100"/>
- <eviction strategy="LRU" wakeUpInterval="5000" threadPolicy="DEFAULT" maxEntries="10000"/>
+
+ <loaders passivation="false" shared="false" preload="false">
+ <loader class="org.exoplatform.services.jcr.impl.core.query.ispn.IndexerCacheStore" fetchPersistentState="false" ignoreModifications="false" purgeOnStartup="false">
+ <async enabled="false"/>
+ </loader>
+ </loaders>
</default>
</infinispan>
13 years, 2 months
exo-jcr SVN: r4010 - jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-02-24 10:19:35 -0500 (Thu, 24 Feb 2011)
New Revision: 4010
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java
Log:
EXOJCR-1078: fix NPE
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java 2011-02-24 07:48:07 UTC (rev 4009)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java 2011-02-24 15:19:35 UTC (rev 4010)
@@ -911,7 +911,7 @@
final private List<LockData> backupLocks = new ArrayList<LockData>();
- private List<LockData> actualLocks;
+ private List<LockData> actualLocks = new ArrayList<LockData>();
CacheLocksRestor(final List<LockData> backupLocks)
{
13 years, 2 months
exo-jcr SVN: r4009 - in jcr/trunk/exo.jcr.component.core/src: main/java/org/exoplatform/services/jcr/impl/core/query/lucene and 1 other directories.
by do-not-reply@jboss.org
Author: nzamosenchuk
Date: 2011-02-24 02:48:07 -0500 (Thu, 24 Feb 2011)
New Revision: 4009
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/OfflinePersistentIndex.java
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/IndexRecoveryImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandler.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandlerContext.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/SlowQueryHandler.java
Log:
EXOJCR-1194 : Introducing OfflinePersistendIndex that collects index for content updated while index was offline.
EXOJCR-1193 : Invoking OfflinePersistendIndex when index retrieval in progress.
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/IndexRecoveryImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/IndexRecoveryImpl.java 2011-02-23 12:40:22 UTC (rev 4008)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/IndexRecoveryImpl.java 2011-02-24 07:48:07 UTC (rev 4009)
@@ -18,6 +18,7 @@
import org.exoplatform.commons.utils.PrivilegedFileHelper;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.impl.core.query.lucene.OfflinePersistentIndex;
import org.exoplatform.services.jcr.impl.util.io.DirectoryHelper;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
@@ -89,6 +90,13 @@
protected Boolean isResponsibleToSetIndexOnline = false;
/**
+ * Indicates whether current node is in online or offline mode
+ */
+ protected Boolean isOnline = true;
+
+ protected final SearchManager searchManager;
+
+ /**
* Constructor IndexRetrieveImpl.
*
* @throws RepositoryConfigurationException
@@ -97,6 +105,7 @@
throws RepositoryConfigurationException
{
this.rpcService = rpcService;
+ this.searchManager = searchManager;
final String commandSuffix = searchManager.getWsId() + "-" + (searchManager.parentSearchManager == null);
final File indexDirectory = searchManager.getIndexDirectory();
@@ -111,9 +120,8 @@
public Serializable execute(Serializable[] args) throws Throwable
{
boolean isOnline = (Boolean)args[0];
-
- // TODO searchManager.setReadOnly(isReadOnly);
-
+ searchManager.setOnline(isOnline);
+ IndexRecoveryImpl.this.isOnline = isOnline;
return null;
}
});
@@ -134,10 +142,14 @@
{
if (!file.isDirectory())
{
- result.add(PrivilegedFileHelper.getAbsolutePath(file).substring(indexDirLen));
+ // if parent directory is not "offline" then add this file. Otherwise skip it.
+ // TODO implement list retrieval via index state manager
+ if (!file.getParent().endsWith(OfflinePersistentIndex.NAME))
+ {
+ result.add(PrivilegedFileHelper.getAbsolutePath(file).substring(indexDirLen));
+ }
}
}
-
return result;
}
});
@@ -156,10 +168,10 @@
RandomAccessFile file = new RandomAccessFile(new File(indexDirectory, filePath), "r");
file.seek(offset);
-
+
byte[] buffer = new byte[BUFFER_SIZE];
int len = file.read(buffer);
-
+
if (len == -1)
{
return null;
@@ -373,7 +385,7 @@
{
try
{
- if (rpcService.isCoordinator())
+ if (rpcService.isCoordinator() && !isOnline)
{
new Thread()
{
@@ -387,14 +399,22 @@
for (Object result : results)
{
- if ((Boolean)result)
+ if (result instanceof Boolean)
{
- return;
+ if ((Boolean)result)
+ {
+ return;
+ }
}
+ else
+ {
+ log.error("Result is not an instance of Boolean" + result);
+ }
}
-
// node which was responsible for resuming leave the cluster, so resume component
- // TODO searchManager.setOnline();
+ log
+ .error("Node responsible for setting index back online seems to leave the cluster. Setting back online.");
+ searchManager.setOnline(true);
}
catch (SecurityException e1)
{
@@ -404,6 +424,10 @@
{
log.error("Exception during command execution", e1);
}
+ catch (IOException e2)
+ {
+ log.error("Exception during setting index back online", e2);
+ }
}
}.start();
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandler.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandler.java 2011-02-23 12:40:22 UTC (rev 4008)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandler.java 2011-02-24 07:48:07 UTC (rev 4009)
@@ -196,4 +196,12 @@
*/
void setIndexUpdateMonitor(IndexUpdateMonitor indexUpdateMonitor);
+ /**
+ * Switches index into corresponding ONLINE or OFFLINE mode. Offline mode means that new indexing data is
+ * collected but index is guaranteed to be unmodified during offline state.
+ *
+ * @param isOnline
+ */
+ void setOnline(boolean isOnline) throws IOException;
+
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandlerContext.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandlerContext.java 2011-02-23 12:40:22 UTC (rev 4008)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandlerContext.java 2011-02-24 07:48:07 UTC (rev 4009)
@@ -23,6 +23,7 @@
import org.exoplatform.services.jcr.impl.core.NamespaceRegistryImpl;
import org.exoplatform.services.jcr.impl.core.nodetype.NodeTypeDataManagerImpl;
import org.exoplatform.services.jcr.impl.core.query.lucene.LuceneVirtualTableResolver;
+import org.exoplatform.services.rpc.RPCService;
/**
* Acts as an argument for the {@link QueryHandler} to keep the interface
@@ -82,8 +83,13 @@
* The class responsible for index retrieving from other place.
*/
private final IndexRecovery indexRecovery;
-
+
/**
+ * Field containing RPCService, if any configured in container
+ */
+ private final RPCService rpcService;
+
+ /**
* Creates a new context instance.
*
* @param fs
@@ -107,11 +113,13 @@
* descendant of that node is also excluded from indexing.
* @param indexRecovery
* the index retriever from other place
+ * @param rpcService
+ * RPCService intance if any
*/
public QueryHandlerContext(WorkspaceContainerFacade container, ItemDataConsumer stateMgr, IndexingTree indexingTree,
NodeTypeDataManager nodeTypeDataManager, NamespaceRegistryImpl nsRegistry, QueryHandler parentHandler,
String indexDirectory, DocumentReaderService extractor, boolean createInitialIndex,
- LuceneVirtualTableResolver virtualTableResolver, IndexRecovery indexRecovery)
+ LuceneVirtualTableResolver virtualTableResolver, IndexRecovery indexRecovery, RPCService rpcService)
{
this.indexRecovery = indexRecovery;
this.container = container;
@@ -124,6 +132,7 @@
this.createInitialIndex = createInitialIndex;
this.virtualTableResolver = virtualTableResolver;
this.propRegistry = new PropertyTypeRegistry(nodeTypeDataManager);
+ this.rpcService = rpcService;
this.parentHandler = parentHandler;
((NodeTypeDataManagerImpl)this.nodeTypeDataManager).addListener(propRegistry);
}
@@ -237,4 +246,12 @@
return indexRecovery;
}
+ /**
+ * @return RPCService if any present in a container.
+ */
+ public RPCService getRPCService()
+ {
+ return rpcService;
+ }
+
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java 2011-02-23 12:40:22 UTC (rev 4008)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java 2011-02-24 07:48:07 UTC (rev 4009)
@@ -382,7 +382,9 @@
try
{
if (reader != null)
+ {
reader.close();
+ }
}
catch (IOException e)
{
@@ -495,7 +497,9 @@
{
if (log.isDebugEnabled())
+ {
log.debug("start");
+ }
try
{
if (indexingTree == null)
@@ -517,7 +521,9 @@
{
ItemData excludeData = itemMgr.getItemData(stringTokenizer.nextToken());
if (excludeData != null)
+ {
excludedPath.add(excludeData.getQPath());
+ }
}
catch (RepositoryException e)
{
@@ -534,7 +540,9 @@
{
ItemData indexingRootDataItem = itemMgr.getItemData(rootNodeIdentifer);
if (indexingRootDataItem != null && indexingRootDataItem.isNode())
+ {
indexingRootData = (NodeData)indexingRootDataItem;
+ }
}
catch (RepositoryException e)
{
@@ -628,14 +636,20 @@
if (item.isNode())
{
if (!indexingTree.isExcluded(item))
+ {
return (NodeData)item;
+ }
}
else
+ {
log.warn("Node not found, but property " + id + ", " + item.getQPath().getAsString()
+ " found. ");
+ }
}
else
+ {
log.warn("Unable to index node with id " + id + ", node does not exist.");
+ }
}
catch (RepositoryException e)
@@ -704,7 +718,7 @@
QueryHandlerContext context =
new QueryHandlerContext(container, itemMgr, indexingTree, nodeTypeDataManager, nsReg, parentHandler,
PrivilegedFileHelper.getAbsolutePath(getIndexDirectory()), extractor, true, virtualTableResolver,
- indexRecovery);
+ indexRecovery, rpcService);
return context;
}
@@ -792,8 +806,8 @@
if (parentSearchManager != null)
{
newChangesFilter =
- constuctor.newInstance(this, parentSearchManager, config, indexingTree,
- parentSearchManager.getIndexingTree(), handler, parentSearchManager.getHandler(), cfm);
+ constuctor.newInstance(this, parentSearchManager, config, indexingTree, parentSearchManager
+ .getIndexingTree(), handler, parentSearchManager.getHandler(), cfm);
}
}
catch (SecurityException e)
@@ -840,7 +854,9 @@
// initialize query handler
String className = config.getType();
if (className == null)
+ {
throw new RepositoryConfigurationException("Content hanler configuration fail");
+ }
try
{
@@ -1015,6 +1031,17 @@
}
/**
+ * Switches index into online or offline modes.
+ *
+ * @param isOnline
+ * @throws IOException
+ */
+ public void setOnline(boolean isOnline) throws IOException
+ {
+ handler.setOnline(isOnline);
+ }
+
+ /**
* {@inheritDoc}
*/
public void resume() throws ResumeException
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java 2011-02-23 12:40:22 UTC (rev 4008)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java 2011-02-24 07:48:07 UTC (rev 4009)
@@ -148,6 +148,8 @@
*/
private VolatileIndex volatileIndex;
+ private OfflinePersistentIndex offlineIndex;
+
/**
* Flag indicating whether an update operation is in progress.
*/
@@ -230,8 +232,10 @@
/**
* Flag indicating whether re-indexing is running.
+ * Or for any other reason it should be switched
+ * to offline mode.
*/
- private boolean reindexing = false;
+ private boolean online = true;
/**
* Flag indicating whether the index is stopped.
@@ -319,6 +323,10 @@
merger.indexAdded(index.getName(), index.getNumDocuments());
}
+ offlineIndex =
+ new OfflinePersistentIndex(handler.getTextAnalyzer(), handler.getSimilarity(), cache, indexingQueue,
+ directoryManager);
+
// this method is run in privileged mode internally
IndexingQueueStore store = new IndexingQueueStore(indexDir);
@@ -433,11 +441,14 @@
// only do an initial index if there are no indexes at all
if (indexNames.size() == 0)
{
- reindexing = true;
+ setOnline(false);
+
try
{
+ // if "from-coordinator" used along with RPC Service present and
if (handler.getIndexRecoveryMode().equals(SearchIndex.INDEX_RECOVERY_MODE_FROM_COORDINATOR)
- && handler.getContext().getIndexRecovery() != null)
+ && handler.getContext().getIndexRecovery() != null && handler.getContext().getRPCService() != null
+ && handler.getContext().getRPCService().isCoordinator() == false)
{
log.info("Retrieving index from coordinator...");
recoveryIndexFromCoordinator();
@@ -447,6 +458,20 @@
}
else
{
+ if (handler.getIndexRecoveryMode().equals(SearchIndex.INDEX_RECOVERY_MODE_FROM_COORDINATOR))
+ {
+ if (handler.getContext().getRPCService() == null)
+ {
+ log
+ .error("RPC Service is not configured but required for copying the index from coordinator node. Index will be created by re-indexing.");
+ }
+ else if (handler.getContext().getRPCService().isCoordinator() == true)
+ {
+ log
+ .info("Copying the index from coordinator configured, but this node is the only one in a cluster. Index will be created by re-indexing.");
+ }
+ }
+
// traverse and index workspace
executeAndLog(new Start(Action.INTERNAL_TRANSACTION));
@@ -484,7 +509,7 @@
}
finally
{
- reindexing = false;
+ setOnline(true);
}
}
else
@@ -509,8 +534,12 @@
*/
synchronized void update(final Collection remove, final Collection add) throws IOException
{
- if (modeHandler.getMode() == IndexerIoMode.READ_WRITE)
+ if (!online)
{
+ doUpdateOffline(remove, add);
+ }
+ else if (modeHandler.getMode() == IndexerIoMode.READ_WRITE)
+ {
doUpdateRW(remove, add);
}
else
@@ -520,7 +549,8 @@
}
/**
- * For investigation purposes only
+ * Performs indexing into volatile index in case of Read_Only mode. This ensures that node
+ * was not present in latest persistent index in case of coordinator has just committed the index
*
* @param remove
* @param add
@@ -716,7 +746,72 @@
});
}
+ private void invokeOfflineIndex() throws IOException
+ {
+ List<String> processedIDs = offlineIndex.getProcessedIDs();
+ // remove all nodes placed in offline index
+ update(processedIDs, Collections.EMPTY_LIST);
+
+ executeAndLog(new Start(Action.INTERNAL_TRANSACTION));
+
+ // create index
+ CreateIndex create = new CreateIndex(getTransactionId(), null);
+ executeAndLog(create);
+
+ // invoke offline (copy offline into working index)
+ executeAndLog(new OfflineInvoke(getTransactionId(), create.getIndexName()));
+
+ // add new index
+ AddIndex add = new AddIndex(getTransactionId(), create.getIndexName());
+ executeAndLog(add);
+
+ executeAndLog(new Commit(getTransactionId()));
+
+ indexNames.write();
+
+ offlineIndex.close();
+ deleteIndex(offlineIndex);
+ offlineIndex = null;
+ }
+
/**
+ * Performs indexing while re-indexing is in progress
+ *
+ * @param remove
+ * @param add
+ * @throws IOException
+ */
+ private void doUpdateOffline(final Collection remove, final Collection add) throws IOException
+ {
+ SecurityHelper.doPrivilegedIOExceptionAction(new PrivilegedExceptionAction<Object>()
+ {
+ public Object run() throws Exception
+ {
+ for (Iterator it = remove.iterator(); it.hasNext();)
+ {
+ Term idTerm = new Term(FieldNames.UUID, (String)it.next());
+ offlineIndex.removeDocument(idTerm);
+ }
+
+ for (Iterator it = add.iterator(); it.hasNext();)
+ {
+ Document doc = (Document)it.next();
+ if (doc != null)
+ {
+ offlineIndex.addDocuments(new Document[]{doc});
+ // reset volatile index if needed
+ if (offlineIndex.getRamSizeInBytes() >= handler.getMaxVolatileIndexSize())
+ {
+ offlineIndex.commit();
+ }
+ }
+ }
+ return null;
+ }
+ });
+ }
+
+ /**
* Adds a document to the index.
*
* @param doc
@@ -994,7 +1089,7 @@
try
{
// if we are reindexing there is already an active transaction
- if (!reindexing)
+ if (online)
{
executeAndLog(new Start(Action.INTERNAL_TRANS_REPL_INDEXES));
}
@@ -1025,7 +1120,7 @@
}
index.commit();
- if (!reindexing)
+ if (online)
{
// only commit if we are not reindexing
// when reindexing the final commit is done at the very end
@@ -1050,7 +1145,7 @@
}
}
}
- if (reindexing)
+ if (!online)
{
// do some cleanup right away when reindexing
attemptDelete();
@@ -1154,6 +1249,11 @@
return volatileIndex;
}
+ OfflinePersistentIndex getOfflinePersistentIndex()
+ {
+ return offlineIndex;
+ }
+
/**
* Closes this <code>MultiIndex</code>.
*/
@@ -2040,11 +2140,21 @@
static final String VOLATILE_COMMIT = "VOL_COM";
/**
+ * Action identifier in redo log for offline index invocation action.
+ */
+ static final String OFFLINE_INVOKE = "OFF_INV";
+
+ /**
* Action type for volatile index commit action.
*/
public static final int TYPE_VOLATILE_COMMIT = 4;
/**
+ * Action type for volatile index commit action.
+ */
+ public static final int TYPE_OFFLINE_INVOKE = 8;
+
+ /**
* Action identifier in redo log for index create action.
*/
static final String CREATE_INDEX = "CRE_IDX";
@@ -2233,6 +2343,10 @@
{
a = VolatileCommit.fromString(transactionId, arguments);
}
+ else if (actionLabel.equals(Action.OFFLINE_INVOKE))
+ {
+ a = OfflineInvoke.fromString(transactionId, arguments);
+ }
else
{
throw new IllegalArgumentException(line);
@@ -2326,8 +2440,8 @@
/**
* The maximum length of a AddNode String.
*/
- private static final int ENTRY_LENGTH = Long.toString(Long.MAX_VALUE).length() + Action.ADD_NODE.length()
- + Constants.UUID_FORMATTED_LENGTH + 2;
+ private static final int ENTRY_LENGTH =
+ Long.toString(Long.MAX_VALUE).length() + Action.ADD_NODE.length() + Constants.UUID_FORMATTED_LENGTH + 2;
/**
* The uuid of the node to add.
@@ -2728,8 +2842,8 @@
/**
* The maximum length of a DeleteNode String.
*/
- private static final int ENTRY_LENGTH = Long.toString(Long.MAX_VALUE).length() + Action.DELETE_NODE.length()
- + Constants.UUID_FORMATTED_LENGTH + 2;
+ private static final int ENTRY_LENGTH =
+ Long.toString(Long.MAX_VALUE).length() + Action.DELETE_NODE.length() + Constants.UUID_FORMATTED_LENGTH + 2;
/**
* The uuid of the node to remove.
@@ -2944,6 +3058,69 @@
}
}
+ private static class OfflineInvoke extends Action
+ {
+
+ /**
+ * The name of the target index to commit to.
+ */
+ private final String targetIndex;
+
+ /**
+ * Creates a new VolatileCommit action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ */
+ OfflineInvoke(long transactionId, String targetIndex)
+ {
+ super(transactionId, Action.TYPE_OFFLINE_INVOKE);
+ this.targetIndex = targetIndex;
+ }
+
+ /**
+ * Creates a new VolatileCommit action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param arguments
+ * ignored by this implementation.
+ * @return the VolatileCommit action.
+ */
+ static OfflineInvoke fromString(long transactionId, String arguments)
+ {
+ return new OfflineInvoke(transactionId, arguments);
+ }
+
+ /**
+ * Commits the volatile index to disk.
+ *
+ * @inheritDoc
+ */
+ @Override
+ public void execute(MultiIndex index) throws IOException
+ {
+ OfflinePersistentIndex offlineIndex = index.getOfflinePersistentIndex();
+ PersistentIndex persistentIndex = index.getOrCreateIndex(targetIndex);
+ persistentIndex.copyIndex(offlineIndex);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public String toString()
+ {
+ StringBuffer logLine = new StringBuffer();
+ logLine.append(Long.toString(getTransactionId()));
+ logLine.append(' ');
+ logLine.append(Action.OFFLINE_INVOKE);
+ logLine.append(' ');
+ logLine.append(targetIndex);
+ return logLine.toString();
+ }
+ }
+
/**
* @see org.exoplatform.services.jcr.impl.core.query.IndexerIoModeListener#onChangeMode(org.exoplatform.services.jcr.impl.core.query.IndexerIoMode)
*/
@@ -3111,12 +3288,39 @@
}
catch (IOException e)
{
- log.error("An erro occurs while trying to wake up the sleeping threads", e);
+ log.error("An error occurred while trying to wake up the sleeping threads", e);
}
}
}
}
+ public synchronized void setOnline(boolean isOnline) throws IOException
+ {
+ // if mode really changed
+ if (online != isOnline)
+ {
+ // switching to ONLINE
+ if (isOnline)
+ {
+ log.info("Setting index back online");
+ offlineIndex.commit(true);
+ //invoking offline index
+ invokeOfflineIndex();
+ online = true;
+ }
+ // switching to OFFLINE
+ else
+ {
+ log.info("Setting index offline");
+ offlineIndex =
+ new OfflinePersistentIndex(handler.getTextAnalyzer(), handler.getSimilarity(), cache, indexingQueue,
+ directoryManager);
+ online = false;
+ flush();
+ }
+ }
+ }
+
/**
* This class is used to index a node and its descendants nodes with several threads
*/
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/OfflinePersistentIndex.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/OfflinePersistentIndex.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/OfflinePersistentIndex.java 2011-02-24 07:48:07 UTC (rev 4009)
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.core.query.lucene;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.Similarity;
+import org.exoplatform.services.jcr.impl.core.query.lucene.directory.DirectoryManager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Class extends {@link PersistentIndex} and designed to be used while Index is not yet started
+ * due to long running jobs, but since it is launched in clustered environment some concurrent
+ * repository operations can be performed (add, delete).
+ *
+ * @author <a href="mailto:nikolazius@gmail.com">Nikolay Zamosenchuk</a>
+ * @version $Id: OfflinePersistentIndex.java 34360 2009-07-22 23:58:59Z nzamosenchuk $
+ *
+ */
+public class OfflinePersistentIndex extends PersistentIndex
+{
+ public static final String NAME = "offline";
+
+ private List<String> processedIDs;
+
+ /**
+ * Creates a new <code>OfflinePersistentIndex</code>.
+ *
+ * @param analyzer the analyzer for text tokenizing.
+ * @param similarity the similarity implementation.
+ * @param cache the document number cache
+ * @param indexingQueue the indexing queue.
+ * @param directoryManager the directory manager.
+ * @throws IOException if an error occurs while opening / creating the
+ * index.
+ */
+ OfflinePersistentIndex(Analyzer analyzer, Similarity similarity, DocNumberCache cache, IndexingQueue indexingQueue,
+ DirectoryManager directoryManager) throws IOException
+ {
+ super(NAME, analyzer, similarity, cache, indexingQueue, directoryManager);
+ this.processedIDs = new ArrayList<String>();
+ }
+
+ @Override
+ int getNumDocuments() throws IOException
+ {
+ return super.getNumDocuments();
+ }
+
+ @Override
+ int removeDocument(Term idTerm) throws IOException
+ {
+ int count = super.removeDocument(idTerm);
+ processedIDs.add(idTerm.text());
+ System.out.println("RM: " + idTerm.text());
+ return count;
+ }
+
+ @Override
+ void addDocuments(Document[] docs) throws IOException
+ {
+ super.addDocuments(docs);
+ for (Document doc : docs)
+ {
+ System.out.println("add: " + doc.get(FieldNames.UUID));
+ processedIDs.add(doc.get(FieldNames.UUID));
+ }
+ }
+
+ @Override
+ synchronized void close()
+ {
+ processedIDs.clear();
+ super.close();
+ }
+
+ /**
+ * @return the list of UUIDs that where processed by this index. They are both added and removed nodes.
+ */
+ public List<String> getProcessedIDs()
+ {
+ return Collections.unmodifiableList(processedIDs);
+ }
+
+}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java 2011-02-23 12:40:22 UTC (rev 4008)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java 2011-02-24 07:48:07 UTC (rev 4009)
@@ -762,7 +762,11 @@
public void apply(ChangesHolder changes) throws RepositoryException, IOException
{
checkOpen();
- index.update(changes.getRemove(), changes.getAdd());
+ // index may not be initialized, but some operation can be performed in cluster environment
+ if (index != null)
+ {
+ index.update(changes.getRemove(), changes.getAdd());
+ }
}
/**
@@ -2945,4 +2949,13 @@
log.error("Can not recover error log.", e);
}
}
+
+ /**
+ * @see org.exoplatform.services.jcr.impl.core.query.QueryHandler#setOnline(boolean)
+ */
+ public void setOnline(boolean isOnline) throws IOException
+ {
+ checkOpen();
+ index.setOnline(isOnline);
+ }
}
Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/SlowQueryHandler.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/SlowQueryHandler.java 2011-02-23 12:40:22 UTC (rev 4008)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/SlowQueryHandler.java 2011-02-24 07:48:07 UTC (rev 4009)
@@ -106,4 +106,13 @@
// TODO Auto-generated method stub
return null;
}
+
+ /**
+ * @see org.exoplatform.services.jcr.impl.core.query.QueryHandler#setOnline(boolean)
+ */
+ public void setOnline(boolean isOnline)
+ {
+ // TODO Auto-generated method stub
+
+ }
}
13 years, 2 months
exo-jcr SVN: r4008 - in jcr/trunk/exo.jcr.component.core/src: main/java/org/exoplatform/services/jcr/infinispan and 1 other directories.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-02-23 07:40:22 -0500 (Wed, 23 Feb 2011)
New Revision: 4008
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ChangesKey.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexerCacheStore.java
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexInfos.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/PrivilegedISPNCacheHelper.java
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-config.xml
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-indexer.xml
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-lock.xml
Log:
EXOJCR-832: implementation
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ChangesKey.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ChangesKey.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ChangesKey.java 2011-02-23 12:40:22 UTC (rev 4008)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.core.query.ispn;
+
+import org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.CacheKey;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 22.02.011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy Bazko</a>
+ * @version $Id: ChangesKey.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public class ChangesKey extends CacheKey
+{
+
+ ChangesKey(String id)
+ {
+ super(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof ChangesKey)
+ {
+ ChangesKey key = (ChangesKey)obj;
+ return (key.hash == hash && key.id.equals(id));
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexChangesFilter.java 2011-02-23 12:40:22 UTC (rev 4008)
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.core.query.ispn;
+
+import org.exoplatform.container.configuration.ConfigurationManager;
+import org.exoplatform.services.jcr.config.QueryHandlerEntry;
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.impl.core.query.IndexerChangesFilter;
+import org.exoplatform.services.jcr.impl.core.query.IndexerIoModeHandler;
+import org.exoplatform.services.jcr.impl.core.query.IndexingTree;
+import org.exoplatform.services.jcr.impl.core.query.QueryHandler;
+import org.exoplatform.services.jcr.impl.core.query.SearchManager;
+import org.exoplatform.services.jcr.impl.core.query.jbosscache.ChangesFilterListsWrapper;
+import org.exoplatform.services.jcr.impl.core.query.lucene.ChangesHolder;
+import org.exoplatform.services.jcr.infinispan.ISPNCacheFactory;
+import org.exoplatform.services.jcr.infinispan.PrivilegedISPNCacheHelper;
+import org.exoplatform.services.jcr.util.IdGenerator;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.infinispan.Cache;
+import org.infinispan.CacheException;
+import org.infinispan.config.CacheLoaderManagerConfig;
+import org.infinispan.config.Configuration.CacheMode;
+import org.infinispan.loaders.AbstractCacheStoreConfig;
+import org.infinispan.loaders.decorators.AsyncStoreConfig;
+import org.infinispan.loaders.decorators.SingletonStoreConfig;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 23.02.2011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy Bazko</a>
+ * @version $Id: ISPNIndexChangesFilter.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public class ISPNIndexChangesFilter extends IndexerChangesFilter
+{
+ /**
+ * Logger instance for this class
+ */
+ private final Log log = ExoLogger.getLogger("exo.jcr.component.core.ISPNIndexChangesFilter");
+
+ public static final String PARAM_INFINISPAN_CONFIGURATION = "infinispan-configuration";
+
+ public static final String PARAM_INFINISPAN_PUSHSTATE = "infinispan-sscl-push.state.enabled";
+
+ public static final String PARAM_INFINISPAN_PUSHSTATE_TIMEOUT = "infinispan-sscl-push.state.timeout";
+
+ // TODO eviction
+
+ /**
+ * ISPN cache.
+ */
+ private final Cache<Serializable, Object> cache;
+
+ /**
+ * ISPNIndexChangesFilter constructor.
+ */
+ public ISPNIndexChangesFilter(SearchManager searchManager, SearchManager parentSearchManager,
+ QueryHandlerEntry config, IndexingTree indexingTree, IndexingTree parentIndexingTree, QueryHandler handler,
+ QueryHandler parentHandler, ConfigurationManager cfm) throws IOException, RepositoryException,
+ RepositoryConfigurationException
+ {
+ super(searchManager, parentSearchManager, config, indexingTree, parentIndexingTree, handler, parentHandler, cfm);
+
+ // create cache using custom factory
+ ISPNCacheFactory<Serializable, Object> factory = new ISPNCacheFactory<Serializable, Object>(cfm);
+ cache = factory.createCache("Indexer-" + searchManager.getWsId(), config);
+
+ // singletonStoreConfig.setSingletonStoreClass(IndexerSingletonStoreCacheLoader.class.getName());
+ // create SingletonStoreConfig
+ SingletonStoreConfig singletonStoreConfig = new SingletonStoreConfig();
+
+ Boolean pushState = config.getParameterBoolean(PARAM_INFINISPAN_PUSHSTATE, false);
+ Long pushStateTimeOut = config.getParameterTime(PARAM_INFINISPAN_PUSHSTATE_TIMEOUT, 10000L);
+
+ singletonStoreConfig.setPushStateWhenCoordinator(pushState);
+ singletonStoreConfig.setPushStateTimeout(pushStateTimeOut);
+ singletonStoreConfig.setSingletonStoreEnabled(true);
+
+ // initialize IndexerCacheLoader
+ IndexerCacheStore indexerCacheStore = new IndexerCacheStore();
+
+ // create CacheLoaderConfig
+ AbstractCacheStoreConfig individualCacheStoreConfig = new AbstractCacheStoreConfig();
+ individualCacheStoreConfig.setSingletonStoreConfig(singletonStoreConfig);
+ individualCacheStoreConfig.setCacheLoaderClassName(IndexerCacheStore.class.getName());
+ individualCacheStoreConfig.setFetchPersistentState(false);
+ individualCacheStoreConfig.setIgnoreModifications(false);
+ individualCacheStoreConfig.setPurgeOnStartup(false);
+
+ AsyncStoreConfig asyncStoreConfig = new AsyncStoreConfig();
+ asyncStoreConfig.setEnabled(false);
+ individualCacheStoreConfig.setAsyncStoreConfig(asyncStoreConfig);
+
+ // create CacheLoaderManagerConfig
+ CacheLoaderManagerConfig cacheLoaderManagerConfig = new CacheLoaderManagerConfig();
+ cacheLoaderManagerConfig.setShared(false);
+ cacheLoaderManagerConfig.setPassivation(false);
+ cacheLoaderManagerConfig.addCacheLoaderConfig(individualCacheStoreConfig);
+
+ // insert CacheLoaderManagerConfig
+ cache.getConfiguration().setCacheLoaderManagerConfig(cacheLoaderManagerConfig);
+
+ // Could have change of cache
+ // IndexerSingletonStoreCacheLoader
+ // IndexerCacheStore issCacheLoader =
+ // (IndexerCacheStore)cache.getConfiguration().getCacheLoaderManagerConfig().getFirstCacheLoaderConfig().g;
+
+ // This code make it possible to use the JBossCacheIndexChangesFilter in
+ // a non-cluster environment
+ if (cache.getConfiguration().getCacheMode() == CacheMode.LOCAL)
+ {
+ // Activate the cache loader
+ // try
+ // {
+ // // issCacheLoader.activeStatusChanged(true);
+ // }
+ // catch (PushStateException e)
+ // {
+ // // ignore me;
+ // }
+ }
+ // indexerCacheStore = (IndexerCacheStore)issCacheLoader.getCacheLoader();
+
+ indexerCacheStore.register(searchManager, parentSearchManager, handler, parentHandler);
+ IndexerIoModeHandler modeHandler = indexerCacheStore.getModeHandler();
+ handler.setIndexerIoModeHandler(modeHandler);
+ parentHandler.setIndexerIoModeHandler(modeHandler);
+
+ if (!parentHandler.isInitialized())
+ {
+ parentHandler.setIndexInfos(new ISPNIndexInfos(searchManager.getWsId(), cache, true, modeHandler));
+ parentHandler.setIndexUpdateMonitor(new ISPNIndexUpdateMonitor(searchManager.getWsId(), cache, true,
+ modeHandler));
+ parentHandler.init();
+ }
+ if (!handler.isInitialized())
+ {
+ handler.setIndexInfos(new ISPNIndexInfos(searchManager.getWsId(), cache, false, modeHandler));
+ handler.setIndexUpdateMonitor(new ISPNIndexUpdateMonitor(searchManager.getWsId(), cache, false, modeHandler));
+ handler.init();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void doUpdateIndex(Set<String> removedNodes, Set<String> addedNodes, Set<String> parentRemovedNodes,
+ Set<String> parentAddedNodes)
+ {
+ ChangesHolder changes = searchManager.getChanges(removedNodes, addedNodes);
+ ChangesHolder parentChanges = parentSearchManager.getChanges(parentRemovedNodes, parentAddedNodes);
+
+ if (changes == null && parentChanges == null)
+ {
+ return;
+ }
+
+ ChangesKey changesKey = new ChangesKey(searchManager.getWsId() + IdGenerator.generate());
+ try
+ {
+ PrivilegedISPNCacheHelper.put(cache, changesKey, new ChangesFilterListsWrapper(changes, parentChanges));
+ }
+ catch (CacheException e)
+ {
+ log.error(e.getLocalizedMessage(), e);
+ logErrorChanges(handler, removedNodes, addedNodes);
+ logErrorChanges(parentHandler, parentRemovedNodes, parentAddedNodes);
+ }
+ }
+
+ /**
+ * Log errors.
+ *
+ * @param logHandler
+ * @param removedNodes
+ * @param addedNodes
+ */
+ private void logErrorChanges(QueryHandler logHandler, Set<String> removedNodes, Set<String> addedNodes)
+ {
+ try
+ {
+ logHandler.logErrorChanges(addedNodes, removedNodes);
+ }
+ catch (IOException ioe)
+ {
+ log.warn("Exception occure when errorLog writed. Error log is not complete. " + ioe, ioe);
+ }
+ }
+}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexInfos.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexInfos.java 2011-02-22 15:03:27 UTC (rev 4007)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexInfos.java 2011-02-23 12:40:22 UTC (rev 4008)
@@ -34,6 +34,7 @@
import java.io.IOException;
import java.io.Serializable;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
/**
* Created by The eXo Platform SAS.
@@ -167,7 +168,7 @@
super.write();
// write to cache
- PrivilegedISPNCacheHelper.put(cache, namesKey, getNames());
+ PrivilegedISPNCacheHelper.put(cache, namesKey, getNames(), -1, TimeUnit.SECONDS);
}
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java 2011-02-22 15:03:27 UTC (rev 4007)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java 2011-02-23 12:40:22 UTC (rev 4008)
@@ -35,6 +35,7 @@
import java.io.Serializable;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
/**
* Created by The eXo Platform SAS.
@@ -152,7 +153,7 @@
localUpdateInProgress = updateInProgress;
if (persitentUpdate)
{
- PrivilegedISPNCacheHelper.put(cache, updateKey, new Boolean(updateInProgress));
+ PrivilegedISPNCacheHelper.put(cache, updateKey, new Boolean(updateInProgress), -1, TimeUnit.SECONDS);
}
for (IndexUpdateMonitorListener listener : listeners)
{
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexerCacheStore.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexerCacheStore.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexerCacheStore.java 2011-02-23 12:40:22 UTC (rev 4008)
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2003-2009 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.core.query.ispn;
+
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.impl.core.query.IndexerIoMode;
+import org.exoplatform.services.jcr.impl.core.query.IndexerIoModeHandler;
+import org.exoplatform.services.jcr.impl.core.query.QueryHandler;
+import org.exoplatform.services.jcr.impl.core.query.SearchManager;
+import org.exoplatform.services.jcr.impl.core.query.jbosscache.ChangesFilterListsWrapper;
+import org.exoplatform.services.jcr.impl.core.query.jbosscache.JBossCacheIndexChangesFilter;
+import org.exoplatform.services.jcr.impl.core.query.lucene.ChangesHolder;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.infinispan.container.entries.InternalCacheEntry;
+import org.infinispan.lifecycle.ComponentStatus;
+import org.infinispan.loaders.AbstractCacheStore;
+import org.infinispan.loaders.CacheLoaderConfig;
+import org.infinispan.loaders.CacheLoaderException;
+import org.jboss.cache.Fqn;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 23.02.2011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy Bazko</a>
+ * @version $Id: IndexerCacheStore.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public class IndexerCacheStore extends AbstractCacheStore
+{
+ private static final Log log = ExoLogger.getLogger("exo.jcr.component.core.IndexerCacheStore");
+
+ /**
+ * A map of all the indexers that has been registered.
+ */
+ private final Map<Fqn<String>, Indexer> indexers = new HashMap<Fqn<String>, Indexer>();
+
+ protected volatile IndexerIoModeHandler modeHandler;
+
+ /**
+ * This method will register a new Indexer according to the given parameters.
+ *
+ * @param searchManager
+ * @param parentSearchManager
+ * @param handler
+ * @param parentHandler
+ * @throws RepositoryConfigurationException
+ */
+ public void register(SearchManager searchManager, SearchManager parentSearchManager, QueryHandler handler,
+ QueryHandler parentHandler) throws RepositoryConfigurationException
+ {
+ indexers.put(Fqn.fromElements(searchManager.getWsId()), new Indexer(searchManager, parentSearchManager, handler,
+ parentHandler));
+ if (log.isDebugEnabled())
+ {
+ log.debug("Register " + searchManager.getWsId() + " " + this + " in " + indexers);
+ }
+ }
+
+ /**
+ * @see org.jboss.cache.loader.CacheLoader#put(org.jboss.cache.Fqn, java.lang.Object, java.lang.Object)
+ */
+ public Object put(Fqn name, Object key, Object value) throws Exception
+ {
+ if (key.equals(JBossCacheIndexChangesFilter.LISTWRAPPER) && value instanceof ChangesFilterListsWrapper)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.info("Received list wrapper, start indexing...");
+ }
+ // updating index
+ ChangesFilterListsWrapper wrapper = (ChangesFilterListsWrapper)value;
+ try
+ {
+ Indexer indexer = indexers.get(name.getParent());
+ if (indexer == null)
+ {
+ log.warn("No indexer could be found for the fqn " + name.getParent());
+ if (log.isDebugEnabled())
+ {
+ log.debug("The current content of the map of indexers is " + indexers);
+ }
+ }
+ else if (wrapper.withChanges())
+ {
+ indexer.updateIndex(wrapper.getChanges(), wrapper.getParentChanges());
+ }
+ else
+ {
+ indexer.updateIndex(wrapper.getAddedNodes(), wrapper.getRemovedNodes(), wrapper.getParentAddedNodes(),
+ wrapper.getParentRemovedNodes());
+ }
+ }
+ finally
+ {
+ if (modeHandler.getMode() == IndexerIoMode.READ_WRITE)
+ {
+ // remove the data from the cache
+ // cache.removeNode(name);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Switches Indexer mode from RO to RW, or from RW to RO
+ *
+ * @param ioMode
+ */
+ void setMode(IndexerIoMode ioMode)
+ {
+ if (modeHandler != null)
+ {
+ modeHandler.setMode(ioMode);
+ }
+ }
+
+ /**
+ * Get the mode handler.
+ */
+ IndexerIoModeHandler getModeHandler()
+ {
+ if (modeHandler == null)
+ {
+ if (cache.getStatus() != ComponentStatus.RUNNING)
+ {
+ throw new IllegalStateException("The cache should be started first");
+ }
+ synchronized (this)
+ {
+ if (modeHandler == null)
+ {
+ boolean isCoordinator = cache.getAdvancedCache().getRpcManager().getTransport().isCoordinator();
+ this.modeHandler =
+ new IndexerIoModeHandler(isCoordinator ? IndexerIoMode.READ_WRITE : IndexerIoMode.READ_ONLY);
+ }
+ }
+ }
+ return modeHandler;
+ }
+
+ /**
+ * This class will update the indexes of the related workspace
+ */
+ private static class Indexer
+ {
+
+ private final SearchManager searchManager;
+
+ private final SearchManager parentSearchManager;
+
+ private final QueryHandler handler;
+
+ private final QueryHandler parentHandler;
+
+ public Indexer(SearchManager searchManager, SearchManager parentSearchManager, QueryHandler handler,
+ QueryHandler parentHandler) throws RepositoryConfigurationException
+ {
+ this.searchManager = searchManager;
+ this.parentSearchManager = parentSearchManager;
+ this.handler = handler;
+ this.parentHandler = parentHandler;
+ }
+
+ /**
+ * Flushes lists of added/removed nodes to SearchManagers, starting indexing.
+ *
+ * @param addedNodes
+ * @param removedNodes
+ * @param parentAddedNodes
+ * @param parentRemovedNodes
+ */
+ protected void updateIndex(Set<String> addedNodes, Set<String> removedNodes, Set<String> parentAddedNodes,
+ Set<String> parentRemovedNodes)
+ {
+ // pass lists to search manager
+ if (searchManager != null && (addedNodes.size() > 0 || removedNodes.size() > 0))
+ {
+ try
+ {
+ searchManager.updateIndex(removedNodes, addedNodes);
+ }
+ catch (RepositoryException e)
+ {
+ log.error("Error indexing changes " + e, e);
+ }
+ catch (IOException e)
+ {
+ log.error("Error indexing changes " + e, e);
+ try
+ {
+ handler.logErrorChanges(removedNodes, addedNodes);
+ }
+ catch (IOException ioe)
+ {
+ log.warn("Exception occure when errorLog writed. Error log is not complete. " + ioe, ioe);
+ }
+ }
+ }
+ // pass lists to parent search manager
+ if (parentSearchManager != null && (parentAddedNodes.size() > 0 || parentRemovedNodes.size() > 0))
+ {
+ try
+ {
+ parentSearchManager.updateIndex(parentRemovedNodes, parentAddedNodes);
+ }
+ catch (RepositoryException e)
+ {
+ log.error("Error indexing changes " + e, e);
+ }
+ catch (IOException e)
+ {
+ log.error("Error indexing changes " + e, e);
+ try
+ {
+ parentHandler.logErrorChanges(parentRemovedNodes, parentAddedNodes);
+ }
+ catch (IOException ioe)
+ {
+ log.warn("Exception occure when errorLog writed. Error log is not complete. " + ioe, ioe);
+ }
+ }
+ }
+ }
+
+ /**
+ * Flushes lists of added/removed nodes to SearchManagers, starting indexing.
+ */
+ protected void updateIndex(ChangesHolder changes, ChangesHolder parentChanges)
+ {
+ // pass lists to search manager
+ if (searchManager != null && changes != null)
+ {
+ try
+ {
+ searchManager.apply(changes);
+ }
+ catch (RepositoryException e)
+ {
+ log.error("Error indexing changes " + e, e);
+ }
+ catch (IOException e)
+ {
+ log.error("Error indexing changes " + e, e);
+ try
+ {
+ handler.logErrorChanges(new HashSet<String>(changes.getRemove()), new HashSet<String>(changes
+ .getAddIds()));
+ }
+ catch (IOException ioe)
+ {
+ log.warn("Exception occure when errorLog writed. Error log is not complete. " + ioe, ioe);
+ }
+ }
+ }
+ // pass lists to parent search manager
+ if (parentSearchManager != null && parentChanges != null)
+ {
+ try
+ {
+ parentSearchManager.apply(parentChanges);
+ }
+ catch (RepositoryException e)
+ {
+ log.error("Error indexing changes " + e, e);
+ }
+ catch (IOException e)
+ {
+ log.error("Error indexing changes " + e, e);
+ try
+ {
+ parentHandler.logErrorChanges(new HashSet<String>(parentChanges.getRemove()), new HashSet<String>(
+ parentChanges.getAddIds()));
+ }
+ catch (IOException ioe)
+ {
+ log.warn("Exception occure when errorLog writed. Error log is not complete. " + ioe, ioe);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void store(InternalCacheEntry entry) throws CacheLoaderException
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void fromStream(ObjectInput inputStream) throws CacheLoaderException
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void toStream(ObjectOutput outputStream) throws CacheLoaderException
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void clear() throws CacheLoaderException
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean remove(Object key) throws CacheLoaderException
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public InternalCacheEntry load(Object key) throws CacheLoaderException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Set<InternalCacheEntry> loadAll() throws CacheLoaderException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Set<InternalCacheEntry> load(int numEntries) throws CacheLoaderException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Set<Object> loadAllKeys(Set<Object> keysToExclude) throws CacheLoaderException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Class<? extends CacheLoaderConfig> getConfigurationClass()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected void purgeInternal() throws CacheLoaderException
+ {
+ // TODO Auto-generated method stub
+
+ }
+}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/PrivilegedISPNCacheHelper.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/PrivilegedISPNCacheHelper.java 2011-02-22 15:03:27 UTC (rev 4007)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/PrivilegedISPNCacheHelper.java 2011-02-23 12:40:22 UTC (rev 4008)
@@ -23,6 +23,7 @@
import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.concurrent.TimeUnit;
/**
* @author <a href="anatoliy.bazko(a)exoplatform.org">Anatoliy Bazko</a>
@@ -37,7 +38,7 @@
*
* @param cache
*/
- public static void start(final org.infinispan.Cache<Serializable, Object> cache)
+ public static void start(final Cache<Serializable, Object> cache)
{
PrivilegedAction<Object> action = new PrivilegedAction<Object>()
{
@@ -102,4 +103,21 @@
return AccessController.doPrivileged(action);
}
+ /**
+ * Put in Infinispan cache in privileged mode.
+ *
+ * @param cache
+ */
+ public static Object put(final Cache<Serializable, Object> cache, final Serializable key, final Object value,
+ final long lifespan, final TimeUnit unit)
+ {
+ PrivilegedAction<Object> action = new PrivilegedAction<Object>()
+ {
+ public Object run()
+ {
+ return cache.put(key, value, lifespan, unit);
+ }
+ };
+ return AccessController.doPrivileged(action);
+ }
}
Modified: jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-config.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-config.xml 2011-02-22 15:03:27 UTC (rev 4007)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-config.xml 2011-02-23 12:40:22 UTC (rev 4008)
@@ -41,10 +41,15 @@
</global>
<default>
+ <clustering mode="replication">
+ <stateRetrieval timeout="20000" fetchInMemoryState="false" />
+ <sync />
+ </clustering>
+
<locking isolationLevel="READ_COMMITTED" lockAcquisitionTimeout="20000" writeSkewCheck="false" concurrencyLevel="500"/>
<transaction transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup" syncRollbackPhase="false" syncCommitPhase="false"/>
<jmxStatistics enabled="true"/>
<deadlockDetection enabled="true" spinDuration="100"/>
- <eviction strategy="LRU" wakeUpInterval="5000" threadPolicy="DEFAULT" maxEntries="5000"/>
+ <eviction strategy="LRU" wakeUpInterval="5000" threadPolicy="DEFAULT" maxEntries="1000000"/>
</default>
</infinispan>
Modified: jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-indexer.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-indexer.xml 2011-02-22 15:03:27 UTC (rev 4007)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-indexer.xml 2011-02-23 12:40:22 UTC (rev 4008)
@@ -25,6 +25,12 @@
xmlns="urn:infinispan:config:4.0">
<global>
+ <evictionScheduledExecutor factory="org.infinispan.executors.DefaultScheduledExecutorFactory">
+ <properties>
+ <property name="threadNamePrefix" value="EvictionThread"/>
+ </properties>
+ </evictionScheduledExecutor>
+
<globalJmxStatistics jmxDomain="infinispan" enabled="true" allowDuplicateDomains="true"/>
<transport transportClass="org.infinispan.remoting.transport.jgroups.JGroupsTransport" clusterName="${infinispan-cluster-name}" distributedSyncTimeout="20000">
@@ -35,9 +41,15 @@
</global>
<default>
+ <clustering mode="replication">
+ <stateRetrieval timeout="20000" fetchInMemoryState="false" />
+ <sync />
+ </clustering>
+
<locking isolationLevel="READ_COMMITTED" lockAcquisitionTimeout="20000" writeSkewCheck="false" concurrencyLevel="500"/>
<transaction transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup" syncRollbackPhase="false" syncCommitPhase="false"/>
<jmxStatistics enabled="true"/>
<deadlockDetection enabled="true" spinDuration="100"/>
+ <eviction strategy="LRU" wakeUpInterval="5000" threadPolicy="DEFAULT" maxEntries="10000"/>
</default>
</infinispan>
Modified: jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-lock.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-lock.xml 2011-02-22 15:03:27 UTC (rev 4007)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-lock.xml 2011-02-23 12:40:22 UTC (rev 4008)
@@ -35,6 +35,11 @@
</global>
<default>
+ <clustering mode="replication">
+ <stateRetrieval timeout="20000" fetchInMemoryState="false" />
+ <sync />
+ </clustering>
+
<locking isolationLevel="READ_COMMITTED" lockAcquisitionTimeout="20000" writeSkewCheck="false" concurrencyLevel="500"/>
<transaction transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup" syncRollbackPhase="false" syncCommitPhase="false"/>
<jmxStatistics enabled="true"/>
13 years, 2 months
exo-jcr SVN: r4007 - in jcr/trunk/exo.jcr.component.core/src: test/resources/conf/standalone/cluster and 1 other directory.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-02-22 10:03:27 -0500 (Tue, 22 Feb 2011)
New Revision: 4007
Added:
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-indexer.xml
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jcr-config-ispn.xml
Log:
EXOJCR-832: add configurations
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java 2011-02-22 14:52:13 UTC (rev 4006)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java 2011-02-22 15:03:27 UTC (rev 4007)
@@ -76,11 +76,16 @@
private final IndexUpdateKey updateKey;
/**
+ * ISPNIndexUpdateMonitor constructor.
*
* @param wsId
+ * unique workspace identifier
* @param cache
+ * ISPN cache
* @param system
+ * notifies if this IndexInfos is from system search manager or not
* @param modeHandler
+ * used to retrieve the current mode
*/
public ISPNIndexUpdateMonitor(String wsId, Cache<Serializable, Object> cache, boolean system,
IndexerIoModeHandler modeHandler)
Added: jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-indexer.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-indexer.xml (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-indexer.xml 2011-02-22 15:03:27 UTC (rev 4007)
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (C) 2009 eXo Platform SAS.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+
+-->
+<infinispan
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:infinispan:config:4.0 http://www.infinispan.org/schemas/infinispan-config-4.0.xsd"
+ xmlns="urn:infinispan:config:4.0">
+
+ <global>
+ <globalJmxStatistics jmxDomain="infinispan" enabled="true" allowDuplicateDomains="true"/>
+
+ <transport transportClass="org.infinispan.remoting.transport.jgroups.JGroupsTransport" clusterName="${infinispan-cluster-name}" distributedSyncTimeout="20000">
+ <properties>
+ <property name="configurationFile" value="${jgroups-configuration}"/>
+ </properties>
+ </transport>
+ </global>
+
+ <default>
+ <locking isolationLevel="READ_COMMITTED" lockAcquisitionTimeout="20000" writeSkewCheck="false" concurrencyLevel="500"/>
+ <transaction transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup" syncRollbackPhase="false" syncCommitPhase="false"/>
+ <jmxStatistics enabled="true"/>
+ <deadlockDetection enabled="true" spinDuration="100"/>
+ </default>
+</infinispan>
Modified: jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jcr-config-ispn.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jcr-config-ispn.xml 2011-02-22 14:52:13 UTC (rev 4006)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jcr-config-ispn.xml 2011-02-22 15:03:27 UTC (rev 4007)
@@ -69,6 +69,11 @@
<query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
<properties>
<property name="index-dir" value="target/temp/index/db1/ws" />
+ <property name="changesfilter-class" value="org.exoplatform.services.jcr.impl.core.query.ispn.ISPNIndexChangesFilter" />
+ <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-indexer.xml" />
+ <property name="jgroups-configuration" value="flush-udp.xml" />
+ <property name="infinispan-cluster-name" value="JCR-cluster" />
+ <property name="max-volatile-time" value="60" />
</properties>
</query-handler>
<lock-manager class="org.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl">
@@ -119,6 +124,11 @@
</cache>
<query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
<properties>
+ <property name="changesfilter-class" value="org.exoplatform.services.jcr.impl.core.query.ispn.ISPNIndexChangesFilter" />
+ <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-indexer.xml" />
+ <property name="jgroups-configuration" value="flush-udp.xml" />
+ <property name="infinispan-cluster-name" value="JCR-cluster" />
+ <property name="max-volatile-time" value="60" />
<property name="index-dir" value="target/temp/index/db1/ws1" />
<property name="synonymprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider" />
<property name="synonymprovider-config-path" value="../../../synonyms.properties" />
@@ -176,6 +186,11 @@
</cache>
<query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
<properties>
+ <property name="changesfilter-class" value="org.exoplatform.services.jcr.impl.core.query.ispn.ISPNIndexChangesFilter" />
+ <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-indexer.xml" />
+ <property name="jgroups-configuration" value="flush-udp.xml" />
+ <property name="infinispan-cluster-name" value="JCR-cluster" />
+ <property name="max-volatile-time" value="60" />
<property name="index-dir" value="target/temp/index/db1/ws2" />
<property name="synonymprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider" />
<property name="synonymprovider-config-path" value="../../../synonyms.properties" />
@@ -251,6 +266,11 @@
</cache>
<query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
<properties>
+ <property name="changesfilter-class" value="org.exoplatform.services.jcr.impl.core.query.ispn.ISPNIndexChangesFilter" />
+ <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-indexer.xml" />
+ <property name="jgroups-configuration" value="flush-udp.xml" />
+ <property name="infinispan-cluster-name" value="JCR-cluster" />
+ <property name="max-volatile-time" value="60" />
<property name="index-dir" value="target/temp/index/db1/ws3" />
<property name="synonymprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider" />
<property name="synonymprovider-config-path" value="../../../synonyms.properties" />
@@ -324,6 +344,11 @@
</cache>
<query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
<properties>
+ <property name="changesfilter-class" value="org.exoplatform.services.jcr.impl.core.query.ispn.ISPNIndexChangesFilter" />
+ <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-indexer.xml" />
+ <property name="jgroups-configuration" value="flush-udp.xml" />
+ <property name="infinispan-cluster-name" value="JCR-cluster" />
+ <property name="max-volatile-time" value="60" />
<property name="index-dir" value="target/temp/index/db2/ws" />
</properties>
</query-handler>
@@ -381,6 +406,11 @@
</cache>
<query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
<properties>
+ <property name="changesfilter-class" value="org.exoplatform.services.jcr.impl.core.query.ispn.ISPNIndexChangesFilter" />
+ <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-indexer.xml" />
+ <property name="jgroups-configuration" value="flush-udp.xml" />
+ <property name="infinispan-cluster-name" value="JCR-cluster" />
+ <property name="max-volatile-time" value="60" />
<property name="index-dir" value="target/temp/index/db2/ws1" />
</properties>
</query-handler>
@@ -448,6 +478,11 @@
</cache>
<query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
<properties>
+ <property name="changesfilter-class" value="org.exoplatform.services.jcr.impl.core.query.ispn.ISPNIndexChangesFilter" />
+ <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-indexer.xml" />
+ <property name="jgroups-configuration" value="flush-udp.xml" />
+ <property name="infinispan-cluster-name" value="JCR-cluster" />
+ <property name="max-volatile-time" value="60" />
<property name="index-dir" value="target/temp/index/db1tck/ws" />
<property name="synonymprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider" />
<property name="synonymprovider-config-path" value="../../../synonyms.properties" />
@@ -512,6 +547,11 @@
</cache>
<query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
<properties>
+ <property name="changesfilter-class" value="org.exoplatform.services.jcr.impl.core.query.ispn.ISPNIndexChangesFilter" />
+ <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-indexer.xml" />
+ <property name="jgroups-configuration" value="flush-udp.xml" />
+ <property name="infinispan-cluster-name" value="JCR-cluster" />
+ <property name="max-volatile-time" value="60" />
<property name="index-dir" value="target/temp/index/db1tck/ws1" />
<property name="synonymprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider" />
<property name="synonymprovider-config-path" value="../../../synonyms.properties" />
@@ -575,6 +615,11 @@
</cache>
<query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
<properties>
+ <property name="changesfilter-class" value="org.exoplatform.services.jcr.impl.core.query.ispn.ISPNIndexChangesFilter" />
+ <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-indexer.xml" />
+ <property name="jgroups-configuration" value="flush-udp.xml" />
+ <property name="infinispan-cluster-name" value="JCR-cluster" />
+ <property name="max-volatile-time" value="60" />
<property name="index-dir" value="target/temp/index/db1tck/ws2" />
<property name="synonymprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider" />
<property name="synonymprovider-config-path" value="../../../synonyms.properties" />
13 years, 2 months
exo-jcr SVN: r4006 - in jcr/trunk/exo.jcr.component.core/src: main/java/org/exoplatform/services/jcr/impl and 7 other directories.
by do-not-reply@jboss.org
Author: sergiykarpenko
Date: 2011-02-22 09:52:13 -0500 (Tue, 22 Feb 2011)
New Revision: 4006
Added:
jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data.xml
jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data_with_versioned_child.xml
jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh.xml
jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh_with_versioned_child.xml
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/ExtendedSession.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/Constants.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/ExportImportFactory.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewStreamExporter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/StreamExporter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/SystemViewStreamExporter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/ContentImporter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/SystemViewImporter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/util/VersionHistoryImporter.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/importing/TestImportVersionedChild.java
Log:
EXOJCR-1207: Export/Import child nodes version history into single xml with parent version history
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/ExtendedSession.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/ExtendedSession.java 2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/ExtendedSession.java 2011-02-22 14:52:13 UTC (rev 4006)
@@ -22,6 +22,7 @@
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.util.Map;
import javax.jcr.InvalidSerializedDataException;
@@ -62,7 +63,7 @@
* @throws RepositoryException if any repository errors occurs
*/
Node getNodeByIdentifier(String identifier) throws ItemNotFoundException, RepositoryException;
-
+
/**
* Deserialize an XML document and adds the resulting item subtree as a child of the node at
* parentAbsPath.
@@ -86,6 +87,60 @@
InvalidSerializedDataException, RepositoryException;
/**
+ * Serializes the node (and if <code>noRecurse</code> is <code>false</code>,
+ * the whole subtree) at <code>absPath</code> into a series of SAX events by
+ * calling the methods of the supplied <code>org.xml.sax.ContentHandler</code>.
+ * The resulting XML is in the document view form. Note that <code>absPath</code>
+ * must be the path of a node, not a property.
+ * <p>
+ * If <code>skipBinary</code> is true then any properties of <code>PropertyType.BINARY</code> will be
+ * serialized as if they are empty. That is, the existence of the property
+ * will be serialized, but its content will not appear in the serialized
+ * output (the value of the attribute will be empty). If <code>skipBinary</code> is false
+ * then the actual value(s) of each <code>BINARY</code> property is recorded using Base64
+ * encoding.
+ * <p>
+ * If <code>noRecurse</code> is true then only the node at
+ * <code>absPath</code> and its properties, but not its child nodes, are
+ * serialized. If <code>noRecurse</code> is <code>false</code> then the entire subtree
+ * rooted at <code>absPath</code> is serialized.
+ * <p>
+ * If the user lacks read access to some subsection of the specified tree,
+ * that section simply does not get serialized, since, from the user's
+ * point of view, it is not there.
+ * <p>
+ * The serialized output will reflect the state of the current workspace as
+ * modified by the state of this <code>Session</code>. This means that
+ * pending changes (regardless of whether they are valid according to
+ * node type constraints) and the current session-mapping of namespaces
+ * are reflected in the output.
+ * <p>
+ * A <code>PathNotFoundException</code> is thrown if no node exists at <code>absPath</code>.
+ * <p>
+ * A <code>SAXException</code> is thrown if an error occurs while feeding events to the
+ * <code>ContentHandler</code>.
+ *
+ * @param absPath The path of the root of the subtree to be serialized.
+ * This must be the path to a node, not a property
+ * @param contentHandler The <code>org.xml.sax.ContentHandler</code> to
+ * which the SAX events representing the XML serialization of the subtree
+ * will be output.
+ * @param skipBinary A <code>boolean</code> governing whether binary
+ * properties are to be serialized.
+ * @param noRecurse A <code>boolean</code> governing whether the subtree at
+ * absPath is to be recursed.
+ * @param exportChildVersionHisotry A <code>boolean</code> governing whether child nodes
+ * version histories must be included into resulting xml.
+ *
+ * @throws PathNotFoundException if no node exists at <code>absPath</code>.
+ * @throws org.xml.sax.SAXException if an error occurs while feeding events to the
+ * <code>org.xml.sax.ContentHandler</code>.
+ * @throws RepositoryException if another error occurs.
+ */
+ void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse,
+ boolean exportChildVersionHisotry) throws IOException, PathNotFoundException, RepositoryException;
+
+ /**
* Registers session listener.
*
* @param listener
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/Constants.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/Constants.java 2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/Constants.java 2011-02-22 14:52:13 UTC (rev 4006)
@@ -579,6 +579,11 @@
public static final String SV_NODE = "node";
/**
+ * SV_VERSION_HISTORY.
+ */
+ public static final String SV_VERSION_HISTORY = "versionhistory";
+
+ /**
* SV_PROPERTY.
*/
public static final String SV_PROPERTY = "property";
@@ -614,6 +619,11 @@
public static final InternalQName SV_NODE_NAME = new InternalQName(NS_SV_URI, SV_NODE);
/**
+ * sv:versionhistory internal name.
+ */
+ public static final InternalQName SV_VERSION_HISTORY_NAME = new InternalQName(NS_SV_URI, SV_VERSION_HISTORY);
+
+ /**
* sv:property internal name.
*/
public static final InternalQName SV_PROPERTY_NAME = new InternalQName(NS_SV_URI, SV_PROPERTY);
@@ -677,7 +687,7 @@
* eXo JCR default Strings encoding.
*/
public static final String DEFAULT_ENCODING = "UTF-8";
-
+
/**
* System identifier for remote workspace initializer changes.
*/
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java 2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java 2011-02-22 14:52:13 UTC (rev 4006)
@@ -409,8 +409,8 @@
/**
* {@inheritDoc}
*/
- public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse)
- throws IOException, PathNotFoundException, RepositoryException
+ public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse,
+ boolean exportChildVersionHisotry) throws IOException, PathNotFoundException, RepositoryException
{
checkLive();
@@ -426,7 +426,8 @@
{
BaseXmlExporter exporter =
new ExportImportFactory().getExportVisitor(XmlMapping.SYSVIEW, out, skipBinary, noRecurse,
- getTransientNodesManager(), repository.getNamespaceRegistry(), valueFactoryImpl);
+ exportChildVersionHisotry, getTransientNodesManager(), repository.getNamespaceRegistry(),
+ valueFactoryImpl);
JCRPath srcNodePath = getLocationFactory().parseAbsPath(absPath);
ItemData srcItemData = dataManager.getItemData(srcNodePath.getInternalPath());
@@ -446,9 +447,19 @@
{
throw new IOException(e.getLocalizedMessage());
}
+
}
/**
+ * {@inheritDoc}
+ */
+ public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse)
+ throws IOException, PathNotFoundException, RepositoryException
+ {
+ exportSystemView(absPath, out, skipBinary, noRecurse, false);
+ }
+
+ /**
* @return Returns the accessManager.
*/
public AccessManager getAccessManager()
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/ExportImportFactory.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/ExportImportFactory.java 2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/ExportImportFactory.java 2011-02-22 14:52:13 UTC (rev 4006)
@@ -112,7 +112,33 @@
ItemDataConsumer dataManager, NamespaceRegistry namespaceRegistry, ValueFactoryImpl systemValueFactory)
throws NamespaceException, RepositoryException, IOException
{
+ return getExportVisitor(type, stream, skipBinary, noRecurse, false, dataManager, namespaceRegistry,
+ systemValueFactory);
+ }
+ /**
+ * Create export visitor for given type of view.\
+ *
+ * @param type - 6.4 XML Mappings
+ * @param stream - output result stream
+ * @param skipBinary- If skipBinary is true then any properties of
+ * PropertyType.BINARY will be serialized as if they are empty.
+ * @param noRecurse- if noRecurse is false, the whole subtree are serialized
+ * @param exportChildVersionHistory - does versioned child nodes version history must be exported
+ * (works ONLY with system view).
+ * @param dataManager - ItemDataConsumer
+ * @param namespaceRegistry - NamespaceRegistry
+ * @param systemValueFactory - default value factory
+ * @return - visitor BaseXmlExporter.
+ * @throws NamespaceException
+ * @throws RepositoryException
+ * @throws IOException
+ */
+ public BaseXmlExporter getExportVisitor(XmlMapping type, OutputStream stream, boolean skipBinary, boolean noRecurse,
+ boolean exportChildVersionHistory, ItemDataConsumer dataManager, NamespaceRegistry namespaceRegistry,
+ ValueFactoryImpl systemValueFactory) throws NamespaceException, RepositoryException, IOException
+ {
+
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
XMLStreamWriter streamWriter;
try
@@ -127,7 +153,7 @@
if (type == XmlMapping.SYSVIEW)
{
return new SystemViewStreamExporter(streamWriter, dataManager, namespaceRegistry, systemValueFactory,
- skipBinary, noRecurse);
+ skipBinary, noRecurse, exportChildVersionHistory);
}
else if (type == XmlMapping.DOCVIEW)
{
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewStreamExporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewStreamExporter.java 2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewStreamExporter.java 2011-02-22 14:52:13 UTC (rev 4006)
@@ -49,7 +49,7 @@
NamespaceRegistry namespaceRegistry, ValueFactoryImpl systemValueFactory, boolean skipBinary, boolean noRecurse)
throws NamespaceException, RepositoryException
{
- super(writer, dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse);
+ super(writer, dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse, false);
}
/**
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/StreamExporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/StreamExporter.java 2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/StreamExporter.java 2011-02-22 14:52:13 UTC (rev 4006)
@@ -38,14 +38,22 @@
protected final XMLStreamWriter writer;
+ protected final boolean exportChildVersionHistory;
+
public StreamExporter(XMLStreamWriter writer, ItemDataConsumer dataManager, NamespaceRegistry namespaceRegistry,
ValueFactoryImpl systemValueFactory, boolean skipBinary, boolean noRecurse) throws NamespaceException,
RepositoryException
{
+ this(writer, dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse, false);
+ }
+ public StreamExporter(XMLStreamWriter writer, ItemDataConsumer dataManager, NamespaceRegistry namespaceRegistry,
+ ValueFactoryImpl systemValueFactory, boolean skipBinary, boolean noRecurse, boolean exportChildVersionHistory)
+ throws NamespaceException, RepositoryException
+ {
super(dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse, noRecurse ? 1 : -1);
this.writer = writer;
-
+ this.exportChildVersionHistory = exportChildVersionHistory;
}
@Override
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/SystemViewStreamExporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/SystemViewStreamExporter.java 2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/SystemViewStreamExporter.java 2011-02-22 14:52:13 UTC (rev 4006)
@@ -21,14 +21,17 @@
import org.apache.ws.commons.util.Base64;
import org.exoplatform.services.jcr.core.ExtendedPropertyType;
import org.exoplatform.services.jcr.dataflow.ItemDataConsumer;
+import org.exoplatform.services.jcr.datamodel.ItemType;
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.datamodel.ValueData;
import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.List;
import javax.jcr.NamespaceException;
@@ -47,6 +50,8 @@
private static final int BUFFER_SIZE = 3 * 1024 * 3;
+ private static final List<String> exportedVersionHistories = new ArrayList<String>();
+
/**
* @param writer
* @param session
@@ -59,9 +64,17 @@
NamespaceRegistry namespaceRegistry, ValueFactoryImpl systemValueFactory, boolean skipBinary, boolean noRecurse)
throws NamespaceException, RepositoryException
{
- super(writer, dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse);
+ this(writer, dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse, false);
}
+ public SystemViewStreamExporter(XMLStreamWriter writer, ItemDataConsumer dataManager,
+ NamespaceRegistry namespaceRegistry, ValueFactoryImpl systemValueFactory, boolean skipBinary, boolean noRecurse,
+ boolean exportChildVersionHistory) throws NamespaceException, RepositoryException
+ {
+ super(writer, dataManager, namespaceRegistry, systemValueFactory, skipBinary, noRecurse,
+ exportChildVersionHistory);
+ }
+
/*
* (non-Javadoc)
* @see
@@ -145,6 +158,40 @@
{
try
{
+ if (exportChildVersionHistory && node.getPrimaryTypeName().equals(Constants.NT_VERSIONEDCHILD))
+ {
+ try
+ {
+ PropertyData childVersionHistory =
+ ((PropertyData)dataManager.getItemData(node, new QPathEntry(Constants.JCR_CHILDVERSIONHISTORY, 1),
+ ItemType.PROPERTY));
+ String childVersionHistoryId =
+ getValueAsStringForExport(childVersionHistory.getValues().get(0), childVersionHistory.getType());
+
+ //check does this child version history was already exported
+ if (!exportedVersionHistories.contains(childVersionHistoryId))
+ {
+
+ writer.writeStartElement(Constants.NS_SV_PREFIX, Constants.SV_VERSION_HISTORY, getSvNamespaceUri());
+ writer.writeAttribute(Constants.NS_SV_PREFIX, getSvNamespaceUri(), Constants.SV_NAME,
+ childVersionHistoryId);
+
+ NodeData versionStorage = (NodeData)dataManager.getItemData(Constants.VERSIONSTORAGE_UUID);
+ NodeData childVersionNodeData =
+ (NodeData)dataManager.getItemData(versionStorage, new QPathEntry("", childVersionHistoryId, 1),
+ ItemType.NODE);
+ childVersionNodeData.accept(this);
+
+ writer.writeEndElement();
+ exportedVersionHistories.add(childVersionHistoryId);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new RepositoryException("Can't export versioned child version history: " + e.getMessage(), e);
+ }
+ }
+
writer.writeEndElement();
}
catch (XMLStreamException e)
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/ContentImporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/ContentImporter.java 2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/ContentImporter.java 2011-02-22 14:52:13 UTC (rev 4006)
@@ -35,6 +35,8 @@
*/
public String RESPECT_PROPERTY_DEFINITIONS_CONSTRAINTS = "respectPropertyDefinitionsConstraints";
+ public final String LIST_OF_IMPORTED_VERSION_HISTORIES = "importedSubversions";
+
/**
* Receive notification of character data.
*
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/SystemViewImporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/SystemViewImporter.java 2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/importing/SystemViewImporter.java 2011-02-22 14:52:13 UTC (rev 4006)
@@ -18,21 +18,6 @@
*/
package org.exoplatform.services.jcr.impl.xml.importing;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.NamespaceRegistry;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.ValueFormatException;
-import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
-
import org.exoplatform.services.jcr.access.AccessManager;
import org.exoplatform.services.jcr.core.ExtendedPropertyType;
import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataManager;
@@ -42,8 +27,10 @@
import org.exoplatform.services.jcr.datamodel.IllegalNameException;
import org.exoplatform.services.jcr.datamodel.IllegalPathException;
import org.exoplatform.services.jcr.datamodel.InternalQName;
+import org.exoplatform.services.jcr.datamodel.ItemType;
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.QPath;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.datamodel.ValueData;
import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.core.JCRName;
@@ -51,6 +38,7 @@
import org.exoplatform.services.jcr.impl.core.RepositoryImpl;
import org.exoplatform.services.jcr.impl.core.value.BaseValue;
import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
+import org.exoplatform.services.jcr.impl.dataflow.ItemDataRemoveVisitor;
import org.exoplatform.services.jcr.impl.dataflow.TransientValueData;
import org.exoplatform.services.jcr.impl.dataflow.ValueDataConvertor;
import org.exoplatform.services.jcr.impl.xml.DecodedValue;
@@ -62,6 +50,21 @@
import org.exoplatform.services.log.Log;
import org.exoplatform.services.security.ConversationState;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+
/**
* Created by The eXo Platform SAS.
*
@@ -171,6 +174,11 @@
DecodedValue curPropValue = propertyInfo.getValues().get(propertyInfo.getValues().size() - 1);
curPropValue.setComplete(true);
}
+ else if (Constants.SV_VERSION_HISTORY_NAME.equals(elementName))
+ {
+ // remove version storage node from tree
+ tree.pop();
+ }
else
{
throw new RepositoryException("invalid element in system view xml document: " + localName);
@@ -260,6 +268,36 @@
propertyInfo.getValues().add(new DecodedValue());
}
+ else if (Constants.SV_VERSION_HISTORY_NAME.equals(elementName))
+ {
+ String svName = getAttribute(atts, Constants.SV_NAME_NAME);
+ if (svName == null)
+ {
+ throw new RepositoryException("Missing mandatory sv:name attribute of element sv:versionhistory");
+ }
+
+ NodeData versionStorage = (NodeData)this.dataConsumer.getItemData(Constants.VERSIONSTORAGE_UUID);
+
+ NodeData versionHistory =
+ (NodeData)dataConsumer.getItemData(versionStorage, new QPathEntry("", svName, 1), ItemType.NODE);
+
+ if (versionHistory != null)
+ {
+ RemoveVisitor rv = new RemoveVisitor();
+ rv.visit(versionHistory);
+ changesLog.addAll(rv.getRemovedStates());
+ }
+ tree.push(versionStorage);
+
+ List<String> list = (List<String>)context.get(ContentImporter.LIST_OF_IMPORTED_VERSION_HISTORIES);
+ if (list == null)
+ {
+ list = new ArrayList<String>();
+ }
+ list.add(svName);
+ context.put(ContentImporter.LIST_OF_IMPORTED_VERSION_HISTORIES, list);
+
+ }
else
{
throw new RepositoryException("Unknown element " + elementName.getAsString());
@@ -687,4 +725,25 @@
JCRName jname = locationFactory.createJCRName(name);
return attributes.get(jname.getAsString());
}
+
+ protected class RemoveVisitor extends ItemDataRemoveVisitor
+ {
+ /**
+ * Default constructor.
+ *
+ * @throws RepositoryException - exception.
+ */
+ RemoveVisitor() throws RepositoryException
+ {
+ super(dataConsumer, null, nodeTypeDataManager, accessManager, userState);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void validateReferential(NodeData node) throws RepositoryException
+ {
+ // no REFERENCE validation here
+ }
+ };
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/util/VersionHistoryImporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/util/VersionHistoryImporter.java 2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/util/VersionHistoryImporter.java 2011-02-22 14:52:13 UTC (rev 4006)
@@ -23,23 +23,31 @@
import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
import org.exoplatform.services.jcr.dataflow.PlainChangesLogImpl;
import org.exoplatform.services.jcr.datamodel.Identifier;
+import org.exoplatform.services.jcr.datamodel.ItemType;
import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.datamodel.PropertyData;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.datamodel.ValueData;
import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.core.NodeImpl;
import org.exoplatform.services.jcr.impl.core.PropertyImpl;
+import org.exoplatform.services.jcr.impl.core.SessionDataManager;
import org.exoplatform.services.jcr.impl.core.SessionImpl;
import org.exoplatform.services.jcr.impl.dataflow.ItemDataRemoveVisitor;
import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
import org.exoplatform.services.jcr.impl.dataflow.TransientValueData;
+import org.exoplatform.services.jcr.impl.dataflow.ValueDataConvertor;
import org.exoplatform.services.jcr.impl.xml.ItemDataKeeperAdapter;
+import org.exoplatform.services.jcr.impl.xml.importing.ContentImporter;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
@@ -144,7 +152,7 @@
{
uuid = versionableNode.getUUID();
path = versionableNode.getVersionHistory().getParent().getPath();
- LOG.info("Started: Import version history for node wiht path=" + path + " and UUID=" + uuid);
+ LOG.info("Started: Import version history for node with path=" + path + " and UUID=" + uuid);
NodeData versionable = (NodeData)versionableNode.getData();
// ----- VERSIONABLE properties -----
@@ -176,32 +184,43 @@
changesLog.add(ItemState.createAddedState(bv));
changesLog.add(ItemState.createAddedState(pd));
// remove version properties to avoid referential integrety check
- PlainChangesLog changesLogDeltete = new PlainChangesLogImpl();
+ PlainChangesLog changesLogDelete = new PlainChangesLogImpl();
- changesLogDeltete.add(ItemState.createDeletedState(((PropertyImpl)versionableNode
+ changesLogDelete.add(ItemState.createDeletedState(((PropertyImpl)versionableNode
.getProperty("jcr:versionHistory")).getData()));
- changesLogDeltete.add(ItemState.createDeletedState(((PropertyImpl)versionableNode
+ changesLogDelete.add(ItemState.createDeletedState(((PropertyImpl)versionableNode
.getProperty("jcr:baseVersion")).getData()));
- changesLogDeltete.add(ItemState.createDeletedState(((PropertyImpl)versionableNode
+ changesLogDelete.add(ItemState.createDeletedState(((PropertyImpl)versionableNode
.getProperty("jcr:predecessors")).getData()));
- dataKeeper.save(changesLogDeltete);
+ dataKeeper.save(changesLogDelete);
// remove version history
dataKeeper.save(changesLog);
userSession.save();
+
// import new version history
- userSession.getWorkspace().importXML(path, versionHistoryStream, 0);
+ Map<String, Object> context = new HashMap<String, Object>();
+ //context.put("versionablenode", versionableNode);
+ context.put(ContentImporter.RESPECT_PROPERTY_DEFINITIONS_CONSTRAINTS, true);
+ userSession.getWorkspace().importXML(path, versionHistoryStream, 0, context);
userSession.save();
- LOG.info("Completed: Import version history for node wiht path=" + path + " and UUID=" + uuid);
+ LOG.info("Completed: Import version history for node with path=" + path + " and UUID=" + uuid);
+
+ // fetch list of imported child nodes versions
+ List<String> versionUuids = (List<String>)context.get(ContentImporter.LIST_OF_IMPORTED_VERSION_HISTORIES);
+ if (versionUuids != null && !versionUuids.isEmpty())
+ {
+ updateVersionedChildNodes(versionUuids);
+ }
}
catch (RepositoryException exception)
{
- LOG.error("Failed: Import version history for node wiht path=" + path + " and UUID=" + uuid, exception);
+ LOG.error("Failed: Import version history for node with path=" + path + " and UUID=" + uuid, exception);
throw new RepositoryException(exception);
}
catch (IOException exception)
{
- LOG.error("Failed: Import version history for node wiht path=" + path + " and UUID=" + uuid, exception);
+ LOG.error("Failed: Import version history for node with path=" + path + " and UUID=" + uuid, exception);
IOException newException = new IOException();
newException.initCause(exception);
throw newException;
@@ -209,6 +228,120 @@
}
/**
+ * Update child nodes that owns versions from versionUuids list.
+ *
+ * @param versionUuids - list of version histories uuids.
+ * @throws RepositoryException
+ * @throws IOException
+ */
+ private void updateVersionedChildNodes(List<String> versionUuids) throws RepositoryException, IOException
+ {
+ SessionDataManager dataManager = userSession.getTransientNodesManager();
+
+ NodeData versionStorage = (NodeData)dataManager.getItemData(Constants.VERSIONSTORAGE_UUID);
+
+ for (String versionUuid : versionUuids)
+ {
+ NodeData versionHistoryData =
+ (NodeData)dataManager.getItemData(versionStorage, new QPathEntry("", versionUuid, 1), ItemType.NODE);
+
+ PropertyData versionableUuidProp =
+ (PropertyData)dataManager.getItemData(versionHistoryData, new QPathEntry(Constants.JCR_VERSIONABLEUUID, 1),
+ ItemType.PROPERTY);
+
+ String versionableUuid = ValueDataConvertor.readString(versionableUuidProp.getValues().get(0));
+
+ // fetch child versionable node
+
+ NodeData versionedChild = (NodeData)dataManager.getItemData(versionableUuid);
+
+ if (versionedChild != null && versionedChild.getQPath().isDescendantOf(versionableNode.getData().getQPath()))
+ {
+ // find latest version
+ String latestVersionUuid = null;
+ for (int versionNumber = 1;; versionNumber++)
+ {
+ NodeData nodeData =
+ (NodeData)dataManager.getItemData(versionHistoryData, new QPathEntry("", Integer
+ .toString(versionNumber), 1), ItemType.NODE);
+
+ if (nodeData == null)
+ {
+ break;
+ }
+ else
+ {
+ latestVersionUuid = nodeData.getIdentifier();
+ }
+ }
+
+ if (latestVersionUuid == null)
+ {
+ // fetch root version
+ NodeData rootVersion =
+ (NodeData)dataManager.getItemData(versionHistoryData, new QPathEntry(Constants.JCR_ROOTVERSION, 1),
+ ItemType.NODE);
+ latestVersionUuid = rootVersion.getIdentifier();
+ }
+
+ PropertyData propVersionHistory =
+ (PropertyData)dataManager.getItemData(versionedChild, new QPathEntry(Constants.JCR_VERSIONHISTORY, 1),
+ ItemType.PROPERTY);
+ String prevVerHistoryId = ValueDataConvertor.readString(propVersionHistory.getValues().get(0));
+
+ PropertyData propBaseVersion =
+ (PropertyData)dataManager.getItemData(versionedChild, new QPathEntry(Constants.JCR_BASEVERSION, 1),
+ ItemType.PROPERTY);
+
+ PropertyData propPredecessors =
+ (PropertyData)dataManager.getItemData(versionedChild, new QPathEntry(Constants.JCR_PREDECESSORS, 1),
+ ItemType.PROPERTY);
+
+ TransientPropertyData newVersionHistoryProp =
+ TransientPropertyData.createPropertyData(versionedChild, Constants.JCR_VERSIONHISTORY,
+ PropertyType.REFERENCE, false, new TransientValueData(new Identifier(versionUuid)));
+
+ // jcr:baseVersion
+ TransientPropertyData newBaseVersionProp =
+ TransientPropertyData.createPropertyData(versionedChild, Constants.JCR_BASEVERSION,
+ PropertyType.REFERENCE, false, new TransientValueData(new Identifier(latestVersionUuid)));
+
+ // jcr:predecessors
+ List<ValueData> predecessorValues = new ArrayList<ValueData>();
+ predecessorValues.add(new TransientValueData(new Identifier(latestVersionUuid)));
+ TransientPropertyData newPredecessorsProp =
+ TransientPropertyData.createPropertyData(versionedChild, Constants.JCR_PREDECESSORS,
+ PropertyType.REFERENCE, true, predecessorValues);
+
+ //remove previous version of childnode nad update properties
+ NodeData prevVersionHistory = (NodeData)dataManager.getItemData(prevVerHistoryId);
+
+ PlainChangesLogImpl changesLog = new PlainChangesLogImpl();
+ if (!prevVerHistoryId.equals(versionUuid))
+ {
+ RemoveVisitor rv = new RemoveVisitor();
+ rv.visit(prevVersionHistory);
+ changesLog.addAll(rv.getRemovedStates());
+ }
+ changesLog.add(ItemState.createAddedState(newVersionHistoryProp));
+ changesLog.add(ItemState.createAddedState(newBaseVersionProp));
+ changesLog.add(ItemState.createAddedState(newPredecessorsProp));
+
+ PlainChangesLogImpl changesLogDelete = new PlainChangesLogImpl();
+ changesLogDelete.add(ItemState.createDeletedState(propVersionHistory));
+ changesLogDelete.add(ItemState.createDeletedState(propBaseVersion));
+ changesLogDelete.add(ItemState.createDeletedState(propPredecessors));
+ dataKeeper.save(changesLogDelete);
+ // remove version history
+ dataKeeper.save(changesLog);
+ userSession.save();
+ LOG.info("Completed: Import version history for node with path=" + versionedChild.getQPath().getAsString()
+ + " and UUID=" + versionedChild.getIdentifier());
+ }
+ }
+ }
+
+ /**
* Remover helper.
*
* @author sj
Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/importing/TestImportVersionedChild.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/importing/TestImportVersionedChild.java 2011-02-22 14:24:33 UTC (rev 4005)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/importing/TestImportVersionedChild.java 2011-02-22 14:52:13 UTC (rev 4006)
@@ -24,10 +24,12 @@
import org.exoplatform.services.jcr.impl.core.NodeImpl;
import org.exoplatform.services.jcr.impl.core.PropertyImpl;
import org.exoplatform.services.jcr.impl.core.SessionDataManager;
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
import org.exoplatform.services.jcr.util.VersionHistoryImporter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
import java.util.Calendar;
import javax.jcr.ImportUUIDBehavior;
@@ -275,4 +277,776 @@
session.save();
}
}
+
+ public void testImportVersionHistoryWithChildVersions() throws Exception
+ {
+ loadTestTree();
+ Node wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+ // make checkin/checkout a lot
+ wc1.checkin();
+ wc1.checkout();
+
+ // export import version history and node
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ session.exportSystemView("/parent/wc1", out, false, false, true);
+
+ ByteArrayOutputStream vhout = new ByteArrayOutputStream();
+ session.exportSystemView(wc1.getVersionHistory().getPath(), vhout, false, false, true);
+
+ // prepare data for version import
+ String versionHistory = wc1.getProperty("jcr:versionHistory").getValue().getString();
+ String baseVersion = wc1.getProperty("jcr:baseVersion").getValue().getString();
+ Value[] jcrPredecessors = wc1.getProperty("jcr:predecessors").getValues();
+ StringBuilder jcrPredecessorsBuilder = new StringBuilder();
+ String[] predecessorsHistory;
+ for (Value value : jcrPredecessors)
+ {
+ if (jcrPredecessorsBuilder.length() > 0)
+ jcrPredecessorsBuilder.append(",");
+ jcrPredecessorsBuilder.append(value.getString());
+ }
+ if (jcrPredecessorsBuilder.toString().indexOf(",") > -1)
+ {
+ predecessorsHistory = jcrPredecessorsBuilder.toString().split(",");
+ }
+ else
+ {
+ predecessorsHistory = new String[]{jcrPredecessorsBuilder.toString()};
+ }
+
+ // remember "picture" nodes version history data
+ Node picture = (NodeImpl)session.getItem("/parent/wc1/medias/picture");
+ String chversionHistory = picture.getProperty("jcr:versionHistory").getValue().getString();
+ String chbaseVersion = picture.getProperty("jcr:baseVersion").getValue().getString();
+ Value[] chjcrPredecessors = picture.getProperty("jcr:predecessors").getValues();
+ StringBuilder chjcrPredecessorsBuilder = new StringBuilder();
+ String[] chpredecessorsHistory;
+ for (Value value : chjcrPredecessors)
+ {
+ if (chjcrPredecessorsBuilder.length() > 0)
+ chjcrPredecessorsBuilder.append(",");
+ chjcrPredecessorsBuilder.append(value.getString());
+ }
+ if (chjcrPredecessorsBuilder.toString().indexOf(",") > -1)
+ {
+ chpredecessorsHistory = chjcrPredecessorsBuilder.toString().split(",");
+ }
+ else
+ {
+ chpredecessorsHistory = new String[]{chjcrPredecessorsBuilder.toString()};
+ }
+
+ // remove node
+ wc1.remove();
+ session.save();
+
+ out.close();
+ vhout.close();
+
+ // import
+ session.importXML("/parent", new ByteArrayInputStream(out.toByteArray()),
+ ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+ session.save();
+
+ wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+ VersionHistoryImporter versionHistoryImporter =
+ new VersionHistoryImporter((NodeImpl)wc1, new ByteArrayInputStream(vhout.toByteArray()), baseVersion,
+ predecessorsHistory, versionHistory);
+ versionHistoryImporter.doImport();
+ session.save();
+
+ picture = wc1.getNode("medias").getNode("picture");
+ assertTrue(picture.isNodeType("mix:versionable"));
+ assertEquals(chversionHistory, picture.getProperty("jcr:versionHistory").getValue().getString());
+ assertEquals(chbaseVersion, picture.getProperty("jcr:baseVersion").getValue().getString());
+ assertEquals(chpredecessorsHistory[0], picture.getProperty("jcr:predecessors").getValues()[0].getString());
+ }
+
+ public void testImportVersionHistoryPreloadChildVersionHistoryWithChildVersions() throws Exception
+ {
+ loadTestTree();
+ Node wc1 = (NodeImpl)session.getItem("/parent/wc1");
+ Node picture = (NodeImpl)session.getItem("/parent/wc1/medias/picture");
+
+ // make checkin/checkout a lot
+
+ wc1.checkin();
+ wc1.checkout();
+
+ picture.checkin();
+ picture.checkout();
+
+ // export import version history and node
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ session.exportSystemView("/parent/wc1", out, false, false);
+
+ ByteArrayOutputStream childvhout = new ByteArrayOutputStream();
+ session.exportSystemView(picture.getVersionHistory().getPath(), childvhout, false, false, true);
+
+ ByteArrayOutputStream vhout = new ByteArrayOutputStream();
+ session.exportSystemView(wc1.getVersionHistory().getPath(), vhout, false, false, true);
+
+ // prepare data for version import
+
+ String versionHistory = wc1.getProperty("jcr:versionHistory").getValue().getString();
+ String baseVersion = wc1.getProperty("jcr:baseVersion").getValue().getString();
+ Value[] jcrPredecessors = wc1.getProperty("jcr:predecessors").getValues();
+ StringBuilder jcrPredecessorsBuilder = new StringBuilder();
+ String[] predecessorsHistory;
+ for (Value value : jcrPredecessors)
+ {
+ if (jcrPredecessorsBuilder.length() > 0)
+ jcrPredecessorsBuilder.append(",");
+ jcrPredecessorsBuilder.append(value.getString());
+ }
+ if (jcrPredecessorsBuilder.toString().indexOf(",") > -1)
+ {
+ predecessorsHistory = jcrPredecessorsBuilder.toString().split(",");
+ }
+ else
+ {
+ predecessorsHistory = new String[]{jcrPredecessorsBuilder.toString()};
+ }
+
+ // prepare data for child version import
+
+ String chversionHistory = picture.getProperty("jcr:versionHistory").getValue().getString();
+ String chbaseVersion = picture.getProperty("jcr:baseVersion").getValue().getString();
+ Value[] chjcrPredecessors = picture.getProperty("jcr:predecessors").getValues();
+ StringBuilder chjcrPredecessorsBuilder = new StringBuilder();
+ String[] chpredecessorsHistory;
+ for (Value value : chjcrPredecessors)
+ {
+ if (chjcrPredecessorsBuilder.length() > 0)
+ chjcrPredecessorsBuilder.append(",");
+ chjcrPredecessorsBuilder.append(value.getString());
+ }
+ if (chjcrPredecessorsBuilder.toString().indexOf(",") > -1)
+ {
+ chpredecessorsHistory = chjcrPredecessorsBuilder.toString().split(",");
+ }
+ else
+ {
+ chpredecessorsHistory = new String[]{chjcrPredecessorsBuilder.toString()};
+ }
+
+ // remove node
+ wc1.remove();
+ session.save();
+
+ out.close();
+ vhout.close();
+
+ // import
+ session.importXML("/parent", new ByteArrayInputStream(out.toByteArray()),
+ ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+ session.save();
+
+ wc1 = (NodeImpl)session.getItem("/parent/wc1");
+ picture = wc1.getNode("medias").getNode("picture");
+
+ VersionHistoryImporter chversionHistoryImporter =
+ new VersionHistoryImporter((NodeImpl)picture, new ByteArrayInputStream(childvhout.toByteArray()),
+ chbaseVersion, chpredecessorsHistory, chversionHistory);
+ chversionHistoryImporter.doImport();
+ session.save();
+
+ VersionHistoryImporter versionHistoryImporter =
+ new VersionHistoryImporter((NodeImpl)wc1, new ByteArrayInputStream(vhout.toByteArray()), baseVersion,
+ predecessorsHistory, versionHistory);
+ versionHistoryImporter.doImport();
+ session.save();
+
+ assertTrue(picture.isNodeType("mix:versionable"));
+ assertEquals(chversionHistory, picture.getProperty("jcr:versionHistory").getValue().getString());
+ assertEquals(chbaseVersion, picture.getProperty("jcr:baseVersion").getValue().getString());
+ assertEquals(chpredecessorsHistory[0], picture.getProperty("jcr:predecessors").getValues()[0].getString());
+ }
+
+ /**
+ * Many mix:versionable subnodes.
+ * @throws Exception
+ */
+ public void testImportVersionHistoryWithManySubversions() throws Exception
+ {
+
+ // wc1/medias/picture
+ Node wc1 = testRoot.addNode("wc1", "nt:folder");
+ wc1.addMixin("mix:versionable");
+ testRoot.save();
+ Node medias = wc1.addNode("medias", "nt:folder");
+
+ Node picture = medias.addNode("picture", "nt:file");
+ picture.addMixin("mix:versionable");
+
+ Node res = picture.addNode("jcr:content", "nt:resource");
+ res.setProperty("jcr:lastModified", Calendar.getInstance());
+ res.setProperty("jcr:data", new ByteArrayInputStream("bla bla".getBytes()));
+ MimeTypeResolver mimres = new MimeTypeResolver();
+ res.setProperty("jcr:mimeType", mimres.getMimeType("screen.txt"));
+ root.save();
+
+ Node subNode1 = medias.addNode("subnode1", "nt:folder");
+ subNode1.addMixin("mix:versionable");
+ root.save();
+
+ Node subNode2 = subNode1.addNode("subnode2", "nt:folder");
+ Node subNode3 = subNode2.addNode("subnode3", "nt:folder");
+ subNode3.addMixin("mix:versionable");
+ root.save();
+
+ Node subNode4 = subNode3.addNode("subnode4", "nt:folder");
+ subNode4.addMixin("mix:versionable");
+ root.save();
+
+ // /medias/subnode1/subnode2/subnode3/subnode4
+ wc1.checkin();
+ wc1.checkout();
+
+ picture.checkin();
+ picture.checkout();
+
+ subNode1.checkin();
+ subNode1.checkout();
+
+ subNode4.checkin();
+ subNode4.checkout();
+
+ subNode3.checkin();
+ subNode3.checkout();
+
+ // export import version history and node
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ session.exportSystemView("/parent/wc1", out, false, false, true);
+
+ ByteArrayOutputStream vhout = new ByteArrayOutputStream();
+ session.exportSystemView(wc1.getVersionHistory().getPath(), vhout, false, false, true);
+
+ // prepare data for version import
+
+ String versionHistory = wc1.getProperty("jcr:versionHistory").getValue().getString();
+ String baseVersion = wc1.getProperty("jcr:baseVersion").getValue().getString();
+ Value[] jcrPredecessors = wc1.getProperty("jcr:predecessors").getValues();
+ StringBuilder jcrPredecessorsBuilder = new StringBuilder();
+ String[] predecessorsHistory;
+ for (Value value : jcrPredecessors)
+ {
+ if (jcrPredecessorsBuilder.length() > 0)
+ jcrPredecessorsBuilder.append(",");
+ jcrPredecessorsBuilder.append(value.getString());
+ }
+ if (jcrPredecessorsBuilder.toString().indexOf(",") > -1)
+ {
+ predecessorsHistory = jcrPredecessorsBuilder.toString().split(",");
+ }
+ else
+ {
+ predecessorsHistory = new String[]{jcrPredecessorsBuilder.toString()};
+ }
+
+ // prepare data for child version import
+
+ String chversionHistory = subNode4.getProperty("jcr:versionHistory").getValue().getString();
+ String chbaseVersion = subNode4.getProperty("jcr:baseVersion").getValue().getString();
+ Value[] chjcrPredecessors = subNode4.getProperty("jcr:predecessors").getValues();
+ StringBuilder chjcrPredecessorsBuilder = new StringBuilder();
+ String[] chpredecessorsHistory;
+ for (Value value : chjcrPredecessors)
+ {
+ if (chjcrPredecessorsBuilder.length() > 0)
+ chjcrPredecessorsBuilder.append(",");
+ chjcrPredecessorsBuilder.append(value.getString());
+ }
+ if (chjcrPredecessorsBuilder.toString().indexOf(",") > -1)
+ {
+ chpredecessorsHistory = chjcrPredecessorsBuilder.toString().split(",");
+ }
+ else
+ {
+ chpredecessorsHistory = new String[]{chjcrPredecessorsBuilder.toString()};
+ }
+
+ // remove node
+ wc1.remove();
+ session.save();
+
+ out.close();
+ vhout.close();
+
+ // import
+ session.importXML("/parent", new ByteArrayInputStream(out.toByteArray()),
+ ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+ session.save();
+
+ wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+ subNode4 = (NodeImpl)session.getItem("/parent/wc1/medias/subnode1/subnode2/subnode3/subnode4");
+
+ VersionHistoryImporter versionHistoryImporter =
+ new VersionHistoryImporter((NodeImpl)wc1, new ByteArrayInputStream(vhout.toByteArray()), baseVersion,
+ predecessorsHistory, versionHistory);
+ versionHistoryImporter.doImport();
+ session.save();
+
+ assertTrue(subNode4.isNodeType("mix:versionable"));
+ assertEquals(chversionHistory, subNode4.getProperty("jcr:versionHistory").getValue().getString());
+ assertEquals(chbaseVersion, subNode4.getProperty("jcr:baseVersion").getValue().getString());
+ assertEquals(chpredecessorsHistory[0], subNode4.getProperty("jcr:predecessors").getValues()[0].getString());
+ }
+
+ public void testImportVersionHistoryManyVersions() throws Exception
+ {
+ // wc1/medias/picture
+ Node wc1 = testRoot.addNode("wc1", "nt:folder");
+ wc1.addMixin("mix:versionable");
+ testRoot.save();
+ Node medias = wc1.addNode("medias", "nt:folder");
+
+ Node picture = medias.addNode("picture", "nt:file");
+ picture.addMixin("mix:versionable");
+
+ Node res = picture.addNode("jcr:content", "nt:resource");
+ res.setProperty("jcr:lastModified", Calendar.getInstance());
+ res.setProperty("jcr:data", new ByteArrayInputStream("bla bla".getBytes()));
+ MimeTypeResolver mimres = new MimeTypeResolver();
+ res.setProperty("jcr:mimeType", mimres.getMimeType("screen.txt"));
+ root.save();
+
+ // make checkin/checkout a lot
+ wc1.checkin();
+ wc1.checkout();
+
+ picture.checkin();
+ picture.checkout();
+
+ res.setProperty("jcr:data", new ByteArrayInputStream("new data".getBytes()));
+ root.save();
+
+ picture.checkin();
+ picture.checkout();
+
+ // check before import
+
+ picture.restore("1", true);
+ String strvalue = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+ assertEquals("bla bla", strvalue);
+
+ picture.restore("2", true);
+ strvalue = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+ assertEquals("new data", strvalue);
+
+ picture.checkout();
+
+ // make new version
+ assertTrue(picture.getProperty("jcr:isCheckedOut").getValue().getBoolean());
+
+ // export import version history and node
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ session.exportSystemView("/parent/wc1", out, false, false, true);
+
+ ByteArrayOutputStream vhout = new ByteArrayOutputStream();
+ session.exportSystemView(wc1.getVersionHistory().getPath(), vhout, false, false, true);
+
+ // prepare data for version import
+
+ String versionHistory = wc1.getProperty("jcr:versionHistory").getValue().getString();
+ String baseVersion = wc1.getProperty("jcr:baseVersion").getValue().getString();
+ Value[] jcrPredecessors = wc1.getProperty("jcr:predecessors").getValues();
+ StringBuilder jcrPredecessorsBuilder = new StringBuilder();
+ String[] predecessorsHistory;
+ for (Value value : jcrPredecessors)
+ {
+ if (jcrPredecessorsBuilder.length() > 0)
+ jcrPredecessorsBuilder.append(",");
+ jcrPredecessorsBuilder.append(value.getString());
+ }
+ if (jcrPredecessorsBuilder.toString().indexOf(",") > -1)
+ {
+ predecessorsHistory = jcrPredecessorsBuilder.toString().split(",");
+ }
+ else
+ {
+ predecessorsHistory = new String[]{jcrPredecessorsBuilder.toString()};
+ }
+
+ String childVersionHistory = picture.getProperty("jcr:versionHistory").getValue().getString();
+ String childBaseVersion = picture.getProperty("jcr:baseVersion").getValue().getString();
+ Value[] childJcrPredecessors = picture.getProperty("jcr:predecessors").getValues();
+ StringBuilder childJcrPredecessorsBuilder = new StringBuilder();
+ String[] childPredecessorsHistory;
+ for (Value value : childJcrPredecessors)
+ {
+ if (childJcrPredecessorsBuilder.length() > 0)
+ childJcrPredecessorsBuilder.append(",");
+ childJcrPredecessorsBuilder.append(value.getString());
+ }
+ if (childJcrPredecessorsBuilder.toString().indexOf(",") > -1)
+ {
+ childPredecessorsHistory = childJcrPredecessorsBuilder.toString().split(",");
+ }
+ else
+ {
+ childPredecessorsHistory = new String[]{childJcrPredecessorsBuilder.toString()};
+ }
+
+ String chversionHistory = picture.getProperty("jcr:versionHistory").getValue().getString();
+ String chbaseVersion = picture.getProperty("jcr:baseVersion").getValue().getString();
+ Value[] chjcrPredecessors = picture.getProperty("jcr:predecessors").getValues();
+ StringBuilder chjcrPredecessorsBuilder = new StringBuilder();
+ String[] chpredecessorsHistory;
+ for (Value value : chjcrPredecessors)
+ {
+ if (chjcrPredecessorsBuilder.length() > 0)
+ chjcrPredecessorsBuilder.append(",");
+ chjcrPredecessorsBuilder.append(value.getString());
+ }
+ if (chjcrPredecessorsBuilder.toString().indexOf(",") > -1)
+ {
+ chpredecessorsHistory = chjcrPredecessorsBuilder.toString().split(",");
+ }
+ else
+ {
+ chpredecessorsHistory = new String[]{chjcrPredecessorsBuilder.toString()};
+ }
+
+ // remove node
+ wc1.remove();
+ session.save();
+
+ out.close();
+ vhout.close();
+
+ // import
+ session.importXML("/parent", new ByteArrayInputStream(out.toByteArray()),
+ ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+ session.save();
+
+ wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+ VersionHistoryImporter versionHistoryImporter =
+ new VersionHistoryImporter((NodeImpl)wc1, new ByteArrayInputStream(vhout.toByteArray()), baseVersion,
+ predecessorsHistory, versionHistory);
+ versionHistoryImporter.doImport();
+ session.save();
+
+ picture = wc1.getNode("medias").getNode("picture");
+ assertTrue(picture.isNodeType("mix:versionable"));
+ assertEquals(chversionHistory, picture.getProperty("jcr:versionHistory").getValue().getString());
+ assertEquals(chbaseVersion, picture.getProperty("jcr:baseVersion").getValue().getString());
+ assertEquals(chpredecessorsHistory[0], picture.getProperty("jcr:predecessors").getValues()[0].getString());
+ assertTrue(picture.getProperty("jcr:isCheckedOut").getValue().getBoolean());
+
+ String value = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+ assertEquals("new data", value);
+
+ picture.restore("1", true);
+ value = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+ assertEquals("bla bla", value);
+
+ picture.restore("2", true);
+ value = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+ assertEquals("new data", value);
+
+ picture.checkout();
+
+ // make new version
+ assertTrue(picture.getProperty("jcr:isCheckedOut").getValue().getBoolean());
+ res = picture.getNode("jcr:content");
+ res.setProperty("jcr:data", new ByteArrayInputStream("third".getBytes()));
+ root.save();
+
+ picture.checkin();
+ picture.checkout();
+
+ picture.restore("1", true);
+ value = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+ assertEquals("bla bla", value);
+
+ picture.restore("3", true);
+ value = picture.getNode("jcr:content").getProperty("jcr:data").getString();
+ assertEquals("third", value);
+ }
+
+ /**
+ * Many mix:versionable subnodes.
+ * @throws Exception
+ */
+ public void testImportVersionHistoryWithManyVersions() throws Exception
+ {
+
+ // wc1/medias/picture
+ Node wc1 = testRoot.addNode("wc1", "nt:folder");
+ wc1.addMixin("mix:versionable");
+ testRoot.save();
+ Node medias = wc1.addNode("medias", "nt:folder");
+
+ Node picture = medias.addNode("picture", "nt:file");
+ picture.addMixin("mix:versionable");
+
+ Node res = picture.addNode("jcr:content", "nt:resource");
+ res.setProperty("jcr:lastModified", Calendar.getInstance());
+ res.setProperty("jcr:data", new ByteArrayInputStream("bla bla".getBytes()));
+ MimeTypeResolver mimres = new MimeTypeResolver();
+ res.setProperty("jcr:mimeType", mimres.getMimeType("screen.txt"));
+ root.save();
+
+ wc1.checkin();
+ wc1.checkout();
+
+ wc1.checkin();
+ wc1.checkout();
+
+ // export import version history and node
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ session.exportSystemView("/parent/wc1", out, false, false, true);
+
+ ByteArrayOutputStream vhout = new ByteArrayOutputStream();
+ session.exportSystemView(wc1.getVersionHistory().getPath(), vhout, false, false, true);
+
+ // prepare data for version import
+ String versionHistory = wc1.getProperty("jcr:versionHistory").getValue().getString();
+ String baseVersion = wc1.getProperty("jcr:baseVersion").getValue().getString();
+ Value[] jcrPredecessors = wc1.getProperty("jcr:predecessors").getValues();
+ StringBuilder jcrPredecessorsBuilder = new StringBuilder();
+ String[] predecessorsHistory;
+ for (Value value : jcrPredecessors)
+ {
+ if (jcrPredecessorsBuilder.length() > 0)
+ jcrPredecessorsBuilder.append(",");
+ jcrPredecessorsBuilder.append(value.getString());
+ }
+ if (jcrPredecessorsBuilder.toString().indexOf(",") > -1)
+ {
+ predecessorsHistory = jcrPredecessorsBuilder.toString().split(",");
+ }
+ else
+ {
+ predecessorsHistory = new String[]{jcrPredecessorsBuilder.toString()};
+ }
+ // remove node
+ wc1.remove();
+ session.save();
+
+ out.close();
+ vhout.close();
+
+ // import
+ session.importXML("/parent", new ByteArrayInputStream(out.toByteArray()),
+ ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+ session.save();
+
+ wc1 = (NodeImpl)session.getItem("/parent/wc1");
+ picture = wc1.getNode("medias").getNode("picture");
+
+ VersionHistoryImporter versionHistoryImporter =
+ new VersionHistoryImporter((NodeImpl)wc1, new ByteArrayInputStream(vhout.toByteArray()), baseVersion,
+ predecessorsHistory, versionHistory);
+ versionHistoryImporter.doImport();
+ session.save();
+
+ assertTrue(picture.isNodeType("mix:versionable"));
+ }
+
+ public void testImportVersionHistoryNonSysWorkspace() throws Exception
+ {
+
+ SessionImpl session = (SessionImpl)this.repository.login(credentials, "ws1");
+
+ Node root = session.getRootNode();
+ Node testRoot = root.addNode("parent", "nt:folder");
+ root.save();
+
+ try
+ {
+ // wc1/medias/picture
+ Node wc1 = testRoot.addNode("wc1", "nt:folder");
+ wc1.addMixin("mix:versionable");
+ testRoot.save();
+ Node medias = wc1.addNode("medias", "nt:folder");
+
+ Node picture = medias.addNode("picture", "nt:file");
+ picture.addMixin("mix:versionable");
+
+ Node res = picture.addNode("jcr:content", "nt:resource");
+ res.setProperty("jcr:lastModified", Calendar.getInstance());
+ res.setProperty("jcr:data", new ByteArrayInputStream("bla bla".getBytes()));
+ MimeTypeResolver mimres = new MimeTypeResolver();
+ res.setProperty("jcr:mimeType", mimres.getMimeType("screen.txt"));
+ root.save();
+
+ // make checkin/checkout a lot
+
+ wc1.checkin();
+ wc1.checkout();
+
+ // export import version history and node
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ session.exportSystemView("/parent/wc1", out, false, false, true);
+
+ ByteArrayOutputStream vhout = new ByteArrayOutputStream();
+ session.exportSystemView(wc1.getVersionHistory().getPath(), vhout, false, false, true);
+
+ // prepare data for version import
+
+ String versionHistory = wc1.getProperty("jcr:versionHistory").getValue().getString();
+ String baseVersion = wc1.getProperty("jcr:baseVersion").getValue().getString();
+ Value[] jcrPredecessors = wc1.getProperty("jcr:predecessors").getValues();
+ StringBuilder jcrPredecessorsBuilder = new StringBuilder();
+ String[] predecessorsHistory;
+ for (Value value : jcrPredecessors)
+ {
+ if (jcrPredecessorsBuilder.length() > 0)
+ jcrPredecessorsBuilder.append(",");
+ jcrPredecessorsBuilder.append(value.getString());
+ }
+ if (jcrPredecessorsBuilder.toString().indexOf(",") > -1)
+ {
+ predecessorsHistory = jcrPredecessorsBuilder.toString().split(",");
+ }
+ else
+ {
+ predecessorsHistory = new String[]{jcrPredecessorsBuilder.toString()};
+ }
+
+ // remove node
+ wc1.remove();
+ session.save();
+
+ out.close();
+ vhout.close();
+
+ // import
+ session.importXML("/parent", new ByteArrayInputStream(out.toByteArray()),
+ ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+ session.save();
+
+ wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+ VersionHistoryImporter versionHistoryImporter =
+ new VersionHistoryImporter((NodeImpl)wc1, new ByteArrayInputStream(vhout.toByteArray()), baseVersion,
+ predecessorsHistory, versionHistory);
+ versionHistoryImporter.doImport();
+ session.save();
+
+ picture = wc1.getNode("medias").getNode("picture");
+ assertTrue(picture.isNodeType("mix:versionable"));
+ }
+ finally
+ {
+ testRoot.remove();
+ root.save();
+ session.logout();
+ }
+ }
+
+ public void testImportVersionHistoryFromFileWithChildVH() throws Exception
+ {
+
+ String baseVersion = "397dad17c0a8004201c7b45ea76d4b1b";
+ String[] predecessorsHistory = new String[]{"397dad17c0a8004201c7b45ea76d4b1b"};
+ String versionHistory = "397dac8bc0a8004201729d052a305832";
+
+ String chbaseVersion = "397dac9ac0a8004201cde5722fec978e";
+ String[] chpredecessorsHistory = new String[]{"397dac9ac0a8004201cde5722fec978e"};
+ String chversionHistory = "397dac9ac0a8004200f37de3ace7b0ad";
+
+ InputStream is =
+ TestImportVersionedChild.class.getResourceAsStream("/import-export/data_with_versioned_child.xml");
+ InputStream vhis =
+ TestImportVersionedChild.class.getResourceAsStream("/import-export/vh_with_versioned_child.xml");
+
+ // import
+ session.importXML("/parent", is, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+ session.save();
+
+ Node wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+ VersionHistoryImporter versionHistoryImporter =
+ new VersionHistoryImporter((NodeImpl)wc1, vhis, baseVersion, predecessorsHistory, versionHistory);
+ versionHistoryImporter.doImport();
+ session.save();
+
+ Node picture = wc1.getNode("medias").getNode("picture");
+ assertTrue(picture.isNodeType("mix:versionable"));
+ assertEquals(chversionHistory, picture.getProperty("jcr:versionHistory").getValue().getString());
+ assertEquals(chbaseVersion, picture.getProperty("jcr:baseVersion").getValue().getString());
+ assertEquals(chpredecessorsHistory[0], picture.getProperty("jcr:predecessors").getValues()[0].getString());
+
+ }
+
+ public void testImportVersionHistoryFromFile() throws Exception
+ {
+
+ String baseVersion = "0019980ec0a80042014313ff82e97096";
+ String[] predecessorsHistory = new String[]{"0019980ec0a80042014313ff82e97096"};
+ String versionHistory = "001997a1c0a80042007d98739b97e1bc";
+
+ String chbaseVersion = "001997b1c0a8004200d65c82779a2e13";
+ String[] chpredecessorsHistory = new String[]{"001997b1c0a8004200d65c82779a2e13"};
+ String chversionHistory = "001997b1c0a8004201d35a6fa36ef4e7";
+
+ InputStream is = TestImportVersionedChild.class.getResourceAsStream("/import-export/data.xml");
+ InputStream vhis = TestImportVersionedChild.class.getResourceAsStream("/import-export/vh.xml");
+
+ // import
+ session.importXML("/parent", is, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true);
+
+ session.save();
+
+ Node wc1 = (NodeImpl)session.getItem("/parent/wc1");
+
+ VersionHistoryImporter versionHistoryImporter =
+ new VersionHistoryImporter((NodeImpl)wc1, vhis, baseVersion, predecessorsHistory, versionHistory);
+ versionHistoryImporter.doImport();
+ session.save();
+
+ Node picture = wc1.getNode("medias").getNode("picture");
+ assertTrue(picture.isNodeType("mix:versionable"));
+ assertFalse(chversionHistory.equals(picture.getProperty("jcr:versionHistory").getValue().getString()));
+ assertFalse(chbaseVersion.equals(picture.getProperty("jcr:baseVersion").getValue().getString()));
+ assertFalse(chpredecessorsHistory[0].equals(picture.getProperty("jcr:predecessors").getValues()[0].getString()));
+
+ // try to remove picture, there must be RepositoryException
+ try
+ {
+ wc1.remove();
+ session.save();
+ fail();
+ }
+ catch (RepositoryException e)
+ {
+ // OK - wc1 Version History contain nt:versionedChild with link to non exist Version history
+
+ // remove bugy version history
+ SessionDataManager dataManager = session.getTransientNodesManager();
+ NodeImpl vhPicture =
+ (NodeImpl)session.getItem("/jcr:system/jcr:versionStorage/" + versionHistory
+ + "/1/jcr:frozenNode/medias/picture");
+
+ assertTrue(vhPicture.isNodeType("nt:versionedChild"));
+
+ PlainChangesLog changesLogDelete = new PlainChangesLogImpl();
+ changesLogDelete.add(ItemState.createDeletedState(((PropertyImpl)vhPicture.getProperty("jcr:primaryType"))
+ .getData()));
+ changesLogDelete.add(ItemState.createDeletedState(((PropertyImpl)vhPicture
+ .getProperty("jcr:childVersionHistory")).getData()));
+
+ for (ItemState itemState : changesLogDelete.getAllStates())
+ {
+ dataManager.delete(itemState.getData(), itemState.getAncestorToSave());
+ }
+
+ session.save();
+ }
+ }
+
}
Added: jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data.xml (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data.xml 2011-02-22 14:52:13 UTC (rev 4006)
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><sv:node xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:test="http://www.apache.org/jackrabbit/test" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:exojcrtest="http://www.exoplatform.org/jcr/test/1.0" xmlns:fn_old="http://www.w3.org/2004/10/xpath-functions" xmlns:mix="http://www.jcp.org/jcr/mix/1.0" xmlns:publication="http://www.exoplatform.com/jcr/publication/1.1/" xmlns:exo="http://www.exoplatform.com/jcr/exo/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rma="http://www.rma.com/jcr/" xmlns:sv="http://www.jcp.org/jcr/sv/1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:metadata="http://www.exoplatform.com/jcr/metadata/1.1/" xmlns:rep="internal" sv:name="wc1"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:folder</sv:value></sv:property><sv:property sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:versionable</sv:value></sv:property><sv:property sv:nam!
e="jcr:uuid" sv:type="String"><sv:value>00199791c0a800420106a227837ca02a</sv:value></sv:property><sv:property sv:name="jcr:baseVersion" sv:type="Reference"><sv:value>0019980ec0a80042014313ff82e97096</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-07T14:30:00.593+02:00</sv:value></sv:property><sv:property sv:name="jcr:isCheckedOut" sv:type="Boolean"><sv:value>true</sv:value></sv:property><sv:property sv:name="jcr:predecessors" sv:type="Reference"><sv:value>0019980ec0a80042014313ff82e97096</sv:value></sv:property><sv:property sv:name="jcr:versionHistory" sv:type="Reference"><sv:value>001997a1c0a80042007d98739b97e1bc</sv:value></sv:property><sv:node sv:name="medias"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:folder</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-07T14:30:00.625+02:00</sv:value></sv:property><sv:node sv:name="picture"><sv:property sv:name="jcr:primary!
Type" sv:type="Name"><sv:value>nt:file</sv:value></sv:property!
><sv:pro
perty sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:versionable</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>001997b1c0a8004201ab6f6dfdaf70f9</sv:value></sv:property><sv:property sv:name="jcr:baseVersion" sv:type="Reference"><sv:value>001997b1c0a8004200d65c82779a2e13</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-07T14:30:00.625+02:00</sv:value></sv:property><sv:property sv:name="jcr:isCheckedOut" sv:type="Boolean"><sv:value>true</sv:value></sv:property><sv:property sv:name="jcr:predecessors" sv:type="Reference"><sv:value>001997b1c0a8004200d65c82779a2e13</sv:value></sv:property><sv:property sv:name="jcr:versionHistory" sv:type="Reference"><sv:value>001997b1c0a8004201d35a6fa36ef4e7</sv:value></sv:property><sv:node sv:name="jcr:content"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:resource</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:!
value>001997b1c0a800420058c90fbc883ce3</sv:value></sv:property><sv:property sv:name="jcr:data" sv:type="Binary"><sv:value>YmxhIGJsYQ==</sv:value></sv:property><sv:property sv:name="jcr:lastModified" sv:type="Date"><sv:value>2011-02-07T14:30:00.625+02:00</sv:value></sv:property><sv:property sv:name="jcr:mimeType" sv:type="String"><sv:value>text/plain</sv:value></sv:property></sv:node></sv:node></sv:node></sv:node>
Added: jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data_with_versioned_child.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data_with_versioned_child.xml (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/data_with_versioned_child.xml 2011-02-22 14:52:13 UTC (rev 4006)
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><sv:node xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:test="http://www.apache.org/jackrabbit/test" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:exojcrtest="http://www.exoplatform.org/jcr/test/1.0" xmlns:fn_old="http://www.w3.org/2004/10/xpath-functions" xmlns:mix="http://www.jcp.org/jcr/mix/1.0" xmlns:publication="http://www.exoplatform.com/jcr/publication/1.1/" xmlns:exo="http://www.exoplatform.com/jcr/exo/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rma="http://www.rma.com/jcr/" xmlns:sv="http://www.jcp.org/jcr/sv/1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:metadata="http://www.exoplatform.com/jcr/metadata/1.1/" xmlns:rep="internal" sv:name="wc1"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:folder</sv:value></sv:property><sv:property sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:versionable</sv:value></sv:property><sv:property sv:nam!
e="jcr:uuid" sv:type="String"><sv:value>397dac7bc0a80042019e86f907ef0339</sv:value></sv:property><sv:property sv:name="jcr:baseVersion" sv:type="Reference"><sv:value>397dad17c0a8004201c7b45ea76d4b1b</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:40.859+02:00</sv:value></sv:property><sv:property sv:name="jcr:isCheckedOut" sv:type="Boolean"><sv:value>true</sv:value></sv:property><sv:property sv:name="jcr:predecessors" sv:type="Reference"><sv:value>397dad17c0a8004201c7b45ea76d4b1b</sv:value></sv:property><sv:property sv:name="jcr:versionHistory" sv:type="Reference"><sv:value>397dac8bc0a8004201729d052a305832</sv:value></sv:property><sv:node sv:name="medias"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:folder</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:40.890+02:00</sv:value></sv:property><sv:node sv:name="picture"><sv:property sv:name="jcr:primary!
Type" sv:type="Name"><sv:value>nt:file</sv:value></sv:property!
><sv:pro
perty sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:versionable</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397dac9ac0a800420182f12f406ca1a3</sv:value></sv:property><sv:property sv:name="jcr:baseVersion" sv:type="Reference"><sv:value>397dac9ac0a8004201cde5722fec978e</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:40.890+02:00</sv:value></sv:property><sv:property sv:name="jcr:isCheckedOut" sv:type="Boolean"><sv:value>true</sv:value></sv:property><sv:property sv:name="jcr:predecessors" sv:type="Reference"><sv:value>397dac9ac0a8004201cde5722fec978e</sv:value></sv:property><sv:property sv:name="jcr:versionHistory" sv:type="Reference"><sv:value>397dac9ac0a8004200f37de3ace7b0ad</sv:value></sv:property><sv:node sv:name="jcr:content"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:resource</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:!
value>397dac9ac0a8004201e6a413bc33907f</sv:value></sv:property><sv:property sv:name="jcr:data" sv:type="Binary"><sv:value>YmxhIGJsYQ==</sv:value></sv:property><sv:property sv:name="jcr:lastModified" sv:type="Date"><sv:value>2011-02-18T17:57:40.890+02:00</sv:value></sv:property><sv:property sv:name="jcr:mimeType" sv:type="String"><sv:value>text/plain</sv:value></sv:property></sv:node></sv:node></sv:node></sv:node>
Added: jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh.xml (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh.xml 2011-02-22 14:52:13 UTC (rev 4006)
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sv:node sv:name="001997a1c0a80042007d98739b97e1bc"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:test="http://www.apache.org/jackrabbit/test"
+ xmlns:sv="http://www.jcp.org/jcr/sv/1.0"
+ xmlns:rma="http://www.rma.com/jcr/" xmlns:rep="internal"
+ xmlns:publication="http://www.exoplatform.com/jcr/publication/1.1/"
+ xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
+ xmlns:mix="http://www.jcp.org/jcr/mix/1.0"
+ xmlns:metadata="http://www.exoplatform.com/jcr/metadata/1.1/"
+ xmlns:jcr="http://www.jcp.org/jcr/1.0"
+ xmlns:fn_old="http://www.w3.org/2004/10/xpath-functions"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions"
+ xmlns:exojcrtest="http://www.exoplatform.org/jcr/test/1.0"
+ xmlns:exo="http://www.exoplatform.com/jcr/exo/1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <sv:property sv:name="jcr:primaryType" sv:type="Name">
+ <sv:value>nt:versionHistory</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:uuid" sv:type="String">
+ <sv:value>001997a1c0a80042007d98739b97e1bc</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:versionableUuid" sv:type="String">
+ <sv:value>00199791c0a800420106a227837ca02a</sv:value>
+ </sv:property>
+
+ <sv:node sv:name="jcr:rootVersion">
+ <sv:property sv:name="jcr:primaryType" sv:type="Name">
+ <sv:value>nt:version</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:mixinTypes" sv:type="Name">
+ <sv:value>mix:referenceable</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:uuid" sv:type="String">
+ <sv:value>001997a1c0a8004201a3af806d45ed9b</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:created" sv:type="Date">
+ <sv:value>2011-02-07T14:30:00.609+02:00</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:successors" sv:type="Reference">
+ <sv:value>0019980ec0a80042014313ff82e97096</sv:value>
+ </sv:property>
+ </sv:node>
+
+ <sv:node sv:name="1">
+ <sv:property sv:name="jcr:primaryType" sv:type="Name">
+ <sv:value>nt:version</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:mixinTypes" sv:type="Name">
+ <sv:value>mix:referenceable</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:uuid" sv:type="String">
+ <sv:value>0019980ec0a80042014313ff82e97096</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:created" sv:type="Date">
+ <sv:value>2011-02-07T14:30:00.718+02:00</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:predecessors" sv:type="Reference">
+ <sv:value>001997a1c0a8004201a3af806d45ed9b</sv:value>
+ </sv:property>
+
+ <sv:node sv:name="jcr:frozenNode">
+ <sv:property sv:name="jcr:primaryType" sv:type="Name">
+ <sv:value>nt:frozenNode</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:mixinTypes" sv:type="Name">
+ <sv:value>mix:referenceable</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:uuid" sv:type="String">
+ <sv:value>0019980ec0a8004200d64e422bf86f49</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:created" sv:type="Date">
+ <sv:value>2011-02-07T14:30:00.734+02:00</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:frozenMixinTypes" sv:type="Name">
+ <sv:value>mix:versionable</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:frozenPrimaryType" sv:type="Name">
+ <sv:value>nt:folder</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:frozenUuid" sv:type="String">
+ <sv:value>00199791c0a800420106a227837ca02a</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:predecessors" sv:type="Reference">
+ <sv:value>001997a1c0a8004201a3af806d45ed9b</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:versionHistory" sv:type="Reference">
+ <sv:value>001997a1c0a80042007d98739b97e1bc</sv:value>
+ </sv:property>
+
+ <sv:node sv:name="medias">
+ <sv:property sv:name="jcr:primaryType" sv:type="Name">
+ <sv:value>nt:folder</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:created" sv:type="Date">
+ <sv:value>2011-02-07T14:30:00.734+02:00</sv:value>
+ </sv:property>
+
+ <sv:node sv:name="picture">
+ <sv:property sv:name="jcr:primaryType" sv:type="Name">
+ <sv:value>nt:versionedChild</sv:value>
+ </sv:property>
+
+ <sv:property sv:name="jcr:childVersionHistory" sv:type="Reference">
+ <sv:value>001997b1c0a8004201d35a6fa36ef4e7</sv:value>
+ </sv:property>
+ </sv:node>
+ </sv:node>
+ </sv:node>
+ </sv:node>
+
+ <sv:node sv:name="jcr:versionLabels">
+ <sv:property sv:name="jcr:primaryType" sv:type="Name">
+ <sv:value>nt:versionLabels</sv:value>
+ </sv:property>
+ </sv:node>
+</sv:node>
Added: jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh_with_versioned_child.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh_with_versioned_child.xml (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/import-export/vh_with_versioned_child.xml 2011-02-22 14:52:13 UTC (rev 4006)
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><sv:node xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:test="http://www.apache.org/jackrabbit/test" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:exojcrtest="http://www.exoplatform.org/jcr/test/1.0" xmlns:fn_old="http://www.w3.org/2004/10/xpath-functions" xmlns:mix="http://www.jcp.org/jcr/mix/1.0" xmlns:publication="http://www.exoplatform.com/jcr/publication/1.1/" xmlns:exo="http://www.exoplatform.com/jcr/exo/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rma="http://www.rma.com/jcr/" xmlns:sv="http://www.jcp.org/jcr/sv/1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:metadata="http://www.exoplatform.com/jcr/metadata/1.1/" xmlns:rep="internal" sv:name="397dac8bc0a8004201729d052a305832"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:versionHistory</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397dac8bc0a8004201729d052a!
305832</sv:value></sv:property><sv:property sv:name="jcr:versionableUuid" sv:type="String"><sv:value>397dac7bc0a80042019e86f907ef0339</sv:value></sv:property><sv:node sv:name="jcr:rootVersion"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:version</sv:value></sv:property><sv:property sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:referenceable</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397dac8bc0a8004201a2e53eb73949bd</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:40.875+02:00</sv:value></sv:property><sv:property sv:name="jcr:successors" sv:type="Reference"><sv:value>397dad17c0a8004201c7b45ea76d4b1b</sv:value></sv:property></sv:node><sv:node sv:name="1"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:version</sv:value></sv:property><sv:property sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:referenceable</sv:value></sv:property><!
sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397d!
ad17c0a8
004201c7b45ea76d4b1b</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:41.031+02:00</sv:value></sv:property><sv:property sv:name="jcr:predecessors" sv:type="Reference"><sv:value>397dac8bc0a8004201a2e53eb73949bd</sv:value></sv:property><sv:node sv:name="jcr:frozenNode"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:frozenNode</sv:value></sv:property><sv:property sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:referenceable</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397dad27c0a800420029031c7e421afa</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:41.031+02:00</sv:value></sv:property><sv:property sv:name="jcr:frozenMixinTypes" sv:type="Name"><sv:value>mix:versionable</sv:value></sv:property><sv:property sv:name="jcr:frozenPrimaryType" sv:type="Name"><sv:value>nt:folder</sv:value></sv:property><sv:property sv:nam!
e="jcr:frozenUuid" sv:type="String"><sv:value>397dac7bc0a80042019e86f907ef0339</sv:value></sv:property><sv:property sv:name="jcr:predecessors" sv:type="Reference"><sv:value>397dac8bc0a8004201a2e53eb73949bd</sv:value></sv:property><sv:property sv:name="jcr:versionHistory" sv:type="Reference"><sv:value>397dac8bc0a8004201729d052a305832</sv:value></sv:property><sv:node sv:name="medias"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:folder</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:41.031+02:00</sv:value></sv:property><sv:node sv:name="picture"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:versionedChild</sv:value></sv:property><sv:property sv:name="jcr:childVersionHistory" sv:type="Reference"><sv:value>397dac9ac0a8004200f37de3ace7b0ad</sv:value></sv:property><sv:versionhistory sv:name="397dac9ac0a8004200f37de3ace7b0ad"><sv:node sv:name="397dac9ac0a8004200f37de3ace7b0ad"><sv:proper!
ty sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:versi!
onHistor
y</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397dac9ac0a8004200f37de3ace7b0ad</sv:value></sv:property><sv:property sv:name="jcr:versionableUuid" sv:type="String"><sv:value>397dac9ac0a800420182f12f406ca1a3</sv:value></sv:property><sv:node sv:name="jcr:rootVersion"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:version</sv:value></sv:property><sv:property sv:name="jcr:mixinTypes" sv:type="Name"><sv:value>mix:referenceable</sv:value></sv:property><sv:property sv:name="jcr:uuid" sv:type="String"><sv:value>397dac9ac0a8004201cde5722fec978e</sv:value></sv:property><sv:property sv:name="jcr:created" sv:type="Date"><sv:value>2011-02-18T17:57:40.890+02:00</sv:value></sv:property></sv:node><sv:node sv:name="jcr:versionLabels"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:versionLabels</sv:value></sv:property></sv:node></sv:node></sv:versionhistory></sv:node></sv:node></sv:node></sv:node><sv:node sv:name="j!
cr:versionLabels"><sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:versionLabels</sv:value></sv:property></sv:node></sv:node>
13 years, 2 months
exo-jcr SVN: r4005 - jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-02-22 09:24:33 -0500 (Tue, 22 Feb 2011)
New Revision: 4005
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexInfosKey.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexUpdateKey.java
Removed:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexNamesKey.java
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexInfos.java
Log:
EXOJCR-832: implementation ISPNIndexUpdateMonitor.java
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexInfos.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexInfos.java 2011-02-22 14:04:54 UTC (rev 4004)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexInfos.java 2011-02-22 14:24:33 UTC (rev 4005)
@@ -77,7 +77,7 @@
/**
* Cache key for storing index names.
*/
- private final IndexNamesKey namesKey;
+ private final IndexInfosKey namesKey;
/**
* ISPNIndexInfos constructor.
@@ -118,7 +118,7 @@
this.cache = cache;
this.modeHandler = modeHandler;
this.modeHandler.addIndexerIoModeListener(this);
- this.namesKey = new IndexNamesKey(wsId + (system ? SYSINDEX_NAMES : INDEX_NAMES));
+ this.namesKey = new IndexInfosKey(wsId + (system ? SYSINDEX_NAMES : INDEX_NAMES));
if (modeHandler.getMode() == IndexerIoMode.READ_ONLY)
{
@@ -172,7 +172,7 @@
}
/**
- * Cache listener method will be invoked when a cache entry has been modified only in READ_ONLY mode.
+ * Method will be invoked when a cache entry has been modified only in READ_ONLY mode.
*
* @param event
* CacheEntryModifiedEvent
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/ISPNIndexUpdateMonitor.java 2011-02-22 14:24:33 UTC (rev 4005)
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.core.query.ispn;
+
+import org.exoplatform.services.jcr.impl.core.query.IndexerIoMode;
+import org.exoplatform.services.jcr.impl.core.query.IndexerIoModeHandler;
+import org.exoplatform.services.jcr.impl.core.query.IndexerIoModeListener;
+import org.exoplatform.services.jcr.impl.core.query.lucene.IndexUpdateMonitor;
+import org.exoplatform.services.jcr.impl.core.query.lucene.IndexUpdateMonitorListener;
+import org.exoplatform.services.jcr.infinispan.PrivilegedISPNCacheHelper;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.infinispan.Cache;
+import org.infinispan.CacheException;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
+import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 22.02.2011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy Bazko</a>
+ * @version $Id: ISPNIndexUpdateMonitor.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+@Listener
+public class ISPNIndexUpdateMonitor implements IndexUpdateMonitor, IndexerIoModeListener
+{
+ /**
+ * Logger instance for this class
+ */
+ private final Log log = ExoLogger.getLogger("exo.jcr.component.core.ISPNIndexUpdateMonitor");
+
+ /**
+ * ISPN cache.
+ */
+ private final Cache<Serializable, Object> cache;
+
+ private boolean localUpdateInProgress = false;
+
+ private static final String INDEX_PARAMETERS = "$index_parameters".intern();
+
+ private static final String SYSINDEX_PARAMETERS = "$sysindex_parameters".intern();
+
+ public final IndexerIoModeHandler modeHandler;
+
+ /**
+ * The list of all the listeners
+ */
+ private final List<IndexUpdateMonitorListener> listeners;
+
+ /**
+ * Cache key for sending notifications.
+ */
+ private final IndexUpdateKey updateKey;
+
+ /**
+ *
+ * @param wsId
+ * @param cache
+ * @param system
+ * @param modeHandler
+ */
+ public ISPNIndexUpdateMonitor(String wsId, Cache<Serializable, Object> cache, boolean system,
+ IndexerIoModeHandler modeHandler)
+ {
+ this.cache = cache;
+ this.modeHandler = modeHandler;
+ this.listeners = new CopyOnWriteArrayList<IndexUpdateMonitorListener>();
+ this.modeHandler.addIndexerIoModeListener(this);
+ this.updateKey = new IndexUpdateKey(wsId + (system ? SYSINDEX_PARAMETERS : INDEX_PARAMETERS));
+
+ if (IndexerIoMode.READ_WRITE == modeHandler.getMode())
+ {
+ // global, replicated set
+ setUpdateInProgress(false, true);
+ }
+ else
+ {
+ // Currently READ_ONLY is set, so new lists should be fired to multiIndex.
+ cache.addListener(this);
+ Object value = cache.get(updateKey);
+ localUpdateInProgress = value != null ? (Boolean)value : false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onChangeMode(IndexerIoMode mode)
+ {
+ if (mode == IndexerIoMode.READ_WRITE)
+ {
+ // In READ_WRITE, the value of UpdateInProgress is changed locally so no need to listen
+ // to the cache
+ cache.removeListener(this);
+ }
+ else
+ {
+ // In READ_ONLY, the value of UpdateInProgress will be changed remotely, so we have
+ // no need but to listen to the cache to be notified when the value changes
+ cache.addListener(this);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean getUpdateInProgress()
+ {
+ return localUpdateInProgress;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setUpdateInProgress(boolean updateInProgress, boolean persitentUpdate)
+ {
+ if (IndexerIoMode.READ_ONLY == modeHandler.getMode())
+ {
+ throw new IllegalStateException("Unable to set updateInProgress value in IndexerIoMode.READ_ONLY mode");
+ }
+ try
+ {
+ // anyway set local update in progress
+ localUpdateInProgress = updateInProgress;
+ if (persitentUpdate)
+ {
+ PrivilegedISPNCacheHelper.put(cache, updateKey, new Boolean(updateInProgress));
+ }
+ for (IndexUpdateMonitorListener listener : listeners)
+ {
+ listener.onUpdateInProgressChange(updateInProgress);
+ }
+
+ }
+ catch (CacheException e)
+ {
+ log.error("Fail to change updateInProgress mode to " + updateInProgress, e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addIndexUpdateMonitorListener(IndexUpdateMonitorListener listener)
+ {
+ listeners.add(listener);
+ }
+
+ /**
+ * Method will be invoked when a cache entry has been modified only in READ_ONLY mode.
+ *
+ * @param event
+ * CacheEntryModifiedEvent
+ */
+ @CacheEntryModified
+ public void cacheEntryModified(CacheEntryModifiedEvent event)
+ {
+ if (!event.isPre() && event.getKey().equals(updateKey))
+ {
+ Object value = event.getValue();
+ localUpdateInProgress = value != null ? (Boolean)value : false;
+
+ for (IndexUpdateMonitorListener listener : listeners)
+ {
+ listener.onUpdateInProgressChange(localUpdateInProgress);
+ }
+ }
+ }
+}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexInfosKey.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexInfosKey.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexInfosKey.java 2011-02-22 14:24:33 UTC (rev 4005)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.core.query.ispn;
+
+import org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.CacheKey;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 22.02.011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy Bazko</a>
+ * @version $Id: IndexNamesKey.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public class IndexInfosKey extends CacheKey
+{
+
+ IndexInfosKey(String id)
+ {
+ super(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof IndexInfosKey)
+ {
+ IndexInfosKey key = (IndexInfosKey)obj;
+ return (key.hash == hash && key.id.equals(id));
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
Deleted: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexNamesKey.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexNamesKey.java 2011-02-22 14:04:54 UTC (rev 4004)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexNamesKey.java 2011-02-22 14:24:33 UTC (rev 4005)
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2009 eXo Platform SAS.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.exoplatform.services.jcr.impl.core.query.ispn;
-
-import org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.CacheKey;
-
-/**
- * Created by The eXo Platform SAS.
- *
- * Date: 22.02.011
- *
- * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy Bazko</a>
- * @version $Id: IndexNamesKey.java 34360 2010-11-11 11:11:11Z tolusha $
- */
-public class IndexNamesKey extends CacheKey
-{
-
- IndexNamesKey(String id)
- {
- super(id);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object obj)
- {
- if (obj instanceof IndexNamesKey)
- {
- IndexNamesKey key = (IndexNamesKey)obj;
- return (key.hash == hash && key.id.equals(id));
- }
- else
- {
- return false;
- }
- }
-}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexUpdateKey.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexUpdateKey.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/ispn/IndexUpdateKey.java 2011-02-22 14:24:33 UTC (rev 4005)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.core.query.ispn;
+
+import org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.CacheKey;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * Date: 22.02.011
+ *
+ * @author <a href="mailto:anatoliy.bazko@exoplatform.com.ua">Anatoliy Bazko</a>
+ * @version $Id: IndexUpdateKey.java 34360 2010-11-11 11:11:11Z tolusha $
+ */
+public class IndexUpdateKey extends CacheKey
+{
+
+ IndexUpdateKey(String id)
+ {
+ super(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof IndexUpdateKey)
+ {
+ IndexUpdateKey key = (IndexUpdateKey)obj;
+ return (key.hash == hash && key.id.equals(id));
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
13 years, 2 months