X-Git-Url: http://rtime.felk.cvut.cz/gitweb/notmuch.git/blobdiff_plain/cec601c4dd94d19ce7e27804b6a2adbb9197824d..d9f5da00bb7707f3244654b4e44df2284e3634be:/lib/database.cc diff --git a/lib/database.cc b/lib/database.cc index a47a71d5..c641bcde 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -50,8 +50,8 @@ typedef struct { /* Here's the current schema for our database (for NOTMUCH_DATABASE_VERSION): * - * We currently have two different types of documents (mail and - * directory) and also some metadata. + * We currently have three different types of documents (mail, ghost, + * and directory) and also some metadata. * * Mail document * ------------- @@ -109,6 +109,15 @@ typedef struct { * * The data portion of a mail document is empty. * + * Ghost mail document [if NOTMUCH_FEATURE_GHOSTS] + * ----------------------------------------------- + * A ghost mail document is like a mail document, but where we don't + * have the message content. These are used to track thread reference + * information for messages we haven't received. + * + * A ghost mail document has type: ghost; id and thread fields that + * are identical to the mail document fields; and a MESSAGE_ID value. + * * Directory document * ------------------ * A directory document is used by a client of the notmuch library to @@ -172,6 +181,13 @@ typedef struct { * generated is 1 and the value will be * incremented for each thread ID. * + * Obsolete metadata + * ----------------- + * + * If ! NOTMUCH_FEATURE_GHOSTS, there are no ghost mail documents. + * Instead, the database has the following additional database + * metadata: + * * thread_id_* A pre-allocated thread ID for a particular * message. This is actually an arbitrarily large * family of metadata name. Any particular name is @@ -286,6 +302,8 @@ static const struct { "from/subject/message-ID in database", "w" }, { NOTMUCH_FEATURE_BOOL_FOLDER, "exact folder:/path: search", "rw" }, + { NOTMUCH_FEATURE_GHOSTS, + "mail documents for missing messages", "w"}, }; const char * @@ -390,8 +408,8 @@ find_document_for_doc_id (notmuch_database_t *notmuch, unsigned doc_id) * * notmuch-sha1- */ -static char * -_message_id_compressed (void *ctx, const char *message_id) +char * +_notmuch_message_id_compressed (void *ctx, const char *message_id) { char *sha1, *compressed; @@ -415,7 +433,7 @@ notmuch_database_find_message (notmuch_database_t *notmuch, return NOTMUCH_STATUS_NULL_POINTER; if (strlen (message_id) > NOTMUCH_MESSAGE_ID_MAX) - message_id = _message_id_compressed (notmuch, message_id); + message_id = _notmuch_message_id_compressed (notmuch, message_id); try { status = _notmuch_database_find_unique_doc_id (notmuch, "id", @@ -1728,7 +1746,7 @@ static char * _get_metadata_thread_id_key (void *ctx, const char *message_id) { if (strlen (message_id) > NOTMUCH_MESSAGE_ID_MAX) - message_id = _message_id_compressed (ctx, message_id); + message_id = _notmuch_message_id_compressed (ctx, message_id); return talloc_asprintf (ctx, NOTMUCH_METADATA_THREAD_ID_PREFIX "%s", message_id); @@ -1958,6 +1976,37 @@ _notmuch_database_link_message_to_children (notmuch_database_t *notmuch, return ret; } +/* Fetch and clear the stored thread_id for message, or NULL if none. */ +static char * +_consume_metadata_thread_id (void *ctx, notmuch_database_t *notmuch, + notmuch_message_t *message) +{ + const char *message_id; + string stored_id; + char *metadata_key; + + message_id = notmuch_message_get_message_id (message); + metadata_key = _get_metadata_thread_id_key (ctx, message_id); + + /* Check if we have already seen related messages to this one. + * If we have then use the thread_id that we stored at that time. + */ + stored_id = notmuch->xapian_db->get_metadata (metadata_key); + if (stored_id.empty ()) { + return NULL; + } else { + Xapian::WritableDatabase *db; + + db = static_cast (notmuch->xapian_db); + + /* Clear the metadata for this message ID. We don't need it + * anymore. */ + db->set_metadata (metadata_key, ""); + + return talloc_strdup (ctx, stored_id.c_str ()); + } +} + /* Given a (mostly empty) 'message' and its corresponding * 'message_file' link it to existing threads in the database. * @@ -1988,42 +2037,25 @@ _notmuch_database_link_message (notmuch_database_t *notmuch, notmuch_message_t *message, notmuch_message_file_t *message_file) { + void *local = talloc_new (NULL); notmuch_status_t status; - const char *message_id, *thread_id = NULL; - char *metadata_key; - string stored_id; - - message_id = notmuch_message_get_message_id (message); - metadata_key = _get_metadata_thread_id_key (message, message_id); - - /* Check if we have already seen related messages to this one. - * If we have then use the thread_id that we stored at that time. - */ - stored_id = notmuch->xapian_db->get_metadata (metadata_key); - if (! stored_id.empty()) { - Xapian::WritableDatabase *db; - - db = static_cast (notmuch->xapian_db); - - /* Clear the metadata for this message ID. We don't need it - * anymore. */ - db->set_metadata (metadata_key, ""); - thread_id = stored_id.c_str(); + const char *thread_id; - _notmuch_message_add_term (message, "thread", thread_id); - } - talloc_free (metadata_key); + /* Check if the message already had a thread ID */ + thread_id = _consume_metadata_thread_id (local, notmuch, message); + if (thread_id) + _notmuch_message_add_term (message, "thread", thread_id); status = _notmuch_database_link_message_to_parents (notmuch, message, message_file, &thread_id); if (status) - return status; + goto DONE; status = _notmuch_database_link_message_to_children (notmuch, message, &thread_id); if (status) - return status; + goto DONE; /* If not part of any existing thread, generate a new thread ID. */ if (thread_id == NULL) { @@ -2032,7 +2064,10 @@ _notmuch_database_link_message (notmuch_database_t *notmuch, _notmuch_message_add_term (message, "thread", thread_id); } - return NOTMUCH_STATUS_SUCCESS; + DONE: + talloc_free (local); + + return status; } notmuch_status_t @@ -2100,14 +2135,6 @@ notmuch_database_add_message (notmuch_database_t *notmuch, * better than no message-id at all. */ if (message_id == NULL) message_id = talloc_strdup (message_file, header); - - /* If a message ID is too long, substitute its sha1 instead. */ - if (message_id && strlen (message_id) > NOTMUCH_MESSAGE_ID_MAX) { - char *compressed = _message_id_compressed (message_file, - message_id); - talloc_free (message_id); - message_id = compressed; - } } if (message_id == NULL ) {