Author: tolusha
Date: 2010-07-20 05:21:29 -0400 (Tue, 20 Jul 2010)
New Revision: 2801
Added:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/InfinispanLockManagerImpl.java
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/InfinispanCacheFactory.java
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan.xml
Removed:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan-lock.xml
Modified:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/test/resources/conf/standalone/test-jcr-config.xml
Log:
EXOJCR-831: can use single file configuration
Added:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/InfinispanLockManagerImpl.java
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/InfinispanLockManagerImpl.java
(rev 0)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/InfinispanLockManagerImpl.java 2010-07-20
09:21:29 UTC (rev 2801)
@@ -0,0 +1,1101 @@
+/*
+ *
+ * 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.lock.infinispan;
+
+import org.exoplatform.container.configuration.ConfigurationManager;
+import org.exoplatform.management.annotations.Managed;
+import org.exoplatform.management.annotations.ManagedDescription;
+import org.exoplatform.management.jmx.annotations.NameTemplate;
+import org.exoplatform.management.jmx.annotations.Property;
+import org.exoplatform.services.jcr.access.SystemIdentity;
+import org.exoplatform.services.jcr.config.MappedParametrizedObjectEntry;
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.dataflow.ChangesLogIterator;
+import org.exoplatform.services.jcr.dataflow.CompositeChangesLog;
+import org.exoplatform.services.jcr.dataflow.DataManager;
+import org.exoplatform.services.jcr.dataflow.ItemState;
+import org.exoplatform.services.jcr.dataflow.ItemStateChangesLog;
+import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
+import org.exoplatform.services.jcr.dataflow.PlainChangesLogImpl;
+import org.exoplatform.services.jcr.dataflow.TransactionChangesLog;
+import org.exoplatform.services.jcr.dataflow.persistent.ItemsPersistenceListener;
+import org.exoplatform.services.jcr.datamodel.ItemData;
+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.impl.Constants;
+import org.exoplatform.services.jcr.impl.core.SessionDataManager;
+import org.exoplatform.services.jcr.impl.core.lock.LockRemover;
+import org.exoplatform.services.jcr.impl.core.lock.SessionLockManager;
+import org.exoplatform.services.jcr.impl.core.lock.jbosscache.CacheableLockManager;
+import org.exoplatform.services.jcr.impl.core.lock.jbosscache.CacheableLockManagerImpl;
+import
org.exoplatform.services.jcr.impl.core.lock.jbosscache.CacheableSessionLockManager;
+import org.exoplatform.services.jcr.impl.core.lock.jbosscache.LockData;
+import org.exoplatform.services.jcr.impl.dataflow.TransientItemData;
+import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
+import
org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager;
+import org.exoplatform.services.jcr.impl.storage.JCRInvalidItemStateException;
+import org.exoplatform.services.jcr.impl.storage.jdbc.DBConstants;
+import org.exoplatform.services.jcr.impl.storage.jdbc.DialectDetecter;
+import org.exoplatform.services.jcr.impl.util.io.PrivilegedCacheHelper;
+import org.exoplatform.services.jcr.infinispan.InfinispanCacheFactory;
+import org.exoplatform.services.jcr.observation.ExtendedEvent;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.exoplatform.services.naming.InitialContextInitializer;
+import org.exoplatform.services.transaction.TransactionService;
+import org.infinispan.Cache;
+import org.picocontainer.Startable;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.security.AccessController;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+import javax.naming.InitialContext;
+import javax.sql.DataSource;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+/**
+ * @author <a href="anatoliy.bazko(a)exoplatform.org">Anatoliy
Bazko</a>
+ * @version $Id: InfinispanLockManagerImpl.java 111 2010-11-11 11:11:11Z tolusha $
+ *
+ */
+@Managed
+@NameTemplate(@Property(key = "service", value = "lockmanager"))
+public class InfinispanLockManagerImpl implements CacheableLockManager,
ItemsPersistenceListener, Startable
+{
+
+ /**
+ * The name to property time out.
+ */
+ public static final String TIME_OUT = "time-out";
+
+ /**
+ * The name to property cache configuration.
+ */
+ public static final String INFINISPAN_JDBC_CL_DATASOURCE =
"infinispan-cl-cache.jdbc.datasource";
+
+ public static final String INFINISPAN_JDBC_CL_DATA_COLUMN =
"infinispan-cl-cache.jdbc.data.type";
+
+ public static final String INFINISPAN_JDBC_CL_TIMESTAMP_COLUMN =
"infinispan-cl-cache.jdbc.timestamp.type";
+
+ public static final String INFINISPAN_JDBC_CL_ID_COLUMN =
"infinispan-cl-cache.jdbc.id.type";
+
+ public static final String INFINISPAN_JDBC_CL_AUTO = "auto";
+
+ /**
+ * Default lock time out. 30min
+ */
+ public static final long DEFAULT_LOCK_TIMEOUT = 1000 * 60 * 30;
+
+ /**
+ * Logger
+ */
+ private final Log LOG =
ExoLogger.getLogger("exo.jcr.component.core.CacheableLockManagerImpl");
+
+ /**
+ * Data manager.
+ */
+ private final DataManager dataManager;
+
+ /**
+ * Run time lock time out.
+ */
+ private long lockTimeOut;
+
+ /**
+ * Lock remover thread.
+ */
+ private LockRemover lockRemover;
+
+ /**
+ * The current Transaction Manager
+ */
+ private TransactionManager tm;
+
+ private Cache<Serializable, Object> cache;
+
+ // private final Fqn<String> lockRoot;
+
+ /**
+ * SessionLockManagers that uses this LockManager.
+ */
+ private Map<String, CacheableSessionLockManager> sessionLockManagers;
+
+ public InfinispanLockManagerImpl(WorkspacePersistentDataManager dataManager,
WorkspaceEntry config,
+ InitialContextInitializer context, TransactionService transactionService,
ConfigurationManager cfm)
+ throws RepositoryConfigurationException, RepositoryException
+ {
+ this(dataManager, config, context, transactionService.getTransactionManager(),
cfm);
+ }
+
+ public InfinispanLockManagerImpl(WorkspacePersistentDataManager dataManager,
WorkspaceEntry config,
+ InitialContextInitializer context, ConfigurationManager cfm) throws
RepositoryConfigurationException,
+ RepositoryException
+ {
+ this(dataManager, config, context, (TransactionManager)null, cfm);
+ }
+
+ public InfinispanLockManagerImpl(WorkspacePersistentDataManager dataManager,
WorkspaceEntry config,
+ InitialContextInitializer context, TransactionManager transactionManager,
ConfigurationManager cfm)
+ throws RepositoryConfigurationException, RepositoryException
+ {
+ this.dataManager = dataManager;
+
+ if (config.getLockManager() != null)
+ {
+ if (config.getLockManager().getParameters() != null
+ && config.getLockManager().getParameterValue(TIME_OUT, null) !=
null)
+ {
+ long timeOut = config.getLockManager().getParameterTime(TIME_OUT);
+ lockTimeOut = timeOut > 0 ? timeOut : DEFAULT_LOCK_TIMEOUT;
+ }
+ else
+ {
+ lockTimeOut =
+ config.getLockManager().getTimeout() > 0 ?
config.getLockManager().getTimeout() : DEFAULT_LOCK_TIMEOUT;
+ }
+ }
+ else
+ {
+ lockTimeOut = DEFAULT_LOCK_TIMEOUT;
+ }
+
+ sessionLockManagers = new ConcurrentHashMap<String,
CacheableSessionLockManager>();
+ dataManager.addItemPersistenceListener(this);
+
+ // make cache
+ if (config.getLockManager() != null)
+ {
+ this.tm = transactionManager;
+
+ // create cache using custom factory
+ InfinispanCacheFactory<Serializable, Object> factory =
+ new InfinispanCacheFactory<Serializable, Object>(cfm,
transactionManager);
+
+ // configure cache loader parameters with correct DB data-types
+ configureJDBCCacheLoader(config.getLockManager());
+
+ cache = factory.createCache(config.getLockManager());
+
+ // Add the cache loader needed to prevent TimeoutException
+ // addCacheLoader();
+
+ PrivilegedCacheHelper.start(cache);
+
+ // createStructuredNode(lockRoot);
+
+ // Context recall is a workaround of JDBCCacheLoader starting.
+ context.recall();
+ }
+ else
+ {
+ throw new RepositoryConfigurationException("Cache configuration not
found");
+ }
+ }
+
+ /**
+ * If JDBC cache loader is used, then fills-in column types. If column type configured
from jcr-configuration file,
+ * then nothing is overridden. Parameters are injected into the given parameterEntry.
+ */
+ private void configureJDBCCacheLoader(MappedParametrizedObjectEntry parameterEntry)
throws RepositoryException
+ {
+ String dataSourceName =
parameterEntry.getParameterValue(INFINISPAN_JDBC_CL_DATASOURCE, null);
+ // if data source is defined, then inject correct data-types.
+ // Also it cans be not defined and nothing should be injected (i.e. no cache loader
is used (possibly pattern is changed, to used another cache loader))
+ if (dataSourceName != null)
+ {
+ String dialect;
+ // detect dialect of data-source
+ try
+ {
+ final DataSource dataSource = (DataSource)new
InitialContext().lookup(dataSourceName);
+ if (dataSource == null)
+ {
+ throw new RepositoryException("DataSource (" + dataSourceName +
") can't be null");
+ }
+
+ Connection jdbcConn = null;
+ try
+ {
+ PrivilegedExceptionAction<Connection> action = new
PrivilegedExceptionAction<Connection>()
+ {
+ public Connection run() throws Exception
+ {
+ return dataSource.getConnection();
+ }
+ };
+ try
+ {
+ jdbcConn = AccessController.doPrivileged(action);
+ }
+ catch (PrivilegedActionException pae)
+ {
+ Throwable cause = pae.getCause();
+ if (cause instanceof SQLException)
+ {
+ throw (SQLException)cause;
+ }
+ else if (cause instanceof RuntimeException)
+ {
+ throw (RuntimeException)cause;
+ }
+ else
+ {
+ throw new RuntimeException(cause);
+ }
+ }
+
+ dialect = DialectDetecter.detect(jdbcConn.getMetaData());
+ }
+ finally
+ {
+ if (jdbcConn != null && !jdbcConn.isClosed())
+ {
+ try
+ {
+ jdbcConn.close();
+ }
+ catch (SQLException e)
+ {
+ throw new RepositoryException("Error of connection close",
e);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ throw new RepositoryException("Error configuring JDBC cache
loader", e);
+ }
+
+ // default values, will be overridden with types suitable for concrete data
base.
+ String blobType = "BLOB";
+ String charType = "VARCHAR(512)";
+ String timeStampType = "BIGINT";
+ // HSSQL
+ if (dialect.equals(DBConstants.DB_DIALECT_HSQLDB))
+ {
+ blobType = "OBJECT";
+ }
+ // MYSQL
+ else if (dialect.equals(DBConstants.DB_DIALECT_MYSQL) ||
dialect.equals(DBConstants.DB_DIALECT_MYSQL_UTF8))
+ {
+ blobType = "LONGBLOB";
+ }
+ // ORACLE
+ else if (dialect.equals(DBConstants.DB_DIALECT_ORACLE) ||
dialect.equals(DBConstants.DB_DIALECT_ORACLEOCI))
+ {
+ // Oracle suggests the use VARCHAR2 instead of VARCHAR while declaring data
type.
+ charType = "VARCHAR2(512)";
+ }
+ // POSTGRE SQL
+ else if (dialect.equals(DBConstants.DB_DIALECT_PGSQL))
+ {
+ blobType = "bytea";
+ }
+ // Microsoft SQL
+ else if (dialect.equals(DBConstants.DB_DIALECT_MSSQL))
+ {
+ blobType = "VARBINARY(MAX)";
+ }
+ // SYBASE
+ else if (dialect.equals(DBConstants.DB_DIALECT_SYBASE))
+ {
+ blobType = "IMAGE";
+ }
+ // INGRES
+ else if (dialect.equals(DBConstants.DB_DIALECT_INGRES))
+ {
+ blobType = "long byte";
+ }
+ // else GENERIC, DB2 etc
+
+ // set parameters if not defined
+ // if parameter is missing in configuration, then
getParameterValue(INFINISPAN_JDBC_CL_NODE_COLUMN, INFINISPAN_JDBC_CL_AUTO)
+ // will return INFINISPAN_JDBC_CL_AUTO. If parameter is present in configuration
and equals to "auto", then it should be replaced
+ // with correct value for given database
+ if (parameterEntry.getParameterValue(INFINISPAN_JDBC_CL_DATA_COLUMN,
INFINISPAN_JDBC_CL_AUTO)
+ .equalsIgnoreCase(INFINISPAN_JDBC_CL_AUTO))
+ {
+ parameterEntry.putParameterValue(INFINISPAN_JDBC_CL_DATA_COLUMN, blobType);
+ }
+
+ if (parameterEntry.getParameterValue(INFINISPAN_JDBC_CL_ID_COLUMN,
INFINISPAN_JDBC_CL_AUTO).equalsIgnoreCase(
+ INFINISPAN_JDBC_CL_AUTO))
+ {
+ parameterEntry.putParameterValue(INFINISPAN_JDBC_CL_ID_COLUMN, charType);
+ }
+
+ if (parameterEntry.getParameterValue(INFINISPAN_JDBC_CL_TIMESTAMP_COLUMN,
INFINISPAN_JDBC_CL_AUTO)
+ .equalsIgnoreCase(INFINISPAN_JDBC_CL_AUTO))
+ {
+ parameterEntry.putParameterValue(INFINISPAN_JDBC_CL_TIMESTAMP_COLUMN,
timeStampType);
+ }
+ }
+ else
+ {
+ LOG.warn("CacheLoader DataSource " + INFINISPAN_JDBC_CL_DATASOURCE +
" is not configured.");
+ }
+ }
+
+ @Managed
+ @ManagedDescription("Remove the expired locks")
+ public void cleanExpiredLocks()
+ {
+ removeExpired();
+ }
+
+ public long getDefaultLockTimeOut()
+ {
+ return lockTimeOut;
+ }
+
+ private final LockActionNonTxAware<Integer, Object> getNumLocks = new
LockActionNonTxAware<Integer, Object>()
+ {
+ public Integer execute(Object arg)
+ {
+ return cache.size();
+ }
+ };
+
+ @Managed
+ @ManagedDescription("The number of active locks")
+ public int getNumLocks()
+ {
+ try
+ {
+ return executeLockActionNonTxAware(getNumLocks, null);
+ }
+ catch (LockException e)
+ {
+ // ignore me will never occur
+ }
+ return -1;
+ }
+
+ private final LockActionNonTxAware<Boolean, Object> hasLocks = new
LockActionNonTxAware<Boolean, Object>()
+ {
+ public Boolean execute(Object arg)
+ {
+ return !cache.isEmpty();
+ }
+ };
+
+ /**
+ * Indicates if some locks have already been created
+ */
+ private boolean hasLocks()
+ {
+ try
+ {
+ return executeLockActionNonTxAware(hasLocks, null);
+ }
+ catch (LockException e)
+ {
+ // ignore me will never occur
+ }
+ return true;
+ }
+
+ /**
+ * Return new instance of session lock manager.
+ */
+ public SessionLockManager getSessionLockManager(String sessionId, SessionDataManager
transientManager)
+ {
+ CacheableSessionLockManager sessionManager = new
CacheableSessionLockManager(sessionId, this, transientManager);
+ sessionLockManagers.put(sessionId, sessionManager);
+ return sessionManager;
+ }
+
+ private final LockActionNonTxAware<Boolean, String> isLockLive = new
LockActionNonTxAware<Boolean, String>()
+ {
+ public Boolean execute(String nodeId)
+ {
+ if (cache.get(nodeId) != null) //pendingLocks.containsKey(nodeId) ||
+ {
+ return true;
+ }
+
+ return false;
+ }
+ };
+
+ /**
+ * Check is LockManager contains lock. No matter it is in pending or persistent
state.
+ *
+ * @param nodeId - locked node id
+ * @return
+ */
+ public boolean isLockLive(String nodeId) throws LockException
+ {
+ try
+ {
+ return executeLockActionNonTxAware(isLockLive, nodeId);
+ }
+ catch (LockException e)
+ {
+ // ignore me will never occur
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isTXAware()
+ {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
@seeorg.exoplatform.services.jcr.dataflow.persistent.ItemsPersistenceListener#onSaveItems(org.
+ * exoplatform.services.jcr.dataflow.ItemStateChangesLog)
+ */
+ public void onSaveItems(ItemStateChangesLog changesLog)
+ {
+ List<PlainChangesLog> chengesLogList = new
ArrayList<PlainChangesLog>();
+ if (changesLog instanceof TransactionChangesLog)
+ {
+ ChangesLogIterator logIterator =
((TransactionChangesLog)changesLog).getLogIterator();
+
+ while (logIterator.hasNextLog())
+ {
+ chengesLogList.add(logIterator.nextLog());
+ }
+ }
+ else if (changesLog instanceof PlainChangesLog)
+ {
+ chengesLogList.add((PlainChangesLog)changesLog);
+ }
+ else if (changesLog instanceof CompositeChangesLog)
+ {
+ for (ChangesLogIterator iter =
((CompositeChangesLog)changesLog).getLogIterator(); iter.hasNextLog();)
+ {
+ chengesLogList.add(iter.nextLog());
+ }
+ }
+
+ List<LockOperationContainer> containers = new
ArrayList<LockOperationContainer>();
+
+ for (PlainChangesLog currChangesLog : chengesLogList)
+ {
+ String sessionId = currChangesLog.getSessionId();
+
+ String nodeIdentifier;
+ try
+ {
+ switch (currChangesLog.getEventType())
+ {
+ case ExtendedEvent.LOCK :
+ if (currChangesLog.getSize() < 2)
+ {
+ LOG.error("Incorrect changes log of type ExtendedEvent.LOCK
size=" + currChangesLog.getSize()
+ + "<2 \n" + currChangesLog.dump());
+ break;
+ }
+ nodeIdentifier =
currChangesLog.getAllStates().get(0).getData().getParentIdentifier();
+
+ CacheableSessionLockManager session =
sessionLockManagers.get(sessionId);
+ if (session != null &&
session.containsPendingLock(nodeIdentifier))
+ {
+ containers.add(new LockOperationContainer(nodeIdentifier,
currChangesLog.getSessionId(),
+ ExtendedEvent.LOCK));
+ }
+ else
+ {
+ LOG.error("Lock must exist in pending locks.");
+ }
+ break;
+ case ExtendedEvent.UNLOCK :
+ if (currChangesLog.getSize() < 2)
+ {
+ LOG.error("Incorrect changes log of type ExtendedEvent.UNLOCK
size=" + currChangesLog.getSize()
+ + "<2 \n" + currChangesLog.dump());
+ break;
+ }
+
+ containers.add(new
LockOperationContainer(currChangesLog.getAllStates().get(0).getData()
+ .getParentIdentifier(), currChangesLog.getSessionId(),
ExtendedEvent.UNLOCK));
+ break;
+ default :
+ HashSet<String> removedLock = new HashSet<String>();
+ for (ItemState itemState : currChangesLog.getAllStates())
+ {
+ // this is a node and node is locked
+ if (itemState.getData().isNode() &&
lockExist(itemState.getData().getIdentifier()))
+ {
+ nodeIdentifier = itemState.getData().getIdentifier();
+ if (itemState.isDeleted())
+ {
+ removedLock.add(nodeIdentifier);
+ }
+ else if (itemState.isAdded() || itemState.isRenamed() ||
itemState.isUpdated())
+ {
+ removedLock.remove(nodeIdentifier);
+ }
+ }
+ }
+ for (String identifier : removedLock)
+ {
+ containers.add(new LockOperationContainer(identifier,
currChangesLog.getSessionId(),
+ ExtendedEvent.UNLOCK));
+ }
+ break;
+ }
+ }
+ catch (IllegalStateException e)
+ {
+ LOG.error(e.getLocalizedMessage(), e);
+ }
+ }
+
+ // sort locking and unlocking operations to avoid deadlocks in JBossCache
+ Collections.sort(containers);
+ for (LockOperationContainer container : containers)
+ {
+ try
+ {
+ container.apply();
+ }
+ catch (LockException e)
+ {
+ LOG.error(e.getMessage(), e);
+ }
+ }
+ }
+
+ /**
+ * Class containing operation type (LOCK or UNLOCK) and all the needed information
like node uuid and session id.
+ */
+ private class LockOperationContainer implements
Comparable<LockOperationContainer>
+ {
+
+ private String identifier;
+
+ private String sessionId;
+
+ private int type;
+
+ /**
+ * @param identifier node identifier
+ * @param sessionId id of session
+ * @param type ExtendedEvent type specifying the operation (LOCK or UNLOCK)
+ */
+ public LockOperationContainer(String identifier, String sessionId, int type)
+ {
+ super();
+ this.identifier = identifier;
+ this.sessionId = sessionId;
+ this.type = type;
+ }
+
+ /**
+ * @return node identifier
+ */
+ public String getIdentifier()
+ {
+ return identifier;
+ }
+
+ public void apply() throws LockException
+ {
+ // invoke internalLock in LOCK operation
+ if (type == ExtendedEvent.LOCK)
+ {
+ internalLock(sessionId, identifier);
+ }
+ // invoke internalUnLock in UNLOCK operation
+ else if (type == ExtendedEvent.UNLOCK)
+ {
+ internalUnLock(sessionId, identifier);
+ }
+ }
+
+ /**
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(LockOperationContainer o)
+ {
+ return identifier.compareTo(o.getIdentifier());
+ }
+ }
+
+ private final LockActionNonTxAware<Object, LockData> refresh = new
LockActionNonTxAware<Object, LockData>()
+ {
+ public Object execute(LockData newLockData) throws LockException
+ {
+ Object oldValue = PrivilegedCacheHelper.putIfAbsent(cache,
newLockData.getNodeIdentifier(), newLockData);
+ if (oldValue == null)
+ {
+ throw new LockException("Can't refresh lock for node " +
newLockData.getNodeIdentifier()
+ + " since lock is not exist");
+ }
+ return null;
+ }
+ };
+
+ /**
+ * Refreshed lock data in cache
+ *
+ * @param newLockData
+ */
+ public void refreshLockData(LockData newLockData) throws LockException
+ {
+ executeLockActionNonTxAware(refresh, newLockData);
+ }
+
+ /**
+ * Remove expired locks. Used from LockRemover.
+ */
+ public synchronized void removeExpired()
+ {
+ final List<String> removeLockList = new ArrayList<String>();
+
+ for (LockData lock : getLockList())
+ {
+ if (!lock.isSessionScoped() && lock.getTimeToDeath() < 0)
+ {
+ removeLockList.add(lock.getNodeIdentifier());
+ }
+ }
+
+ Collections.sort(removeLockList);
+
+ for (String rLock : removeLockList)
+ {
+ removeLock(rLock);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.picocontainer.Startable#start()
+ */
+ public void start()
+ {
+ lockRemover = new LockRemover(this);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.picocontainer.Startable#stop()
+ */
+ public void stop()
+ {
+ lockRemover.halt();
+ lockRemover.interrupt();
+ sessionLockManagers.clear();
+
+ PrivilegedCacheHelper.stop(cache);
+ }
+
+ /**
+ * Copy <code>PropertyData prop<code> to new TransientItemData
+ *
+ * @param prop
+ * @return
+ * @throws RepositoryException
+ */
+ private TransientItemData copyItemData(PropertyData prop) throws RepositoryException
+ {
+ if (prop == null)
+ {
+ return null;
+ }
+
+ // make a copy, value may be null for deleting items
+ TransientPropertyData newData =
+ new TransientPropertyData(prop.getQPath(), prop.getIdentifier(),
prop.getPersistedVersion(), prop.getType(),
+ prop.getParentIdentifier(), prop.isMultiValued(), prop.getValues());
+
+ return newData;
+ }
+
+ /**
+ * Internal lock
+ *
+ * @param nodeIdentifier
+ * @throws LockException
+ */
+ private synchronized void internalLock(String sessionId, String nodeIdentifier) throws
LockException
+ {
+ CacheableSessionLockManager session = sessionLockManagers.get(sessionId);
+ if (session != null && session.containsPendingLock(nodeIdentifier))
+ {
+ LockData lockData = session.getPendingLock(nodeIdentifier);
+
+ // this will return null if success. And old data if something exists...
+ LockData oldLockData = (LockData)PrivilegedCacheHelper.putIfAbsent(cache,
nodeIdentifier, lockData);
+
+ if (oldLockData != null)
+ {
+ throw new LockException("Unable to write LockData. Node [" +
lockData.getNodeIdentifier()
+ + "] already has LockData!");
+ }
+
+ session.notifyLockPersisted(nodeIdentifier);
+ }
+ else
+ {
+ throw new LockException("No lock in pending locks");
+ }
+ }
+
+ /**
+ * Internal unlock.
+ *
+ * @param sessionId
+ * @param nodeIdentifier
+ * @throws LockException
+ */
+ private synchronized void internalUnLock(String sessionId, String nodeIdentifier)
throws LockException
+ {
+ LockData lData = getLockDataById(nodeIdentifier);
+
+ if (lData != null)
+ {
+ cache.remove(nodeIdentifier);
+
+ CacheableSessionLockManager sessMgr = sessionLockManagers.get(sessionId);
+ if (sessMgr != null)
+ {
+ sessMgr.notifyLockRemoved(nodeIdentifier);
+ }
+ }
+ }
+
+ private final LockActionNonTxAware<Boolean, String> lockExist = new
LockActionNonTxAware<Boolean, String>()
+ {
+ public Boolean execute(String nodeId) throws LockException
+ {
+ return cache.get(nodeId) != null;
+ }
+ };
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean lockExist(String nodeId)
+ {
+ try
+ {
+ return executeLockActionNonTxAware(lockExist, nodeId);
+ }
+ catch (LockException e)
+ {
+ // ignore me will never occur
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getLockTokenHash(String token)
+ {
+ String hash = "";
+ try
+ {
+ MessageDigest m = MessageDigest.getInstance("MD5");
+ m.update(token.getBytes(), 0, token.length());
+ hash = new BigInteger(1, m.digest()).toString(16);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ LOG.error("Can't get instanse of MD5 MessageDigest!", e);
+ }
+ return hash;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public LockData getExactNodeOrCloseParentLock(NodeData node) throws
RepositoryException
+ {
+ return getExactNodeOrCloseParentLock(node, true);
+ }
+
+ private LockData getExactNodeOrCloseParentLock(NodeData node, boolean checkHasLocks)
throws RepositoryException
+ {
+
+ if (node == null || (checkHasLocks && !hasLocks()))
+ {
+ return null;
+ }
+ LockData retval = null;
+ retval = getLockDataById(node.getIdentifier());
+ if (retval == null)
+ {
+ NodeData parentData =
(NodeData)dataManager.getItemData(node.getParentIdentifier());
+ if (parentData != null)
+ {
+ retval = getExactNodeOrCloseParentLock(parentData, false);
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public LockData getExactNodeLock(NodeData node) throws RepositoryException
+ {
+ if (node == null || !hasLocks())
+ {
+ return null;
+ }
+
+ return getLockDataById(node.getIdentifier());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public LockData getClosedChild(NodeData node) throws RepositoryException
+ {
+ return getClosedChild(node, true);
+ }
+
+ private LockData getClosedChild(NodeData node, boolean checkHasLocks) throws
RepositoryException
+ {
+
+ if (node == null || (checkHasLocks && !hasLocks()))
+ {
+ return null;
+ }
+ LockData retval = null;
+
+ List<NodeData> childData = dataManager.getChildNodesData(node);
+ for (NodeData nodeData : childData)
+ {
+ retval = getLockDataById(nodeData.getIdentifier());
+ if (retval != null)
+ return retval;
+ }
+ // child not found try to find dipper
+ for (NodeData nodeData : childData)
+ {
+ retval = getClosedChild(nodeData, false);
+ if (retval != null)
+ return retval;
+ }
+ return retval;
+ }
+
+ private final LockActionNonTxAware<LockData, String> getLockDataById = new
LockActionNonTxAware<LockData, String>()
+ {
+ public LockData execute(String nodeId) throws LockException
+ {
+ return (LockData)cache.get(nodeId);
+ }
+ };
+
+ protected LockData getLockDataById(String nodeId)
+ {
+ try
+ {
+ return executeLockActionNonTxAware(getLockDataById, nodeId);
+ }
+ catch (LockException e)
+ {
+ // ignore me will never occur
+ }
+ return null;
+ }
+
+ private final LockActionNonTxAware<List<LockData>, Object> getLockList =
+ new LockActionNonTxAware<List<LockData>, Object>()
+ {
+ public List<LockData> execute(Object arg) throws LockException
+ {
+ Collection<Object> datas = cache.values();
+
+ List<LockData> locksData = new ArrayList<LockData>();
+ for (Object lockData : datas)
+ {
+ if (lockData != null)
+ {
+ locksData.add((LockData)lockData);
+ }
+ }
+ return locksData;
+ }
+ };
+
+ protected synchronized List<LockData> getLockList()
+ {
+ try
+ {
+ return executeLockActionNonTxAware(getLockList, null);
+ }
+ catch (LockException e)
+ {
+ // ignore me will never occur
+ }
+ return null;
+ }
+
+ /**
+ * Remove lock, used by Lock remover.
+ *
+ * @param nodeIdentifier String
+ */
+ protected void removeLock(String nodeIdentifier)
+ {
+ try
+ {
+ NodeData nData = (NodeData)dataManager.getItemData(nodeIdentifier);
+
+ //TODO EXOJCR-412, should be refactored in future.
+ //Skip removing, because that node was removed in other node of cluster.
+ if (nData == null)
+ {
+ return;
+ }
+
+ PlainChangesLog changesLog =
+ new PlainChangesLogImpl(new ArrayList<ItemState>(),
SystemIdentity.SYSTEM, ExtendedEvent.UNLOCK);
+
+ ItemData lockOwner =
+ copyItemData((PropertyData)dataManager.getItemData(nData, new
QPathEntry(Constants.JCR_LOCKOWNER, 1)));
+
+ //TODO EXOJCR-412, should be refactored in future.
+ //Skip removing, because that lock was removed in other node of cluster.
+ if (lockOwner == null)
+ {
+ return;
+ }
+
+ changesLog.add(ItemState.createDeletedState(lockOwner));
+
+ ItemData lockIsDeep =
+ copyItemData((PropertyData)dataManager.getItemData(nData, new
QPathEntry(Constants.JCR_LOCKISDEEP, 1)));
+
+ //TODO EXOJCR-412, should be refactored in future.
+ //Skip removing, because that lock was removed in other node of cluster.
+ if (lockIsDeep == null)
+ {
+ return;
+ }
+
+ changesLog.add(ItemState.createDeletedState(lockIsDeep));
+
+ // lock probably removed by other thread
+ if (lockOwner == null && lockIsDeep == null)
+ {
+ return;
+ }
+
+ dataManager.save(new TransactionChangesLog(changesLog));
+ }
+ catch (JCRInvalidItemStateException e)
+ {
+ //TODO EXOJCR-412, should be refactored in future.
+ //Skip property not found in DB, because that lock property was removed in other
node of cluster.
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("The propperty was removed in other node of cluster.",
e);
+ }
+
+ }
+ catch (RepositoryException e)
+ {
+ LOG.error("Error occur during removing lock" +
e.getLocalizedMessage(), e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void closeSessionLockManager(String sessionID)
+ {
+ sessionLockManagers.remove(sessionID);
+ }
+
+ /**
+ * Execute the given action outside a transaction. This is needed since the {@link
Cache} used by {@link CacheableLockManagerImpl}
+ * manages the persistence of its locks thanks to a {@link CacheLoader} and a {@link
CacheLoader} lock the JBoss cache {@link Node}
+ * even for read operations which cause deadlock issue when a XA {@link Transaction}
is already opened
+ * @throws LockException when a exception occurs
+ */
+ private <R, A> R executeLockActionNonTxAware(LockActionNonTxAware<R, A>
action, A arg) throws LockException
+ {
+ Transaction tx = null;
+ try
+ {
+ if (tm != null)
+ {
+ try
+ {
+ tx = tm.suspend();
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Cannot suspend the current transaction", e);
+ }
+ }
+ return action.execute(arg);
+ }
+ finally
+ {
+ if (tx != null)
+ {
+ try
+ {
+ tm.resume(tx);
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Cannot resume the current transaction", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Actions that are not supposed to be called within a transaction
+ *
+ * Created by The eXo Platform SAS
+ * Author : Nicolas Filotto
+ * nicolas.filotto(a)exoplatform.com
+ * 21 janv. 2010
+ */
+ private static interface LockActionNonTxAware<R, A>
+ {
+ R execute(A arg) throws LockException;
+ }
+
+}
Added:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/InfinispanCacheFactory.java
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/InfinispanCacheFactory.java
(rev 0)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/InfinispanCacheFactory.java 2010-07-20
09:21:29 UTC (rev 2801)
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2010 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.infinispan;
+
+import org.exoplatform.container.configuration.ConfigurationManager;
+import org.exoplatform.services.jcr.config.MappedParametrizedObjectEntry;
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.config.TemplateConfigurationHelper;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.infinispan.Cache;
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.manager.EmbeddedCacheManager;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.transaction.TransactionManager;
+
+/**
+ * Factory that creates pre-configured instances of Infinispan, without starting it.
+ * Path to Infinispan configuration or template should be provided as
+ * "infinispan-configuration" property in parameterEntry instance. If
+ * transaction manager is configure in InfinispanCacheFactory, then it
+ * is injected into the cache instance.
+ * <br>
+ * If parameterEntry has "jgroups-multiplexer-stack" (=true) and
+ * "jgroups-configuration" parameters then Multiplexing stack is enabled
+ * in JBossCache (this is highly recommended by RH specialists).
+ *
+ * @author <a href="mailto:nikolazius@gmail.com">Nikolay
Zamosenchuk</a>
+ * @version $Id: ExoCacheFactoryImpl.java 34360 2009-07-22 23:58:59Z nzamosenchuk $
+ *
+ */
+public class InfinispanCacheFactory<K, V>
+{
+
+ public static final String INFINISPAN_CONFIG = "infinispan-configuration";
+
+ public static final String INFINISPAN_CACHE_NAME = "infinispan-cache-name";
+
+ public static final String JGROUPS_CONFIG = "jgroups-configuration";
+
+ public static final String JGROUPS_MUX_ENABLED =
"jgroups-multiplexer-stack";
+
+ private final TemplateConfigurationHelper configurationHelper;
+
+ private final TransactionManager transactionManager;
+
+ private ConfigurationManager configurationManager;
+
+ private final Log log =
ExoLogger.getLogger("exo.jcr.component.core.InfinispanCacheFactory");
+
+ /**
+ * Creates InfinispanCacheFactory with provided configuration transaction managers.
+ * Transaction manager will later be injected to cache instance.
+ *
+ * @param configurationManager
+ * @param transactionManager
+ */
+ public InfinispanCacheFactory(ConfigurationManager configurationManager,
TransactionManager transactionManager)
+ {
+ this.configurationManager = configurationManager;
+ this.configurationHelper =
TemplateConfigurationHelper.createJBossCacheHelper(configurationManager);
+ this.transactionManager = transactionManager;
+ }
+
+ /**
+ * Creates InfinispanCacheFactory with provided configuration manager and without
transaction manager.
+ *
+ * @param configurationManager
+ */
+ public InfinispanCacheFactory(ConfigurationManager configurationManager)
+ {
+ this(configurationManager, null);
+ }
+
+ /**
+ * Creates pre-configured instance of Infinispan, without starting it.
+ * Path to Infinispan configuration or template should be provided as
+ * "jbosscache-configuration" property in parameterEntry instance. If
+ * transaction manager is configure in ExoJBossCacheFactory, then it
+ * is injected into the cache instance.
+ * <br>
+ * If parameterEntry has "jgroups-multiplexer-stack" (=true) and
+ * "jgroups-configuration" parameters then Multiplexing stack is enabled
+ * in JBossCache (this is highly recommended by RH specialists).
+ *
+ * @param parameterEntry
+ * @return
+ * @throws RepositoryConfigurationException
+ */
+ public Cache<K, V> createCache(MappedParametrizedObjectEntry parameterEntry)
throws RepositoryConfigurationException
+ {
+ // get Infinispan configuration file path and cache name
+ final String configurationPath =
parameterEntry.getParameterValue(INFINISPAN_CONFIG);
+ final String cacheName = parameterEntry.getParameterValue(INFINISPAN_CACHE_NAME);
+ log.info("Infinispan Cache configuration used: " + configurationPath +
" cache name: " + cacheName);
+
+ // prepare configuration
+ InputStream configStream;
+ try
+ {
+ // fill template
+ configStream = configurationHelper.fillTemplate(configurationPath,
parameterEntry.getParameters());
+ }
+ catch (IOException e)
+ {
+ throw new RepositoryConfigurationException(e);
+ }
+
+ // create cache
+ final EmbeddedCacheManager manager;
+ try
+ {
+ manager = new DefaultCacheManager(configStream);
+ }
+ catch (IOException e)
+ {
+ throw new RepositoryConfigurationException(e);
+ }
+
+ PrivilegedAction<Cache<K, V>> action = new
PrivilegedAction<Cache<K, V>>()
+ {
+ public Cache<K, V> run()
+ {
+ return manager.getCache(cacheName);
+ }
+ };
+ Cache<K, V> cache = AccessController.doPrivileged(action);
+
+ // inject transaction manager if defined
+ // if (transactionManager != null)
+ // {
+ //
cache.getConfiguration().getRuntimeConfig().setTransactionManager(transactionManager);
+ // }
+
+ // JGroups multiplexer configuration if enabled
+ // if (parameterEntry.getParameterBoolean(JGROUPS_MUX_ENABLED, false))
+ // {
+ // try
+ // {
+ // // Get path to JGroups configuration
+ // String jgroupsConfigurationFilePath =
parameterEntry.getParameterValue(JGROUPS_CONFIG);
+ // if (jgroupsConfigurationFilePath != null)
+ // {
+ // // Create and inject multiplexer factory
+ // JChannelFactory muxFactory = new JChannelFactory();
+ //
muxFactory.setMultiplexerConfig(configurationManager.getResource(jgroupsConfigurationFilePath));
+ //
cache.getConfiguration().getRuntimeConfig().setMuxChannelFactory(muxFactory);
+ // log.info("Multiplexer stack successfully enabled for the
cache.");
+ // }
+ // }
+ // catch (Exception e)
+ // {
+ // // exception occurred setting mux factory
+ // e.printStackTrace();
+ // throw new RepositoryConfigurationException("Error setting
multiplexer configuration.", e);
+ // }
+ // }
+ // else
+ // {
+ // // Multiplexer is not enabled. If jGroups configuration preset it is
applied
+ // String jgroupsConfigurationFilePath =
parameterEntry.getParameterValue(JGROUPS_CONFIG, null);
+ // if (jgroupsConfigurationFilePath != null)
+ // {
+ // try
+ // {
+ // cache.getConfiguration().setJgroupsConfigFile(
+ //
configurationManager.getResource(jgroupsConfigurationFilePath));
+ // log.info("Custom JGroups configuration set:"
+ // +
configurationManager.getResource(jgroupsConfigurationFilePath));
+ // }
+ // catch (Exception e)
+ // {
+ // throw new RepositoryConfigurationException("Error setting
JGroups configuration.", e);
+ // }
+ // }
+ // }
+ return cache;
+ }
+}
Deleted:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan-lock.xml
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan-lock.xml 2010-07-20
08:15:54 UTC (rev 2800)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan-lock.xml 2010-07-20
09:21:29 UTC (rev 2801)
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<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">
-
- <default>
- <loaders passivation="false" shared="true"
preload="true">
- <loader
class="org.infinispan.loaders.jdbc.stringbased.JdbcStringBasedCacheStore"
fetchPersistentState="false" ignoreModifications="false"
purgeOnStartup="false">
- <properties>
- <property name="stringsTableNamePrefix"
value="${infinispan-cl-cache.jdbc.table.name}"/>
- <property name="idColumnName"
value="${infinispan-cl-cache.jdbc.id.column}"/>
- <property name="dataColumnName"
value="${infinispan-cl-cache.jdbc.data.column}"/>
- <property name="timestampColumnName"
value="${infinispan-cl-cache.jdbc.timestamp.column}"/>
- <property name="idColumnType"
value="${infinispan-cl-cache.jdbc.id.type}"/>
- <property name="dataColumnType"
value="${infinispan-cl-cache.jdbc.data.type}"/>
- <property name="timestampColumnType"
value="${infinispan-cl-cache.jdbc.timestamp.type}"/>
- <property name="dropTableOnExit"
value="${infinispan-cl-cache.jdbc.table.drop}"/>
- <property name="createTableOnStart"
value="${infinispan-cl-cache.jdbc.table.create}"/>
- <property name="connectionFactoryClass"
value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory"/>
- <property name="datasourceJndiLocation"
value="${infinispan-cl-cache.jdbc.datasource}"/>
- </properties>
- <async enabled="false"/>
- </loader>
- </loaders>
- </default>
-</infinispan>
Added:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan.xml
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan.xml
(rev 0)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan.xml 2010-07-20
09:21:29 UTC (rev 2801)
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <namedCache name="lockCache">
+ <loaders passivation="false" shared="true"
preload="true">
+ <loader
class="org.infinispan.loaders.jdbc.stringbased.JdbcStringBasedCacheStore"
fetchPersistentState="false" ignoreModifications="false"
purgeOnStartup="false">
+ <properties>
+ <property name="stringsTableNamePrefix"
value="${infinispan-cl-cache.jdbc.table.name}"/>
+ <property name="idColumnName"
value="${infinispan-cl-cache.jdbc.id.column}"/>
+ <property name="dataColumnName"
value="${infinispan-cl-cache.jdbc.data.column}"/>
+ <property name="timestampColumnName"
value="${infinispan-cl-cache.jdbc.timestamp.column}"/>
+ <property name="idColumnType"
value="${infinispan-cl-cache.jdbc.id.type}"/>
+ <property name="dataColumnType"
value="${infinispan-cl-cache.jdbc.data.type}"/>
+ <property name="timestampColumnType"
value="${infinispan-cl-cache.jdbc.timestamp.type}"/>
+ <property name="dropTableOnExit"
value="${infinispan-cl-cache.jdbc.table.drop}"/>
+ <property name="createTableOnStart"
value="${infinispan-cl-cache.jdbc.table.create}"/>
+ <property name="connectionFactoryClass"
value="${infinispan-cl-cache.jdbc.connectionFactory}"/>
+ <property name="datasourceJndiLocation"
value="${infinispan-cl-cache.jdbc.datasource}"/>
+ </properties>
+ <async enabled="false"/>
+ </loader>
+ </loaders>
+ </namedCache>
+</infinispan>
Modified:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/test/resources/conf/standalone/test-jcr-config.xml
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/test/resources/conf/standalone/test-jcr-config.xml 2010-07-20
08:15:54 UTC (rev 2800)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/test/resources/conf/standalone/test-jcr-config.xml 2010-07-20
09:21:29 UTC (rev 2801)
@@ -81,14 +81,16 @@
<lock-manager
class="org.exoplatform.services.jcr.impl.core.lock.infinispan.InfinispanLockManagerImpl">
<properties>
<property name="time-out" value="15m" />
- <property name="infinispan-configuration"
value="conf/standalone/test-infinispan-lock.xml" />
+ <property name="infinispan-configuration"
value="conf/standalone/test-infinispan.xml" />
+ <property name="infinispan-cache-name"
value="lockCache" />
<property name="infinispan-cl-cache.jdbc.table.name"
value="jcrlocks_db1_ws" />
<property name="infinispan-cl-cache.jdbc.table.create"
value="true" />
<property name="infinispan-cl-cache.jdbc.table.drop"
value="false" />
<property name="infinispan-cl-cache.jdbc.id.column"
value="id" />
<property name="infinispan-cl-cache.jdbc.data.column"
value="data" />
- <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="time_stamp"
/>
+ <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp"
/>
<property name="infinispan-cl-cache.jdbc.datasource"
value="jdbcjcr" />
+ <property
name="infinispan-cl-cache.jdbc.connectionFactory"
value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory"
/>
</properties>
</lock-manager>
</workspace>
@@ -133,14 +135,16 @@
<lock-manager
class="org.exoplatform.services.jcr.impl.core.lock.infinispan.InfinispanLockManagerImpl">
<properties>
<property name="time-out" value="15m" />
- <property name="infinispan-configuration"
value="conf/standalone/test-infinispan-lock.xml" />
+ <property name="infinispan-configuration"
value="conf/standalone/test-infinispan.xml" />
+ <property name="infinispan-cache-name"
value="lockCache" />
<property name="infinispan-cl-cache.jdbc.table.name"
value="jcrlocks_db1_ws1" />
<property name="infinispan-cl-cache.jdbc.table.create"
value="true" />
<property name="infinispan-cl-cache.jdbc.table.drop"
value="false" />
<property name="infinispan-cl-cache.jdbc.id.column"
value="id" />
<property name="infinispan-cl-cache.jdbc.data.column"
value="data" />
- <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="time_stamp"
/>
- <property name="infinispan-cl-cache.jdbc.datasource"
value="jdbcjcr1" />
+ <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp"
/>
+ <property name="infinispan-cl-cache.jdbc.datasource"
value="jdbcjcr1" />
+ <property
name="infinispan-cl-cache.jdbc.connectionFactory"
value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory"
/>
</properties>
</lock-manager>
</workspace>
@@ -185,14 +189,16 @@
<lock-manager
class="org.exoplatform.services.jcr.impl.core.lock.infinispan.InfinispanLockManagerImpl">
<properties>
<property name="time-out" value="15m" />
- <property name="infinispan-configuration"
value="conf/standalone/test-infinispan-lock.xml" />
+ <property name="infinispan-configuration"
value="conf/standalone/test-infinispan.xml" />
+ <property name="infinispan-cache-name"
value="lockCache" />
<property name="infinispan-cl-cache.jdbc.table.name"
value="jcrlocks_db1_ws2" />
<property name="infinispan-cl-cache.jdbc.table.create"
value="true" />
<property name="infinispan-cl-cache.jdbc.table.drop"
value="false" />
<property name="infinispan-cl-cache.jdbc.id.column"
value="id" />
<property name="infinispan-cl-cache.jdbc.data.column"
value="data" />
- <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="time_stamp"
/>
+ <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp"
/>
<property name="infinispan-cl-cache.jdbc.datasource"
value="jdbcjcr2" />
+ <property
name="infinispan-cl-cache.jdbc.connectionFactory"
value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory"
/>
</properties>
</lock-manager>
</workspace>
@@ -266,14 +272,16 @@
<lock-manager
class="org.exoplatform.services.jcr.impl.core.lock.infinispan.InfinispanLockManagerImpl">
<properties>
<property name="time-out" value="15m" />
- <property name="infinispan-configuration"
value="conf/standalone/test-infinispan-lock.xml" />
+ <property name="infinispan-configuration"
value="conf/standalone/test-infinispan.xml" />
+ <property name="infinispan-cache-name"
value="lockCache" />
<property name="infinispan-cl-cache.jdbc.table.name"
value="jcrlocks_db1_ws3" />
<property name="infinispan-cl-cache.jdbc.table.create"
value="true" />
<property name="infinispan-cl-cache.jdbc.table.drop"
value="false" />
<property name="infinispan-cl-cache.jdbc.id.column"
value="id" />
<property name="infinispan-cl-cache.jdbc.data.column"
value="data" />
- <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="time_stamp"
/>
+ <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp"
/>
<property name="infinispan-cl-cache.jdbc.datasource"
value="jdbcjcr3" />
+ <property
name="infinispan-cl-cache.jdbc.connectionFactory"
value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory"
/>
</properties>
</lock-manager>
</workspace>
@@ -335,14 +343,16 @@
<lock-manager
class="org.exoplatform.services.jcr.impl.core.lock.infinispan.InfinispanLockManagerImpl">
<properties>
<property name="time-out" value="15m" />
- <property name="infinispan-configuration"
value="conf/standalone/test-infinispan-lock.xml" />
+ <property name="infinispan-configuration"
value="conf/standalone/test-infinispan.xml" />
+ <property name="infinispan-cache-name"
value="lockCache" />
<property name="infinispan-cl-cache.jdbc.table.name"
value="jcrlocks_db1tck_ws" />
<property name="infinispan-cl-cache.jdbc.table.create"
value="true" />
<property name="infinispan-cl-cache.jdbc.table.drop"
value="false" />
<property name="infinispan-cl-cache.jdbc.id.column"
value="id" />
<property name="infinispan-cl-cache.jdbc.data.column"
value="data" />
- <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="time_stamp"
/>
+ <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp"
/>
<property name="infinispan-cl-cache.jdbc.datasource"
value="jdbcjcrtck" />
+ <property
name="infinispan-cl-cache.jdbc.connectionFactory"
value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory"
/>
</properties>
</lock-manager>
</workspace>
@@ -393,14 +403,16 @@
<lock-manager
class="org.exoplatform.services.jcr.impl.core.lock.infinispan.InfinispanLockManagerImpl">
<properties>
<property name="time-out" value="15m" />
- <property name="infinispan-configuration"
value="conf/standalone/test-infinispan-lock.xml" />
+ <property name="infinispan-configuration"
value="conf/standalone/test-infinispan.xml" />
+ <property name="infinispan-cache-name"
value="lockCache" />
<property name="infinispan-cl-cache.jdbc.table.name"
value="jcrlocks_db1tck_ws1" />
<property name="infinispan-cl-cache.jdbc.table.create"
value="true" />
<property name="infinispan-cl-cache.jdbc.table.drop"
value="false" />
<property name="infinispan-cl-cache.jdbc.id.column"
value="id" />
<property name="infinispan-cl-cache.jdbc.data.column"
value="data" />
- <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="time_stamp"
/>
+ <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp"
/>
<property name="infinispan-cl-cache.jdbc.datasource"
value="jdbcjcr1tck" />
+ <property
name="infinispan-cl-cache.jdbc.connectionFactory"
value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory"
/>
</properties>
</lock-manager>
</workspace>
@@ -454,14 +466,16 @@
<lock-manager
class="org.exoplatform.services.jcr.impl.core.lock.infinispan.InfinispanLockManagerImpl">
<properties>
<property name="time-out" value="15m" />
- <property name="infinispan-configuration"
value="conf/standalone/test-infinispan-lock.xml" />
+ <property name="infinispan-configuration"
value="conf/standalone/test-infinispan.xml" />
+ <property name="infinispan-cache-name"
value="lockCache" />
<property name="infinispan-cl-cache.jdbc.table.name"
value="jcrlocks_db1tck_ws2" />
<property name="infinispan-cl-cache.jdbc.table.create"
value="true" />
<property name="infinispan-cl-cache.jdbc.table.drop"
value="false" />
<property name="infinispan-cl-cache.jdbc.id.column"
value="id" />
<property name="infinispan-cl-cache.jdbc.data.column"
value="data" />
- <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="time_stamp"
/>
+ <property
name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp"
/>
<property name="infinispan-cl-cache.jdbc.datasource"
value="jdbcjcr2tck" />
+ <property
name="infinispan-cl-cache.jdbc.connectionFactory"
value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory"
/>
</properties>
</lock-manager>
</workspace>