X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=lib%2Fdatabase.cc;h=df83e2048673b235e6c1055ccb47d39923f480a7;hp=f96ba7c004bd6338d0c0a92bb5ad94464a3d7f50;hb=2786aa4d548d28579c761e9358d44c84dfb29068;hpb=c447fe92c7ec3e6730d2cd0d739d8978cf8696f1 diff --git a/lib/database.cc b/lib/database.cc index f96ba7c0..df83e204 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -49,7 +49,8 @@ typedef struct { #define LOG_XAPIAN_EXCEPTION(message, error) _log_xapian_exception (__location__, message, error) static void -_log_xapian_exception (const char *where, notmuch_database_t *notmuch, const Xapian::Error error) { +_log_xapian_exception (const char *where, notmuch_database_t *notmuch, const Xapian::Error error) +{ _notmuch_database_log (notmuch, "A Xapian exception occurred at %s: %s\n", where, @@ -292,12 +293,26 @@ notmuch_status_to_string (notmuch_status_t status) return "Operation requires a database upgrade"; case NOTMUCH_STATUS_PATH_ERROR: return "Path supplied is illegal for this function"; + case NOTMUCH_STATUS_IGNORED: + return "Argument was ignored"; + case NOTMUCH_STATUS_ILLEGAL_ARGUMENT: + return "Illegal argument for function"; case NOTMUCH_STATUS_MALFORMED_CRYPTO_PROTOCOL: return "Crypto protocol missing, malformed, or unintelligible"; case NOTMUCH_STATUS_FAILED_CRYPTO_CONTEXT_CREATION: return "Crypto engine initialization failure"; case NOTMUCH_STATUS_UNKNOWN_CRYPTO_PROTOCOL: return "Unknown crypto protocol"; + case NOTMUCH_STATUS_NO_CONFIG: + return "No configuration file found"; + case NOTMUCH_STATUS_NO_DATABASE: + return "No database found"; + case NOTMUCH_STATUS_DATABASE_EXISTS: + return "Database exists, not recreated"; + case NOTMUCH_STATUS_BAD_QUERY_SYNTAX: + return "Syntax error in query"; + case NOTMUCH_STATUS_NO_MAIL_ROOT: + return "No mail root found"; default: case NOTMUCH_STATUS_LAST_STATUS: return "Unknown error status value"; @@ -491,22 +506,15 @@ notmuch_database_close (notmuch_database_t *notmuch) * close it. Thus, we explicitly close it here. */ if (notmuch->open) { try { - /* If there's an outstanding transaction, it's unclear if - * closing the Xapian database commits everything up to - * that transaction, or may discard committed (but - * unflushed) transactions. To be certain, explicitly - * cancel any outstanding transaction before closing. */ - if (_notmuch_database_mode (notmuch) == NOTMUCH_DATABASE_MODE_READ_WRITE && - notmuch->atomic_nesting) - notmuch->writable_xapian_db->cancel_transaction (); - /* Close the database. This implicitly flushes - * outstanding changes. */ + * outstanding changes. If there is an open (non-flushed) + * transaction, ALL pending changes will be discarded */ notmuch->xapian_db->close (); } catch (const Xapian::Error &error) { status = NOTMUCH_STATUS_XAPIAN_EXCEPTION; if (! notmuch->exception_reported) { - _notmuch_database_log (notmuch, "Error: A Xapian exception occurred closing database: %s\n", + _notmuch_database_log (notmuch, + "Error: A Xapian exception occurred closing database: %s\n", error.get_msg ().c_str ()); } } @@ -515,28 +523,6 @@ notmuch_database_close (notmuch_database_t *notmuch) return status; } -notmuch_status_t -_notmuch_database_reopen (notmuch_database_t *notmuch) -{ - if (_notmuch_database_mode (notmuch) != NOTMUCH_DATABASE_MODE_READ_ONLY) - return NOTMUCH_STATUS_UNSUPPORTED_OPERATION; - - try { - notmuch->xapian_db->reopen (); - } catch (const Xapian::Error &error) { - if (! notmuch->exception_reported) { - _notmuch_database_log (notmuch, "Error: A Xapian exception reopening database: %s\n", - error.get_msg ().c_str ()); - notmuch->exception_reported = true; - } - return NOTMUCH_STATUS_XAPIAN_EXCEPTION; - } - - notmuch->view++; - - return NOTMUCH_STATUS_SUCCESS; -} - static int unlink_cb (const char *path, unused (const struct stat *sb), @@ -606,10 +592,12 @@ notmuch_database_compact (const char *path, notmuch_database_t *notmuch = NULL; char *message = NULL; - ret = notmuch_database_open_verbose (path, - NOTMUCH_DATABASE_MODE_READ_WRITE, - ¬much, - &message); + ret = notmuch_database_open_with_config (path, + NOTMUCH_DATABASE_MODE_READ_WRITE, + "", + NULL, + ¬much, + &message); if (ret) { if (status_cb) status_cb (message, closure); return ret; @@ -627,13 +615,15 @@ notmuch_status_t notmuch_database_compact_db (notmuch_database_t *notmuch, const char *backup_path, notmuch_compact_status_cb_t status_cb, - void *closure) { + void *closure) +{ void *local; - char *notmuch_path, *xapian_path, *compact_xapian_path; - const char* path; + const char *xapian_path, *compact_xapian_path; + const char *path; notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS; struct stat statbuf; bool keep_backup; + char *message; ret = _notmuch_database_ensure_writable (notmuch); if (ret) @@ -647,15 +637,9 @@ notmuch_database_compact_db (notmuch_database_t *notmuch, if (! local) return NOTMUCH_STATUS_OUT_OF_MEMORY; - if (! (notmuch_path = talloc_asprintf (local, "%s/%s", path, ".notmuch"))) { - ret = NOTMUCH_STATUS_OUT_OF_MEMORY; - goto DONE; - } - - if (! (xapian_path = talloc_asprintf (local, "%s/%s", notmuch_path, "xapian"))) { - ret = NOTMUCH_STATUS_OUT_OF_MEMORY; + ret = _notmuch_choose_xapian_path (local, path, &xapian_path, &message); + if (ret) goto DONE; - } if (! (compact_xapian_path = talloc_asprintf (local, "%s.compact", xapian_path))) { ret = NOTMUCH_STATUS_OUT_OF_MEMORY; @@ -692,7 +676,8 @@ notmuch_database_compact_db (notmuch_database_t *notmuch, try { NotmuchCompactor compactor (status_cb, closure); - notmuch->xapian_db->compact (compact_xapian_path, Xapian::DBCOMPACT_NO_RENUMBER, 0, compactor); + notmuch->xapian_db->compact (compact_xapian_path, Xapian::DBCOMPACT_NO_RENUMBER, 0, + compactor); } catch (const Xapian::Error &error) { _notmuch_database_log (notmuch, "Error while compacting: %s\n", error.get_msg ().c_str ()); ret = NOTMUCH_STATUS_XAPIAN_EXCEPTION; @@ -746,6 +731,15 @@ notmuch_status_t notmuch_database_destroy (notmuch_database_t *notmuch) { notmuch_status_t status; + const char *talloc_report; + + talloc_report = getenv ("NOTMUCH_TALLOC_REPORT"); + if (talloc_report && strcmp (talloc_report, "") != 0) { + FILE *report = fopen (talloc_report, "a"); + if (report) { + talloc_report_full (notmuch, report); + } + } status = notmuch_database_close (notmuch); @@ -761,6 +755,8 @@ notmuch_database_destroy (notmuch_database_t *notmuch) notmuch->date_range_processor = NULL; delete notmuch->last_mod_range_processor; notmuch->last_mod_range_processor = NULL; + delete notmuch->stemmer; + notmuch->stemmer = NULL; talloc_free (notmuch); @@ -770,7 +766,7 @@ notmuch_database_destroy (notmuch_database_t *notmuch) const char * notmuch_database_get_path (notmuch_database_t *notmuch) { - return notmuch->path; + return notmuch_config_get (notmuch, NOTMUCH_CONFIG_DATABASE_PATH); } unsigned int @@ -840,8 +836,8 @@ handle_sigalrm (unused (int signal)) */ notmuch_status_t notmuch_database_upgrade (notmuch_database_t *notmuch, - void (*progress_notify) (void *closure, - double progress), + void (*progress_notify)(void *closure, + double progress), void *closure) { void *local = talloc_new (NULL); @@ -1065,7 +1061,8 @@ notmuch_database_upgrade (notmuch_database_t *notmuch, if (private_status) { _notmuch_database_log (notmuch, "Upgrade failed while creating ghost messages.\n"); - status = COERCE_STATUS (private_status, "Unexpected status from _notmuch_message_initialize_ghost"); + status = COERCE_STATUS (private_status, + "Unexpected status from _notmuch_message_initialize_ghost"); goto DONE; } @@ -1145,13 +1142,21 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch) db = notmuch->writable_xapian_db; try { db->commit_transaction (); - - /* This is a hack for testing. Xapian never flushes on a - * non-flushed commit, even if the flush threshold is 1. - * However, we rely on flushing to test atomicity. */ + notmuch->transaction_count++; + + /* Xapian never flushes on a non-flushed commit, even if the + * flush threshold is 1. However, we rely on flushing to test + * atomicity. On the other hand, we can't straight replace + * XAPIAN_FLUSH_THRESHOLD with our autocommit counter, because + * the former also applies outside notmuch atomic + * commits. Hence the follow complicated test */ const char *thresh = getenv ("XAPIAN_FLUSH_THRESHOLD"); - if (thresh && atoi (thresh) == 1) + if ((notmuch->transaction_threshold > 0 && + notmuch->transaction_count >= notmuch->transaction_threshold) || + (thresh && atoi (thresh) == 1)) { db->commit (); + notmuch->transaction_count = 0; + } } catch (const Xapian::Error &error) { _notmuch_database_log (notmuch, "A Xapian exception occurred committing transaction: %s.\n", error.get_msg ().c_str ()); @@ -1367,7 +1372,7 @@ _notmuch_database_relative_path (notmuch_database_t *notmuch, const char *db_path, *relative; unsigned int db_path_len; - db_path = notmuch_database_get_path (notmuch); + db_path = notmuch_config_get (notmuch, NOTMUCH_CONFIG_MAIL_ROOT); db_path_len = strlen (db_path); relative = path; @@ -1498,7 +1503,8 @@ notmuch_database_find_message_by_filename (notmuch_database_t *notmuch, status = NOTMUCH_STATUS_OUT_OF_MEMORY; } } catch (const Xapian::Error &error) { - _notmuch_database_log (notmuch, "Error: A Xapian exception occurred finding message by filename: %s\n", + _notmuch_database_log (notmuch, + "Error: A Xapian exception occurred finding message by filename: %s\n", error.get_msg ().c_str ()); notmuch->exception_reported = true; status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;