X-Git-Url: https://git.notmuchmail.org/git?a=blobdiff_plain;ds=sidebyside;f=database.cc;h=b58d92d974915c52808c4f761aaf3a750606c906;hb=69b25a75ec8f4a8b27fe25f234a39a7e67287d36;hp=e46fe5d8915dd55910a9822560ddb3ba0e37427d;hpb=6c5054ebee5beb72c22d91a57c66b8ecdc65f7bf;p=notmuch diff --git a/database.cc b/database.cc index e46fe5d8..b58d92d9 100644 --- a/database.cc +++ b/database.cc @@ -28,42 +28,30 @@ using namespace std; -/* "128 bits of thread-id ought to be enough for anybody" */ -#define NOTMUCH_THREAD_ID_BITS 128 -#define NOTMUCH_THREAD_ID_DIGITS (NOTMUCH_THREAD_ID_BITS / 4) -typedef struct _thread_id { - char str[NOTMUCH_THREAD_ID_DIGITS + 1]; -} thread_id_t; - -static void -thread_id_generate (thread_id_t *thread_id) +const char * +notmuch_status_to_string (notmuch_status_t status) { - static int seeded = 0; - FILE *dev_random; - uint32_t value; - char *s; - int i; - - if (! seeded) { - dev_random = fopen ("/dev/random", "r"); - if (dev_random == NULL) { - srand (time (NULL)); - } else { - fread ((void *) &value, sizeof (value), 1, dev_random); - srand (value); - fclose (dev_random); - } - seeded = 1; - } - - s = thread_id->str; - for (i = 0; i < NOTMUCH_THREAD_ID_DIGITS; i += 8) { - value = rand (); - sprintf (s, "%08x", value); - s += 8; + switch (status) { + case NOTMUCH_STATUS_SUCCESS: + return "No error occurred"; + case NOTMUCH_STATUS_XAPIAN_EXCEPTION: + return "A Xapian exception occurred"; + case NOTMUCH_STATUS_FILE_ERROR: + return "Something went wrong trying to read or write a file"; + case NOTMUCH_STATUS_FILE_NOT_EMAIL: + return "File is not an email"; + case NOTMUCH_STATUS_NULL_POINTER: + return "Erroneous NULL pointer"; + case NOTMUCH_STATUS_TAG_TOO_LONG: + return "Tag value is too long"; + default: + case NOTMUCH_STATUS_LAST_STATUS: + return "Unknown error status value"; } } +/* XXX: We should drop this function and convert all callers to call + * _notmuch_message_add_term instead. */ static void add_term (Xapian::Document doc, const char *prefix_name, @@ -111,6 +99,29 @@ find_message_by_docid (Xapian::Database *db, Xapian::docid docid) return db->get_document (docid); } +static void +insert_thread_id (GHashTable *thread_ids, Xapian::Document doc) +{ + string value_string; + const char *value, *id, *comma; + + value_string = doc.get_value (NOTMUCH_VALUE_THREAD); + value = value_string.c_str(); + if (strlen (value)) { + id = value; + while (*id) { + comma = strchr (id, ','); + if (comma == NULL) + comma = id + strlen (id); + g_hash_table_insert (thread_ids, + strndup (id, comma - id), NULL); + id = comma; + if (*id) + id++; + } + } +} + notmuch_message_t * notmuch_database_find_message (notmuch_database_t *notmuch, const char *message_id) @@ -152,16 +163,8 @@ find_thread_ids (notmuch_database_t *notmuch, find_messages_by_term (db, "ref", message_id, &child, &children_end); for ( ; child != children_end; child++) { - const char *thread_id; doc = find_message_by_docid (db, *child); - - thread_id = doc.get_value (NOTMUCH_VALUE_THREAD).c_str (); - if (strlen (thread_id) == 0) { - fprintf (stderr, "Database error: Message with doc_id %u has empty thread-id value (value index %d)\n", - *child, NOTMUCH_VALUE_THREAD); - } else { - g_hash_table_insert (thread_ids, strdup (thread_id), NULL); - } + insert_thread_id (thread_ids, doc); } for (i = 0; i < parents->len; i++) { @@ -450,7 +453,8 @@ notmuch_database_add_message (notmuch_database_t *notmuch, { Xapian::WritableDatabase *db = notmuch->xapian_db; Xapian::Document doc; - notmuch_message_file_t *message; + notmuch_message_file_t *message_file; + notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS; GPtrArray *parents, *thread_ids; @@ -461,55 +465,70 @@ notmuch_database_add_message (notmuch_database_t *notmuch, time_t time_value; unsigned int i; - message = notmuch_message_file_open (filename); + message_file = notmuch_message_file_open (filename); + if (message_file == NULL) { + ret = NOTMUCH_STATUS_FILE_ERROR; + goto DONE; + } - notmuch_message_file_restrict_headers (message, + notmuch_message_file_restrict_headers (message_file, "date", "from", "in-reply-to", "message-id", "references", "subject", + "to", (char *) NULL); try { + header = notmuch_message_file_get_header (message_file, "message-id"); + if (header) { + message_id = parse_message_id (header, NULL); + /* So the header value isn't RFC-compliant, but it's + * better than no message-id at all. */ + if (message_id == NULL) + message_id = xstrdup (header); + } else { + /* No message-id at all, let's generate one by taking a + * hash over the file's contents. */ + char *sha1 = notmuch_sha1_of_file (filename); + + /* If that failed too, something is really wrong. Give up. */ + if (sha1 == NULL) { + ret = NOTMUCH_STATUS_FILE_ERROR; + goto DONE; + } + + message_id = g_strdup_printf ("notmuch-sha1-%s", sha1); + free (sha1); + } + doc.set_data (filename); add_term (doc, "type", "mail"); parents = g_ptr_array_new (); - refs = notmuch_message_file_get_header (message, "references"); + refs = notmuch_message_file_get_header (message_file, "references"); parse_references (parents, refs); - in_reply_to = notmuch_message_file_get_header (message, "in-reply-to"); + in_reply_to = notmuch_message_file_get_header (message_file, "in-reply-to"); parse_references (parents, in_reply_to); for (i = 0; i < parents->len; i++) add_term (doc, "ref", (char *) g_ptr_array_index (parents, i)); - header = notmuch_message_file_get_header (message, "message-id"); - if (header) { - message_id = parse_message_id (header, NULL); - /* So the header value isn't RFC-compliant, but it's - * better than no message-id at all. */ - if (message_id == NULL) - message_id = xstrdup (header); - } else { - /* XXX: Should generate a message_id here, (such as a SHA1 - * sum of the message itself) */ - message_id = NULL; - } - thread_ids = find_thread_ids (notmuch, parents, message_id); for (i = 0; i < parents->len; i++) g_free (g_ptr_array_index (parents, i)); g_ptr_array_free (parents, TRUE); - if (message_id) { - add_term (doc, "msgid", message_id); - doc.add_value (NOTMUCH_VALUE_MESSAGE_ID, message_id); - } + + add_term (doc, "msgid", message_id); + doc.add_value (NOTMUCH_VALUE_MESSAGE_ID, message_id); + + free (message_id); if (thread_ids->len) { unsigned int i; @@ -528,7 +547,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch, } doc.add_value (NOTMUCH_VALUE_THREAD, thread_id->str); g_string_free (thread_id, TRUE); - } else if (message_id) { + } else { /* If not part of any existing thread, generate a new thread_id. */ thread_id_t thread_id; @@ -539,34 +558,35 @@ notmuch_database_add_message (notmuch_database_t *notmuch, g_ptr_array_free (thread_ids, TRUE); - free (message_id); - - date = notmuch_message_file_get_header (message, "date"); + date = notmuch_message_file_get_header (message_file, "date"); time_value = notmuch_parse_date (date, NULL); doc.add_value (NOTMUCH_VALUE_DATE, Xapian::sortable_serialise (time_value)); - from = notmuch_message_file_get_header (message, "from"); - subject = notmuch_message_file_get_header (message, "subject"); - to = notmuch_message_file_get_header (message, "to"); + from = notmuch_message_file_get_header (message_file, "from"); + subject = notmuch_message_file_get_header (message_file, "subject"); + to = notmuch_message_file_get_header (message_file, "to"); if (from == NULL && subject == NULL && to == NULL) { - notmuch_message_file_close (message); - return NOTMUCH_STATUS_FILE_NOT_EMAIL; + ret = NOTMUCH_STATUS_FILE_NOT_EMAIL; + goto DONE; } else { db->add_document (doc); } } catch (const Xapian::Error &error) { fprintf (stderr, "A Xapian exception occurred: %s.\n", error.get_msg().c_str()); - return NOTMUCH_STATUS_XAPIAN_EXCEPTION; + ret = NOTMUCH_STATUS_XAPIAN_EXCEPTION; + goto DONE; } - notmuch_message_file_close (message); + DONE: + if (message_file) + notmuch_message_file_close (message_file); - return NOTMUCH_STATUS_SUCCESS; + return ret; }