You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2010/07/29 15:15:04 UTC

svn commit: r980440 - in /james/imap/trunk: api/src/main/java/org/apache/james/imap/api/ store/src/main/java/org/apache/james/imap/store/

Author: norman
Date: Thu Jul 29 13:15:03 2010
New Revision: 980440

URL: http://svn.apache.org/viewvc?rev=980440&view=rev
Log:
Add a new helper class to allow locking per MailboxPath
Remove MailboxPathHashMap because its not needed now after override hashCode() in MailboxPath

Added:
    james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MailboxPathLock.java
Removed:
    james/imap/trunk/api/src/main/java/org/apache/james/imap/api/MailboxPathHashMap.java
Modified:
    james/imap/trunk/api/src/main/java/org/apache/james/imap/api/MailboxPath.java
    james/imap/trunk/store/src/main/java/org/apache/james/imap/store/DelegatingMailboxListener.java
    james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java

Modified: james/imap/trunk/api/src/main/java/org/apache/james/imap/api/MailboxPath.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/api/src/main/java/org/apache/james/imap/api/MailboxPath.java?rev=980440&r1=980439&r2=980440&view=diff
==============================================================================
--- james/imap/trunk/api/src/main/java/org/apache/james/imap/api/MailboxPath.java (original)
+++ james/imap/trunk/api/src/main/java/org/apache/james/imap/api/MailboxPath.java Thu Jul 29 13:15:03 2010
@@ -133,6 +133,8 @@ public class MailboxPath {
      */
     @Override
     public boolean equals(Object mailboxPath) {
+        if (this == mailboxPath) return true;
+        
         if (!(mailboxPath instanceof MailboxPath))
             return false;
         MailboxPath mp = (MailboxPath) mailboxPath;
@@ -156,5 +158,15 @@ public class MailboxPath {
                 return false;
         return true;
     }
+
+    @Override
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        if (getName() != null) result = PRIME * result + getName().hashCode();
+        if  (getUser() != null) result = PRIME * result + getUser().hashCode();  
+        if  (getNamespace() != null) result = PRIME * result + getNamespace().hashCode();  
+        return result;
+   }
     
 }

Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/DelegatingMailboxListener.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/DelegatingMailboxListener.java?rev=980440&r1=980439&r2=980440&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/DelegatingMailboxListener.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/DelegatingMailboxListener.java Thu Jul 29 13:15:03 2010
@@ -20,10 +20,11 @@
 package org.apache.james.imap.store;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.james.imap.api.MailboxPath;
-import org.apache.james.imap.api.MailboxPathHashMap;
 import org.apache.james.imap.mailbox.MailboxListener;
 
 /**
@@ -32,7 +33,7 @@ import org.apache.james.imap.mailbox.Mai
  */
 public class DelegatingMailboxListener implements MailboxListener{
 
-    private MailboxPathHashMap<List<MailboxListener>> listeners = new MailboxPathHashMap<List<MailboxListener>>();
+    private Map<MailboxPath, List<MailboxListener>> listeners = new HashMap<MailboxPath, List<MailboxListener>>();
 
     public synchronized void addListener(MailboxPath path, MailboxListener listener) {
         List<MailboxListener> mListeners = listeners.get(path);

Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MailboxPathLock.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MailboxPathLock.java?rev=980440&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MailboxPathLock.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MailboxPathLock.java Thu Jul 29 13:15:03 2010
@@ -0,0 +1,74 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.imap.store;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.james.imap.api.MailboxPath;
+
+/**
+ * 
+ * Helper class which helps to synchronize the access the 
+ * same MailboxPath. This is done using one {@link ReentrantLock}
+ * per {@link MailboxPath}.
+ * 
+ * Its very important to call the {@link #unlock(MailboxPath)} method
+ * in a finally block to not risk a dead lock
+ *
+ */
+public final class MailboxPathLock {
+
+    private final Map<MailboxPath, ReentrantLock> paths = new HashMap<MailboxPath, ReentrantLock>();
+    
+    /**
+     * Obtain a {@link Lock} for the given path
+     * 
+     * @param path
+     */
+    public void lock(MailboxPath path) {
+        ReentrantLock lock;
+        synchronized (paths) {
+            lock = paths.get(path);
+
+            if (lock == null) {
+                lock = new ReentrantLock();
+                paths.put(path, lock);
+            }
+        }
+        lock.lock();
+    }
+    
+    /**
+     * Unlock the previous obtained {@link Lock} for the given path
+     * 
+     * @param path
+     */
+    public void unlock(MailboxPath path) {
+        synchronized (paths) {
+            ReentrantLock lock = paths.remove(path);
+            if (lock != null) {
+                lock.unlock();
+            }
+        }
+    }
+}

Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java?rev=980440&r1=980439&r2=980440&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java Thu Jul 29 13:15:03 2010
@@ -58,7 +58,7 @@ public abstract class StoreMailboxManage
     
     private final MailboxEventDispatcher dispatcher = new MailboxEventDispatcher();
     private final DelegatingMailboxListener delegatingListener = new DelegatingMailboxListener();   
-    
+    private final MailboxPathLock lock = new MailboxPathLock();
     protected final MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory;
     private UidConsumer<Id> consumer;
     
@@ -138,9 +138,14 @@ public abstract class StoreMailboxManage
             // If any creation fails then the mailbox will not be created
             // TODO: transaction
             for (MailboxPath mailbox : mailboxPath.getHierarchyLevels(MailboxConstants.DEFAULT_DELIMITER))
-                if (!mailboxExists(mailbox, mailboxSession))
-                    doCreateMailbox(mailbox, mailboxSession);
-
+                if (!mailboxExists(mailbox, mailboxSession)) {
+                    try {
+                        lock.lock(mailbox);
+                        doCreateMailbox(mailbox, mailboxSession);
+                    } finally {
+                        lock.unlock(mailbox);
+                    }
+                }
         }
     }
 
@@ -198,18 +203,24 @@ public abstract class StoreMailboxManage
 
                 // rename submailboxes
                 MailboxPath children = new MailboxPath(MailboxConstants.USER_NAMESPACE, from.getUser(), from.getName() + MailboxConstants.DEFAULT_DELIMITER + "%");
-                final List<Mailbox<Id>> subMailboxes = mapper.findMailboxWithPathLike(children);
-                for (Mailbox<Id> sub : subMailboxes) {
-                    final String subOriginalName = sub.getName();
-                    final String subNewName = to.getName() + subOriginalName.substring(from.getName().length());
-                    sub.setName(subNewName);
-                    mapper.save(sub);
+                try {
+                    lock.lock(children);
+                    final List<Mailbox<Id>> subMailboxes = mapper.findMailboxWithPathLike(children);
+                    for (Mailbox<Id> sub : subMailboxes) {
+                        final String subOriginalName = sub.getName();
+                        final String subNewName = to.getName() + subOriginalName.substring(from.getName().length());
+                        sub.setName(subNewName);
+                        mapper.save(sub);
 
-                    changeMailboxName(new MailboxPath(children, subOriginalName), new MailboxPath(children, subNewName), session);
+                        changeMailboxName(new MailboxPath(children, subOriginalName), new MailboxPath(children, subNewName), session);
 
-                    if (log.isDebugEnabled())
-                        log.debug("Rename mailbox sub-mailbox " + subOriginalName + " to " + subNewName);
+                        if (log.isDebugEnabled())
+                            log.debug("Rename mailbox sub-mailbox " + subOriginalName + " to " + subNewName);
+                    }
+                } finally {
+                    lock.unlock(children);
                 }
+                
             }
 
         });



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org