aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Dmitry Isaikin <isaikin-dmitry@yandex.ru>2016-05-17 05:22:59 +0400
committerGravatar HoĆ  V. DINH <dinh.viet.hoa@gmail.com>2016-05-16 18:22:59 -0700
commitdf85a8925e4de9480a5a153f3101486743979570 (patch)
tree3f613d1da44c4fa385d1bc198bc881349fb9697a
parentced3f8648d116cf1bba1ff106093c7148df129ce (diff)
Try to use IMAP connection with minimum queue size among connections that already selected into needed folder (#1404)
-rwxr-xr-xsrc/async/imap/MCIMAPAsyncSession.cpp109
-rwxr-xr-xsrc/async/imap/MCIMAPAsyncSession.h10
2 files changed, 78 insertions, 41 deletions
diff --git a/src/async/imap/MCIMAPAsyncSession.cpp b/src/async/imap/MCIMAPAsyncSession.cpp
index af8a8dfa..5c599558 100755
--- a/src/async/imap/MCIMAPAsyncSession.cpp
+++ b/src/async/imap/MCIMAPAsyncSession.cpp
@@ -286,11 +286,21 @@ IMAPAsyncConnection * IMAPAsyncSession::session()
IMAPAsyncConnection * IMAPAsyncSession::sessionForFolder(String * folder, bool urgent)
{
if (folder == NULL) {
- return availableSession();
+ return matchingSessionForFolder(NULL);
}
else {
IMAPAsyncConnection * s = NULL;
+
+ // try find session with empty queue, selected to the folder
+ s = sessionWithMinQueue(true, folder);
+ if (s != NULL && s->operationsCount() == 0) {
+ s->setLastFolder(folder);
+ return s;
+ }
+
if (urgent && mAllowsFolderConcurrentAccessEnabled) {
+ // in urgent mode try reuse any available session with
+ // empty queue or create new one, if maximum connections limit does not reached.
s = availableSession();
if (s->operationsCount() == 0) {
s->setLastFolder(folder);
@@ -298,6 +308,7 @@ IMAPAsyncConnection * IMAPAsyncSession::sessionForFolder(String * folder, bool u
}
}
+ // otherwise returns session with minimum size of queue among selected to the folder.
s = matchingSessionForFolder(folder);
s->setLastFolder(folder);
return s;
@@ -306,58 +317,74 @@ IMAPAsyncConnection * IMAPAsyncSession::sessionForFolder(String * folder, bool u
IMAPAsyncConnection * IMAPAsyncSession::availableSession()
{
- if (mMaximumConnections == 0) {
- for(unsigned int i = 0 ; i < mSessions->count() ; i ++) {
- IMAPAsyncConnection * s = (IMAPAsyncConnection *) mSessions->objectAtIndex(i);
- if (s->operationsCount() == 0)
- return s;
- }
- IMAPAsyncConnection * chosenSession = session();
+ // try find existant session with empty queue for reusing.
+ IMAPAsyncConnection * chosenSession = sessionWithMinQueue(false, NULL);
+ if ((chosenSession != NULL) && (chosenSession->operationsCount() == 0)) {
+ return chosenSession;
+ }
+
+ // create new session, if maximum connections limit does not reached yet.
+ if ((mMaximumConnections == 0) || (mSessions->count() < mMaximumConnections)) {
+ chosenSession = session();
mSessions->addObject(chosenSession);
return chosenSession;
}
- else {
- IMAPAsyncConnection * chosenSession = NULL;
- unsigned int minOperationsCount = 0;
- for(unsigned int i = 0 ; i < mSessions->count() ; i ++) {
- IMAPAsyncConnection * s = (IMAPAsyncConnection *) mSessions->objectAtIndex(i);
- if (chosenSession == NULL) {
- chosenSession = s;
- minOperationsCount = s->operationsCount();
- }
- else if (s->operationsCount() < minOperationsCount) {
- chosenSession = s;
- minOperationsCount = s->operationsCount();
- }
- }
- if (mSessions->count() < mMaximumConnections) {
- if ((chosenSession != NULL) && (minOperationsCount == 0)) {
- return chosenSession;
- }
- chosenSession = session();
- mSessions->addObject(chosenSession);
- return chosenSession;
+
+ // otherwise returns existant session with minimum size of queue.
+ return chosenSession;
+}
+
+IMAPAsyncConnection * IMAPAsyncSession::matchingSessionForFolder(String * folder)
+{
+ IMAPAsyncConnection * s = NULL;
+ if (folder == NULL) {
+ // try find session with minimum size of queue among non-selected to the any folder.
+ s = sessionWithMinQueue(true, NULL);
+
+ if (s == NULL) {
+ // prefer to use INBOX-selected folders for commands does not tight to specific folder.
+ s = sessionWithMinQueue(true, MCSTR("INBOX"));
}
- else {
- return chosenSession;
+ } else {
+ // try find session with minimum size of queue among selected to the folder.
+ s = sessionWithMinQueue(true, folder);
+
+ if (s == NULL) {
+ // try find session with minimum size of queue among non-selected to any folder ones.
+ s = sessionWithMinQueue(true, NULL);
}
}
+
+ if (s != NULL) {
+ return s;
+ }
+
+ // otherwise returns existant session with minumum size of queue or create new one.
+ return availableSession();
}
-IMAPAsyncConnection * IMAPAsyncSession::matchingSessionForFolder(String * folder)
+IMAPAsyncConnection * IMAPAsyncSession::sessionWithMinQueue(bool filterByFolder, String * folder)
{
- for(unsigned int i = 0 ; i < mSessions->count() ; i ++) {
- IMAPAsyncConnection * currentSession = (IMAPAsyncConnection *) mSessions->objectAtIndex(i);
- if (currentSession->lastFolder() != NULL) {
- if (currentSession->lastFolder()->isEqual(folder)) {
- return currentSession;
+ IMAPAsyncConnection * chosenSession = NULL;
+ unsigned int minOperationsCount = 0;
+
+ for (unsigned int i = 0 ; i < mSessions->count() ; i ++) {
+ IMAPAsyncConnection * s = (IMAPAsyncConnection *) mSessions->objectAtIndex(i);
+ if ((chosenSession == NULL) || (s->operationsCount() < minOperationsCount)) {
+ bool matched = true;
+ if (filterByFolder) {
+ // filter by last selested folder
+ matched = ((folder != NULL && s->lastFolder() != NULL && s->lastFolder()->isEqual(folder))
+ || (folder == NULL && s->lastFolder() == NULL));
+ }
+ if (matched) {
+ chosenSession = s;
+ minOperationsCount = s->operationsCount();
}
- }
- else {
- return currentSession;
}
}
- return availableSession();
+
+ return chosenSession;
}
IMAPFolderInfoOperation * IMAPAsyncSession::folderInfoOperation(String * folder)
diff --git a/src/async/imap/MCIMAPAsyncSession.h b/src/async/imap/MCIMAPAsyncSession.h
index 78ebd9b9..0230deda 100755
--- a/src/async/imap/MCIMAPAsyncSession.h
+++ b/src/async/imap/MCIMAPAsyncSession.h
@@ -212,8 +212,18 @@ namespace mailcore {
String * mGmailUserDisplayName;
bool mIdleEnabled;
+ /*! Create new IMAP session */
virtual IMAPAsyncConnection * session();
+ /*! Returns a new or an existing session, it is best suited to run the IMAP command
+ in the specified folder. */
virtual IMAPAsyncConnection * matchingSessionForFolder(String * folder);
+ /*! Returns a session with minimum operation queue among already created ones.
+ If @param filterByFolder is true, then function filters sessions with
+ predicate (lastFolder() EQUALS TO @param folder). In case of @param folder is NULL
+ the function would search a session among non-selected ones. */
+ virtual IMAPAsyncConnection * sessionWithMinQueue(bool filterByFolder, String * folder);
+ /*! Returns existant or new session with empty operation queue, if it can.
+ Otherwise, returns the session with the minimum size of the operation queue. */
virtual IMAPAsyncConnection * availableSession();
virtual IMAPMessageRenderingOperation * renderingOperation(IMAPMessage * message,
String * folder,