[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