Author: norman Date: Sat Sep 3 18:19:07 2011 New Revision: 1164903 URL: http://svn.apache.org/viewvc?rev=1164903&view=rev Log: Make sure we have an higher uid on each append so we don't generate out of order events and so are imap compliant. See MAILBOX-131
Modified: james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/AbstractStressTest.java james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMailboxManager.java james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMailboxManager.java james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java Modified: james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/AbstractStressTest.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/AbstractStressTest.java?rev=1164903&r1=1164902&r2=1164903&view=diff ============================================================================== --- james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/AbstractStressTest.java (original) +++ james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/AbstractStressTest.java Sat Sep 3 18:19:07 2011 @@ -19,7 +19,9 @@ package org.apache.james.mailbox; import java.io.ByteArrayInputStream; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -28,6 +30,8 @@ import java.util.concurrent.atomic.Atomi import javax.mail.Flags; +import junit.framework.Assert; + import org.apache.james.mailbox.MailboxConstants; import org.apache.james.mailbox.MailboxException; import org.apache.james.mailbox.MailboxManager; @@ -49,13 +53,26 @@ public abstract class AbstractStressTest final CountDownLatch latch = new CountDownLatch(APPEND_OPERATIONS); final ExecutorService pool = Executors.newFixedThreadPool(APPEND_OPERATIONS/2); - + final List<Long> uList = new ArrayList<Long>(); MailboxSession session = getMailboxManager().createSystemSession("test", LoggerFactory.getLogger("Test")); getMailboxManager().startProcessingRequest(session); final MailboxPath path = new MailboxPath(MailboxConstants.USER_NAMESPACE, "username", "INBOX"); getMailboxManager().createMailbox(path, session); + getMailboxManager().addListener(path, new MailboxListener() { + @Override + public boolean isClosed() { + return false; + } + + @Override + public void event(Event event) { + long u = ((Added) event).getUids().get(0); + uList.add(u); + } + }, session); getMailboxManager().endProcessingRequest(session); getMailboxManager().logout(session, false); + final AtomicBoolean fail = new AtomicBoolean(false); final ConcurrentHashMap<Long, Object> uids = new ConcurrentHashMap<Long, Object>(); @@ -76,6 +93,7 @@ public abstract class AbstractStressTest getMailboxManager().startProcessingRequest(session); MessageManager m = getMailboxManager().getMailbox(path, session); Long uid = m.appendMessage(new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), session, false, new Flags()); + System.out.println("Append message with uid=" + uid); if (uids.put(uid, new Object()) != null) { fail.set(true); @@ -96,6 +114,17 @@ public abstract class AbstractStressTest latch.await(); + // check if the uids were higher on each append. See MAILBOX-131 + long last = 0; + for (int i = 0; i < uList.size(); i++) { + long l = uList.get(i); + if (l <= last) { + Assert.fail(l + "->" + last); + } else { + last = l; + } + + } org.junit.Assert.assertFalse("Unable to append all messages",fail.get()); pool.shutdown(); Modified: james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMailboxManager.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMailboxManager.java?rev=1164903&r1=1164902&r2=1164903&view=diff ============================================================================== --- james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMailboxManager.java (original) +++ james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMailboxManager.java Sat Sep 3 18:19:07 2011 @@ -50,7 +50,7 @@ public class JCRMailboxManager extends S @Override protected StoreMessageManager<String> createMessageManager(Mailbox<String> mailboxEntity, MailboxSession session) throws MailboxException{ - return new JCRMessageManager(getMapperFactory(), getMessageSearchIndex(), getEventDispatcher(), (JCRMailbox) mailboxEntity, logger, getDelimiter()); + return new JCRMessageManager(getMapperFactory(), getMessageSearchIndex(), getEventDispatcher(), getLocker(), (JCRMailbox) mailboxEntity, logger, getDelimiter()); } @Override Modified: james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java?rev=1164903&r1=1164902&r2=1164903&view=diff ============================================================================== --- james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java (original) +++ james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java Sat Sep 3 18:19:07 2011 @@ -24,6 +24,7 @@ import javax.mail.Flags; import javax.mail.internet.SharedInputStream; import org.apache.james.mailbox.MailboxException; +import org.apache.james.mailbox.MailboxPathLocker; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.jcr.mail.model.JCRMailbox; import org.apache.james.mailbox.jcr.mail.model.JCRMessage; @@ -44,8 +45,8 @@ public class JCRMessageManager extends S private final Logger log; public JCRMessageManager(MailboxSessionMapperFactory<String> mapperFactory, MessageSearchIndex<String> index, - final MailboxEventDispatcher<String> dispatcher, final JCRMailbox mailbox, final Logger log, final char delimiter) throws MailboxException { - super(mapperFactory, index, dispatcher, mailbox); + final MailboxEventDispatcher<String> dispatcher, final MailboxPathLocker locker, final JCRMailbox mailbox, final Logger log, final char delimiter) throws MailboxException { + super(mapperFactory, index, dispatcher, locker, mailbox); this.log = log; } Modified: james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java?rev=1164903&r1=1164902&r2=1164903&view=diff ============================================================================== --- james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java (original) +++ james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java Sat Sep 3 18:19:07 2011 @@ -24,6 +24,7 @@ import javax.mail.Flags; import javax.mail.internet.SharedInputStream; import org.apache.james.mailbox.MailboxException; +import org.apache.james.mailbox.MailboxPathLocker; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.jpa.mail.model.JPAMailbox; import org.apache.james.mailbox.jpa.mail.model.openjpa.JPAMessage; @@ -40,8 +41,8 @@ import org.apache.james.mailbox.store.se */ public class JPAMessageManager extends StoreMessageManager<Long> { - public JPAMessageManager(MailboxSessionMapperFactory<Long> mapperFactory, final MessageSearchIndex<Long> index, final MailboxEventDispatcher<Long> dispatcher,final Mailbox<Long> mailbox) throws MailboxException { - super(mapperFactory, index, dispatcher, mailbox); + public JPAMessageManager(MailboxSessionMapperFactory<Long> mapperFactory, final MessageSearchIndex<Long> index, final MailboxEventDispatcher<Long> dispatcher, final MailboxPathLocker locker, final Mailbox<Long> mailbox) throws MailboxException { + super(mapperFactory, index, dispatcher, locker, mailbox); } @Override Modified: james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMailboxManager.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMailboxManager.java?rev=1164903&r1=1164902&r2=1164903&view=diff ============================================================================== --- james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMailboxManager.java (original) +++ james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMailboxManager.java Sat Sep 3 18:19:07 2011 @@ -65,7 +65,7 @@ public class OpenJPAMailboxManager exten @Override protected StoreMessageManager<Long> createMessageManager(Mailbox<Long> mailboxRow, MailboxSession session) throws MailboxException { - StoreMessageManager<Long> result = new OpenJPAMessageManager(getMapperFactory(), getMessageSearchIndex(), getEventDispatcher(), mailboxRow, feature); + StoreMessageManager<Long> result = new OpenJPAMessageManager(getMapperFactory(), getMessageSearchIndex(), getEventDispatcher(), getLocker(), mailboxRow, feature); return result; } } Modified: james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java?rev=1164903&r1=1164902&r2=1164903&view=diff ============================================================================== --- james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java (original) +++ james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java Sat Sep 3 18:19:07 2011 @@ -25,6 +25,7 @@ import javax.mail.Flags; import javax.mail.internet.SharedInputStream; import org.apache.james.mailbox.MailboxException; +import org.apache.james.mailbox.MailboxPathLocker; import org.apache.james.mailbox.jpa.JPAMessageManager; import org.apache.james.mailbox.jpa.mail.model.JPAMailbox; import org.apache.james.mailbox.jpa.mail.model.openjpa.JPAEncryptedMessage; @@ -50,13 +51,13 @@ public class OpenJPAMessageManager exten } public OpenJPAMessageManager(MailboxSessionMapperFactory<Long> mapperFactory, MessageSearchIndex<Long> index, - MailboxEventDispatcher<Long> dispatcher, Mailbox<Long> mailbox) throws MailboxException { - this(mapperFactory, index, dispatcher, mailbox, AdvancedFeature.None); + MailboxEventDispatcher<Long> dispatcher, MailboxPathLocker locker, Mailbox<Long> mailbox) throws MailboxException { + this(mapperFactory, index, dispatcher, locker, mailbox, AdvancedFeature.None); } public OpenJPAMessageManager(MailboxSessionMapperFactory<Long> mapperFactory, MessageSearchIndex<Long> index, - MailboxEventDispatcher<Long> dispatcher, Mailbox<Long> mailbox, final AdvancedFeature f) throws MailboxException { - super(mapperFactory, index, dispatcher, mailbox); + MailboxEventDispatcher<Long> dispatcher, MailboxPathLocker locker, Mailbox<Long> mailbox, final AdvancedFeature f) throws MailboxException { + super(mapperFactory, index, dispatcher, locker, mailbox); this.feature = f; } Modified: james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java?rev=1164903&r1=1164902&r2=1164903&view=diff ============================================================================== --- james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java (original) +++ james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java Sat Sep 3 18:19:07 2011 @@ -148,6 +148,10 @@ public class StoreMailboxManager<Id> imp return mailboxSessionMapperFactory; } + public MailboxPathLocker getLocker() { + return locker; + } + /** * Set the {@link AbstractDelegatingMailboxListener} to use with this {@link MailboxManager} instance. If none is set here a {@link HashMapDelegatingMailboxListener} instance will @@ -258,7 +262,7 @@ public class StoreMailboxManager<Id> imp * @return storeMailbox */ protected StoreMessageManager<Id> createMessageManager(Mailbox<Id> mailbox, MailboxSession session) throws MailboxException { - return new StoreMessageManager<Id>(getMapperFactory(), getMessageSearchIndex(), getEventDispatcher(), mailbox); + return new StoreMessageManager<Id>(getMapperFactory(), getMessageSearchIndex(), getEventDispatcher(), getLocker(), mailbox); } /** Modified: james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java URL: http://svn.apache.org/viewvc/james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java?rev=1164903&r1=1164902&r2=1164903&view=diff ============================================================================== --- james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java (original) +++ james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java Sat Sep 3 18:19:07 2011 @@ -41,6 +41,7 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.TeeInputStream; import org.apache.james.mailbox.MailboxException; import org.apache.james.mailbox.MailboxListener; +import org.apache.james.mailbox.MailboxPathLocker; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageManager; import org.apache.james.mailbox.MessageMetaData; @@ -103,12 +104,15 @@ public class StoreMessageManager<Id> imp private final MessageMapperFactory<Id> mapperFactory; private final MessageSearchIndex<Id> index; + + private MailboxPathLocker locker; - public StoreMessageManager(final MessageMapperFactory<Id> mapperFactory, final MessageSearchIndex<Id> index, final MailboxEventDispatcher<Id> dispatcher, final Mailbox<Id> mailbox) throws MailboxException { + public StoreMessageManager(final MessageMapperFactory<Id> mapperFactory, final MessageSearchIndex<Id> index, final MailboxEventDispatcher<Id> dispatcher, final MailboxPathLocker locker, final Mailbox<Id> mailbox) throws MailboxException { this.mailbox = mailbox; this.dispatcher = dispatcher; this.mapperFactory = mapperFactory; this.index = index; + this.locker = locker; } @@ -193,6 +197,7 @@ public class StoreMessageManager<Id> imp public long appendMessage(final InputStream msgIn, Date internalDate, final MailboxSession mailboxSession,final boolean isRecent, final Flags flagsToBeSet) throws MailboxException { + File file = null; TeeInputStream tmpMsgIn = null; BodyOffsetInputStream bIn = null; @@ -315,12 +320,19 @@ public class StoreMessageManager<Id> imp final int size = (int) file.length(); final Message<Id> message = createMessage(internalDate, size, bodyStartOctet, contentIn, flags, propertyBuilder); - MessageMetaData data = appendMessageToStore(message, mailboxSession); - - Map<Long, MessageMetaData> uids = new HashMap<Long, MessageMetaData>(); - uids.put(data.getUid(), data); - dispatcher.added(mailboxSession, uids, getMailboxEntity()); - return data.getUid(); + return locker.executeWithLock(mailboxSession, new StoreMailboxPath<Id>(getMailboxEntity()), new MailboxPathLocker.LockAwareExecution<Long>() { + + @Override + public Long execute() throws MailboxException { + MessageMetaData data = appendMessageToStore(message, mailboxSession); + + Map<Long, MessageMetaData> uids = new HashMap<Long, MessageMetaData>(); + uids.put(data.getUid(), data); + dispatcher.added(mailboxSession, uids, getMailboxEntity()); + return data.getUid(); + } + }, true); + } catch (IOException e) { throw new MailboxException("Unable to parse message", e); } catch (MimeException e) { --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org