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 cd9efb4795475067438a4ff6a8770df2390223bc
Author: Benoit Tellier <[email protected]>
AuthorDate: Fri May 6 10:00:50 2022 +0700

    [PERF] IMAP avoid memory allocation when parsing STATUS items
    
    This represents ~10% of IMAP command decoding memory consumption.
---
 .../imap/decode/parser/StatusCommandParser.java    | 128 +++++++++++++++++----
 testing/base/src/main/resources/logback-test.xml   |   3 -
 2 files changed, 106 insertions(+), 25 deletions(-)

diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StatusCommandParser.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StatusCommandParser.java
index 5aa3b69403..eb697ab49e 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StatusCommandParser.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StatusCommandParser.java
@@ -61,36 +61,120 @@ public class StatusCommandParser extends 
AbstractImapCommandParser {
         request.nextWordChar();
 
         while (request.nextChar() != ')') {
-            String nextWord = 
request.consumeWord(ImapRequestLineReader.NoopCharValidator.INSTANCE, true);
-            if (nextWord.isEmpty()) {
-                // Throw to avoid an infinite loop...
-                throw new DecodingException(HumanReadableText.FAILED, "Empty 
word encountered");
-            }
-            words.add(parseStatus(nextWord));
+            words.add(parseStatus(request));
             request.nextWordChar();
         }
         request.consumeChar(')');
         return words;
     }
 
-    private StatusDataItems.StatusItem parseStatus(String nextWord) throws 
DecodingException {
+    private StatusDataItems.StatusItem parseStatus(ImapRequestLineReader 
request) throws DecodingException {
         // All the matching must be done in a case-insensitive fashion.
         // See rfc3501 9. Formal Syntax and IMAP-282
-        if (nextWord.equalsIgnoreCase(ImapConstants.STATUS_MESSAGES)) {
-            return StatusDataItems.StatusItem.MESSAGES;
-        } else if (nextWord.equalsIgnoreCase(ImapConstants.STATUS_RECENT)) {
-            return StatusDataItems.StatusItem.RECENT;
-        } else if (nextWord.equalsIgnoreCase(ImapConstants.STATUS_UIDNEXT)) {
-            return StatusDataItems.StatusItem.UID_NEXT;
-        } else if 
(nextWord.equalsIgnoreCase(ImapConstants.STATUS_UIDVALIDITY)) {
-            return StatusDataItems.StatusItem.UID_VALIDITY;
-        } else if (nextWord.equalsIgnoreCase(ImapConstants.STATUS_UNSEEN)) {
-            return StatusDataItems.StatusItem.UNSEEN;
-        } else if 
(nextWord.equalsIgnoreCase(ImapConstants.STATUS_HIGHESTMODSEQ)) {
-            // HIGHESTMODSEQ status item as defined in RFC4551 3.6 
HIGHESTMODSEQ Status Data Items
-            return StatusDataItems.StatusItem.HIGHEST_MODSEQ;
-        } else {
-            throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, 
"Unknown status item: '" + nextWord + "'");
+        char c = request.nextWordChar();
+        if (c == 'm' || c == 'M') {
+            return readMessages(request);
+        }
+        if (c == 'r' || c == 'R') {
+            return readRecent(request);
+        }
+        if (c == 'h' || c == 'H') {
+            return readHighestModseq(request);
+        }
+        if (c == 'u' || c == 'U') {
+            return readU(request);
+        }
+        throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, 
"Unknown status item: '" + 
request.consumeWord(ImapRequestLineReader.NoopCharValidator.INSTANCE) + "'");
+    }
+
+    private StatusDataItems.StatusItem readU(ImapRequestLineReader request) 
throws DecodingException {
+        char c;
+        assertChar(request, 'u', 'U');
+        c = request.nextWordChar();
+        if (c == 'n' || c == 'N') {
+            return readUnseen(request);
+        }
+        assertChar(request, 'i', 'I');
+        assertChar(request, 'd', 'D');
+        c = request.nextWordChar();
+        if (c == 'n' || c == 'N') {
+            return readUidNext(request);
+        }
+        readValidity(request);
+        return StatusDataItems.StatusItem.UID_VALIDITY;
+    }
+
+    private void readValidity(ImapRequestLineReader request) throws 
DecodingException {
+        assertChar(request, 'v', 'V');
+        assertChar(request, 'a', 'A');
+        assertChar(request, 'l', 'L');
+        assertChar(request, 'i', 'I');
+        assertChar(request, 'd', 'D');
+        assertChar(request, 'i', 'I');
+        assertChar(request, 't', 'T');
+        assertChar(request, 'y', 'Y');
+    }
+
+    private StatusDataItems.StatusItem readUidNext(ImapRequestLineReader 
request) throws DecodingException {
+        assertChar(request, 'n', 'N');
+        assertChar(request, 'e', 'E');
+        assertChar(request, 'x', 'X');
+        assertChar(request, 't', 'T');
+        return StatusDataItems.StatusItem.UID_NEXT;
+    }
+
+    private StatusDataItems.StatusItem readUnseen(ImapRequestLineReader 
request) throws DecodingException {
+        assertChar(request, 'n', 'N');
+        assertChar(request, 's', 'S');
+        assertChar(request, 'e', 'E');
+        assertChar(request, 'e', 'E');
+        assertChar(request, 'n', 'N');
+        return StatusDataItems.StatusItem.UNSEEN;
+    }
+
+    private StatusDataItems.StatusItem readHighestModseq(ImapRequestLineReader 
request) throws DecodingException {
+        assertChar(request, 'h', 'H');
+        assertChar(request, 'i', 'I');
+        assertChar(request, 'g', 'G');
+        assertChar(request, 'h', 'H');
+        assertChar(request, 'e', 'E');
+        assertChar(request, 's', 'S');
+        assertChar(request, 't', 'T');
+        assertChar(request, 'm', 'M');
+        assertChar(request, 'o', 'O');
+        assertChar(request, 'd', 'D');
+        assertChar(request, 's', 'S');
+        assertChar(request, 'e', 'E');
+        assertChar(request, 'q', 'Q');
+        return StatusDataItems.StatusItem.HIGHEST_MODSEQ;
+    }
+
+    private StatusDataItems.StatusItem readRecent(ImapRequestLineReader 
request) throws DecodingException {
+        assertChar(request, 'r', 'R');
+        assertChar(request, 'e', 'E');
+        assertChar(request, 'c', 'C');
+        assertChar(request, 'e', 'E');
+        assertChar(request, 'n', 'N');
+        assertChar(request, 't', 'T');
+        return StatusDataItems.StatusItem.RECENT;
+    }
+
+    private StatusDataItems.StatusItem readMessages(ImapRequestLineReader 
request) throws DecodingException {
+        assertChar(request, 'm', 'M');
+        assertChar(request, 'e', 'E');
+        assertChar(request, 's', 'S');
+        assertChar(request, 's', 'S');
+        assertChar(request, 'a', 'A');
+        assertChar(request, 'g', 'G');
+        assertChar(request, 'e', 'E');
+        assertChar(request, 's', 'S');
+        return StatusDataItems.StatusItem.MESSAGES;
+    }
+
+    private void assertChar(ImapRequestLineReader reader, char low, char up) 
throws DecodingException {
+        char c = reader.consume();
+        if (c != low && c != up) {
+            throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, 
"Unexpected token in Status item. Expecting " + up + " got " + c);
         }
     }
 }
diff --git a/testing/base/src/main/resources/logback-test.xml 
b/testing/base/src/main/resources/logback-test.xml
index ddcf72c376..1fe8d21504 100644
--- a/testing/base/src/main/resources/logback-test.xml
+++ b/testing/base/src/main/resources/logback-test.xml
@@ -18,9 +18,6 @@
                         <pattern>%d{HH:mm:ss.SSS} [%-5level] %logger{15} - 
%msg%n%rEx</pattern>
                 </encoder>
                 <immediateFlush>false</immediateFlush>
-                <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-                        <level>ERROR</level>
-                </filter>
         </appender>
 
         <root level="WARN">


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to