[haiku-commits] haiku: hrev50079 - in src: add-ons/mail_daemon/inbound_protocols/imap add-ons/mail_daemon/inbound_protocols/imap/imap_lib preferences/mail

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 10 Feb 2016 14:09:19 +0100 (CET)

hrev50079 adds 6 changesets to branch 'master'
old head: c1ad6121ca4471bbfd0e967f7b593009caf38e40
new head: 9cbc5b82c22f6e181704a655b51c996d2bb103d3
overview: 
http://cgit.haiku-os.org/haiku/log/?qt=range&q=9cbc5b82c22f+%5Ec1ad6121ca44

----------------------------------------------------------------------------

7d6cefeb508c: IMAP: Ignore \Noselect mailboxes.
  
  * They aren't selectable, so we can just hide them from the user.
  * This should fix #12369.

1870a4b1f940: IMAP: Fixed sync command handling.
  
  * The counter did not take continuation commands into account, so that
    it would never reach zero again.
  * Optimized IMAPConnectionWorker::_WaitForCommands() such that it will
    always acquire all available "slots".

15216b261ad4: IMAP: Retrieve on-disk folder state async.
  
  * Messages that we don't have info for during synchronization are now
    collected, and synchronized once the folder state is available,
    instead of waiting for that particular entry to become available
    (without proper means to wait).

f429e4f4424b: IMAP: Fixed stream vs. parse exception handling.
  
  * Protocol::HandleNextResponse() will now exit when a stream exception
    occurs.
  * This should fix bug #12601.

1f105f67506e: Mail: Fixed double delete in PersonList.
  
  * This should fix #12615.

9cbc5b82c22f: E-mail: Stop the mail_daemon if there are no accounts left.
  
  * This fixes part of #12347.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

9 files changed, 156 insertions(+), 29 deletions(-)
.../imap/IMAPConnectionWorker.cpp                | 52 +++++++++++--
.../inbound_protocols/imap/IMAPFolder.cpp        | 81 ++++++++++++++++++--
.../inbound_protocols/imap/IMAPFolder.h          | 10 ++-
.../inbound_protocols/imap/imap_lib/Commands.cpp |  8 ++
.../inbound_protocols/imap/imap_lib/Protocol.cpp |  4 +-
.../inbound_protocols/imap/imap_lib/Response.cpp |  4 +-
.../inbound_protocols/imap/imap_lib/Response.h   |  9 ++-
src/apps/mail/People.cpp                         |  5 +-
src/preferences/mail/ConfigWindow.cpp            | 12 ++-

############################################################################

Commit:      7d6cefeb508c8f479d6d5f839fde1ea9516e2dec
URL:         http://cgit.haiku-os.org/haiku/commit/?id=7d6cefeb508c
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Wed Jan 27 19:57:43 2016 UTC

Ticket:      https://dev.haiku-os.org/ticket/12369

IMAP: Ignore \Noselect mailboxes.

* They aren't selectable, so we can just hide them from the user.
* This should fix #12369.

----------------------------------------------------------------------------

diff --git 
a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.cpp 
b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.cpp
index 31cf6e4..ebe0431 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.cpp
@@ -687,6 +687,14 @@ ListCommand::HandleUntagged(Response& response)
                && response.IsStringAt(3)) {
                fSeparator = response.StringAt(2);
 
+               if (response.IsListAt(1)) {
+                       // We're not supposed to select \Noselect mailboxes,
+                       // so we'll just hide them
+                       ArgumentList& attributes = response.ListAt(1);
+                       if (attributes.Contains("\\Noselect"))
+                               return true;
+               }
+
                BString folder = response.StringAt(3);
                if (folder == "")
                        return true;

############################################################################

Commit:      1870a4b1f9406c8e01a12883905a89544e385b95
URL:         http://cgit.haiku-os.org/haiku/commit/?id=1870a4b1f940
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Wed Feb  3 20:16:06 2016 UTC

IMAP: Fixed sync command handling.

* The counter did not take continuation commands into account, so that
  it would never reach zero again.
* Optimized IMAPConnectionWorker::_WaitForCommands() such that it will
  always acquire all available "slots".

----------------------------------------------------------------------------

diff --git 
a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp 
b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp
index 5f986a8..701c685 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp
@@ -95,11 +95,35 @@ private:
 
 class WorkerCommand {
 public:
-                                                               WorkerCommand() 
{}
-       virtual                                         ~WorkerCommand() {}
+       WorkerCommand()
+               :
+               fContinuation(false)
+       {
+       }
+
+       virtual ~WorkerCommand()
+       {
+       }
+
+       virtual status_t Process(IMAPConnectionWorker& worker) = 0;
+
+       virtual bool IsDone() const
+       {
+               return true;
+       }
+
+       bool IsContinuation() const
+       {
+               return fContinuation;
+       }
 
-       virtual status_t                        Process(IMAPConnectionWorker& 
worker) = 0;
-       virtual bool                            IsDone() const { return true; }
+       void SetContinuation()
+       {
+               fContinuation = true;
+       }
+
+private:
+                       bool                            fContinuation;
 };
 
 
@@ -695,9 +719,11 @@ IMAPConnectionWorker::_Worker()
                BAutolock locker(fLocker);
 
                if (fPendingCommands.IsEmpty()) {
-                       _Disconnect();
+                       if (!fIdle)
+                               _Disconnect();
                        locker.Unlock();
 
+                       // TODO: in idle mode, we'd need to parse any incoming 
message here
                        _WaitForCommands();
                        continue;
                }
@@ -718,6 +744,7 @@ IMAPConnectionWorker::_Worker()
 
                if (!command->IsDone()) {
                        deleter.Detach();
+                       command->SetContinuation();
                        _EnqueueCommand(command);
                }
        }
@@ -740,7 +767,8 @@ IMAPConnectionWorker::_EnqueueCommand(WorkerCommand* 
command)
                return B_NO_MEMORY;
        }
 
-       if (dynamic_cast<SyncCommand*>(command) != NULL)
+       if (dynamic_cast<SyncCommand*>(command) != NULL
+               && !command->IsContinuation())
                fSyncPending++;
 
        locker.Unlock();
@@ -752,7 +780,13 @@ IMAPConnectionWorker::_EnqueueCommand(WorkerCommand* 
command)
 void
 IMAPConnectionWorker::_WaitForCommands()
 {
-       while (acquire_sem(fPendingCommandsSemaphore) == B_INTERRUPTED);
+       int32 count = 1;
+       get_sem_count(fPendingCommandsSemaphore, &count);
+       if (count < 1)
+               count = 1;
+
+       while (acquire_sem_etc(fPendingCommandsSemaphore, count, 0,
+                       B_INFINITE_TIMEOUT) == B_INTERRUPTED);
 }
 
 
@@ -822,7 +856,9 @@ IMAPConnectionWorker::_Connect()
        if (status != B_OK)
                return status;
 
-       fIdle = fSettings.IdleMode() && 
fProtocol.Capabilities().Contains("IDLE");
+       //fIdle = fSettings.IdleMode() && 
fProtocol.Capabilities().Contains("IDLE");
+       // TODO: Idle mode is not yet implemented!
+       fIdle = false;
        return B_OK;
 }
 

############################################################################

Commit:      15216b261ad4379e86171ce6d93f02c7c7440885
URL:         http://cgit.haiku-os.org/haiku/commit/?id=15216b261ad4
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Wed Feb  3 20:19:02 2016 UTC

IMAP: Retrieve on-disk folder state async.

* Messages that we don't have info for during synchronization are now
  collected, and synchronized once the folder state is available,
  instead of waiting for that particular entry to become available
  (without proper means to wait).

----------------------------------------------------------------------------

diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp 
b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp
index 6d45284..8b882c2 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp
@@ -93,14 +93,21 @@ IMAPFolder::IMAPFolder(IMAPProtocol& protocol, const 
BString& mailboxName,
        fMailboxName(mailboxName),
        fUIDValidity(UINT32_MAX),
        fLastUID(0),
-       fListener(NULL)
+       fListener(NULL),
+       fFolderStateInitialized(false),
+       fQuitFolderState(false)
 {
        mutex_init(&fLock, "imap folder lock");
+       mutex_init(&fFolderStateLock, "imap folder state lock");
 }
 
 
 IMAPFolder::~IMAPFolder()
 {
+       if (!fFolderStateInitialized) {
+               fQuitFolderState = true;
+               wait_for_thread(fReadFolderStateThread, NULL);
+       }
 }
 
 
@@ -245,8 +252,10 @@ IMAPFolder::SyncMessageFlags(uint32 uid, uint32 
mailboxFlags)
                }
                if (status == B_OK)
                        status = node.SetTo(&ref);
-               if (status == B_TIMED_OUT)
-                       continue;
+               if (status == B_TIMED_OUT) {
+                       // We don't know the message state yet
+                       fPendingFlagsMap.insert(std::make_pair(uid, 
mailboxFlags));
+               }
                if (status != B_OK)
                        return;
 
@@ -288,15 +297,32 @@ IMAPFolder::SyncMessageFlags(uint32 uid, uint32 
mailboxFlags)
 void
 IMAPFolder::MessageEntriesFetched()
 {
-       // Delete all local messages that weren't synchronized with the server
+       _WaitForFolderState();
+
+       // Synchronize all pending flags first
+       UIDToFlagsMap::const_iterator pendingIterator = 
fPendingFlagsMap.begin();
+       for (; pendingIterator != fPendingFlagsMap.end(); pendingIterator++)
+               SyncMessageFlags(pendingIterator->first, 
pendingIterator->second);
+
+       fPendingFlagsMap.clear();
+
+       // Delete all local messages that are no longer found on the server
+
+       MutexLocker locker(fLock);
+       UIDSet deleteUIDs;
        UIDToRefMap::const_iterator iterator = fRefMap.begin();
        for (; iterator != fRefMap.end(); iterator++) {
                uint32 uid = iterator->first;
                if (fSynchronizedUIDsSet.find(uid) == 
fSynchronizedUIDsSet.end())
-                       _DeleteLocalMessage(uid);
+                       deleteUIDs.insert(uid);
        }
 
        fSynchronizedUIDsSet.clear();
+       locker.Unlock();
+
+       UIDSet::const_iterator deleteIterator = deleteUIDs.begin();
+       for (; deleteIterator != deleteUIDs.end(); deleteIterator++)
+               _DeleteLocalMessage(*deleteIterator);
 }
 
 
@@ -446,14 +472,42 @@ IMAPFolder::DeleteMessage(uint32 uid)
 void
 IMAPFolder::MessageReceived(BMessage* message)
 {
+       switch (message->what) {
+               default:
+                       BHandler::MessageReceived(message);
+                       break;
+       }
+}
+
+
+void
+IMAPFolder::_WaitForFolderState()
+{
+       while (true) {
+               MutexLocker locker(fFolderStateLock);
+               if (fFolderStateInitialized)
+                       return;
+       }
 }
 
 
 void
 IMAPFolder::_InitializeFolderState()
 {
-       fInitializing = true;
+       mutex_lock(&fFolderStateLock);
 
+       fReadFolderStateThread = spawn_thread(&IMAPFolder::_ReadFolderState,
+               "IMAP folder state", B_NORMAL_PRIORITY, this);
+       if (fReadFolderStateThread >= 0)
+               resume_thread(fReadFolderStateThread);
+       else
+               mutex_unlock(&fFolderStateLock);
+}
+
+
+void
+IMAPFolder::_ReadFolderState()
+{
        BDirectory directory(&fRef);
        BEntry entry;
        while (directory.GetNextEntry(&entry) == B_OK) {
@@ -472,6 +526,8 @@ IMAPFolder::_InitializeFolderState()
                uint32 flags = _ReadFlags(node);
 
                MutexLocker locker(fLock);
+               if (fQuitFolderState)
+                       return;
 
                fRefMap.insert(std::make_pair(uid, ref));
                fFlagsMap.insert(std::make_pair(uid, flags));
@@ -497,7 +553,16 @@ IMAPFolder::_InitializeFolderState()
 //
        }
 
-       fInitializing = false;
+       fFolderStateInitialized = true;
+       mutex_unlock(&fFolderStateLock);
+}
+
+
+/*static*/ status_t
+IMAPFolder::_ReadFolderState(void* self)
+{
+       ((IMAPFolder*)self)->_ReadFolderState();
+       return B_OK;
 }
 
 
@@ -535,7 +600,7 @@ IMAPFolder::_GetMessageEntryRef(uint32 uid, entry_ref& ref) 
const
 {
        UIDToRefMap::const_iterator found = fRefMap.find(uid);
        if (found == fRefMap.end())
-               return fInitializing ? B_TIMED_OUT : B_ENTRY_NOT_FOUND;
+               return !fFolderStateInitialized ? B_TIMED_OUT : 
B_ENTRY_NOT_FOUND;
 
        ref = found->second;
        return B_OK;
diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h 
b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h
index f976ca6..ae24a74 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h
@@ -98,7 +98,11 @@ public:
        virtual void                            MessageReceived(BMessage* 
message);
 
 private:
+                       void                            _WaitForFolderState();
                        void                            
_InitializeFolderState();
+                       void                            _ReadFolderState();
+       static  status_t                        _ReadFolderState(void* self);
+
                        const MessageToken      _Token(uint32 uid) const;
                        void                            _NotifyStoredBody(const 
entry_ref& ref,
                                                                        uint32 
uid, status_t status);
@@ -150,10 +154,14 @@ private:
                        uint32                          fLastUID;
                        FolderListener*         fListener;
                        mutex                           fLock;
-                       bool                            fInitializing;
+                       mutex                           fFolderStateLock;
+                       thread_id                       fReadFolderStateThread;
+                       bool                            fFolderStateInitialized;
+                       bool                            fQuitFolderState;
                        UIDToRefMap                     fRefMap;
                        UIDToFlagsMap           fFlagsMap;
                        UIDSet                          fSynchronizedUIDsSet;
+                       UIDToFlagsMap           fPendingFlagsMap;
                        MessengerMap            fPendingBodies;
 };
 

############################################################################

Commit:      f429e4f4424b1c9797f49071e280edc6747c8a9f
URL:         http://cgit.haiku-os.org/haiku/commit/?id=f429e4f4424b
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Thu Feb  4 19:44:35 2016 UTC

Ticket:      https://dev.haiku-os.org/ticket/12601

IMAP: Fixed stream vs. parse exception handling.

* Protocol::HandleNextResponse() will now exit when a stream exception
  occurs.
* This should fix bug #12601.

----------------------------------------------------------------------------

diff --git 
a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Protocol.cpp 
b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Protocol.cpp
index 73517c5..61c98c0 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Protocol.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Protocol.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2015, Haiku Inc. All Rights Reserved.
+ * Copyright 2010-2016, Haiku Inc. All Rights Reserved.
  * Copyright 2010 Clemens Zeidler. All rights reserved.
  *
  * Distributed under the terms of the MIT License.
@@ -355,6 +355,8 @@ Protocol::HandleResponse(Command* command, bigtime_t 
timeout,
                        }
                } catch (ParseException& exception) {
                        printf("Error during parsing: %s\n", 
exception.Message());
+               } catch (StreamException& exception) {
+                       return exception.Status();
                }
 
                if (fOngoingCommands.size() == 0)
diff --git 
a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.cpp 
b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.cpp
index 76182b8..81abd61 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011-2013, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2011-2016, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -393,7 +393,7 @@ ParseException::ParseException(const char* format, ...)
 
 StreamException::StreamException(status_t status)
        :
-       ParseException("Error from stream: %s", status)
+       fStatus(status)
 {
 }
 
diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.h 
b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.h
index b37bc98..1438171 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.h
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011-2013, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2011-2016, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 #ifndef RESPONSE_H
@@ -107,9 +107,14 @@ protected:
 };
 
 
-class StreamException : public ParseException {
+class StreamException : public std::exception {
 public:
                                                                
StreamException(status_t status);
+
+                       status_t                        Status() const { return 
fStatus; }
+
+private:
+                       status_t                        fStatus;
 };
 
 

############################################################################

Commit:      1f105f67506ee683149f295401c74135e23a2333
URL:         http://cgit.haiku-os.org/haiku/commit/?id=1f105f67506e
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Thu Feb  4 19:50:08 2016 UTC

Ticket:      https://dev.haiku-os.org/ticket/12615

Mail: Fixed double delete in PersonList.

* This should fix #12615.

----------------------------------------------------------------------------

diff --git a/src/apps/mail/People.cpp b/src/apps/mail/People.cpp
index 8955384..b8650c8 100644
--- a/src/apps/mail/People.cpp
+++ b/src/apps/mail/People.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2015-2016, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -137,9 +137,8 @@ PersonList::EntryRemoved(QueryList& source, const node_ref& 
nodeRef)
        PersonMap::iterator found = fPersonMap.find(nodeRef);
        if (found != fPersonMap.end()) {
                Person* person = found->second;
-               fPersons.RemoveItem(person);
                fPersonMap.erase(found);
-               delete person;
+               fPersons.RemoveItem(person);
        }
 }
 

############################################################################

Revision:    hrev50079
Commit:      9cbc5b82c22f6e181704a655b51c996d2bb103d3
URL:         http://cgit.haiku-os.org/haiku/commit/?id=9cbc5b82c22f
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Thu Feb  4 20:03:27 2016 UTC

Ticket:      https://dev.haiku-os.org/ticket/12347

E-mail: Stop the mail_daemon if there are no accounts left.

* This fixes part of #12347.

----------------------------------------------------------------------------

diff --git a/src/preferences/mail/ConfigWindow.cpp 
b/src/preferences/mail/ConfigWindow.cpp
index 1d46ec9..1547825 100644
--- a/src/preferences/mail/ConfigWindow.cpp
+++ b/src/preferences/mail/ConfigWindow.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2015 Haiku, Inc. All rights reserved.
+ * Copyright 2007-2016 Haiku, Inc. All rights reserved.
  * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
  *
  * Distributed under the terms of the MIT License.
@@ -499,10 +499,14 @@ ConfigWindow::_SaveSettings()
                messenger.SendMessage(&changedAccounts);
        }
 
-       // Start the mail_daemon if auto start was selected
+       // Start/stop the mail_daemon depending on the settings
        BMailDaemon daemon;
-       if (fSaveSettings && settings.DaemonAutoStarts() && !daemon.IsRunning())
-               daemon.Launch();
+       if (fSaveSettings) {
+               if (settings.DaemonAutoStarts() && !daemon.IsRunning())
+                       daemon.Launch();
+               else if (!settings.DaemonAutoStarts() && daemon.IsRunning())
+                       daemon.Quit();
+       }
 }
 
 


Other related posts:

  • » [haiku-commits] haiku: hrev50079 - in src: add-ons/mail_daemon/inbound_protocols/imap add-ons/mail_daemon/inbound_protocols/imap/imap_lib preferences/mail - axeld