From 992843feed3380be6cd76cc804a8b36ab3cc0f08 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Sun, 1 Dec 2013 15:14:00 +0200 Subject: [PATCH] [PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle --- bc/4bcc06282640f7e2de53c285c0bf1e70f06497 | 671 ++++++++++++++++++++++ 1 file changed, 671 insertions(+) create mode 100644 bc/4bcc06282640f7e2de53c285c0bf1e70f06497 diff --git a/bc/4bcc06282640f7e2de53c285c0bf1e70f06497 b/bc/4bcc06282640f7e2de53c285c0bf1e70f06497 new file mode 100644 index 000000000..63bacf736 --- /dev/null +++ b/bc/4bcc06282640f7e2de53c285c0bf1e70f06497 @@ -0,0 +1,671 @@ +Return-Path: +X-Original-To: notmuch@notmuchmail.org +Delivered-To: notmuch@notmuchmail.org +Received: from localhost (localhost [127.0.0.1]) + by olra.theworths.org (Postfix) with ESMTP id 45D0A429E37 + for ; Sun, 1 Dec 2013 05:14:21 -0800 (PST) +X-Virus-Scanned: Debian amavisd-new at olra.theworths.org +X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" +X-Spam-Flag: NO +X-Spam-Score: -0.7 +X-Spam-Level: +X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5 + tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled +Received: from olra.theworths.org ([127.0.0.1]) + by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id wILZwBwNO8cq for ; + Sun, 1 Dec 2013 05:14:16 -0800 (PST) +Received: from mail-ea0-f176.google.com (mail-ea0-f176.google.com + [209.85.215.176]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) + (No client certificate requested) + by olra.theworths.org (Postfix) with ESMTPS id B2E91431FDC + for ; Sun, 1 Dec 2013 05:14:14 -0800 (PST) +Received: by mail-ea0-f176.google.com with SMTP id h14so8145704eaj.35 + for ; Sun, 01 Dec 2013 05:14:13 -0800 (PST) +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20130820; + h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to + :references:in-reply-to:references; + bh=YAsMLe1afCIk4XzUWa68mP7QmhaTsh/rPVEI/q/voNE=; + b=HvdnWKAJvijwp9w0HMSnWPUOitHmMWITqOET/4Rq1Mp8CQUhz+2iOfm1w2yexwtSvI + n+RJoAGbWiV7fuZBQ4w60XUGOt8RPL6FDBTfqUiO2geEIaa1Eu0gZZtwHe2UxAZeRMwn + NkumMlfhje6nxjG7qFZ2sNNBoBBjceo/qZyekKAGwhgZUO8xG8LCLZx3pwQzofq+LGlp + IJXknT8/oq5x/2mAcTbXIvN9JtNplrm16maNCfrqRi8rMGeor4y6zO2QzSuLb2Ro/XGS + irLCivai/AX0Tn1dqYCb9Fztrh+erWHIOAGdIPG1PN1VRUTVGtXUYq9FbcR/4icnceMh + QVFw== +X-Gm-Message-State: + ALoCoQmzcCntAWbCg4RzEfyQY33iR0xvoUvhb6jp1jxG2hPeFRmBGYNEoOuM59QFRO3Em1EPgKxm +X-Received: by 10.15.86.75 with SMTP id h51mr75434eez.44.1385903653491; + Sun, 01 Dec 2013 05:14:13 -0800 (PST) +Received: from localhost (dsl-hkibrasgw2-58c36f-91.dhcp.inet.fi. + [88.195.111.91]) + by mx.google.com with ESMTPSA id m1sm54883447eeg.0.2013.12.01.05.14.11 + for + (version=TLSv1.2 cipher=RC4-SHA bits=128/128); + Sun, 01 Dec 2013 05:14:12 -0800 (PST) +From: Jani Nikula +To: notmuch@notmuchmail.org +Subject: [PATCH 2/2] lib: introduce notmuch_database_new for initializing a + database handle +Date: Sun, 1 Dec 2013 15:14:00 +0200 +Message-Id: + +X-Mailer: git-send-email 1.8.4.2 +In-Reply-To: +References: +In-Reply-To: +References: +X-BeenThere: notmuch@notmuchmail.org +X-Mailman-Version: 2.1.13 +Precedence: list +List-Id: "Use and development of the notmuch mail system." + +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +X-List-Received-Date: Sun, 01 Dec 2013 13:14:21 -0000 + +There is a need for setting options before opening a database, such as +setting a logging function to use instead of writing to stdout or +stderr. It would be possible to do this by adding new parameters to +notmuch_database_create and notmuch_database_open, but maintaining a +backwards compatible API and ABI when new options are added becomes +burdensome. + +Instead, split the opaque database object creation from +notmuch_database_create and notmuch_database_open into a new +notmuch_database_new call, to allow operations on the handle before +create and open. This creates API and ABI breakage now, but allows +easier future extensions. + +The notmuch_database_new call becomes a natural pair to the already +existing notmuch_database_destroy, and it should be possible to call +open/close multiple times using an initialized handle. +--- + lib/database.cc | 64 ++++++++++++++++++++++++++++------------------------ + lib/notmuch.h | 52 ++++++++++++++++++++++++++++++++---------- + notmuch-compact.c | 11 ++++++++- + notmuch-count.c | 10 ++++++-- + notmuch-dump.c | 10 ++++++-- + notmuch-insert.c | 10 ++++++-- + notmuch-new.c | 14 +++++++----- + notmuch-reply.c | 10 ++++++-- + notmuch-restore.c | 10 ++++++-- + notmuch-search.c | 10 ++++++-- + notmuch-show.c | 10 ++++++-- + notmuch-tag.c | 10 ++++++-- + test/random-corpus.c | 10 ++++++-- + test/symbol-test.cc | 3 ++- + 14 files changed, 166 insertions(+), 68 deletions(-) + +diff --git a/lib/database.cc b/lib/database.cc +index 98e2c31..386b93a 100644 +--- a/lib/database.cc ++++ b/lib/database.cc +@@ -539,10 +539,21 @@ parse_references (void *ctx, + } + + notmuch_status_t +-notmuch_database_create (const char *path, notmuch_database_t **database) ++notmuch_database_new (notmuch_database_t **notmuch) ++{ ++ /* Note: try to avoid error conditions! No error printing! */ ++ ++ *notmuch = talloc_zero (NULL, notmuch_database_t); ++ if (! *notmuch) ++ return NOTMUCH_STATUS_OUT_OF_MEMORY; ++ ++ return NOTMUCH_STATUS_SUCCESS; ++} ++ ++notmuch_status_t ++notmuch_database_create (notmuch_database_t *notmuch, const char *path) + { + notmuch_status_t status = NOTMUCH_STATUS_SUCCESS; +- notmuch_database_t *notmuch = NULL; + char *notmuch_path = NULL; + struct stat st; + int err; +@@ -579,25 +590,18 @@ notmuch_database_create (const char *path, notmuch_database_t **database) + goto DONE; + } + +- status = notmuch_database_open (path, +- NOTMUCH_DATABASE_MODE_READ_WRITE, +- ¬much); ++ status = notmuch_database_open (notmuch, path, ++ NOTMUCH_DATABASE_MODE_READ_WRITE); + if (status) + goto DONE; + status = notmuch_database_upgrade (notmuch, NULL, NULL); +- if (status) { ++ if (status) + notmuch_database_close(notmuch); +- notmuch = NULL; +- } + + DONE: + if (notmuch_path) + talloc_free (notmuch_path); + +- if (database) +- *database = notmuch; +- else +- talloc_free (notmuch); + return status; + } + +@@ -612,14 +616,15 @@ _notmuch_database_ensure_writable (notmuch_database_t *notmuch) + return NOTMUCH_STATUS_SUCCESS; + } + ++/* ++ * XXX: error handling should clean up *all* state created! ++ */ + notmuch_status_t +-notmuch_database_open (const char *path, +- notmuch_database_mode_t mode, +- notmuch_database_t **database) ++notmuch_database_open (notmuch_database_t *notmuch, const char *path, ++ notmuch_database_mode_t mode) + { + notmuch_status_t status = NOTMUCH_STATUS_SUCCESS; + void *local = talloc_new (NULL); +- notmuch_database_t *notmuch = NULL; + char *notmuch_path, *xapian_path; + struct stat st; + int err; +@@ -663,7 +668,6 @@ notmuch_database_open (const char *path, + initialized = 1; + } + +- notmuch = talloc_zero (NULL, notmuch_database_t); + notmuch->exception_reported = FALSE; + notmuch->path = talloc_strdup (notmuch, path); + +@@ -689,8 +693,7 @@ notmuch_database_open (const char *path, + " read-write mode.\n", + notmuch_path, version, NOTMUCH_DATABASE_VERSION); + notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY; +- notmuch_database_destroy (notmuch); +- notmuch = NULL; ++ notmuch_database_close (notmuch); + status = NOTMUCH_STATUS_FILE_ERROR; + goto DONE; + } +@@ -752,21 +755,19 @@ notmuch_database_open (const char *path, + } catch (const Xapian::Error &error) { + fprintf (stderr, "A Xapian exception occurred opening database: %s\n", + error.get_msg().c_str()); +- notmuch_database_destroy (notmuch); +- notmuch = NULL; ++ notmuch_database_close (notmuch); + status = NOTMUCH_STATUS_XAPIAN_EXCEPTION; + } + + DONE: + talloc_free (local); + +- if (database) +- *database = notmuch; +- else +- talloc_free (notmuch); + return status; + } + ++/* ++ * XXX: close should clean up *all* state created by open/create! ++ */ + notmuch_status_t + notmuch_database_close (notmuch_database_t *notmuch) + { +@@ -869,7 +870,8 @@ public: + * compaction process to protect data integrity. + */ + notmuch_status_t +-notmuch_database_compact (const char *path, ++notmuch_database_compact (notmuch_database_t *notmuch, ++ const char *path, + const char *backup_path, + notmuch_compact_status_cb_t status_cb, + void *closure) +@@ -877,7 +879,6 @@ notmuch_database_compact (const char *path, + void *local; + char *notmuch_path, *xapian_path, *compact_xapian_path; + notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS; +- notmuch_database_t *notmuch = NULL; + struct stat statbuf; + notmuch_bool_t keep_backup; + +@@ -885,7 +886,8 @@ notmuch_database_compact (const char *path, + if (! local) + return NOTMUCH_STATUS_OUT_OF_MEMORY; + +- ret = notmuch_database_open (path, NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much); ++ ret = notmuch_database_open (notmuch, path, ++ NOTMUCH_DATABASE_MODE_READ_WRITE); + if (ret) { + goto DONE; + } +@@ -971,8 +973,9 @@ notmuch_database_compact (const char *path, + } + + DONE: ++ /* XXX: error handling */ + if (notmuch) +- ret = notmuch_database_destroy (notmuch); ++ ret = notmuch_database_close (notmuch); + + talloc_free (local); + +@@ -980,7 +983,8 @@ notmuch_database_compact (const char *path, + } + #else + notmuch_status_t +-notmuch_database_compact (unused (const char *path), ++notmuch_database_compact (unused (notmuch_database_t *notmuch), ++ unused (const char *path), + unused (const char *backup_path), + unused (notmuch_compact_status_cb_t status_cb), + unused (void *closure)) +diff --git a/lib/notmuch.h b/lib/notmuch.h +index dbdce86..cd58d15 100644 +--- a/lib/notmuch.h ++++ b/lib/notmuch.h +@@ -149,6 +149,28 @@ typedef struct _notmuch_tags notmuch_tags_t; + typedef struct _notmuch_directory notmuch_directory_t; + typedef struct _notmuch_filenames notmuch_filenames_t; + ++/* Initialize a new, empty database handle. ++ * ++ * The database handle is required for creating, opening, and ++ * compacting a database. For further database operations, the ++ * database needs to be created or opened. ++ * ++ * After a successful call to notmuch_database_new, the returned ++ * database handle will remain in memory, so the caller should call ++ * notmuch_database_destroy when finished with the database handle. ++ * ++ * In case of any failure, this function returns an error status and ++ * sets *notmuch to NULL. ++ * ++ * Return value: ++ * ++ * NOTMUCH_STATUS_SUCCESS: Successfully created the database object. ++ * ++ * NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory. ++ */ ++notmuch_status_t ++notmuch_database_new (notmuch_database_t **notmuch); ++ + /* Create a new, empty notmuch database located at 'path'. + * + * The path should be a top-level directory to a collection of +@@ -156,9 +178,9 @@ typedef struct _notmuch_filenames notmuch_filenames_t; + * create a new ".notmuch" directory within 'path' where notmuch will + * store its data. + * +- * After a successful call to notmuch_database_create, the returned +- * database will be open so the caller should call +- * notmuch_database_destroy when finished with it. ++ * After a successful call to notmuch_database_create, the database ++ * will be open so the caller should call notmuch_database_close (or ++ * notmuch_database_destroy) when finished with the database. + * + * The database will not yet have any data in it + * (notmuch_database_create itself is a very cheap function). Messages +@@ -166,7 +188,8 @@ typedef struct _notmuch_filenames notmuch_filenames_t; + * notmuch_database_add_message. + * + * In case of any failure, this function returns an error status and +- * sets *database to NULL (after printing an error message on stderr). ++ * the database will be closed (after printing an error message on ++ * stderr). + * + * Return value: + * +@@ -183,7 +206,7 @@ typedef struct _notmuch_filenames notmuch_filenames_t; + * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred. + */ + notmuch_status_t +-notmuch_database_create (const char *path, notmuch_database_t **database); ++notmuch_database_create (notmuch_database_t *notmuch, const char *path); + + typedef enum { + NOTMUCH_DATABASE_MODE_READ_ONLY = 0, +@@ -201,11 +224,13 @@ typedef enum { + * An existing notmuch database can be identified by the presence of a + * directory named ".notmuch" below 'path'. + * +- * The caller should call notmuch_database_destroy when finished with +- * this database. ++ * After a successful call to notmuch_database_open, the database will ++ * be open so the caller should call notmuch_database_close (or ++ * notmuch_database_destroy) when finished with the database. + * + * In case of any failure, this function returns an error status and +- * sets *database to NULL (after printing an error message on stderr). ++ * the database will be closed (after printing an error message on ++ * stderr). + * + * Return value: + * +@@ -222,9 +247,8 @@ typedef enum { + * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred. + */ + notmuch_status_t +-notmuch_database_open (const char *path, +- notmuch_database_mode_t mode, +- notmuch_database_t **database); ++notmuch_database_open (notmuch_database_t *notmuch, const char *path, ++ notmuch_database_mode_t mode); + + /* Close the given notmuch database. + * +@@ -264,7 +288,8 @@ typedef void (*notmuch_compact_status_cb_t)(const char *message, void *closure); + * 'closure' is passed verbatim to any callback invoked. + */ + notmuch_status_t +-notmuch_database_compact (const char* path, ++notmuch_database_compact (notmuch_database_t *notmuch, ++ const char* path, + const char* backup_path, + notmuch_compact_status_cb_t status_cb, + void *closure); +@@ -272,6 +297,9 @@ notmuch_database_compact (const char* path, + /* Destroy the notmuch database, closing it if necessary and freeing + * all associated resources. + * ++ * A database handle initialized with notmuch_database_new should be ++ * destroyed by calling notmuch_database_destroy. ++ * + * Return value as in notmuch_database_close if the database was open; + * notmuch_database_destroy itself has no failure modes. + */ +diff --git a/notmuch-compact.c b/notmuch-compact.c +index 8b820c0..626685e 100644 +--- a/notmuch-compact.c ++++ b/notmuch-compact.c +@@ -29,6 +29,7 @@ status_update_cb (const char *msg, unused (void *closure)) + int + notmuch_compact_command (notmuch_config_t *config, int argc, char *argv[]) + { ++ notmuch_database_t *notmuch = NULL; + const char *path = notmuch_config_get_database_path (config); + const char *backup_path = NULL; + notmuch_status_t ret; +@@ -46,7 +47,13 @@ notmuch_compact_command (notmuch_config_t *config, int argc, char *argv[]) + + if (! quiet) + printf ("Compacting database...\n"); +- ret = notmuch_database_compact (path, backup_path, ++ ++ if (notmuch_database_new (¬much)) { ++ fprintf (stderr, "Out of memory\n"); ++ return 1; ++ } ++ ++ ret = notmuch_database_compact (notmuch, path, backup_path, + quiet ? NULL : status_update_cb, NULL); + if (ret) { + fprintf (stderr, "Compaction failed: %s\n", notmuch_status_to_string (ret)); +@@ -60,5 +67,7 @@ notmuch_compact_command (notmuch_config_t *config, int argc, char *argv[]) + printf ("Done.\n"); + } + ++ notmuch_database_destroy (notmuch); ++ + return 0; + } +diff --git a/notmuch-count.c b/notmuch-count.c +index 01e4e30..15c95c7 100644 +--- a/notmuch-count.c ++++ b/notmuch-count.c +@@ -170,8 +170,14 @@ notmuch_count_command (notmuch_config_t *config, int argc, char *argv[]) + return 1; + } + +- if (notmuch_database_open (notmuch_config_get_database_path (config), +- NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) ++ if (notmuch_database_new (¬much)) { ++ fprintf (stderr, "Out of memory\n"); ++ return 1; ++ } ++ ++ if (notmuch_database_open (notmuch, ++ notmuch_config_get_database_path (config), ++ NOTMUCH_DATABASE_MODE_READ_ONLY)) + return 1; + + query_str = query_string_from_args (config, argc-opt_index, argv+opt_index); +diff --git a/notmuch-dump.c b/notmuch-dump.c +index 2024e30..73579bc 100644 +--- a/notmuch-dump.c ++++ b/notmuch-dump.c +@@ -33,8 +33,14 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[]) + notmuch_tags_t *tags; + const char *query_str = ""; + +- if (notmuch_database_open (notmuch_config_get_database_path (config), +- NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) ++ if (notmuch_database_new (¬much)) { ++ fprintf (stderr, "Out of memory\n"); ++ return 1; ++ } ++ ++ if (notmuch_database_open (notmuch, ++ notmuch_config_get_database_path (config), ++ NOTMUCH_DATABASE_MODE_READ_ONLY)) + return 1; + + char *output_file_name = NULL; +diff --git a/notmuch-insert.c b/notmuch-insert.c +index 2207b1e..4a8aad3 100644 +--- a/notmuch-insert.c ++++ b/notmuch-insert.c +@@ -467,8 +467,14 @@ notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[]) + action.sa_flags = 0; + sigaction (SIGINT, &action, NULL); + +- if (notmuch_database_open (notmuch_config_get_database_path (config), +- NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) ++ if (notmuch_database_new (¬much)) { ++ fprintf (stderr, "Out of memory\n"); ++ return 1; ++ } ++ ++ if (notmuch_database_open (notmuch, ++ notmuch_config_get_database_path (config), ++ NOTMUCH_DATABASE_MODE_READ_WRITE)) + return 1; + + ret = insert_message (config, notmuch, STDIN_FILENO, maildir, tag_ops); +diff --git a/notmuch-new.c b/notmuch-new.c +index ba05cb4..f72a4de 100644 +--- a/notmuch-new.c ++++ b/notmuch-new.c +@@ -914,6 +914,11 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[]) + return ret; + } + ++ if (notmuch_database_new (¬much)) { ++ fprintf (stderr, "Out of memory\n"); ++ return 1; ++ } ++ + dot_notmuch_path = talloc_asprintf (config, "%s/%s", db_path, ".notmuch"); + + if (stat (dot_notmuch_path, &st)) { +@@ -925,12 +930,12 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[]) + return 1; + + printf ("Found %d total files (that's not much mail).\n", count); +- if (notmuch_database_create (db_path, ¬much)) ++ if (notmuch_database_create (notmuch, db_path)) + return 1; + add_files_state.total_files = count; + } else { +- if (notmuch_database_open (db_path, NOTMUCH_DATABASE_MODE_READ_WRITE, +- ¬much)) ++ if (notmuch_database_open (notmuch, db_path, ++ NOTMUCH_DATABASE_MODE_READ_WRITE)) + return 1; + + if (notmuch_database_needs_upgrade (notmuch)) { +@@ -945,9 +950,6 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[]) + add_files_state.total_files = 0; + } + +- if (notmuch == NULL) +- return 1; +- + /* Setup our handler for SIGINT. We do this after having + * potentially done a database upgrade we this interrupt handler + * won't support. */ +diff --git a/notmuch-reply.c b/notmuch-reply.c +index 9d6f843..7b80841 100644 +--- a/notmuch-reply.c ++++ b/notmuch-reply.c +@@ -769,8 +769,14 @@ notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[]) + return 1; + } + +- if (notmuch_database_open (notmuch_config_get_database_path (config), +- NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) ++ if (notmuch_database_new (¬much)) { ++ fprintf (stderr, "Out of memory\n"); ++ return 1; ++ } ++ ++ if (notmuch_database_open (notmuch, ++ notmuch_config_get_database_path (config), ++ NOTMUCH_DATABASE_MODE_READ_ONLY)) + return 1; + + query = notmuch_query_create (notmuch, query_string); +diff --git a/notmuch-restore.c b/notmuch-restore.c +index 1419621..fc37838 100644 +--- a/notmuch-restore.c ++++ b/notmuch-restore.c +@@ -138,8 +138,14 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) + int opt_index; + int input_format = DUMP_FORMAT_AUTO; + +- if (notmuch_database_open (notmuch_config_get_database_path (config), +- NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) ++ if (notmuch_database_new (¬much)) { ++ fprintf (stderr, "Out of memory\n"); ++ return 1; ++ } ++ ++ if (notmuch_database_open (notmuch, ++ notmuch_config_get_database_path (config), ++ NOTMUCH_DATABASE_MODE_READ_WRITE)) + return 1; + + if (notmuch_config_get_maildir_synchronize_flags (config)) +diff --git a/notmuch-search.c b/notmuch-search.c +index 7c973b3..50aace9 100644 +--- a/notmuch-search.c ++++ b/notmuch-search.c +@@ -430,8 +430,14 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[]) + + notmuch_exit_if_unsupported_format (); + +- if (notmuch_database_open (notmuch_config_get_database_path (config), +- NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) ++ if (notmuch_database_new (¬much)) { ++ fprintf (stderr, "Out of memory\n"); ++ return 1; ++ } ++ ++ if (notmuch_database_open (notmuch, ++ notmuch_config_get_database_path (config), ++ NOTMUCH_DATABASE_MODE_READ_ONLY)) + return 1; + + query_str = query_string_from_args (notmuch, argc-opt_index, argv+opt_index); +diff --git a/notmuch-show.c b/notmuch-show.c +index c07f887..bc44b2c 100644 +--- a/notmuch-show.c ++++ b/notmuch-show.c +@@ -1201,8 +1201,14 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[]) + return 1; + } + +- if (notmuch_database_open (notmuch_config_get_database_path (config), +- NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) ++ if (notmuch_database_new (¬much)) { ++ fprintf (stderr, "Out of memory\n"); ++ return 1; ++ } ++ ++ if (notmuch_database_open (notmuch, ++ notmuch_config_get_database_path (config), ++ NOTMUCH_DATABASE_MODE_READ_ONLY)) + return 1; + + query = notmuch_query_create (notmuch, query_string); +diff --git a/notmuch-tag.c b/notmuch-tag.c +index 3b09df9..6e29799 100644 +--- a/notmuch-tag.c ++++ b/notmuch-tag.c +@@ -254,8 +254,14 @@ notmuch_tag_command (notmuch_config_t *config, int argc, char *argv[]) + } + } + +- if (notmuch_database_open (notmuch_config_get_database_path (config), +- NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) ++ if (notmuch_database_new (¬much)) { ++ fprintf (stderr, "Out of memory\n"); ++ return 1; ++ } ++ ++ if (notmuch_database_open (notmuch, ++ notmuch_config_get_database_path (config), ++ NOTMUCH_DATABASE_MODE_READ_WRITE)) + return 1; + + if (notmuch_config_get_maildir_synchronize_flags (config)) +diff --git a/test/random-corpus.c b/test/random-corpus.c +index 790193d..2b205e5 100644 +--- a/test/random-corpus.c ++++ b/test/random-corpus.c +@@ -164,8 +164,14 @@ main (int argc, char **argv) + if (config == NULL) + return 1; + +- if (notmuch_database_open (notmuch_config_get_database_path (config), +- NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) ++ if (notmuch_database_new (¬much)) { ++ fprintf (stderr, "Out of memory\n"); ++ return 1; ++ } ++ ++ if (notmuch_database_open (notmuch, ++ notmuch_config_get_database_path (config), ++ NOTMUCH_DATABASE_MODE_READ_WRITE)) + return 1; + + srandom (seed); +diff --git a/test/symbol-test.cc b/test/symbol-test.cc +index 3e96c03..47c5351 100644 +--- a/test/symbol-test.cc ++++ b/test/symbol-test.cc +@@ -5,7 +5,8 @@ + + int main() { + notmuch_database_t *notmuch; +- notmuch_database_open("fakedb", NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much); ++ notmuch_database_new (¬much); ++ notmuch_database_open (notmuch, "fakedb", NOTMUCH_DATABASE_MODE_READ_ONLY); + + try { + (void) new Xapian::WritableDatabase("./nonexistant", Xapian::DB_OPEN); +-- +1.8.4.2 + -- 2.26.2