From 93171a5b90f8748790245cff11591064af343863 Mon Sep 17 00:00:00 2001 From: djcb Date: Sun, 19 Aug 2012 09:57:49 +0300 Subject: [PATCH] * lib: try to reopen database when it got updated from the outside (for guile) --- lib/mu-msg-iter.cc | 13 +++++++++++-- lib/mu-msg-iter.h | 5 ++++- lib/mu-query.cc | 35 +++++++++++++++++++++++++++++++---- lib/mu-util.h | 2 ++ 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/lib/mu-msg-iter.cc b/lib/mu-msg-iter.cc index f6fef8db..3f6ecbc7 100644 --- a/lib/mu-msg-iter.cc +++ b/lib/mu-msg-iter.cc @@ -110,9 +110,12 @@ private: MuMsg *_msg; }; + + MuMsgIter* mu_msg_iter_new (XapianEnquire *enq, size_t maxnum, - gboolean threads, MuMsgFieldId sortfield, gboolean revert) + gboolean threads, MuMsgFieldId sortfield, gboolean revert, + GError **err) { g_return_val_if_fail (enq, NULL); /* sortfield should be set to .._NONE when we're not threading */ @@ -125,7 +128,13 @@ mu_msg_iter_new (XapianEnquire *enq, size_t maxnum, return new MuMsgIter ((Xapian::Enquire&)*enq, maxnum, threads, sortfield, revert ? true : false); - } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); + } catch (const Xapian::DatabaseModifiedError &dbmex) { + + mu_util_g_set_error (err, MU_ERROR_XAPIAN_MODIFIED, + "database was modified; please reopen"); + return 0; + + } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, 0); } diff --git a/lib/mu-msg-iter.h b/lib/mu-msg-iter.h index 6471a308..d6da9184 100644 --- a/lib/mu-msg-iter.h +++ b/lib/mu-msg-iter.h @@ -48,13 +48,16 @@ typedef struct _MuMsgIter MuMsgIter; * @param sorting field when using threads; note, when 'threads' is * FALSE, this should be MU_MSG_FIELD_ID_NONE * @param if TRUE, revert the sorting order + * @param err receives error information. if the error is MU_ERROR_XAPIAN_MODIFIED, + * the database should be reloaded. * * @return a new MuMsgIter, or NULL in case of error */ MuMsgIter *mu_msg_iter_new (XapianEnquire *enq, size_t batchsize, gboolean threads, MuMsgFieldId threadsortfield, - gboolean revert) G_GNUC_WARN_UNUSED_RESULT; + gboolean revert, + GError **err) G_GNUC_WARN_UNUSED_RESULT; /** * get the next message (which you got from diff --git a/lib/mu-query.cc b/lib/mu-query.cc index 10a72fdd..da39a21d 100644 --- a/lib/mu-query.cc +++ b/lib/mu-query.cc @@ -309,6 +309,26 @@ mu_query_preprocess (const char *query, GError **err) } +/* this function is for handling the case where a DatabaseModified + * exception is raised. We try to reopen the database, and run the + * query again. */ +static MuMsgIter * +try_requery (MuQuery *self, const char* searchexpr, gboolean threads, + MuMsgFieldId sortfieldid, gboolean revert, int maxnum, + GError **err) +{ + try { + /* let's assume that infinite regression is + * impossible */ + self->db().reopen(); + MU_WRITE_LOG ("reopening db after modification"); + return mu_query_run (self, searchexpr, threads, sortfieldid, + revert, maxnum, err); + + } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, 0); +} + + MuMsgIter* mu_query_run (MuQuery *self, const char* searchexpr, gboolean threads, MuMsgFieldId sortfieldid, gboolean revert, int maxnum, @@ -320,6 +340,7 @@ mu_query_run (MuQuery *self, const char* searchexpr, gboolean threads, sortfieldid == MU_MSG_FIELD_ID_NONE, NULL); try { + MuMsgIter *iter; Xapian::Enquire enq (self->db()); /* note, when our result will be *threaded*, we sort @@ -336,12 +357,18 @@ mu_query_run (MuQuery *self, const char* searchexpr, gboolean threads, enq.set_cutoff(0,0); - return mu_msg_iter_new ( + iter = mu_msg_iter_new ( reinterpret_cast(&enq), maxnum <= 0 ? self->db().get_doccount() : maxnum, - threads, - threads ? sortfieldid : MU_MSG_FIELD_ID_NONE, - revert); + threads, threads ? sortfieldid : MU_MSG_FIELD_ID_NONE, + revert, err); + + if (err && *err && (*err)->code == MU_ERROR_XAPIAN_MODIFIED) { + g_clear_error (err); + return try_requery (self, searchexpr, threads, sortfieldid, + revert, maxnum, err); + } else + return iter; } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, 0); } diff --git a/lib/mu-util.h b/lib/mu-util.h index 7a0b0c40..69cdf9e2 100644 --- a/lib/mu-util.h +++ b/lib/mu-util.h @@ -414,6 +414,8 @@ enum _MuError { MU_ERROR_XAPIAN_STORE_FAILED = 20, /* could not remove */ MU_ERROR_XAPIAN_REMOVE_FAILED = 21, + /* database was modified; reload */ + MU_ERROR_XAPIAN_MODIFIED = 22, /* GMime related errors */