X-Git-Url: https://git.notmuchmail.org/git?a=blobdiff_plain;f=lib%2Fmessage.cc;h=71ce8b799f8e3ab385f825697d3f3dbeec8bb287;hb=bc80ff829ac205c68dfab45a21d4732cf5b8c2d0;hp=73a7805f8a2714eb48cfb6cdaec921563e77151b;hpb=1121299905e2b2684d7cc56ec35c26c3a012783e;p=notmuch diff --git a/lib/message.cc b/lib/message.cc index 73a7805f..71ce8b79 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -68,7 +68,7 @@ struct maildir_flag_tag { }; /* ASCII ordered table of Maildir flags and associated tags */ -static struct maildir_flag_tag flag2tag[] = { +static const struct maildir_flag_tag flag2tag[] = { { 'D', "draft", false }, { 'F', "flagged", false }, { 'P', "passed", false }, @@ -169,6 +169,7 @@ _notmuch_message_create_for_document (const void *talloc_owner, message->doc = doc; message->termpos = 0; + message->modified = false; return message; } @@ -288,7 +289,7 @@ _notmuch_message_create_for_message_id (notmuch_database_t *notmuch, doc_id = _notmuch_database_generate_doc_id (notmuch); } catch (const Xapian::Error &error) { - _notmuch_database_log (notmuch_message_get_database (message), + _notmuch_database_log (notmuch, "A Xapian exception occurred creating message: %s\n", error.get_msg ().c_str ()); notmuch->exception_reported = true; @@ -340,23 +341,6 @@ _notmuch_message_get_term (notmuch_message_t *message, return value; } -/* - * For special applications where we only want the thread id, reading - * in all metadata is a heavy I/O penalty. - */ -const char * -_notmuch_message_get_thread_id_only (notmuch_message_t *message) -{ - - Xapian::TermIterator i = message->doc.termlist_begin (); - Xapian::TermIterator end = message->doc.termlist_end (); - - message->thread_id = _notmuch_message_get_term (message, i, end, - _find_prefix ("thread")); - return message->thread_id; -} - - static void _notmuch_message_ensure_metadata (notmuch_message_t *message, void *field) { @@ -742,7 +726,7 @@ _notmuch_message_remove_terms (notmuch_message_t *message, const char *prefix) * properties, along with any automatic tags*/ /* According to Xapian API docs, none of these calls throw * exceptions */ -notmuch_private_status_t +static notmuch_private_status_t _notmuch_message_remove_indexed_terms (notmuch_message_t *message) { Xapian::TermIterator i; @@ -1102,7 +1086,7 @@ _notmuch_message_ensure_filename_list (notmuch_message_t *message) *colon = '\0'; - db_path = notmuch_database_get_path (message->notmuch); + db_path = notmuch_config_get (message->notmuch, NOTMUCH_CONFIG_MAIL_ROOT); directory = _notmuch_database_get_directory_path (local, message->notmuch, @@ -1356,11 +1340,10 @@ notmuch_status_t _notmuch_message_delete (notmuch_message_t *message) { notmuch_status_t status; - const char *mid, *tid, *query_string; + const char *mid, *tid; notmuch_message_t *ghost; notmuch_private_status_t private_status; notmuch_database_t *notmuch; - notmuch_query_t *query; unsigned int count = 0; bool is_ghost; @@ -1382,16 +1365,33 @@ _notmuch_message_delete (notmuch_message_t *message) if (is_ghost) return NOTMUCH_STATUS_SUCCESS; - query_string = talloc_asprintf (message, "thread:%s", tid); - query = notmuch_query_create (notmuch, query_string); - if (query == NULL) - return NOTMUCH_STATUS_OUT_OF_MEMORY; - status = notmuch_query_count_messages (query, &count); - if (status) { - notmuch_query_destroy (query); - return status; + /* look for a non-ghost message in the same thread */ + try { + Xapian::PostingIterator thread_doc, thread_doc_end; + Xapian::PostingIterator mail_doc, mail_doc_end; + + _notmuch_database_find_doc_ids (message->notmuch, "thread", tid, &thread_doc, + &thread_doc_end); + _notmuch_database_find_doc_ids (message->notmuch, "type", "mail", &mail_doc, &mail_doc_end); + + while (count == 0 && + thread_doc != thread_doc_end && + mail_doc != mail_doc_end) { + thread_doc.skip_to (*mail_doc); + if (thread_doc != thread_doc_end) { + if (*thread_doc == *mail_doc) { + count++; + } else { + mail_doc.skip_to (*thread_doc); + if (mail_doc != mail_doc_end && *thread_doc == *mail_doc) + count++; + } + } + } + } catch (Xapian::Error &error) { + LOG_XAPIAN_EXCEPTION (message, error); + return NOTMUCH_STATUS_XAPIAN_EXCEPTION; } - if (count > 0) { /* reintroduce a ghost in its place because there are still * other active messages in this thread: */ @@ -1410,27 +1410,21 @@ _notmuch_message_delete (notmuch_message_t *message) notmuch_message_destroy (ghost); status = COERCE_STATUS (private_status, "Error converting to ghost message"); } else { - /* the thread is empty; drop all ghost messages from it */ - notmuch_messages_t *messages; - status = _notmuch_query_search_documents (query, - "ghost", - &messages); - if (status == NOTMUCH_STATUS_SUCCESS) { - notmuch_status_t last_error = NOTMUCH_STATUS_SUCCESS; - while (notmuch_messages_valid (messages)) { - message = notmuch_messages_get (messages); - status = _notmuch_message_delete (message); - if (status) /* we'll report the last failure we see; - * if there is more than one failure, we - * forget about previous ones */ - last_error = status; - notmuch_message_destroy (message); - notmuch_messages_move_to_next (messages); + /* the thread now contains only ghosts: delete them */ + try { + Xapian::PostingIterator doc, doc_end; + + _notmuch_database_find_doc_ids (message->notmuch, "thread", tid, &doc, &doc_end); + + for (; doc != doc_end; doc++) { + message->notmuch->writable_xapian_db->delete_document (*doc); } - status = last_error; + } catch (Xapian::Error &error) { + LOG_XAPIAN_EXCEPTION (message, error); + return NOTMUCH_STATUS_XAPIAN_EXCEPTION; } + } - notmuch_query_destroy (query); return status; } @@ -1479,24 +1473,30 @@ _notmuch_message_add_term (notmuch_message_t *message, { char *term; + notmuch_private_status_t status = NOTMUCH_PRIVATE_STATUS_SUCCESS; if (value == NULL) return NOTMUCH_PRIVATE_STATUS_NULL_POINTER; term = talloc_asprintf (message, "%s%s", _find_prefix (prefix_name), value); + if (strlen (term) > NOTMUCH_TERM_MAX) { + status = NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG; + goto DONE; + } - if (strlen (term) > NOTMUCH_TERM_MAX) - return NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG; - - message->doc.add_term (term, 0); - message->modified = true; + try { + message->doc.add_term (term, 0); + message->modified = true; + _notmuch_message_invalidate_metadata (message, prefix_name); + } catch (Xapian::Error &error) { + LOG_XAPIAN_EXCEPTION (message, error); + status = NOTMUCH_PRIVATE_STATUS_XAPIAN_EXCEPTION; + } + DONE: talloc_free (term); - - _notmuch_message_invalidate_metadata (message, prefix_name); - - return NOTMUCH_PRIVATE_STATUS_SUCCESS; + return status; } /* Parse 'text' and add a term to 'message' for each parsed word. Each @@ -1560,11 +1560,12 @@ _notmuch_message_remove_term (notmuch_message_t *message, try { message->doc.remove_term (term); message->modified = true; - } catch (const Xapian::InvalidArgumentError) { + } catch (const Xapian::InvalidArgumentError &error) { /* We'll let the philosophers try to wrestle with the * question of whether failing to remove that which was not * there in the first place is failure. For us, we'll silently * consider it all good. */ + LOG_XAPIAN_EXCEPTION (message, error); } talloc_free (term);