From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by arlo.cworth.org (Postfix) with ESMTP id 748566DE1D82 for ; Thu, 23 Feb 2017 18:01:00 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at cworth.org X-Spam-Flag: NO X-Spam-Score: -0.005 X-Spam-Level: X-Spam-Status: No, score=-0.005 tagged_above=-999 required=5 tests=[AWL=0.006, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01] autolearn=disabled Received: from arlo.cworth.org ([127.0.0.1]) by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bF-VHbDnQdhL for ; Thu, 23 Feb 2017 18:00:59 -0800 (PST) Received: from fethera.tethera.net (fethera.tethera.net [198.245.60.197]) by arlo.cworth.org (Postfix) with ESMTPS id 962B26DE1D76 for ; Thu, 23 Feb 2017 18:00:59 -0800 (PST) Received: from remotemail by fethera.tethera.net with local (Exim 4.84_2) (envelope-from ) id 1ch5BF-0004Pa-7Z; Thu, 23 Feb 2017 21:00:21 -0500 Received: (nullmailer pid 10766 invoked by uid 1000); Fri, 24 Feb 2017 02:00:57 -0000 From: David Bremner To: David Bremner , Gaute Hope , notmuch@notmuchmail.org Subject: [RFC patch 2/2] lib: handle DatabaseModifiedError in _n_message_ensure_metadata Date: Thu, 23 Feb 2017 22:00:48 -0400 Message-Id: <20170224020048.10718-2-david@tethera.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170224020048.10718-1-david@tethera.net> References: <87y3wx2k3s.fsf@tethera.net> <20170224020048.10718-1-david@tethera.net> X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Feb 2017 02:01:00 -0000 The error handling here still needs work. The retry count should be handled in more sane way, and both running out of retries and an error return from notmuch_database_reopen should be handled. --- lib/message.cc | 144 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 80 insertions(+), 64 deletions(-) diff --git a/lib/message.cc b/lib/message.cc index 2fb67d85..b7c377fc 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -310,10 +310,12 @@ _notmuch_message_get_term (notmuch_message_t *message, return value; } -static void +void _notmuch_message_ensure_metadata (notmuch_message_t *message) { Xapian::TermIterator i, end; + notmuch_bool_t success = FALSE; + const char *thread_prefix = _find_prefix ("thread"), *tag_prefix = _find_prefix ("tag"), *id_prefix = _find_prefix ("id"), @@ -327,73 +329,87 @@ _notmuch_message_ensure_metadata (notmuch_message_t *message) * slightly more costly than looking up individual fields if only * one field of the message object is actually used, it's a huge * win as more fields are used. */ + for (int count=0; count < 100 && !success; count++) { + try { + i = message->doc.termlist_begin (); + end = message->doc.termlist_end (); + + /* Get thread */ + if (!message->thread_id) + message->thread_id = + _notmuch_message_get_term (message, i, end, thread_prefix); + + /* Get tags */ + assert (strcmp (thread_prefix, tag_prefix) < 0); + if (!message->tag_list) { + message->tag_list = + _notmuch_database_get_terms_with_prefix (message, i, end, + tag_prefix); + _notmuch_string_list_sort (message->tag_list); + } - i = message->doc.termlist_begin (); - end = message->doc.termlist_end (); - - /* Get thread */ - if (!message->thread_id) - message->thread_id = - _notmuch_message_get_term (message, i, end, thread_prefix); - - /* Get tags */ - assert (strcmp (thread_prefix, tag_prefix) < 0); - if (!message->tag_list) { - message->tag_list = - _notmuch_database_get_terms_with_prefix (message, i, end, - tag_prefix); - _notmuch_string_list_sort (message->tag_list); - } + /* Get id */ + assert (strcmp (tag_prefix, id_prefix) < 0); + if (!message->message_id) + message->message_id = + _notmuch_message_get_term (message, i, end, id_prefix); + + /* Get document type */ + assert (strcmp (id_prefix, type_prefix) < 0); + if (! NOTMUCH_TEST_BIT (message->lazy_flags, NOTMUCH_MESSAGE_FLAG_GHOST)) { + i.skip_to (type_prefix); + /* "T" is the prefix "type" fields. See + * BOOLEAN_PREFIX_INTERNAL. */ + if (*i == "Tmail") + NOTMUCH_CLEAR_BIT (&message->flags, NOTMUCH_MESSAGE_FLAG_GHOST); + else if (*i == "Tghost") + NOTMUCH_SET_BIT (&message->flags, NOTMUCH_MESSAGE_FLAG_GHOST); + else + INTERNAL_ERROR ("Message without type term"); + NOTMUCH_SET_BIT (&message->lazy_flags, NOTMUCH_MESSAGE_FLAG_GHOST); + } - /* Get id */ - assert (strcmp (tag_prefix, id_prefix) < 0); - if (!message->message_id) - message->message_id = - _notmuch_message_get_term (message, i, end, id_prefix); - - /* Get document type */ - assert (strcmp (id_prefix, type_prefix) < 0); - if (! NOTMUCH_TEST_BIT (message->lazy_flags, NOTMUCH_MESSAGE_FLAG_GHOST)) { - i.skip_to (type_prefix); - /* "T" is the prefix "type" fields. See - * BOOLEAN_PREFIX_INTERNAL. */ - if (*i == "Tmail") - NOTMUCH_CLEAR_BIT (&message->flags, NOTMUCH_MESSAGE_FLAG_GHOST); - else if (*i == "Tghost") - NOTMUCH_SET_BIT (&message->flags, NOTMUCH_MESSAGE_FLAG_GHOST); - else - INTERNAL_ERROR ("Message without type term"); - NOTMUCH_SET_BIT (&message->lazy_flags, NOTMUCH_MESSAGE_FLAG_GHOST); + /* Get filename list. Here we get only the terms. We lazily + * expand them to full file names when needed in + * _notmuch_message_ensure_filename_list. */ + assert (strcmp (type_prefix, filename_prefix) < 0); + if (!message->filename_term_list && !message->filename_list) + message->filename_term_list = + _notmuch_database_get_terms_with_prefix (message, i, end, + filename_prefix); + + + /* Get property terms. Mimic the setup with filenames above */ + assert (strcmp (filename_prefix, property_prefix) < 0); + if (!message->property_map && !message->property_term_list) + message->property_term_list = + _notmuch_database_get_terms_with_prefix (message, i, end, + property_prefix); + + /* Get reply to */ + assert (strcmp (property_prefix, replyto_prefix) < 0); + if (!message->in_reply_to) + message->in_reply_to = + _notmuch_message_get_term (message, i, end, replyto_prefix); + + + /* It's perfectly valid for a message to have no In-Reply-To + * header. For these cases, we return an empty string. */ + if (!message->in_reply_to) + message->in_reply_to = talloc_strdup (message, ""); + + /* all the way without an exception */ + success = TRUE; + } catch (const Xapian::DatabaseModifiedError &error) { + (void) notmuch_database_reopen (message->notmuch); + success = FALSE; + } catch (const Xapian::Error &error) { + _notmuch_database_log(_notmuch_message_database (message), "A Xapian exception occurred fetching message metadata\n", + error.get_msg().c_str()); + message->notmuch->exception_reported = TRUE; + } } - /* Get filename list. Here we get only the terms. We lazily - * expand them to full file names when needed in - * _notmuch_message_ensure_filename_list. */ - assert (strcmp (type_prefix, filename_prefix) < 0); - if (!message->filename_term_list && !message->filename_list) - message->filename_term_list = - _notmuch_database_get_terms_with_prefix (message, i, end, - filename_prefix); - - - /* Get property terms. Mimic the setup with filenames above */ - assert (strcmp (filename_prefix, property_prefix) < 0); - if (!message->property_map && !message->property_term_list) - message->property_term_list = - _notmuch_database_get_terms_with_prefix (message, i, end, - property_prefix); - - /* Get reply to */ - assert (strcmp (property_prefix, replyto_prefix) < 0); - if (!message->in_reply_to) - message->in_reply_to = - _notmuch_message_get_term (message, i, end, replyto_prefix); - - - /* It's perfectly valid for a message to have no In-Reply-To - * header. For these cases, we return an empty string. */ - if (!message->in_reply_to) - message->in_reply_to = talloc_strdup (message, ""); } void -- 2.11.0