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/04/28 22:07:30 UTC

svn commit: r939071 - in /james/imap/trunk: deployment/src/test/java/org/apache/james/imap/functional/jpa/ jpa/src/main/java/org/apache/james/imap/jpa/ jpa/src/main/java/org/apache/james/imap/jpa/mail/ jpa/src/main/java/org/apache/james/imap/jpa/mail/o...

Author: norman
Date: Wed Apr 28 20:07:29 2010
New Revision: 939071

URL: http://svn.apache.org/viewvc?rev=939071&view=rev
Log:
* Fix for JPA fails to persist MailboxMembership Entity on heavy load by using persimistic locking (IMAP-137)
* Do not cache Mailbox instances in store api  to prevent GC  (IMAP-131)
* Fix inmemory implementation

Removed:
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/openjpa/OpenJPAMailboxMapper.java
Modified:
    james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.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/JPAMailboxManager.java
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/MailboxSessionEntityManagerFactory.java
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java
    james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java
    james/imap/trunk/mailbox/src/main/java/org/apache/james/imap/mailbox/Content.java
    james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.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/StoreMailbox.java

Modified: james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java?rev=939071&r1=939070&r2=939071&view=diff
==============================================================================
--- james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java (original)
+++ james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java Wed Apr 28 20:07:29 2010
@@ -66,7 +66,11 @@ public class JPAHostSystem extends ImapH
                 "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");
         userManager = new InMemoryUserManager();
         entityManagerFactory = OpenJPAPersistence.getEntityManagerFactory(properties);
         MailboxSessionEntityManagerFactory factory = new MailboxSessionEntityManagerFactory(entityManagerFactory);

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=939071&r1=939070&r2=939071&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 Wed Apr 28 20:07:29 2010
@@ -25,6 +25,8 @@ 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.mail.JPAMailboxMapper;
 import org.apache.james.imap.jpa.mail.JPAMessageMapper;
@@ -105,12 +107,19 @@ public abstract class JPAMailbox extends
     }
 
     /**
-     * Reserve next Uid in mailbox and return the mailbox. This method needs to be synchronized 
-     * to be sure we don't get any race-condition
+     * 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 {
-        final JPAMailboxMapper mapper = createMailboxMapper(session);
-        final Mailbox<Long> mailbox = mapper.consumeNextUid(getMailboxId());
+        EntityManager entityManager = entityManagerFactory.getEntityManager(session);
+
+        EntityTransaction transaction = entityManager.getTransaction();
+        transaction.begin();
+        Query query = entityManager.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();
+        entityManager.persist(mailbox);
+        transaction.commit();
         return mailbox;
-    } 
+    }
 }

Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java?rev=939071&r1=939070&r2=939071&view=diff
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java (original)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java Wed Apr 28 20:07:29 2010
@@ -19,6 +19,9 @@
 package org.apache.james.imap.jpa;
 
 
+import javax.persistence.EntityManager;
+
+import org.apache.james.imap.jpa.mail.JPAMailboxMapper;
 import org.apache.james.imap.mailbox.MailboxException;
 import org.apache.james.imap.mailbox.MailboxSession;
 import org.apache.james.imap.store.Authenticator;
@@ -37,7 +40,6 @@ import org.apache.james.imap.store.trans
 public abstract class JPAMailboxManager extends StoreMailboxManager<Long> {
 
     protected final MailboxSessionEntityManagerFactory entityManagerFactory;
-
     public JPAMailboxManager(final Authenticator authenticator, final Subscriber subscriber, 
             final MailboxSessionEntityManagerFactory entityManagerFactory) {
         super(authenticator, subscriber);
@@ -77,6 +79,11 @@ public abstract class JPAMailboxManager 
        
     }
     
-    
+    @Override
+    protected MailboxMapper<Long> createMailboxMapper(MailboxSession session) {
+        EntityManager manager = entityManagerFactory.getEntityManager(session);
+        return new JPAMailboxMapper(manager);
+    }
+
     
 }

Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/MailboxSessionEntityManagerFactory.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/MailboxSessionEntityManagerFactory.java?rev=939071&r1=939070&r2=939071&view=diff
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/MailboxSessionEntityManagerFactory.java (original)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/MailboxSessionEntityManagerFactory.java Wed Apr 28 20:07:29 2010
@@ -1,10 +1,31 @@
+/****************************************************************
+ * 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.jpa;
 
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 
 import org.apache.james.imap.mailbox.MailboxSession;
-
+/**
+ * Make sure the {@link EntityManager} is always the same till the {@link MailboxSession} change
+ *
+ */
 public class MailboxSessionEntityManagerFactory {
 
     private EntityManagerFactory factory;
@@ -14,16 +35,28 @@ public class MailboxSessionEntityManager
         this.factory = factory;
     }
     
+    /**
+     * Return the {@link EntityManager} for this session. If not exists create one and save it in the session. If one is found in the session return it
+     * 
+     * @param session
+     * @return manager
+     */
     public EntityManager getEntityManager(MailboxSession session) {
         EntityManager manager = (EntityManager) session.getAttributes().get(ENTITYMANAGER);
         if (manager == null || manager.isOpen() == false) {
             manager = factory.createEntityManager();
             session.getAttributes().put(ENTITYMANAGER, manager);
+            
         } 
         
         return manager;
     }
     
+    /**
+     * Close the {@link EntityManager} stored in the session if one exists and is open
+     * 
+     * @param session
+     */
     public void closeEntityManager(MailboxSession session) {
         if (session != null) {
             EntityManager manager = (EntityManager) session.getAttributes().remove(ENTITYMANAGER);

Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java?rev=939071&r1=939070&r2=939071&view=diff
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java (original)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java Wed Apr 28 20:07:29 2010
@@ -36,7 +36,7 @@ import org.apache.james.imap.store.mail.
 /**
  * Data access management for mailbox.
  */
-public abstract class JPAMailboxMapper extends JPATransactionalMapper implements MailboxMapper<Long> {
+public class JPAMailboxMapper extends JPATransactionalMapper implements MailboxMapper<Long> {
 
     private static final char SQL_WILDCARD_CHAR = '%';
     
@@ -138,23 +138,4 @@ public abstract class JPAMailboxMapper e
             throw new StorageException(HumanReadableText.SEARCH_FAILED, e);
         } 
     }
-
-
-
-    /*
-     * 
-     */
-    public Mailbox<Long> consumeNextUid(Long mailboxId) throws StorageException, MailboxNotFoundException {
-        try {
-            return doConsumeNextUid(mailboxId);
-        } catch (NoResultException e) {
-            throw new MailboxNotFoundException(mailboxId);
-        } catch (PersistenceException e) {
-            e.printStackTrace();
-            throw new StorageException(HumanReadableText.COMSUME_UID_FAILED, e);
-        } 
-    }
-
-    /** Locking is required and is implementation specific */
-    protected abstract JPAMailbox doConsumeNextUid(long mailboxId) throws PersistenceException;
 }

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=939071&r1=939070&r2=939071&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 Wed Apr 28 20:07:29 2010
@@ -33,7 +33,6 @@ import org.apache.james.imap.jpa.mail.JP
 import org.apache.james.imap.jpa.mail.model.AbstractJPAMailboxMembership;
 import org.apache.james.imap.jpa.mail.model.JPAHeader;
 import org.apache.james.imap.jpa.mail.model.openjpa.JPAStreamingMailboxMembership;
-import org.apache.james.imap.jpa.mail.openjpa.OpenJPAMailboxMapper;
 import org.apache.james.imap.mailbox.MailboxException;
 import org.apache.james.imap.mailbox.MailboxSession;
 import org.apache.james.imap.mailbox.util.MailboxEventDispatcher;
@@ -65,7 +64,7 @@ public class OpenJPAMailbox extends JPAM
 	protected JPAMailboxMapper createMailboxMapper(MailboxSession session) {
 	    EntityManager manager = entityManagerFactory.getEntityManager(session);
 	    	    
-        JPAMailboxMapper mapper = new OpenJPAMailboxMapper(manager);
+        JPAMailboxMapper mapper = new JPAMailboxMapper(manager);
 
         return mapper;
     }

Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java?rev=939071&r1=939070&r2=939071&view=diff
==============================================================================
--- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java (original)
+++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java Wed Apr 28 20:07:29 2010
@@ -19,17 +19,12 @@
 
 package org.apache.james.imap.jpa.openjpa;
 
-import javax.persistence.EntityManager;
-
 import org.apache.james.imap.jpa.JPAMailboxManager;
 import org.apache.james.imap.jpa.MailboxSessionEntityManagerFactory;
-import org.apache.james.imap.jpa.mail.openjpa.OpenJPAMailboxMapper;
-import org.apache.james.imap.mailbox.MailboxSession;
 import org.apache.james.imap.mailbox.util.MailboxEventDispatcher;
 import org.apache.james.imap.store.Authenticator;
 import org.apache.james.imap.store.StoreMailbox;
 import org.apache.james.imap.store.Subscriber;
-import org.apache.james.imap.store.mail.MailboxMapper;
 import org.apache.james.imap.store.mail.model.Mailbox;
 
 /**
@@ -49,12 +44,6 @@ public class OpenJPAMailboxManager exten
         this(authenticator, subscriber, entityManagerFactory, false);
     }
 
-    @Override
-    protected MailboxMapper<Long> createMailboxMapper(MailboxSession session) {
-        EntityManager manager = entityManagerFactory.getEntityManager(session);
-        return new OpenJPAMailboxMapper(manager);
-    }
-
     protected StoreMailbox<Long> createMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> mailboxRow) {
         StoreMailbox<Long> result =  new OpenJPAMailbox(dispatcher,mailboxRow, entityManagerFactory, useStreaming);
         return result;

Modified: james/imap/trunk/mailbox/src/main/java/org/apache/james/imap/mailbox/Content.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/mailbox/src/main/java/org/apache/james/imap/mailbox/Content.java?rev=939071&r1=939070&r2=939071&view=diff
==============================================================================
--- james/imap/trunk/mailbox/src/main/java/org/apache/james/imap/mailbox/Content.java (original)
+++ james/imap/trunk/mailbox/src/main/java/org/apache/james/imap/mailbox/Content.java Wed Apr 28 20:07:29 2010
@@ -33,6 +33,10 @@ public interface Content {
     /**
      * Writes content to the given channel.
      * 
+     * Be aware that this operation may only be called once one the content because its possible dispose
+     * temp data. If you need to write the content more then one time you 
+     * should "re-create" the content
+     * 
      * @param channel
      *            <code>Channel</code> open, not null
      * @throws MailboxException

Modified: james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java?rev=939071&r1=939070&r2=939071&view=diff
==============================================================================
--- james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java (original)
+++ james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java Wed Apr 28 20:07:29 2010
@@ -41,26 +41,38 @@ public class InMemoryMailboxManager exte
 
     private static final int INITIAL_SIZE = 128;
     private Map<Long, InMemoryMailbox> mailboxesById;
-    
+    private Map<String, InMemoryStoreMailbox> storeMailboxByName;
+    private Map<Long, String> idNameMap;
+    private MailboxSession session;
+
     public InMemoryMailboxManager(Authenticator authenticator, Subscriber subscriber) {
         super(authenticator, subscriber);
         mailboxesById = new ConcurrentHashMap<Long, InMemoryMailbox>(INITIAL_SIZE);
+        storeMailboxByName = new ConcurrentHashMap<String, InMemoryStoreMailbox>(INITIAL_SIZE);
+        idNameMap = new ConcurrentHashMap<Long, String>(INITIAL_SIZE);
     }
 
     @Override
     protected StoreMailbox<Long> createMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> mailboxRow) {
-        final InMemoryStoreMailbox storeMailbox = new InMemoryStoreMailbox(dispatcher, (InMemoryMailbox)mailboxRow);
+        InMemoryStoreMailbox storeMailbox = storeMailboxByName.get(mailboxRow.getName());
+        if (storeMailbox == null) {
+            storeMailbox = new InMemoryStoreMailbox(dispatcher, (InMemoryMailbox)mailboxRow);
+            storeMailboxByName.put(mailboxRow.getName(), storeMailbox);
+        }
+        
         return storeMailbox;
     }
 
     @Override
     protected MailboxMapper<Long> createMailboxMapper(MailboxSession session) {
+        this.session = session;
         return this;
     }
 
     @Override
     protected void doCreate(String namespaceName, MailboxSession session) throws StorageException {
         InMemoryMailbox mailbox = new InMemoryMailbox(randomId(), namespaceName, randomUidValidity());
+        idNameMap.put(mailbox.getMailboxId(), mailbox.getName());
         save(mailbox);
     }
 
@@ -69,7 +81,7 @@ public class InMemoryMailboxManager exte
      * (non-Javadoc)
      * @see org.apache.james.imap.store.mail.MailboxMapper#countMailboxesWithName(java.lang.String)
      */
-    public synchronized long countMailboxesWithName(String name) throws StorageException {
+    public long countMailboxesWithName(String name) throws StorageException {
         int total = 0;
         for (final InMemoryMailbox mailbox:mailboxesById.values()) {
             if (mailbox.getName().equals(name)) {
@@ -83,7 +95,7 @@ public class InMemoryMailboxManager exte
      * (non-Javadoc)
      * @see org.apache.james.imap.store.mail.MailboxMapper#delete(org.apache.james.imap.store.mail.model.Mailbox)
      */
-    public synchronized void delete(Mailbox<Long> mailbox) throws StorageException {
+    public void delete(Mailbox<Long> mailbox) throws StorageException {
         mailboxesById.remove(mailbox.getMailboxId());
     }
 
@@ -91,7 +103,7 @@ public class InMemoryMailboxManager exte
      * (non-Javadoc)
      * @see org.apache.james.imap.store.mail.MailboxMapper#deleteAll()
      */
-    public synchronized void deleteAll() throws StorageException {
+    public void deleteAll() throws StorageException {
         mailboxesById.clear();
     }
 
@@ -100,7 +112,7 @@ public class InMemoryMailboxManager exte
      * (non-Javadoc)
      * @see org.apache.james.imap.store.mail.MailboxMapper#findMailboxById(java.lang.Object)
      */
-    public synchronized Mailbox<Long> findMailboxById(Long mailboxId) throws StorageException, MailboxNotFoundException {
+    public Mailbox<Long> findMailboxById(Long mailboxId) throws StorageException, MailboxNotFoundException {
         return mailboxesById.get(mailboxesById);
     }
 
@@ -123,7 +135,7 @@ public class InMemoryMailboxManager exte
      * (non-Javadoc)
      * @see org.apache.james.imap.store.mail.MailboxMapper#findMailboxWithNameLike(java.lang.String)
      */
-    public synchronized List<Mailbox<Long>> findMailboxWithNameLike(String name) throws StorageException {
+    public List<Mailbox<Long>> findMailboxWithNameLike(String name) throws StorageException {
         final String regex = name.replace("%", ".*");
         List<Mailbox<Long>> results = new ArrayList<Mailbox<Long>>();
         for (final InMemoryMailbox mailbox:mailboxesById.values()) {
@@ -138,7 +150,7 @@ public class InMemoryMailboxManager exte
      * (non-Javadoc)
      * @see org.apache.james.imap.store.mail.MailboxMapper#existsMailboxStartingWith(java.lang.String)
      */
-    public synchronized boolean existsMailboxStartingWith(String mailboxName) throws StorageException {
+    public boolean existsMailboxStartingWith(String mailboxName) throws StorageException {
         boolean result = false;
         for (final InMemoryMailbox mailbox:mailboxesById.values()) {
             if (mailbox.getName().startsWith(mailboxName)) {
@@ -153,8 +165,21 @@ public class InMemoryMailboxManager exte
      * (non-Javadoc)
      * @see org.apache.james.imap.store.mail.MailboxMapper#save(org.apache.james.imap.store.mail.model.Mailbox)
      */
-    public synchronized void save(Mailbox<Long> mailbox) throws StorageException {
+    public void save(Mailbox<Long> mailbox) throws StorageException {
         mailboxesById.put(mailbox.getMailboxId(), (InMemoryMailbox) mailbox);
+        String name = idNameMap.remove(mailbox.getMailboxId());
+        if (name != null) {
+            InMemoryStoreMailbox m = storeMailboxByName.remove(name);
+            if (m!= null) {
+                try {
+                    m.getMailboxRow(session).setName(mailbox.getName());
+                    storeMailboxByName.put(mailbox.getName(), m);
+                } catch (MailboxException e) {
+                    throw new StorageException(e.getKey(), e);
+                } 
+            }
+        }
+        idNameMap.put(mailbox.getMailboxId(), mailbox.getName());
     }
 
     /*
@@ -180,6 +205,8 @@ public class InMemoryMailboxManager exte
             }
             
         });
+        storeMailboxByName.clear();
+        idNameMap.clear();
     }
     
 }

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=939071&r1=939070&r2=939071&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 Wed Apr 28 20:07:29 2010
@@ -50,7 +50,7 @@ public class DelegatingMailboxListener i
      * (non-Javadoc)
      * @see org.apache.james.imap.mailbox.MailboxListener#event(org.apache.james.imap.mailbox.MailboxListener.Event)
      */
-    public synchronized void event(Event event) {
+    public void event(Event event) {
         List<MailboxListener> mListeners = listeners.get(event.getMailboxName());
         if (mListeners != null && mListeners.isEmpty() == false) {
             for (int i = 0; i < mListeners.size(); i++) {

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=939071&r1=939070&r2=939071&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 Wed Apr 28 20:07:29 2010
@@ -149,161 +149,157 @@ public abstract class StoreMailbox<Id> i
             final MailboxSession mailboxSession,final boolean isRecent, final Flags flagsToBeSet)
     throws MailboxException {
         // this will hold the uid after the transaction was complete
-        final List<Long> uidHolder = new ArrayList<Long>();
         final MessageMapper<Id> mapper = createMessageMapper(mailboxSession);
-        mapper.execute(new TransactionalMapper.Transaction() {
-          
-            public void run() throws MailboxException {
-                final Mailbox<Id> mailbox = reserveNextUid(mailboxSession);
+        
+        final Mailbox<Id> mailbox = reserveNextUid(mailboxSession);
+        final long uid = mailbox.getLastUid();
+        
+        
+        File file = null;
+        try {
+            // Create a temporary file and copy the message to it. We will work with the file as
+            // source for the InputStream
+            file = File.createTempFile("imap", ".msg");
+            FileOutputStream out = new FileOutputStream(file);
+            
+            byte[] buf = new byte[1024];
+            int i = 0;
+            while ((i = msgIn.read(buf)) != -1) {
+                out.write(buf, 0, i);
+            }
+            out.flush();
+            out.close();
+            
+            FileInputStream tmpMsgIn = new FileInputStream(file);
+            // To be thread safe, we first get our own copy and the
+            // exclusive
+            // Uid
+            // TODO create own message_id and assign uid later
+            // at the moment it could lead to the situation that uid 5
+            // is
+            // inserted long before 4, when
+            // mail 4 is big and comes over a slow connection.
+            final int size = tmpMsgIn.available();
+            final int bodyStartOctet = bodyStartOctet(new FileInputStream(file));
+
+            // Disable line length... This should be handled by the smtp server component and not the parser itself
+            // https://issues.apache.org/jira/browse/IMAP-122
+            MimeEntityConfig config = new MimeEntityConfig();
+            config.setMaximalBodyDescriptor(true);
+            config.setMaxLineLen(-1);
+            final ConfigurableMimeTokenStream parser = new ConfigurableMimeTokenStream(config);
+           
+            parser.setRecursionMode(MimeTokenStream.M_NO_RECURSE);
+            parser.parse(new FileInputStream(file));
+            final List<Header> headers = new ArrayList<Header>(INITIAL_SIZE_HEADERS);
+            
+            int lineNumber = 0;
+            int next = parser.next();
+            while (next != MimeTokenStream.T_BODY
+                    && next != MimeTokenStream.T_END_OF_STREAM
+                    && next != MimeTokenStream.T_START_MULTIPART) {
+                if (next == MimeTokenStream.T_FIELD) {
+                    String fieldValue = parser.getField().getBody();
+                    if (fieldValue.endsWith("\r\f")) {
+                        fieldValue = fieldValue.substring(0,fieldValue.length() - 2);
+                    }
+                    if (fieldValue.startsWith(" ")) {
+                        fieldValue = fieldValue.substring(1);
+                    }
+                    final Header header 
+                        = createHeader(++lineNumber, parser.getField().getName(), 
+                            fieldValue);
+                    headers.add(header);
+                }
+                next = parser.next();
+            }
+            final MaximalBodyDescriptor descriptor = (MaximalBodyDescriptor) parser.getBodyDescriptor();
+            final PropertyBuilder propertyBuilder = new PropertyBuilder();
+            final String mediaType;
+            final String mediaTypeFromHeader = descriptor.getMediaType();
+            final String subType;
+            if (mediaTypeFromHeader == null) {
+                mediaType = "text";
+                subType = "plain";
+            } else {
+                mediaType = mediaTypeFromHeader;
+                subType = descriptor.getSubType();
+            }
+            propertyBuilder.setMediaType(mediaType);
+            propertyBuilder.setSubType(subType);
+            propertyBuilder.setContentID(descriptor.getContentId());
+            propertyBuilder.setContentDescription(descriptor.getContentDescription());
+            propertyBuilder.setContentLocation(descriptor.getContentLocation());
+            propertyBuilder.setContentMD5(descriptor.getContentMD5Raw());
+            propertyBuilder.setContentTransferEncoding(descriptor.getTransferEncoding());
+            propertyBuilder.setContentLanguage(descriptor.getContentLanguage());
+            propertyBuilder.setContentDispositionType(descriptor.getContentDispositionType());
+            propertyBuilder.setContentDispositionParameters(descriptor.getContentDispositionParameters());
+            propertyBuilder.setContentTypeParameters(descriptor.getContentTypeParameters());
+            // Add missing types
+            final String codeset = descriptor.getCharset();
+            if (codeset == null) {
+                if ("TEXT".equalsIgnoreCase(mediaType)) {
+                    propertyBuilder.setCharset("us-ascii");
+                }
+            } else {
+                propertyBuilder.setCharset(codeset);
+            }
+            
+            final String boundary = descriptor.getBoundary();
+            if (boundary != null) {
+                propertyBuilder.setBoundary(boundary);
+            }   
+            if ("text".equalsIgnoreCase(mediaType)) {
+                final CountingInputStream bodyStream = new CountingInputStream(parser.getInputStream());
+                bodyStream.readAll();
+                long lines = bodyStream.getLineCount();
                 
-                File file = null;
-                try {
-                    // Create a temporary file and copy the message to it. We will work with the file as
-                    // source for the InputStream
-                    file = File.createTempFile("imap", ".msg");
-                    FileOutputStream out = new FileOutputStream(file);
-                    
-                    byte[] buf = new byte[1024];
-                    int i = 0;
-                    while ((i = msgIn.read(buf)) != -1) {
-                        out.write(buf, 0, i);
-                    }
-                    out.flush();
-                    out.close();
-                    
-                    FileInputStream tmpMsgIn = new FileInputStream(file);
-                    // To be thread safe, we first get our own copy and the
-                    // exclusive
-                    // Uid
-                    // TODO create own message_id and assign uid later
-                    // at the moment it could lead to the situation that uid 5
-                    // is
-                    // inserted long before 4, when
-                    // mail 4 is big and comes over a slow connection.
-
-                    final long uid = mailbox.getLastUid();
-                    final int size = tmpMsgIn.available();
-                    final int bodyStartOctet = bodyStartOctet(new FileInputStream(file));
-
-                    // Disable line length... This should be handled by the smtp server component and not the parser itself
-                    // https://issues.apache.org/jira/browse/IMAP-122
-                    MimeEntityConfig config = new MimeEntityConfig();
-                    config.setMaximalBodyDescriptor(true);
-                    config.setMaxLineLen(-1);
-                    final ConfigurableMimeTokenStream parser = new ConfigurableMimeTokenStream(config);
-                   
-                    parser.setRecursionMode(MimeTokenStream.M_NO_RECURSE);
-                    parser.parse(new FileInputStream(file));
-                    final List<Header> headers = new ArrayList<Header>(INITIAL_SIZE_HEADERS);
-                    
-                    int lineNumber = 0;
-                    int next = parser.next();
-                    while (next != MimeTokenStream.T_BODY
-                            && next != MimeTokenStream.T_END_OF_STREAM
-                            && next != MimeTokenStream.T_START_MULTIPART) {
-                        if (next == MimeTokenStream.T_FIELD) {
-                            String fieldValue = parser.getField().getBody();
-                            if (fieldValue.endsWith("\r\f")) {
-                                fieldValue = fieldValue.substring(0,fieldValue.length() - 2);
-                            }
-                            if (fieldValue.startsWith(" ")) {
-                                fieldValue = fieldValue.substring(1);
-                            }
-                            final Header header 
-                                = createHeader(++lineNumber, parser.getField().getName(), 
-                                    fieldValue);
-                            headers.add(header);
-                        }
-                        next = parser.next();
-                    }
-                    final MaximalBodyDescriptor descriptor = (MaximalBodyDescriptor) parser.getBodyDescriptor();
-                    final PropertyBuilder propertyBuilder = new PropertyBuilder();
-                    final String mediaType;
-                    final String mediaTypeFromHeader = descriptor.getMediaType();
-                    final String subType;
-                    if (mediaTypeFromHeader == null) {
-                        mediaType = "text";
-                        subType = "plain";
-                    } else {
-                        mediaType = mediaTypeFromHeader;
-                        subType = descriptor.getSubType();
-                    }
-                    propertyBuilder.setMediaType(mediaType);
-                    propertyBuilder.setSubType(subType);
-                    propertyBuilder.setContentID(descriptor.getContentId());
-                    propertyBuilder.setContentDescription(descriptor.getContentDescription());
-                    propertyBuilder.setContentLocation(descriptor.getContentLocation());
-                    propertyBuilder.setContentMD5(descriptor.getContentMD5Raw());
-                    propertyBuilder.setContentTransferEncoding(descriptor.getTransferEncoding());
-                    propertyBuilder.setContentLanguage(descriptor.getContentLanguage());
-                    propertyBuilder.setContentDispositionType(descriptor.getContentDispositionType());
-                    propertyBuilder.setContentDispositionParameters(descriptor.getContentDispositionParameters());
-                    propertyBuilder.setContentTypeParameters(descriptor.getContentTypeParameters());
-                    // Add missing types
-                    final String codeset = descriptor.getCharset();
-                    if (codeset == null) {
-                        if ("TEXT".equalsIgnoreCase(mediaType)) {
-                            propertyBuilder.setCharset("us-ascii");
-                        }
-                    } else {
-                        propertyBuilder.setCharset(codeset);
-                    }
-                    
-                    final String boundary = descriptor.getBoundary();
-                    if (boundary != null) {
-                        propertyBuilder.setBoundary(boundary);
-                    }   
-                    if ("text".equalsIgnoreCase(mediaType)) {
-                        final CountingInputStream bodyStream = new CountingInputStream(parser.getInputStream());
-                        bodyStream.readAll();
-                        long lines = bodyStream.getLineCount();
-                        
-                        next = parser.next();
-                        if (next == MimeTokenStream.T_EPILOGUE)  {
-                            final CountingInputStream epilogueStream = new CountingInputStream(parser.getInputStream());
-                            epilogueStream.readAll();
-                            lines+=epilogueStream.getLineCount();
-                        }
-                        propertyBuilder.setTextualLineCount(lines);
-                    }
-                    
-                    final Flags flags;
-                    if (flagsToBeSet == null) {
-                        flags = new Flags();
-                    } else {
-                        flags = flagsToBeSet;
-                    }
-                    if (isRecent) {
-                        flags.add(Flags.Flag.RECENT);
-                    }
-                    
-                    final MailboxMembership<Id> message = createMessage(internalDate, uid, size, bodyStartOctet, new FileInputStream(file), flags, headers, propertyBuilder);
+                next = parser.next();
+                if (next == MimeTokenStream.T_EPILOGUE)  {
+                    final CountingInputStream epilogueStream = new CountingInputStream(parser.getInputStream());
+                    epilogueStream.readAll();
+                    lines+=epilogueStream.getLineCount();
+                }
+                propertyBuilder.setTextualLineCount(lines);
+            }
+            
+            final Flags flags;
+            if (flagsToBeSet == null) {
+                flags = new Flags();
+            } else {
+                flags = flagsToBeSet;
+            }
+            if (isRecent) {
+                flags.add(Flags.Flag.RECENT);
+            }
+            final MailboxMembership<Id> message = createMessage(internalDate, uid, size, bodyStartOctet, new FileInputStream(file), flags, headers, propertyBuilder);
+
+            mapper.execute(new TransactionalMapper.Transaction() {
+                
+                public void run() throws MailboxException {
                     mapper.save(message);
-                       
-                        
-                   
-                    dispatcher.added(uid, mailboxSession.getSessionId(), getMailboxRow(mailboxSession).getName());
-                    //tracker.found(uid, message.createFlags());
-                    uidHolder.add(uid);
-                } catch (IOException e) {
-                    e.printStackTrace();
-                    throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e);
-                } catch (MessagingException e) {
-                    e.printStackTrace();
-                    throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e);
-                } catch (MimeException e) {
-                    e.printStackTrace();
-                    throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e);
-                } finally {
-                    // delete the temporary file if one was specified
-                    if (file != null) {
-                        file.delete();
-                    }
                 }
+            });
+           
+            dispatcher.added(uid, mailboxSession.getSessionId(), getMailboxRow(mailboxSession).getName());
+            return uid;
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e);
+        } catch (MessagingException e) {
+            e.printStackTrace();
+            throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e);
+        } catch (MimeException e) {
+            e.printStackTrace();
+            throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e);
+        } finally {
+            // delete the temporary file if one was specified
+            if (file != null) {
+                file.delete();
             }
-        });
-       
-        return uidHolder.get(0);
+        }
+
     }
 
     /**
@@ -616,22 +612,27 @@ public abstract class StoreMailbox<Id> i
         try {
             final List<MailboxMembership<Id>> copiedRows = new ArrayList<MailboxMembership<Id>>();
             final MessageMapper<Id> mapper = createMessageMapper(session);
-            mapper.execute(new TransactionalMapper.Transaction() {
+            
 
-                public void run() throws MailboxException {
-                    for (MailboxMembership<Id> originalMessage:originalRows) {
+            for (final MailboxMembership<Id> originalMessage:originalRows) {
+                final Mailbox<Id> mailbox = reserveNextUid(session );
+                final long uid = mailbox.getLastUid();
+                
+                mapper.execute(new TransactionalMapper.Transaction() {
+
+                    public void run() throws MailboxException {
+                        final MailboxMembership<Id> newRow = copyMessage(originalMessage, uid, session);
+                        mapper.save(newRow);
+                        copiedRows.add(newRow);
+                          
+                    }
+                    
+                });
 
-                        final Mailbox<Id> mailbox = reserveNextUid(session );
-                        if (mailbox != null) {
-                            long uid = mailbox.getLastUid();
-                            final MailboxMembership<Id> newRow = copyMessage(originalMessage, uid, session);
-                            mapper.save(newRow);
-                            copiedRows.add(newRow);
-                        }
-                    }  
-                }
                 
-            });
+            }  
+            
+           
             
             
             // Wait until commit before issuing events



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