X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=database.cc;h=415040bc7000c4f9cb195e25cb9119d72c15a29d;hp=15d159ffd13494d6f672491a04b3e3868630238c;hb=edd37e68a96ada9187976dd0421b3f545fffbf78;hpb=9fc4a365d6cf478563caa012862c58a9b3945f76 diff --git a/database.cc b/database.cc index 15d159ff..415040bc 100644 --- a/database.cc +++ b/database.cc @@ -43,7 +43,7 @@ notmuch_status_to_string (notmuch_status_t status) case NOTMUCH_STATUS_NULL_POINTER: return "Erroneous NULL pointer"; case NOTMUCH_STATUS_TAG_TOO_LONG: - return "Tag value is too long"; + return "Tag value is too long (exceeds NOTMUCH_TAG_MAX)"; default: case NOTMUCH_STATUS_LAST_STATUS: return "Unknown error status value"; @@ -92,10 +92,49 @@ find_doc_ids (notmuch_database_t *notmuch, free (term); } -Xapian::Document -find_message_by_docid (Xapian::Database *db, Xapian::docid docid) +static notmuch_private_status_t +find_unique_doc_id (notmuch_database_t *notmuch, + const char *prefix_name, + const char *value, + unsigned int *doc_id) { - return db->get_document (docid); + Xapian::PostingIterator i, end; + + find_doc_ids (notmuch, prefix_name, value, &i, &end); + + if (i == end) { + *doc_id = 0; + return NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND; + } else { + *doc_id = *i; + return NOTMUCH_PRIVATE_STATUS_SUCCESS; + } +} + +static Xapian::Document +find_document_for_doc_id (notmuch_database_t *notmuch, unsigned doc_id) +{ + return notmuch->xapian_db->get_document (doc_id); +} + +static notmuch_private_status_t +find_unique_document (notmuch_database_t *notmuch, + const char *prefix_name, + const char *value, + Xapian::Document *document, + unsigned int *doc_id) +{ + notmuch_private_status_t status; + + status = find_unique_doc_id (notmuch, prefix_name, value, doc_id); + + if (status) { + *document = Xapian::Document (); + return status; + } + + *document = find_document_for_doc_id (notmuch, *doc_id); + return NOTMUCH_PRIVATE_STATUS_SUCCESS; } static void @@ -125,14 +164,15 @@ notmuch_message_t * notmuch_database_find_message (notmuch_database_t *notmuch, const char *message_id) { - Xapian::PostingIterator i, end; + notmuch_private_status_t status; + unsigned int doc_id; - find_doc_ids (notmuch, "msgid", message_id, &i, &end); + status = find_unique_doc_id (notmuch, "msgid", message_id, &doc_id); - if (i == end) + if (status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) return NULL; - return _notmuch_message_create (notmuch, notmuch, *i); + return _notmuch_message_create (notmuch, notmuch, doc_id); } /* Return one or more thread_ids, (as a GPtrArray of strings), for the @@ -147,7 +187,6 @@ find_thread_ids (notmuch_database_t *notmuch, GPtrArray *parents, const char *message_id) { - Xapian::WritableDatabase *db = notmuch->xapian_db; Xapian::PostingIterator child, children_end; Xapian::Document doc; GHashTable *thread_ids; @@ -161,7 +200,7 @@ find_thread_ids (notmuch_database_t *notmuch, find_doc_ids (notmuch, "ref", message_id, &child, &children_end); for ( ; child != children_end; child++) { - doc = find_message_by_docid (db, *child); + doc = find_document_for_doc_id (notmuch, *child); insert_thread_id (thread_ids, doc); } @@ -445,6 +484,101 @@ notmuch_database_get_path (notmuch_database_t *notmuch) return notmuch->path; } +notmuch_private_status_t +find_timestamp_document (notmuch_database_t *notmuch, const char *db_key, + Xapian::Document *doc, unsigned int *doc_id) +{ + return find_unique_document (notmuch, "timestamp", db_key, doc, doc_id); +} + +/* We allow the user to use arbitrarily long keys for timestamps, + * (they're for filesystem paths after all, which have no limit we + * know about). But we have a term-length limit. So if we exceed that, + * we'll use the SHA-1 of the user's key as the actual key for + * constructing a database term. + * + * Caution: This function returns a newly allocated string which the + * caller should free() when finished. + */ +static char * +timestamp_db_key (const char *key) +{ + if (strlen (key) + 1 > NOTMUCH_TERM_MAX) { + return notmuch_sha1_of_string (key); + } else { + return strdup (key); + } +} + +notmuch_status_t +notmuch_database_set_timestamp (notmuch_database_t *notmuch, + const char *key, time_t timestamp) +{ + Xapian::Document doc; + unsigned int doc_id; + notmuch_private_status_t status; + notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS; + char *db_key = NULL; + + db_key = timestamp_db_key (key); + + try { + status = find_timestamp_document (notmuch, db_key, &doc, &doc_id); + + doc.add_value (0, Xapian::sortable_serialise (timestamp)); + + if (status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) { + char *term = talloc_asprintf (NULL, "%s%s", + _find_prefix ("timestamp"), db_key); + doc.add_term (term); + talloc_free (term); + + notmuch->xapian_db->add_document (doc); + } else { + notmuch->xapian_db->replace_document (doc_id, doc); + } + + } catch (Xapian::Error &error) { + fprintf (stderr, "A Xapian exception occurred: %s.\n", + error.get_msg().c_str()); + ret = NOTMUCH_STATUS_XAPIAN_EXCEPTION; + } + + if (db_key) + free (db_key); + + return ret; +} + +time_t +notmuch_database_get_timestamp (notmuch_database_t *notmuch, const char *key) +{ + Xapian::Document doc; + unsigned int doc_id; + notmuch_private_status_t status; + char *db_key = NULL; + time_t ret = 0; + + db_key = timestamp_db_key (key); + + try { + status = find_timestamp_document (notmuch, db_key, &doc, &doc_id); + + if (status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) + goto DONE; + + ret = Xapian::sortable_unserialise (doc.get_value (0)); + } catch (Xapian::Error &error) { + goto DONE; + } + + DONE: + if (db_key) + free (db_key); + + return ret; +} + notmuch_status_t notmuch_database_add_message (notmuch_database_t *notmuch, const char *filename)