summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Totzke <patricktotzke@gmail.com>2012-02-08 22:17:15 +0000
committerPatrick Totzke <patricktotzke@gmail.com>2012-02-08 22:17:15 +0000
commitca9d44b2d96180efb9a48780298bd8e7ad7bd7d4 (patch)
tree6679a58818e56c83dba2f9fc1965cacaf912a8ce
parentb7e66fc4449b7eb5942c93e35eaf6f4f8dd31666 (diff)
parent0a04bd8dd6609667a423668e1c5e10afb4c39b10 (diff)
Merge branch 'flush-rewrite-296' into testing
-rw-r--r--alot/account.py3
-rw-r--r--alot/db.py123
2 files changed, 76 insertions, 50 deletions
diff --git a/alot/account.py b/alot/account.py
index 1a405df9..abd44db5 100644
--- a/alot/account.py
+++ b/alot/account.py
@@ -134,8 +134,7 @@ class Account(object):
# I wish the mailbox module were more helpful...
path = glob.glob(os.path.join(mbx._path, '*', message_id + '*'))[0]
- message = self.dbman.add_message(path)
- message.add_tags(tags)
+ message = self.dbman.add_message(path, tags)
self.dbman.flush()
return True
diff --git a/alot/db.py b/alot/db.py
index 16a288e6..954c7f9c 100644
--- a/alot/db.py
+++ b/alot/db.py
@@ -1,6 +1,7 @@
from notmuch import Database, NotmuchError, XapianError
import notmuch
import multiprocessing
+import logging
from datetime import datetime
from collections import deque
@@ -85,43 +86,77 @@ class DBManager(object):
if self.ro:
raise DatabaseROError()
if self.writequeue:
+ # aquire a writeable db handler
try:
mode = Database.MODE.READ_WRITE
db = Database(path=self.path, mode=mode)
except NotmuchError:
raise DatabaseLockedError()
+
+ # read notmuch's config regarding imap flag synchronization
+ sync = config.getboolean('maildir', 'synchronize_flags')
+
+ # go through writequeue entries
while self.writequeue:
current_item = self.writequeue.popleft()
- cmd, querystring, tags, sync, afterwards = current_item
- try: # make this a transaction
+ logging.debug('write-out item: %s' % str(current_item))
+
+ # watch out for notmuch errors to re-insert current_item
+ # to the queue on errors
+ try:
+ # the first two coordinants are cnmdname and post-callback
+ cmd, afterwards = current_item[:2]
+
+ # make this a transaction
db.begin_atomic()
- except XapianError:
- raise DatabaseError()
- query = db.create_query(querystring)
- for msg in query.search_messages():
- msg.freeze()
- if cmd == 'tag':
- for tag in tags:
- msg.add_tag(tag.encode(DB_ENC),
- sync_maildir_flags=sync)
- if cmd == 'set':
- msg.remove_all_tags()
+
+ if cmd == 'add':
+ path, tags = current_item[2:]
+ msg, status = db.add_message(path,
+ sync_maildir_flags=sync)
+ msg.freeze()
for tag in tags:
msg.add_tag(tag.encode(DB_ENC),
sync_maildir_flags=sync)
- elif cmd == 'untag':
- for tag in tags:
- msg.remove_tag(tag.encode(DB_ENC),
- sync_maildir_flags=sync)
- msg.thaw()
-
- # end transaction and reinsert queue item on error
- if db.end_atomic() != notmuch.STATUS.SUCCESS:
- self.writequeue.appendleft(current_item)
- else:
+ msg.thaw()
+
+ elif cmd == 'remove':
+ path = current_item[2]
+ db.remove_message(path)
+
+ else: # tag/set/untag
+ querystring, tags = current_item[2:]
+ query = db.create_query(querystring)
+ for msg in query.search_messages():
+ msg.freeze()
+ if cmd == 'tag':
+ for tag in tags:
+ msg.add_tag(tag.encode(DB_ENC),
+ sync_maildir_flags=sync)
+ if cmd == 'set':
+ msg.remove_all_tags()
+ for tag in tags:
+ msg.add_tag(tag.encode(DB_ENC),
+ sync_maildir_flags=sync)
+ elif cmd == 'untag':
+ for tag in tags:
+ msg.remove_tag(tag.encode(DB_ENC),
+ sync_maildir_flags=sync)
+ msg.thaw()
+
+ # end transaction and reinsert queue item on error
+ if db.end_atomic() != notmuch.STATUS.SUCCESS:
+ raise DatabaseError('fail-status from end_atomic')
+
+ # call post-callback
if callable(afterwards):
afterwards()
+ # re-insert item to the queue upon Xapian/NotmuchErrors
+ except (XapianError, NotmuchError) as e:
+ self.writequeue.appendleft(current_item)
+ raise DatabaseError(unicode(e))
+
def kill_search_processes(self):
"""
terminate all search processes that originate from
@@ -153,13 +188,10 @@ class DBManager(object):
"""
if self.ro:
raise DatabaseROError()
- sync_maildir_flags = config.getboolean('maildir', 'synchronize_flags')
if remove_rest:
- self.writequeue.append(('set', querystring, tags,
- sync_maildir_flags, afterwards))
+ self.writequeue.append(('set', afterwards, querystring, tags))
else:
- self.writequeue.append(('tag', querystring, tags,
- sync_maildir_flags, afterwards))
+ self.writequeue.append(('tag', afterwards, querystring, tags))
def untag(self, querystring, tags, afterwards=None):
"""
@@ -181,9 +213,7 @@ class DBManager(object):
"""
if self.ro:
raise DatabaseROError()
- sync_maildir_flags = config.getboolean('maildir', 'synchronize_flags')
- self.writequeue.append(('untag', querystring, tags,
- sync_maildir_flags, afterwards))
+ self.writequeue.append(('untag', afterwards, querystring, tags))
def count_messages(self, querystring):
"""returns number of messages that match `querystring`"""
@@ -288,37 +318,34 @@ class DBManager(object):
db = Database(path=self.path, mode=mode)
return db.create_query(querystring)
- def add_message(self, path):
+ def add_message(self, path, tags=[], afterwards=None):
"""
Adds a file to the notmuch index.
:param path: path to the file
:type path: str
- :returns: the message object corresponding the added message
- :rtype: :class:`alot.message.Message`
+ :param tags: tagstrings to add
+ :type tags: list of str
+ :param afterwards: callback to trigger after adding
+ :type afterwards: callable or None
"""
- db = Database(path=self.path, mode=Database.MODE.READ_WRITE)
- try:
- message, status = db.add_message(path,
- sync_maildir_flags=True)
- except NotmuchError as e:
- raise DatabaseError(unicode(e))
-
- return Message(self, message)
+ if self.ro:
+ raise DatabaseROError()
+ self.writequeue.append(('add', afterwards, path, tags))
- def remove_message(self, message):
+ def remove_message(self, message, afterwards=None):
"""
Remove a message from the notmuch index
:param message: message to remove
:type message: :class:`Message`
+ :param afterwards: callback to trigger after removing
+ :type afterwards: callable or None
"""
+ if self.ro:
+ raise DatabaseROError()
path = message.get_filename()
- db = Database(path=self.path, mode=Database.MODE.READ_WRITE)
- try:
- db.remove_message(path)
- except NotmuchError as e:
- raise DatabaseError(unicode(e))
+ self.writequeue.append(('remove', afterwards, path))
class Thread(object):