[exo-jcr-commits] exo-jcr SVN: r1403 - jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cache.
do-not-reply at jboss.org
do-not-reply at jboss.org
Fri Jan 15 05:55:26 EST 2010
Author: sergiykarpenko
Date: 2010-01-15 05:55:25 -0500 (Fri, 15 Jan 2010)
New Revision: 1403
Modified:
jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cache/CacheableLockManager.java
Log:
EXOJCR-332: CacheableLockManager remake
Modified: jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cache/CacheableLockManager.java
===================================================================
--- jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cache/CacheableLockManager.java 2010-01-15 10:17:28 UTC (rev 1402)
+++ jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cache/CacheableLockManager.java 2010-01-15 10:55:25 UTC (rev 1403)
@@ -58,6 +58,9 @@
import org.jboss.cache.Node;
import java.io.Serializable;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -111,10 +114,6 @@
public static final String LOCK_DATA = "$LOCK_DATA";
- public static final String LOCKED_NODE_ID = "$NODE_ID";
-
- public static final String TOKENS = "$TOKENS";
-
public static final String LOCKS = "$LOCKS";
/**
@@ -123,11 +122,6 @@
private final Log log = ExoLogger.getLogger("jcr.lock.LockManager");
/**
- * Map NodeIdentifier -- lockData
- */
- //private final Map<String, LockData> locks;
-
- /**
* Data manager.
*/
private final DataManager dataManager;
@@ -138,21 +132,11 @@
private final Map<String, LockData> pendingLocks;
/**
- * Map lockToken --lockData
+ * [session id , [lock tokens id..]]
*/
- //private final Map<String, LockData> tokensMap;
-
- /**
- * [session id , [lock tokens ids..]]
- */
private final Map<String, Set<String>> lockTokenHolders;
/**
- * Pending token maps. [lock tokens, node id]
- */
- private final Map<String, String> pendingLockTokens;
-
- /**
* Run time lock time out.
*/
private long lockTimeOut;
@@ -162,17 +146,10 @@
*/
private LockRemover lockRemover;
- /**
- * Lock persister instance.
- */
- //private final LockPersister persister;
-
private BufferedJBossCache cache;
private Node<Serializable, Object> lockRoot;
- private Node<Serializable, Object> tokenRoot;
-
/**
* Constructor for workspace without LockPersister
*
@@ -190,7 +167,6 @@
{
super(dataManager, config, null);
this.dataManager = dataManager;
- //this.persister = persister;
if (config.getLockManager() != null)
{
lockTimeOut =
@@ -200,24 +176,17 @@
lockTimeOut = DEFAULT_LOCK_TIMEOUT;
lockTokenHolders = new HashMap<String, Set<String>>();
- pendingLockTokens = new HashMap<String, String>();
pendingLocks = new HashMap<String, LockData>();
- //locks = new HashMap<String, LockData>();
- //tokensMap = new HashMap<String, LockData>();
+ // dataManager.addItemPersistenceListener(this);
- dataManager.addItemPersistenceListener(this);
-
- CacheFactory<Serializable, Object> factory = new DefaultCacheFactory<Serializable, Object>();
- cache = new BufferedJBossCache(factory.createCache(readJBCConfig(config), false));
- cache.create();
- }
-
- protected static String readJBCConfig(final WorkspaceEntry wsConfig) throws RepositoryConfigurationException
- {
- if (wsConfig.getLockManager() != null)
+ // make cache
+ if (config.getLockManager() != null && config.getLockManager().getCacheConfig() != null)
{
- return wsConfig.getLockManager().getCacheConfig();
+ String pathToConfig = config.getLockManager().getCacheConfig();
+ CacheFactory<Serializable, Object> factory = new DefaultCacheFactory<Serializable, Object>();
+ cache = new BufferedJBossCache(factory.createCache(pathToConfig, false));
+ cache.create();
}
else
{
@@ -233,22 +202,9 @@
*/
public synchronized void addLockToken(String sessionId, String lt)
{
- //LockData currLock = tokensMap.get(lt);
- if (pendingLockTokens.get(lt) != null || tokenRoot.hasChild(Fqn.fromString(lt)))
- {
- holdLockToken(sessionId, lt);
- }
+ holdLockToken(sessionId, lt);
}
- private void holdLockToken(String sessionId, String lt)
- {
- if (lockTokenHolders.get(sessionId) == null)
- {
- lockTokenHolders.put(sessionId, new HashSet<String>());
- }
- lockTokenHolders.get(sessionId).add(lt);
- }
-
/*
* (non-Javadoc)
* @see
@@ -281,18 +237,20 @@
new LockData(node.getInternalIdentifier(), lockToken, isDeep, isSessionScoped, node.getSession().getUserID(),
timeOut > 0 ? timeOut : lockTimeOut);
- //lData.addLockHolder(node.getSession().getId());
-
holdLockToken(node.getSession().getId(), lockToken);
-
pendingLocks.put(node.getInternalIdentifier(), lData);
- pendingLockTokens.put(lockToken, node.getInternalIdentifier());
- //tokensMap.put(lockToken, lData);
LockImpl lock = new CacheLockImpl(node.getSession(), lData, this);
return lock;
}
+ @Managed
+ @ManagedDescription("Remove the expired locks")
+ public void cleanExpiredLocks()
+ {
+ removeExpired();
+ }
+
/*
* (non-Javadoc)
* @see
@@ -331,6 +289,13 @@
}
}
+ @Managed
+ @ManagedDescription("The number of active locks")
+ public int getNumLocks()
+ {
+ return lockRoot.getChildrenNames().size();
+ }
+
/*
* (non-Javadoc)
* @see
@@ -371,14 +336,12 @@
return lData != null && isLockHolder(node.getSession().getId(), lData.getToken());
}
- private boolean isLockHolder(String sessionId, String lockToken)
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isTXAware()
{
- Set<String> lockTokens = lockTokenHolders.get(sessionId);
- if (lockTokens != null)
- {
- return lockTokens.contains(lockToken);
- }
- return false;
+ return true;
}
/*
@@ -389,67 +352,56 @@
*/
public synchronized void onCloseSession(ExtendedSession session)
{
- // List<String> deadLocksList = new ArrayList<String>();
SessionImpl sessionImpl = (SessionImpl)session;
- if (lockTokenHolders.containsKey(session.getId()))
+ for (LockData lockData : getLockList())
{
- Set<String> lockTokens = lockTokenHolders.get(session.getId());
-
- for (String token : lockTokens)
+ //TODO check is live or remove it
+ //if (lockData.isLive())
+ //{
+ // check is lock holder
+ if (lockTokenHolders.containsKey(session.getId())
+ && lockTokenHolders.get(session.getId()).contains(lockData.getToken()))
{
- String nodeId = null;
- if (pendingLockTokens.containsKey(token))
+ if (lockData.isSessionScoped())
{
- nodeId = pendingLockTokens.get(token);
- }
- if (tokenRoot.hasChild(Fqn.fromString(token)))
- {
- nodeId = (String)tokenRoot.getData().get(LOCKED_NODE_ID);
- }
-
- if (nodeId != null)
- {
- LockData lockData = this.getLockDataById(nodeId);
-
- if (lockData.isSessionScoped())
+ // if no session currently holds lock except this
+ try
{
- // unlock node
- try
- {
- // TODO it's possible to have next error
- // java.lang.NullPointerException
- // at
- // org.exoplatform.services.jcr.impl.core.lock.LockManagerImpl.onCloseSession(LockManagerImpl.java:312)
- // at org.exoplatform.services.jcr.impl.core.SessionImpl.logout(SessionImpl.java:794)
- // at
- // org.exoplatform.services.jcr.impl.core.XASessionImpl.logout(XASessionImpl.java:254)
- // at
- // org.exoplatform.services.jcr.impl.core.SessionRegistry$SessionCleaner.callPeriodically(SessionRegistry.java:165)
- // at
- // org.exoplatform.services.jcr.impl.proccess.WorkerThread.run(WorkerThread.java:46)
- ((NodeImpl)sessionImpl.getTransientNodesManager().getItemByIdentifier(nodeId, false)).unlock();
- }
- catch (UnsupportedRepositoryOperationException e)
- {
- log.error(e.getLocalizedMessage());
- }
- catch (LockException e)
- {
- log.error(e.getLocalizedMessage());
- }
- catch (AccessDeniedException e)
- {
- log.error(e.getLocalizedMessage());
- }
- catch (RepositoryException e)
- {
- log.error(e.getLocalizedMessage());
- }
+ ((NodeImpl)sessionImpl.getTransientNodesManager().getItemByIdentifier(lockData.getNodeIdentifier(),
+ false)).unlock();
}
+ catch (UnsupportedRepositoryOperationException e)
+ {
+ log.error(e.getLocalizedMessage());
+ }
+ catch (LockException e)
+ {
+ log.error(e.getLocalizedMessage());
+ }
+ catch (AccessDeniedException e)
+ {
+ log.error(e.getLocalizedMessage());
+ }
+ catch (RepositoryException e)
+ {
+ log.error(e.getLocalizedMessage());
+ }
+
}
+ else
+ {
+ this.removeLockToken(session.getId(), lockData.getToken());
+ }
}
+ //TODO
+ // }
+ // else
+ // {
+ // entries.remove();
+ // }
}
+
}
/*
@@ -504,27 +456,6 @@
else
{
throw new LockException("Lock must exist in pending locks.");
-
- // log.warn("No lock in pendingLocks for identifier " + nodeIdentifier
- // + " Probably lock come from replication.");
- //
- // String lockToken = IdGenerator.generate();
- // ItemState ownerState = getItemState(currChangesLog, Constants.JCR_LOCKOWNER);
- // ItemState isDeepState = getItemState(currChangesLog, Constants.JCR_LOCKISDEEP);
- // if (ownerState != null && isDeepState != null)
- // {
- //
- // String owner =
- // new String(((((TransientPropertyData)(ownerState.getData())).getValues()).get(0))
- // .getAsByteArray(), Constants.DEFAULT_ENCODING);
- //
- // boolean isDeep =
- // Boolean.valueOf(
- // new String(((((TransientPropertyData)(isDeepState.getData())).getValues()).get(0))
- // .getAsByteArray(), Constants.DEFAULT_ENCODING)).booleanValue();
- //
- // createRemoteLock(currChangesLog.getSessionId(), nodeIdentifier, lockToken, isDeep, false, owner);
- // }
}
break;
case ExtendedEvent.UNLOCK :
@@ -567,71 +498,38 @@
{
log.error(e.getLocalizedMessage(), e);
}
- // catch (UnsupportedEncodingException e)
- // {
- // log.error(e.getLocalizedMessage(), e);
- // }
catch (IllegalStateException e)
{
log.error(e.getLocalizedMessage(), e);
}
- // catch (IOException e)
- // {
- // log.error(e.getLocalizedMessage(), e);
- // }
}
}
- private boolean lockExist(String nodeId)
- {
- return lockRoot.hasChild(Fqn.fromString(nodeId));
- }
-
- /*
- * (non-Javadoc)
- * @see
- * org.exoplatform.services.jcr.impl.core.lock.LockManager#lockTokenRemoved(org.exoplatform.services
- * .jcr.impl.core.SessionImpl, java.lang.String)
+ /**
+ * Refreshed lock data in cache
+ *
+ * @param newLockData
*/
- public synchronized void removeLockToken(String sessionId, String lt)
+ public void refresh(LockData newLockData) throws LockException
{
- if (lockTokenHolders.containsKey(sessionId) && lockTokenHolders.get(sessionId).contains(lt))
+ //first look pending locks
+ if (pendingLocks.containsKey(newLockData.getNodeIdentifier()))
{
- lockTokenHolders.get(sessionId).remove(lt);
+ pendingLocks.put(newLockData.getNodeIdentifier(), newLockData);
}
- }
-
- /*
- * (non-Javadoc)
- * @see org.picocontainer.Startable#start()
- */
- public void start()
- {
- cache.start();
- tokenRoot = cache.getRoot().addChild(Fqn.fromString(TOKENS));
- lockRoot = cache.getRoot().addChild(Fqn.fromString(LOCKS));
- lockRemover = new LockRemover(this);
- }
-
- // Quick method. We need to reconstruct
- // TODO was synchronized
- protected List<LockData> getLockList()
- {
- Set<Node<Serializable, Object>> lockSet = lockRoot.getChildren();
-
- List<LockData> locksData = new ArrayList<LockData>();
- for (Node<Serializable, Object> node : lockSet)
+ else
{
- if (node != null)
+ Fqn<String> id = Fqn.fromString(newLockData.getNodeIdentifier());
+ if (lockRoot.hasChild(id))
{
- LockData lockData = (LockData)node.get(LOCK_DATA);
- if (lockData != null)
- {
- locksData.add(lockData);
- }
+ lockRoot.addChild(id);
}
+ else
+ {
+ throw new LockException("Can't refresh lock for node " + newLockData.getNodeIdentifier()
+ + " since lock is not exist");
+ }
}
- return locksData;
}
/**
@@ -657,17 +555,41 @@
/*
* (non-Javadoc)
+ * @see
+ * org.exoplatform.services.jcr.impl.core.lock.LockManager#lockTokenRemoved(org.exoplatform.services
+ * .jcr.impl.core.SessionImpl, java.lang.String)
+ */
+ public synchronized void removeLockToken(String sessionId, String lt)
+ {
+ if (lockTokenHolders.containsKey(sessionId) && lockTokenHolders.get(sessionId).contains(lt))
+ {
+ lockTokenHolders.get(sessionId).remove(lt);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.picocontainer.Startable#start()
+ */
+ public void start()
+ {
+ cache.start();
+ //tokenRoot = cache.getRoot().addChild(Fqn.fromString(TOKENS));
+ lockRoot = cache.getRoot().addChild(Fqn.fromString(LOCKS));
+ lockRemover = new LockRemover(this);
+ }
+
+ /*
+ * (non-Javadoc)
* @see org.picocontainer.Startable#stop()
*/
public void stop()
{
-
lockRemover.halt();
lockRemover.interrupt();
- //locks.clear();
+
pendingLocks.clear();
- pendingLockTokens.clear();
- //tokensMap.clear();
+
cache.stop();
}
@@ -694,6 +616,28 @@
}
/**
+ * Calculates md5 hash of string.
+ *
+ * @param token
+ * @return
+ */
+ private String getHash(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;
+ }
+
+ /**
* Search item with name <code>itemName<code> in changesLog
*
* @param changesLog
@@ -774,15 +718,13 @@
return retval;
}
- protected LockData getLockDataById(String nodeId)
+ private void holdLockToken(String sessionId, String lt)
{
- LockData lockData = null;
- Node<Serializable, Object> node = lockRoot.getChild(Fqn.fromString(nodeId));
- if (node != null)
+ if (lockTokenHolders.get(sessionId) == null)
{
- lockData = (LockData)node.get(LOCK_DATA);
+ lockTokenHolders.put(sessionId, new HashSet<String>());
}
- return lockData;
+ lockTokenHolders.get(sessionId).add(lt);
}
/**
@@ -793,89 +735,31 @@
*/
private synchronized void internalLock(String nodeIdentifier) throws LockException
{
- // LockData ldata = pendingLocks.get(nodeIdentifier);
- // if (ldata != null)
- // {
- // locks.put(nodeIdentifier, ldata);
- //
- // if (persister != null)
- // {
- // persister.add(ldata);
- // }
- // pendingLocks.remove(nodeIdentifier);
- // }
- // else
- // {
- // throw new LockException("No lock in pending locks");
- // }
-
LockData lockData = pendingLocks.get(nodeIdentifier);
-
- if (lockData == null)
+ if (lockData != null)
{
- //TODO remove me
- throw new LockException("Lock data to write can't be null!");
- }
- // addChild will add if absent or return old if present
- Node<Serializable, Object> node = lockRoot.addChild(Fqn.fromString(lockData.getNodeIdentifier()));
-
- // this will prevent from deleting by eviction.
- node.setResident(true);
-
- // this will return null if success. And old data if something exists...
- LockData oldLockData = (LockData)node.putIfAbsent(LOCK_DATA, lockData);
- // if oldLockData is present (not null):
- // 1. this is Lock.refresh(): oldLockData and lockData will have the same tokens
- // 2. this node is already locked: data-s will have different tokens
-
- if (oldLockData != null)
- {
- // if LockData already present with different lock token, then node has already been locked!
- if (!oldLockData.getToken().equals(lockData.getToken()))
+ Fqn<String> lockPath = Fqn.fromString(lockData.getNodeIdentifier());
+ if (lockRoot.hasChild(lockPath))
{
throw new LockException("Unable to write LockData. Node [" + lockData.getNodeIdentifier()
+ "] already has LockData!");
}
- else
- {
- // token is the same, then Lock is just refreshed. Putting new LockData.
- if (!node.replace(LOCK_DATA, oldLockData, lockData))
- {
- throw new LockException("Unable to re-write LockData. Possibly LockData for the Node["
- + lockData.getNodeIdentifier() + "] has just been changed!");
- }
- }
- }
- }
- /**
- * Internal unlock.
- *
- * @param sessionId
- * @param nodeIdentifier
- * @throws LockException
- */
- private synchronized void internalUnLock(String sessionId, String nodeIdentifier) throws LockException
- {
- LockData lData = getLockDataById(nodeIdentifier);
+ // addChild will add if absent or return old if present
+ Node<Serializable, Object> node = lockRoot.addChild(lockPath);
- if (lData != null)
- {
- //tokensMap.remove(lData.getLockToken(sessionId));
+ // this will prevent from deleting by eviction.
+ node.setResident(true);
- tokenRoot.removeChild(Fqn.fromString(lData.getToken()));
- lockRoot.removeChild(Fqn.fromString(nodeIdentifier));
+ // this will return null if success. And old data if something exists...
+ node.putIfAbsent(LOCK_DATA, lockData);
- // remove session holder
- if (lockTokenHolders.containsKey(sessionId))
- {
- lockTokenHolders.get(sessionId).remove(lData.getToken());
- if (lockTokenHolders.get(sessionId).size() == 0)
- {
- lockTokenHolders.remove(sessionId);
- }
- }
+ pendingLocks.remove(nodeIdentifier);
}
+ else
+ {
+ throw new LockException("No lock in pending locks");
+ }
}
/**
@@ -907,6 +791,81 @@
// }
/**
+ * 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)
+ {
+ //tokenRoot.removeChild(Fqn.fromString(lData.getToken()));
+ lockRoot.removeChild(Fqn.fromString(nodeIdentifier));
+
+ // remove session holder
+ if (lockTokenHolders.containsKey(sessionId))
+ {
+ lockTokenHolders.get(sessionId).remove(lData.getToken());
+ if (lockTokenHolders.get(sessionId).size() == 0)
+ {
+ lockTokenHolders.remove(sessionId);
+ }
+ }
+ }
+ }
+
+ private boolean isLockHolder(String sessionId, String lockToken)
+ {
+ Set<String> lockTokens = lockTokenHolders.get(sessionId);
+ if (lockTokens != null)
+ {
+ return lockTokens.contains(lockToken);
+ }
+ return false;
+ }
+
+ private boolean lockExist(String nodeId)
+ {
+ return lockRoot.hasChild(Fqn.fromString(nodeId));
+ }
+
+ protected LockData getLockDataById(String nodeId)
+ {
+ LockData lockData = null;
+ Node<Serializable, Object> node = lockRoot.getChild(Fqn.fromString(nodeId));
+ if (node != null)
+ {
+ lockData = (LockData)node.get(LOCK_DATA);
+ }
+ return lockData;
+ }
+
+ // Quick method. We need to reconstruct
+ // TODO was synchronized
+ protected List<LockData> getLockList()
+ {
+ Set<Node<Serializable, Object>> lockSet = lockRoot.getChildren();
+
+ List<LockData> locksData = new ArrayList<LockData>();
+ for (Node<Serializable, Object> node : lockSet)
+ {
+ if (node != null)
+ {
+ LockData lockData = (LockData)node.get(LOCK_DATA);
+ if (lockData != null)
+ {
+ locksData.add(lockData);
+ }
+ }
+ }
+ return locksData;
+ }
+
+ /**
* Remove lock, used by Lock remover.
*
* @param nodeIdentifier String
@@ -940,52 +899,4 @@
}
}
- @Managed
- @ManagedDescription("The number of active locks")
- public int getNumLocks()
- {
- return lockRoot.getChildrenNames().size();
- }
-
- @Managed
- @ManagedDescription("Remove the expired locks")
- public void cleanExpiredLocks()
- {
- removeExpired();
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isTXAware()
- {
- return true;
- }
-
- /**
- * Refreshed lock data in cache
- *
- * @param newLockData
- */
- public void refresh(LockData newLockData) throws LockException
- {
- //first look pending locks
- if (pendingLocks.containsKey(newLockData.getNodeIdentifier()))
- {
- pendingLocks.put(newLockData.getNodeIdentifier(), newLockData);
- }
- else
- {
- Fqn<String> id = Fqn.fromString(newLockData.getNodeIdentifier());
- if (lockRoot.hasChild(id))
- {
- lockRoot.addChild(id);
- }
- else
- {
- throw new LockException("Can't refresh lock for node " + newLockData.getNodeIdentifier()
- + " since lock is not exist");
- }
- }
- }
}
More information about the exo-jcr-commits
mailing list