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 er...@apache.org on 2013/08/01 17:50:29 UTC

svn commit: r1509309 - /james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java

Author: eric
Date: Thu Aug  1 15:50:28 2013
New Revision: 1509309

URL: http://svn.apache.org/r1509309
Log:
Improve SimpleMessageSearchIndex performance, patch contributed by Jan-Philipp Niewerth (MAILBOX-198)

Modified:
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java

Modified: james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java?rev=1509309&r1=1509308&r2=1509309&view=diff
==============================================================================
--- james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java (original)
+++ james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java Thu Aug  1 15:50:28 2013
@@ -18,15 +18,16 @@
  ****************************************************************/
 package org.apache.james.mailbox.store.search;
 
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
 
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.SearchQuery;
+import org.apache.james.mailbox.model.SearchQuery.ConjunctionCriterion;
 import org.apache.james.mailbox.model.SearchQuery.Criterion;
 import org.apache.james.mailbox.model.SearchQuery.NumericRange;
 import org.apache.james.mailbox.model.SearchQuery.UidCriterion;
@@ -52,66 +53,58 @@ public class SimpleMessageSearchIndex<Id
         this.factory = factory;
     }
     
+    /**
+     * Walks down the query tree's conjunctions to find a UidCriterion
+     * @param crits - list of Criterion to search from
+     * @return
+     *      first UidCriterion found
+     *      null - if not found
+     */
+  	private static UidCriterion findConjugatedUidCriterion(List<Criterion> crits) {
+		for (Criterion crit : crits) {
+			if (crit instanceof UidCriterion) {
+				return (UidCriterion) crit;
+			} else if (crit instanceof ConjunctionCriterion) {
+				return findConjugatedUidCriterion(((ConjunctionCriterion) crit)
+						.getCriteria());
+			}
+		}
+		return null;
+	}
+    
     @Override
     public Iterator<Long> search(MailboxSession session, Mailbox<Id> mailbox, SearchQuery query) throws MailboxException {
-        List<Criterion> crits = query.getCriterias();
         MessageMapper<Id> mapper = factory.getMessageMapper(session);
-        
-        // Ok we only search for a range so we can optimize the call
-        if (crits.size() == 1  && crits.get(0) instanceof UidCriterion) {
-            final List<Long> uids = new ArrayList<Long>();
-            UidCriterion uidCrit = (UidCriterion) crits.get(0);
+
+        final SortedSet<Message<?>> hitSet = new TreeSet<Message<?>>();
+
+        UidCriterion uidCrit = findConjugatedUidCriterion(query.getCriterias());
+        if (uidCrit != null) {
+            // if there is a conjugated uid range criterion in the query tree we can optimize by
+            // only fetching this uid range
             NumericRange[] ranges = uidCrit.getOperator().getRange();
             for (int i = 0; i < ranges.length; i++) {
                 NumericRange r = ranges[i];
-                Iterator<Message<Id>> messages = mapper.findInMailbox(mailbox, MessageRange.range(r.getLowValue(), r.getHighValue()), FetchType.Metadata, -1);
-                
-                while(messages.hasNext()) {
-                    long uid = messages.next().getUid();
-                    if (uids.contains(uid) == false) {
-                        uids.add(uid);
-                    }
+                Iterator<Message<Id>> it = mapper.findInMailbox(mailbox, MessageRange.range(r.getLowValue(), r.getHighValue()), FetchType.Metadata, -1);
+                while(it.hasNext()) {
+                	hitSet.add(it.next());
                 }
             }
-            Collections.sort(uids);
-            return uids.iterator();
-            
-           
         } else {
-            
-            final List<Message<Id>> hits = new ArrayList<Message<Id>>();
-
+        	// we have to fetch all messages
             Iterator<Message<Id>> messages = mapper.findInMailbox(mailbox, MessageRange.all(), FetchType.Full, -1);
             while(messages.hasNext()) {
             	Message<Id> m = messages.next();
-                if (hits.contains(m) == false) {
-                    hits.add(m);
-                }
-            }
-            Collections.sort(hits);
-            
-            Iterator<Message<?>> it = new Iterator<Message<?>>() {
-                final Iterator<Message<Id>> it = hits.iterator();
-                public boolean hasNext() {
-                    return it.hasNext();
-                }
-
-                public Message<?> next() {
-                    return it.next();
-                }
-
-                public void remove() {
-                    it.remove();
-                }
-                
-            };
-            
-            if (session == null) {
-                return new MessageSearches(it, query).iterator();
-            } else {
-                return new MessageSearches(it, query, session.getLog()).iterator();
+            	hitSet.add(m);
             }
         }
+        
+        // MessageSearches does the filtering for us
+        if (session == null) {
+			return new MessageSearches(hitSet.iterator(), query).iterator();
+		} else {
+			return new MessageSearches(hitSet.iterator(), query, session.getLog()).iterator();
+		}
     }
 
 }



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