summaryrefslogtreecommitdiff
path: root/mail/src
diff options
context:
space:
mode:
authorKali Kaneko <kali@leap.se>2014-02-11 02:53:28 -0400
committerKali Kaneko <kali@leap.se>2014-02-17 11:39:49 -0400
commitc36c3f2a58f5e6440e5b79f0265398048c7b8425 (patch)
tree90696757cd71cc942a43e458f8b832e58f44d8f6 /mail/src
parent6d13b7308b127d5d7b7eedde67e36dc45d7884e1 (diff)
defer fetch to thread
also, dispatch query for all headers to its own method.
Diffstat (limited to 'mail/src')
-rw-r--r--mail/src/leap/mail/imap/mailbox.py38
-rw-r--r--mail/src/leap/mail/imap/memorystore.py27
-rw-r--r--mail/src/leap/mail/imap/messages.py7
-rw-r--r--mail/src/leap/mail/imap/server.py15
4 files changed, 70 insertions, 17 deletions
diff --git a/mail/src/leap/mail/imap/mailbox.py b/mail/src/leap/mail/imap/mailbox.py
index fa97512..21f0554 100644
--- a/mail/src/leap/mail/imap/mailbox.py
+++ b/mail/src/leap/mail/imap/mailbox.py
@@ -211,6 +211,9 @@ class SoledadMailbox(WithMsgFields, MBoxParser):
fields.TYPE_MBOX_VAL, self.mbox)
if query:
return query.pop()
+ else:
+ logger.error("Could not find mbox document for %r" %
+ (self.mbox,))
except Exception as exc:
logger.exception("Unhandled error %r" % exc)
@@ -576,10 +579,30 @@ class SoledadMailbox(WithMsgFields, MBoxParser):
otherwise.
:type uid: bool
+ :rtype: deferred
+ """
+ d = defer.Deferred()
+ self.reactor.callInThread(self._do_fetch, messages_asked, uid, d)
+ if PROFILE_CMD:
+ do_profile_cmd(d, "FETCH")
+ return d
+
+ # called in thread
+ def _do_fetch(self, messages_asked, uid, d):
+ """
+ :param messages_asked: IDs of the messages to retrieve information
+ about
+ :type messages_asked: MessageSet
+
+ :param uid: If true, the IDs are UIDs. They are message sequence IDs
+ otherwise.
+ :type uid: bool
+ :param d: deferred whose callback will be called with result.
+ :type d: Deferred
+
:rtype: A tuple of two-tuples of message sequence numbers and
LeapMessage
"""
- from twisted.internet import reactor
# For the moment our UID is sequential, so we
# can treat them all the same.
# Change this to the flag that twisted expects when we
@@ -597,9 +620,11 @@ class SoledadMailbox(WithMsgFields, MBoxParser):
logger.debug("Getting msg by index: INEFFICIENT call!")
raise NotImplementedError
else:
- result = ((msgid, getmsg(msgid)) for msgid in seq_messg)
- reactor.callLater(0, self.unset_recent_flags, seq_messg)
- return result
+ got_msg = [(msgid, getmsg(msgid)) for msgid in seq_messg]
+ result = ((msgid, msg) for msgid, msg in got_msg
+ if msg is not None)
+ self.reactor.callLater(0, self.unset_recent_flags, seq_messg)
+ self.reactor.callFromThread(d.callback, result)
def fetch_flags(self, messages_asked, uid):
"""
@@ -668,6 +693,8 @@ class SoledadMailbox(WithMsgFields, MBoxParser):
MessagePart.
:rtype: tuple
"""
+ # TODO how often is thunderbird doing this?
+
class headersPart(object):
def __init__(self, uid, headers):
self.uid = uid
@@ -685,10 +712,9 @@ class SoledadMailbox(WithMsgFields, MBoxParser):
messages_asked = self._bound_seq(messages_asked)
seq_messg = self._filter_msg_seq(messages_asked)
- all_chash = self.messages.all_flags_chash()
all_headers = self.messages.all_headers()
result = ((msgid, headersPart(
- msgid, all_headers.get(all_chash.get(msgid, 'nil'), {})))
+ msgid, all_headers.get(msgid, {})))
for msgid in seq_messg)
return result
diff --git a/mail/src/leap/mail/imap/memorystore.py b/mail/src/leap/mail/imap/memorystore.py
index 2835826..e8e8152 100644
--- a/mail/src/leap/mail/imap/memorystore.py
+++ b/mail/src/leap/mail/imap/memorystore.py
@@ -434,6 +434,8 @@ class MemoryStore(object):
hdoc = self._hdoc_store[chash]
if empty(hdoc):
hdoc = self._permanent_store.get_headers_doc(chash)
+ if empty(hdoc):
+ return None
if not empty(hdoc.content):
self._hdoc_store[chash] = hdoc.content
hdoc = hdoc.content
@@ -699,6 +701,31 @@ class MemoryStore(object):
continue
return flags_dict
+ def all_headers(self, mbox):
+ """
+ Return a dictionary with all the header docs for a given mbox.
+
+ :param mbox: the mailbox
+ :type mbox: str or unicode
+ :rtype: dict
+ """
+ headers_dict = {}
+ uids = self.get_uids(mbox)
+ fdoc_store = self._fdoc_store[mbox]
+ hdoc_store = self._hdoc_store
+
+ for uid in uids:
+ try:
+ chash = fdoc_store[uid][fields.CONTENT_HASH_KEY]
+ hdoc = hdoc_store[chash]
+ if not empty(hdoc):
+ headers_dict[uid] = hdoc
+ except KeyError:
+ continue
+
+ import pprint; pprint.pprint(headers_dict)
+ return headers_dict
+
# Counting sheeps...
def count_new_mbox(self, mbox):
diff --git a/mail/src/leap/mail/imap/messages.py b/mail/src/leap/mail/imap/messages.py
index bbc9deb..7884fb0 100644
--- a/mail/src/leap/mail/imap/messages.py
+++ b/mail/src/leap/mail/imap/messages.py
@@ -28,7 +28,6 @@ from functools import partial
from twisted.mail import imap4
from twisted.internet import defer
-from twisted.python import log
from zope.interface import implements
from zope.proxy import sameProxiedObjects
@@ -1248,12 +1247,14 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser):
all_flags = dict(all_docs)
return all_flags
- # TODO get from memstore
def all_headers(self):
"""
- Return a dict with all the headers documents for this
+ Return a dict with all the header documents for this
mailbox.
+
+ :rtype: dict
"""
+ return self.memstore.all_headers(self.mbox)
def count(self):
"""
diff --git a/mail/src/leap/mail/imap/server.py b/mail/src/leap/mail/imap/server.py
index 3497a8b..7c09784 100644
--- a/mail/src/leap/mail/imap/server.py
+++ b/mail/src/leap/mail/imap/server.py
@@ -119,15 +119,14 @@ class LeapIMAPServer(imap4.IMAP4Server):
cbFetch, tag, query, uid
).addErrback(ebFetch, tag)
- # XXX not implemented yet --- should hit memstore
- #elif len(query) == 1 and str(query[0]) == "rfc822.header":
- #self._oldTimeout = self.setTimeout(None)
+ elif len(query) == 1 and str(query[0]) == "rfc822.header":
+ self._oldTimeout = self.setTimeout(None)
# no need to call iter, we get a generator
- #maybeDeferred(
- #self.mbox.fetch_headers, messages, uid=uid
- #).addCallback(
- #cbFetch, tag, query, uid
- #).addErrback(ebFetch, tag)
+ maybeDeferred(
+ self.mbox.fetch_headers, messages, uid=uid
+ ).addCallback(
+ cbFetch, tag, query, uid
+ ).addErrback(ebFetch, tag)
else:
self._oldTimeout = self.setTimeout(None)
# no need to call iter, we get a generator