You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2022/03/22 02:03:43 UTC

[james-project] 14/25: JAMES-3722 Fix for IMAP SELECT QRESYNC known sequences application

This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit e33ef693b603cc674e177fb5f0f59493129c5d7b
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Tue Mar 8 14:54:15 2022 +0700

    JAMES-3722 Fix for IMAP SELECT QRESYNC known sequences application
    
    Known sequence sets are buggy and never restrict vanished replies
    
    Known sequence sets are a way to restrict the scope of vanished
    responses for servers not storing deletion sequences.
    
    Applying correctly the known sequence trick will dramatically reduce
    the amount of 'VANISHED' notifications sent in a real world scenario,
    saving network, bandwidth and processing time.
---
 .../imap/processor/AbstractSelectionProcessor.java | 82 ++++++++--------------
 .../james/imapserver/netty/IMAPServerTest.java     |  7 --
 2 files changed, 28 insertions(+), 61 deletions(-)

diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
index 5dfa2dc..0fcb04c 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
@@ -21,7 +21,9 @@ package org.apache.james.imap.processor;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.IntStream;
 
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.events.EventBus;
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
@@ -62,6 +64,8 @@ import org.slf4j.LoggerFactory;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 
+import io.vavr.Tuple;
+
 abstract class AbstractSelectionProcessor<R extends AbstractMailboxSelectionRequest> extends AbstractMailboxProcessor<R> implements PermitEnableCapabilityProcessor {
     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSelectionProcessor.class);
     private static final List<Capability> CAPS = ImmutableList.of(ImapConstants.SUPPORTS_QRESYNC, ImapConstants.SUPPORTS_CONDSTORE);
@@ -259,63 +263,33 @@ abstract class AbstractSelectionProcessor<R extends AbstractMailboxSelectionRequ
 
     @VisibleForTesting
     UidRange[] recomputeUidSet(IdRange[] knownSequences, UidRange[] knownUids, SelectedMailbox selected, UidRange[] uidSet) {
-        // Add all uids which are contained in the knownuidsset to a List so we can later access them via the index
-        List<MessageUid> knownUidsList = new ArrayList<>();
-        for (UidRange range : knownUids) {
-            for (MessageUid uid : range) {
-                knownUidsList.add(uid);
-            }
-        }
-
-        // loop over the known sequences and check the UID for MSN X again the known UID X
-        MessageUid firstUid = MessageUid.MIN_VALUE;
-        int index = 0;
-        for (IdRange knownSequence : knownSequences) {
-            boolean done = false;
-            for (Long msn : knownSequence) {
-
-                // Check if we have uids left to check against
-                if (knownUidsList.size() > index) {
-                    int msnAsInt = msn.intValue();
-                    MessageUid knownUid = knownUidsList.get(index);
-
-                    // Check if the uid match if not we are done here
-                    done = selected.uid(msnAsInt)
-                        .filter(selectedUid -> selectedUid.equals(knownUid))
-                        .isPresent();
-                    if (done) {
-                        break;
-                    } else {
-                        firstUid = knownUid;
-                    }
-                    index += 1;
-                } else {
-                    done = true;
-                    break;
-                }
-            }
-
-            // We found the first uid to start with
-            if (done) {
-                firstUid = firstUid.next();
-
-                // Ok now its time to filter out the IdRanges which we are not interested in
-                List<UidRange> filteredUidSet = new ArrayList<>();
-                for (UidRange r : uidSet) {
-                    if (r.getLowVal().compareTo(firstUid) < 0) {
-                        if (r.getHighVal().compareTo(firstUid) > 0) {
-                            filteredUidSet.add(new UidRange(firstUid, r.getHighVal()));
-                        }
-                    } else {
-                        filteredUidSet.add(r);
-                    }
+        int size = Math.min(knownSequences.length, knownUids.length);
+        MessageUid firstKnownUid = IntStream.range(0, size)
+            .mapToObj(i -> Pair.of(knownSequences[i], knownUids[i]))
+            // We are guarantied of the ranges being individual items
+            .map(pair -> Pair.of(pair.getLeft().getLowVal(), pair.getRight().getLowVal()))
+            // T3(MSN, UID, MATCH)
+            .map(pair -> Tuple.of(pair.getLeft(), pair.getRight(),
+                selected.uid(pair.getLeft().intValue())
+                    .filter(selectedUid -> selectedUid.equals(pair.getRight()))
+                    .isPresent()))
+            .takeWhile(t3 -> t3._3)
+            .map(t3 -> t3._2)
+            .reduce((t3_1, t3_2) -> t3_2)
+            .orElse(MessageUid.MIN_VALUE);
+
+        // Ok now its time to filter out the IdRanges which we are not interested in
+        List<UidRange> filteredUidSet = new ArrayList<>();
+        for (UidRange r : uidSet) {
+            if (r.getLowVal().compareTo(firstKnownUid) < 0) {
+                if (r.getHighVal().compareTo(firstKnownUid) > 0) {
+                    filteredUidSet.add(new UidRange(firstKnownUid, r.getHighVal()));
                 }
-                uidSet = filteredUidSet.toArray(UidRange[]::new);
-
-                break;
+            } else {
+                filteredUidSet.add(r);
             }
         }
-        return uidSet;
+        return filteredUidSet.toArray(UidRange[]::new);
     }
 
 
diff --git a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
index aa00b8d..5c0c424 100644
--- a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
+++ b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
@@ -63,7 +63,6 @@ import javax.net.ssl.X509TrustManager;
 import org.apache.commons.configuration2.HierarchicalConfiguration;
 import org.apache.commons.configuration2.ex.ConfigurationException;
 import org.apache.commons.configuration2.tree.ImmutableNode;
-import org.apache.commons.io.IOUtils;
 import org.apache.commons.net.imap.AuthenticatingIMAPClient;
 import org.apache.commons.net.imap.IMAPReply;
 import org.apache.commons.net.imap.IMAPSClient;
@@ -1579,9 +1578,6 @@ class IMAPServerTest {
                 .hasSize(1);
         }
 
-        @Disabled("JAMES-3722 Known sequence sets are buggy and never restrict vanished replies." +
-            "Known sequence sets are a way to restrict the scope of vanished responses for servers " +
-            "not storing deletion sequences.")
         @Test
         void knownUidSetShouldBeUsedToRestrictVanishedResponses() throws Exception {
             inbox.delete(ImmutableList.of(MessageUid.MIN_VALUE), mailboxSession);
@@ -1617,9 +1613,6 @@ class IMAPServerTest {
                 .hasSize(1);
         }
 
-        @Disabled("JAMES-3722 Known sequence sets are buggy and never restrict vanished replies." +
-            "Known sequence sets are a way to restrict the scope of vanished responses for servers " +
-            "not storing deletion sequences.")
         @Test
         void knownUidSetShouldTorelateDeletedMessages() throws Exception {
             inbox.delete(ImmutableList.of(MessageUid.MIN_VALUE), mailboxSession);

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