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]