From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id 491BB431FD2 for ; Wed, 4 Dec 2013 15:11:28 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org 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 OryFt9l6vpw4 for ; Wed, 4 Dec 2013 15:11:23 -0800 (PST) Received: from dmz-mailsec-scanner-8.mit.edu (dmz-mailsec-scanner-8.mit.edu [18.7.68.37]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by olra.theworths.org (Postfix) with ESMTPS id 7A010431FD0 for ; Wed, 4 Dec 2013 15:11:22 -0800 (PST) X-AuditID: 12074425-b7fd96d000000c39-7e-529fb698e984 Received: from mailhub-auth-4.mit.edu ( [18.7.62.39]) (using TLS with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by dmz-mailsec-scanner-8.mit.edu (Symantec Messaging Gateway) with SMTP id 8F.AE.03129.896BF925; Wed, 4 Dec 2013 18:11:20 -0500 (EST) Received: from outgoing.mit.edu (outgoing-auth-1.mit.edu [18.9.28.11]) by mailhub-auth-4.mit.edu (8.13.8/8.9.2) with ESMTP id rB4NBJJ7032395; Wed, 4 Dec 2013 18:11:20 -0500 Received: from awakening.csail.mit.edu (awakening.csail.mit.edu [18.26.4.91]) (authenticated bits=0) (User authenticated as amdragon@ATHENA.MIT.EDU) by outgoing.mit.edu (8.13.8/8.12.4) with ESMTP id rB4NBGGu022234 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NOT); Wed, 4 Dec 2013 18:11:18 -0500 Received: from amthrax by awakening.csail.mit.edu with local (Exim 4.80) (envelope-from ) id 1VoLb7-0002im-TJ; Wed, 04 Dec 2013 18:11:15 -0500 Date: Wed, 4 Dec 2013 18:11:13 -0500 From: Austin Clements To: Jani Nikula Subject: Re: [PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle Message-ID: <20131204231113.GD8854@mit.edu> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmplleLIzCtJLcpLzFFi42IRYrdT152xbX6QwawPKhZN050trt+cyezA 5HHr/mt2j2erbjEHMEVx2aSk5mSWpRbp2yVwZex5uImloPsIY8WEjuuMDYyPZzJ2MXJySAiY SLy9fw3KFpO4cG89WxcjF4eQwGwmic7PW5ghnA2MEr+71rBCOKeYJC6tvcAI4SxhlNjw/T8z SD+LgIpE/7ElbCA2m4CGxLb9y8HmiggoSmw+uR/MZhaQlvj2u5kJxBYWSJS4unkvWD2vgLbE /fZ2VhBbSKBOYt66fqi4oMTJmU9YIHq1JG78ewnUywE2Z/k/DpAwp0CYxI2OxewgtijQCVNO bmObwCg0C0n3LCTdsxC6FzAyr2KUTcmt0s1NzMwpTk3WLU5OzMtLLdK10MvNLNFLTSndxAgO bRfVHYwTDikdYhTgYFTi4XVImR8kxJpYVlyZe4hRkoNJSZTXZiNQiC8pP6UyI7E4I76oNCe1 +BCjBAezkgjvvxqgHG9KYmVValE+TEqag0VJnPcWh32QkEB6YklqdmpqQWoRTFaGg0NJgvfH VqBGwaLU9NSKtMycEoQ0EwcnyHAeoOGXQWp4iwsSc4sz0yHypxgVpcR580ASAiCJjNI8uF5Y 6nnFKA70ijDvbZAqHmDagut+BTSYCWhw84N5IINLEhFSUg2MzTu/Z7Zmthk8mjLZhFF+d7Pr 1EPlktd5+ucGNt2qlssvWzbP8aWnQkbirMDm7k4PnTt35WO2aS4WLhDVvfZp3wHnD8EvDc8m 54XaxLpKH93R5Pgn26Xsi1zNknMfroW0+lgt41plNiW+hC2O63Tlp/pnV4VW822vXsP7btuB z1d6Txs8FStRYinOSDTUYi4qTgQAf5Qg3RgDAAA= Cc: notmuch@notmuchmail.org 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: Wed, 04 Dec 2013 23:11:28 -0000 Quoth Jani Nikula on Dec 01 at 3:14 pm: > 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. A high-level comment about the API: Currently, an allocated notmuch_database_t has two "memory states", if you will: open and closed. (I wish it didn't have any memory states, and was on the fence about this API for a while until I realized that the ship had already sailed.) It's pretty clear how all of the notmuch APIs will behave in both states (modulo some bounded non-determinism in the closed state). I think this patch introduces a new "pre-open" state, and I don't know how most of the notmuch APIs behave in that state. My guess is poorly. If it's feasible, I'd much rather a fresh baked notmuch_database_t act like it's in the closed state, including that notmuch_database_{create,open} are well-defined as transitions from closed state to open state (even if the closed state was reached by calling notmuch_database_close). Or, if we do have a "pre-open" state, it should at least be well-specified what that means (preferably the specification is *not* "most APIs segfault"). Orthogonally -- and this may be a complete pipe dream of mine -- if we just had a way to return more detailed error information than a simple error code from notmuch_database_{create,open}, I think we wouldn't need any of this. Everything that these functions currently log (modulo one warning) is error details, so if we could return the error details *with the error* or somehow make them accessible, we wouldn't need a logger at this point (or at several other points in the library). > --- > 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) The naming of this is unfortunate... Other APIs use x_create to allocate objects (e.g., notmuch_query_create, several internal APIs). I would lean towards calling this function notmuch_database_create, but that leaves the question of what to call the other. While we're breaking APIs, would it be completely crazy to merge open and create into one API with an extra mode to indicate creation (it can be its own mode because creation implies read/write)? (Or, in UNIX tradition, we could call this function notmuch_database_create and the other notmuch_database_creat.) notmuch_database_create is already just a shell around notmuch_database_open (we could keep it as a separate function, but just make it internal). > +{ > + /* 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) > { This should fail if passed a database that is already open. > 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! > + */ I think the only thing that will currently leak from this in an error case is notmuch->path. > 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) > { This should also fail if passed a database that is already open. > 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); > It might be simpler to call notmuch_database_close here if status != NOTMUCH_STATUS_SUCCESS, rather than calling it at several places above (and not on all error paths). > - if (database) > - *database = notmuch; > - else > - talloc_free (notmuch); > return status; > } > > +/* > + * XXX: close should clean up *all* state created by open/create! > + */ I believe the only thing it doesn't clean up is path. (Note that cleaning up path here doesn't currently negate the need to clean up path above, though if you float the close call to the DONE path, it would suffice.) > 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)) Does this need to destroy the database? (Likewise for all the others.) > 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);