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: [email protected]
For additional commands, e-mail: [email protected]