>From 92b89aad3101faa42c6fdca9b6683ebfa42ab3b0 Mon Sep 17 00:00:00 2001
From: Martin Owens <doctormo@gmail.com>
Date: Wed, 7 Sep 2011 21:15:54 -0400
Subject: [PATCH] Add flush and reopen methods to the libnotmuch and to the python bindings. Flush allows read_write databases to commit their changes, forcing a flush to disk and reopen allows a read_only database to reread from the disk.

Also added a handler for Xapian DatabaseChangedError which occurs when the flush happens to read only databases.
---
 bindings/python/notmuch/database.py |   10 ++++++++++
 debian/changelog                    |    6 +++++-
 debian/control                      |    2 +-
 debian/libnotmuch1.symbols          |    2 ++
 lib/database.cc                     |   33 ++++++++++++++++++++++++++-------
 lib/notmuch.h                       |    8 ++++++++
 lib/query.cc                        |   10 +++++++---
 7 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py
index f18ca14..b6c1c31 100644
--- a/bindings/python/notmuch/database.py
+++ b/bindings/python/notmuch/database.py
@@ -432,6 +432,16 @@ class Database(object):
 
         return Query(self, querystring)
 
+    def reopen(self):
+        """Reopens a read only database, when the data has changed, this is required."""
+        if self._db is not None:
+            nmlib.notmuch_database_reopen(self._db)
+
+    def flush(self):
+        """Flushes the search database, only available when in read-write."""
+        if self._db is not None:
+            nmlib.notmuch_database_flush(self._db)
+
     def __repr__(self):
         return "'Notmuch DB " + self.get_path() + "'"
 
diff --git a/debian/changelog b/debian/changelog
index c2b7552..565edfb 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,12 @@
 notmuch (0.8~rc1-1) experimental; urgency=low
 
+  [ David Bremner ]
   * Upstream release candidate.
 
- -- David Bremner <bremner@debian.org>  Tue, 06 Sep 2011 22:24:24 -0300
+  [ Martin Owens (DoctorMO) ]
+  * Re-new-world-order
+
+ -- Martin Owens (DoctorMO) <doctormo@gmail.com>  Wed, 07 Sep 2011 18:19:50 -0400
 
 notmuch (0.7-1) unstable; urgency=low
 
diff --git a/debian/control b/debian/control
index 03afdf4..a72fe1b 100644
--- a/debian/control
+++ b/debian/control
@@ -5,7 +5,7 @@ Maintainer: Carl Worth <cworth@debian.org>
 Uploaders: Jameson Graef Rollins <jrollins@finestructure.net>, martin f. krafft <madduck@debian.org>, 
 	   David Bremner <bremner@debian.org>
 Build-Depends: debhelper (>= 7.0.50~), pkg-config, libxapian-dev, 
- libgmime-2.4-dev, libtalloc-dev, libz-dev,  python-all (>= 2.6.6-3~),
+ libgmime-2.4-dev, libtalloc-dev, libz-dev,  python-all (>= 2.6.6),
  emacs23-nox | emacs23 (>=23~) | emacs23-lucid (>=23~)
 Standards-Version: 3.9.2
 Homepage: http://notmuchmail.org/
diff --git a/debian/libnotmuch1.symbols b/debian/libnotmuch1.symbols
index 05d86e6..7e42b0e 100644
--- a/debian/libnotmuch1.symbols
+++ b/debian/libnotmuch1.symbols
@@ -3,6 +3,7 @@ libnotmuch.so.1 libnotmuch1 #MINVER#
  notmuch_database_close@Base 0.3
  notmuch_database_create@Base 0.3
  notmuch_database_find_message@Base 0.3
+ notmuch_database_flush@Base 0.3
  notmuch_database_get_all_tags@Base 0.3
  notmuch_database_get_directory@Base 0.3
  notmuch_database_get_path@Base 0.3
@@ -10,6 +11,7 @@ libnotmuch.so.1 libnotmuch1 #MINVER#
  notmuch_database_needs_upgrade@Base 0.3
  notmuch_database_open@Base 0.3
  notmuch_database_remove_message@Base 0.3
+ notmuch_database_reopen@Base 0.3
  notmuch_database_upgrade@Base 0.3
  notmuch_directory_destroy@Base 0.3
  notmuch_directory_get_child_directories@Base 0.3
diff --git a/lib/database.cc b/lib/database.cc
index 9c2f4ec..58b6c75 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -700,18 +700,37 @@ notmuch_database_open (const char *path,
 }
 
 void
-notmuch_database_close (notmuch_database_t *notmuch)
+notmuch_database_reopen (notmuch_database_t *notmuch)
 {
     try {
-	if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_WRITE)
-	    (static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db))->flush ();
+        if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
+            (static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db))->reopen();
     } catch (const Xapian::Error &error) {
-	if (! notmuch->exception_reported) {
-	    fprintf (stderr, "Error: A Xapian exception occurred flushing database: %s\n",
-		     error.get_msg().c_str());
-	}
+        if (! notmuch->exception_reported) {
+            fprintf (stderr, "Error: A Xapian exception occurred reopening database: %s\n",
+                error.get_msg().c_str());
+        }
     }
+}
 
+void
+notmuch_database_flush (notmuch_database_t *notmuch)
+{
+    try {
+        if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_WRITE)
+            (static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db))->flush();
+    } catch (const Xapian::Error &error) {
+        if (! notmuch->exception_reported) {
+            fprintf (stderr, "Error: A Xapian exception occurred flushing database: %s\n",
+                error.get_msg().c_str());
+        }
+    }
+}
+
+void
+notmuch_database_close (notmuch_database_t *notmuch)
+{
+    notmuch_database_flush (notmuch);
     delete notmuch->term_gen;
     delete notmuch->query_parser;
     delete notmuch->xapian_db;
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 974be8d..ca87b89 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -171,6 +171,14 @@ notmuch_database_t *
 notmuch_database_open (const char *path,
 		       notmuch_database_mode_t mode);
 
+/* Reopen a read_only database when the data source has changed */
+void
+notmuch_database_reopen (notmuch_database_t *database);
+
+/* Force a flush of the xapian database, also done on close */
+void
+notmuch_database_flush (notmuch_database_t *database);
+
 /* Close the given notmuch database, freeing all associated
  * resources. See notmuch_database_open. */
 void
diff --git a/lib/query.cc b/lib/query.cc
index 6f02b04..d116367 100644
--- a/lib/query.cc
+++ b/lib/query.cc
@@ -185,10 +185,14 @@ notmuch_query_search_messages (notmuch_query_t *query)
 	messages->iterator_end = mset.end ();
 
 	return &messages->base;
-
+    } catch (const Xapian::DatabaseModifiedError &error) {
+      fprintf (stderr, "Database changed, you need to reopen it before performing queries.\n");
+      notmuch->exception_reported = TRUE;
+      talloc_free (messages);
+      return NULL;
     } catch (const Xapian::Error &error) {
-	fprintf (stderr, "A Xapian exception occurred performing query: %s\n",
-		 error.get_msg().c_str());
+	fprintf (stderr, "A Xapian exception occurred performing query: %s '%s'\n",
+		 error.get_msg().c_str(), error.get_type());
 	fprintf (stderr, "Query string was: %s\n", query->query_string);
 	notmuch->exception_reported = TRUE;
 	talloc_free (messages);
-- 
1.7.1

