Author: norman
Date: Mon May 10 11:05:24 2010
New Revision: 942708

URL: http://svn.apache.org/viewvc?rev=942708&view=rev
Log:
* Make sure we use PERSIMISTIC_WRITE lock during uid consuming
* Add some javadocs to reflect the need of atomic operation for reserveNextUid()

Modified:
    
james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAStressTest.java
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java
    
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java
    
james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java

Modified: 
james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAStressTest.java
URL: 
http://svn.apache.org/viewvc/james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAStressTest.java?rev=942708&r1=942707&r2=942708&view=diff
==============================================================================
--- 
james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAStressTest.java
 (original)
+++ 
james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAStressTest.java
 Mon May 10 11:05:24 2010
@@ -25,6 +25,7 @@ import javax.persistence.EntityManagerFa
 import org.apache.commons.logging.impl.SimpleLog;
 import org.apache.james.imap.functional.AbstractStressTest;
 import org.apache.james.imap.jpa.JPASubscriptionManager;
+import org.apache.james.imap.jpa.MailboxSessionEntityManagerFactory;
 import org.apache.james.imap.jpa.openjpa.OpenJPAMailboxManager;
 import org.apache.james.imap.mailbox.MailboxException;
 import org.apache.james.imap.mailbox.MailboxSession;
@@ -58,17 +59,19 @@ public class JPAStressTest extends Abstr
                 "org.apache.james.imap.jpa.mail.model.JPAMessage;" +
                 "org.apache.james.imap.jpa.mail.model.JPAProperty;" +
                 "org.apache.james.imap.jpa.user.model.JPASubscription)");
+        /*
         // persimistic locking..
         properties.put("openjpa.LockManager", "pessimistic");
         properties.put("openjpa.ReadLockLevel", "read");
         properties.put("openjpa.WriteLockLevel", "write");
         properties.put("openjpa.jdbc.TransactionIsolation", "repeatable-read");
+        */
         EntityManagerFactory entityManagerFactory = 
OpenJPAPersistence.getEntityManagerFactory(properties);
-        
-        //mailboxManager = new OpenJPAMailboxManager(null, new 
JPASubscriptionManager(entityManagerFactory), entityManagerFactory);
+        MailboxSessionEntityManagerFactory emf = new 
MailboxSessionEntityManagerFactory(entityManagerFactory);
+        mailboxManager = new OpenJPAMailboxManager(null, new 
JPASubscriptionManager(emf), emf);
     }
     
-    /*
+ 
     @After
     public void tearDown() {
         MailboxSession session = mailboxManager.createSystemSession("test", 
new SimpleLog("Test"));
@@ -79,11 +82,6 @@ public class JPAStressTest extends Abstr
         }
         session.close();
     }
-*/
-    @Override
-    public void testStessTest() throws InterruptedException, MailboxException {
-        // 
-    }
 
     @Override
     protected StoreMailboxManager<?> getMailboxManager() {

Modified: 
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java
URL: 
http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java?rev=942708&r1=942707&r2=942708&view=diff
==============================================================================
--- 
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java 
(original)
+++ 
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java 
Mon May 10 11:05:24 2010
@@ -25,6 +25,8 @@ import java.util.List;
 
 import javax.mail.Flags;
 import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+import javax.persistence.LockModeType;
 
 import org.apache.james.imap.jpa.mail.JPAMailboxMapper;
 import org.apache.james.imap.jpa.mail.JPAMessageMapper;
@@ -43,11 +45,12 @@ import org.apache.james.imap.store.mail.
 import org.apache.james.imap.store.mail.model.PropertyBuilder;
 
 /**
- * Abstract base class which should be used from JPA implementations
+ * Abstract base class which should be used from JPA 2.0 implementations
+ * 
  * 
  *
  */
-public abstract class JPAMailbox extends StoreMailbox<Long> {
+public class JPAMailbox extends StoreMailbox<Long> {
 
     protected final EntityManager manager;
     
@@ -85,6 +88,27 @@ public abstract class JPAMailbox extends
         return newRow;
     }
     
+    /**
+     * Reserve next Uid in mailbox and return the mailbox. We use a 
PESSIMISTIC_WRITE lock here to be sure we don't see any duplicates here when
+     * accessing the database with many different threads / connections
+     * 
+     */
+    protected Mailbox<Long> reserveNextUid(MailboxSession session) throws 
MailboxException {
+
+        EntityTransaction transaction = manager.getTransaction();
+        transaction.begin();
+
+        // we need to set a persimistic write lock to be sure we don't get any 
problems with dirty reads etc
+        org.apache.james.imap.jpa.mail.model.JPAMailbox mailbox = 
manager.find(org.apache.james.imap.jpa.mail.model.JPAMailbox.class, 
getMailboxId(), LockModeType.PESSIMISTIC_WRITE);
+        manager.refresh(mailbox);
+        mailbox.consumeUid();
+        manager.persist(mailbox);
+        manager.flush();
+        transaction.commit();
+        return mailbox;
+
+    }
+    
     @Override
     protected Header createHeader(int lineNumber, String name, String value) {
         final Header header = new JPAHeader(lineNumber, name, value);

Modified: 
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java
URL: 
http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java?rev=942708&r1=942707&r2=942708&view=diff
==============================================================================
--- 
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java
 (original)
+++ 
james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java
 Mon May 10 11:05:24 2010
@@ -26,8 +26,6 @@ import java.util.List;
 
 import javax.mail.Flags;
 import javax.persistence.EntityManager;
-import javax.persistence.EntityTransaction;
-import javax.persistence.Query;
 
 import org.apache.james.imap.jpa.JPAMailbox;
 import org.apache.james.imap.jpa.mail.model.AbstractJPAMailboxMembership;
@@ -48,9 +46,10 @@ import org.apache.james.imap.store.mail.
 public class OpenJPAMailbox extends JPAMailbox{
 
     private final boolean useStreaming;
-    public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> 
mailbox,  EntityManager entityManager) {
-               this(dispatcher, mailbox, entityManager, false);
-       }
+
+    public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> 
mailbox, EntityManager entityManager) {
+        this(dispatcher, mailbox, entityManager, false);
+    }
 
     public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> 
mailbox, EntityManager entityManager, final boolean useStreaming) {
         super(dispatcher, mailbox, entityManager);
@@ -79,22 +78,5 @@ public class OpenJPAMailbox extends JPAM
         }
     }
     
-    /**
-     * Reserve next Uid in mailbox and return the mailbox. We use a 
transaction here to be sure we don't get any duplicates
-     * 
-     */
-    protected Mailbox<Long> reserveNextUid(MailboxSession session) throws 
MailboxException {
-        EntityTransaction transaction = manager.getTransaction();
-        transaction.begin();
-        Query query = 
manager.createNamedQuery("findMailboxById").setParameter("idParam", 
getMailboxId());
-        org.apache.james.imap.jpa.mail.model.JPAMailbox mailbox = 
(org.apache.james.imap.jpa.mail.model.JPAMailbox) query.getSingleResult();
-        mailbox.consumeUid();
-        manager.persist(mailbox);
-        manager.flush();
-        transaction.commit();
-        //oem.close();
-        return mailbox;
-     
-    }
 
 }

Modified: 
james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java
URL: 
http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java?rev=942708&r1=942707&r2=942708&view=diff
==============================================================================
--- 
james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java
 (original)
+++ 
james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java
 Mon May 10 11:05:24 2010
@@ -380,7 +380,9 @@ public abstract class StoreMailbox<Id> i
 
 
     /**
-     * Reserve the next Uid on the underlying {...@link Mailbox} 
+     * Reserve the next Uid on the underlying {...@link Mailbox}. Its 
important that the implementation guaranteer a thread-safe/atomic calculation 
of the 
+     * next uid. So be sure you don't use any caching etc.
+     * 
      * 
      * @return mailbox
      * @throws MailboxException



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to