יום ראשון, אוקטובר 12, 2014

SEARCH fail on Exchange (NO Server Unavailable. 15)

משום מה לאחרונה שרת האקסצינג' מסרב לאפשר לKMail לעבוד (לא מאפשר סינכרון אם יש הרבה הודעות בתיבה).

כפתרון זמני היה את הפאטצ' הלקוי הבא - (מתברר שאם אתה מנותק באמצע זה מתחיל מהתחלה ומכניס אותך ללוף ארוך מאוד של מתחיל כל פעם מ 0).


From 7189cf7664e354402e5093bba9e623d4fd4670ad Mon Sep 17 00:00:00 2001
From: me 
Date: Mon, 13 Oct 2014 11:22:23 +0300
Subject: [PATCH] [IMAP resource] Split large UID Search commands to multiple
 smaller ones

On exchange 2007 a long request may trigger "NO Server Unavailable. 15", when splitting to lower amount the error is avoided
---
 resources/imap/batchfetcher.cpp | 37 +++++++++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 6 deletions(-)

diff --git a/resources/imap/batchfetcher.cpp b/resources/imap/batchfetcher.cpp
index 7419bbd..200521a 100644
--- a/resources/imap/batchfetcher.cpp
+++ b/resources/imap/batchfetcher.cpp
@@ -63,12 +63,37 @@ void BatchFetcher::setGmailExtensionsEnabled(bool enable)
 void BatchFetcher::start()
 {
     if (!m_searchTerm.isNull()) {
-        //Resolve the uid to sequence numbers
-        KIMAP::SearchJob *search = new KIMAP::SearchJob(m_session);
-        search->setUidBased(true);
-        search->setTerm(m_searchTerm);
-        connect(search, &KIMAP::SearchJob::result, this, &BatchFetcher::onUidSearchDone);
-        search->start();
+        //I take the idea of using 2K chunks from 6cc5af5b150628a250e67, it solve Exchange disconnecting on too long SearchJob
+        const qint64 maxAmountOfUidToSearchInOneTime = 2000;
+        KIMAP::ImapSet workingSet=KIMAP::ImapSet(m_currentSet);//not passing to Q_FOREACH as it may be modified 
+        Q_FOREACH (const KIMAP::ImapInterval &interval, workingSet.intervals()) {
+            //in case we are dealing with a single bellow threshold interval or end is undefined we fallback to old code
+            if ((! interval.hasDefinedEnd()) || (maxAmountOfUidToSearchInOneTime >  interval.size())) {
+                qCDebug(RESOURCE_IMAP_LOG) << " Search on all elements in one attempt " ;
+                KIMAP::SearchJob * search = new KIMAP::SearchJob(m_session);
+                search->setUidBased(true);
+                search->setTerm(m_searchTerm);
+                connect(search, SIGNAL(result(KJob*)), this, SLOT(onUidSearchDone(KJob*)));
+                search->start();
+            } else {
+               qCDebug(RESOURCE_IMAP_LOG) << "Interval has # " << interval.size() << " elements, will try to search using multiple search sessions";
+               //this is purly for exchange 2007 that get disconnected on too long SearchJob, brake the SearchJob to 2K pieces each one will trigger smaller fetches 
+               qint64 firstUidToSearch = interval.begin();
+               qint64 lastUidToSearch  = qMin ( firstUidToSearch + maxAmountOfUidToSearchInOneTime, interval.end());
+
+               while (firstUidToSearch < interval.end()) {
+                 lastUidToSearch  = qMin ( firstUidToSearch + maxAmountOfUidToSearchInOneTime, interval.end());
+
+                 KIMAP::SearchJob *search = new KIMAP::SearchJob(m_session);
+                 search->setUidBased(true);
+                 search->setTerm(KIMAP::Term(KIMAP::Term::Uid, KIMAP::ImapSet(firstUidToSearch,lastUidToSearch)));
+                 connect(search, SIGNAL(result(KJob*)), this, SLOT(onUidSearchDone(KJob*)));
+                 search->start();
+ 
+                 firstUidToSearch = lastUidToSearch + 1;
+               }
+            }
+        }
     } else {
         fetchNextBatch();
     }
-- 
2.1.0

למה לקויי ?  יש הרבה קוד מועתק וזה נראה מכוער.

למה בכל זאת אני שם את זה פה ? כי לבנתיים זה הכי טוב שיש (הדבר היחידי שמאפשר למשוך מיילים), ואני עדיין לא עשיתי משהוא טוב יותר (מתכנן לכתוב בימים הקרובים כשיהיה לי זמן).

לצערי גם אני חוטף את הניתוק המעצבן (יכול להיות הבאג הזה)

akonadi_imap_resource_15(16371)/kdepimlibs (kimap) KIMAP::LoginJob::~LoginJob: KIMAP::LoginJob(0xd20d20)
akonadi_imap_resource_15(16371)/kdepimlibs (kimap) BatchFetcher::fetchNextBatch: Fetching  39  intervals
akonadi_imap_resource_15(16371)/kdepimlibs (kimap) BatchFetcher::fetchNextBatch: Fetching  27  intervals
akonadi_imap_resource_15(16371)/kdepimlibs (kimap) BatchFetcher::fetchNextBatch: Fetching  39  intervals
akonadi_imap_resource_15(16371)/kdepimlibs (kimap) BatchFetcher::fetchNextBatch: Fetching  36  intervals
akonadi_imap_resource_15(16371)/kdepimlibs (kimap) BatchFetcher::fetchNextBatch: Fetching  35  intervals
akonadi_imap_resource_15(16371)/kdepimlibs (kimap) BatchFetcher::fetchNextBatch: Fetching  23  intervals
akonadi_imap_resource_15(16371)/kdepimlibs (kimap) KIMAP::SessionPrivate::onSocketTimeout: Socket timeout!
The stream parser raised an exception: Unable to read more data 
akonadi_imap_resource_15(16371)/kdepimlibs (kimap) KIMAP::SessionThread::doCloseSocket: close
akonadi_imap_resource_15(16371)/kdepimlibs (kimap) KIMAP::SessionThread::doCloseSocket: close
akonadi_imap_resource_15(16371) BatchFetcher::onHeadersFetchDone: Fetch job failed  "Connection to server lost." 
akonadi_imap_resource_15(16371) RetrieveItemsTask::onRetrievalDone: "" 
akonadi_imap_resource_15(16371)/kdepimlibs (kimap) KIMAP::LoginJob::Logi

אבל זה עדיין מושך , לאט בקפיצות של 100 עם ניתוקים. 

עריכה : זה רק עשה קולות של עובד, זה לא באמת פותר את הבעיה.

אין תגובות:

הוסף רשומת תגובה