From: Jani Nikula Date: Thu, 5 Dec 2013 18:17:58 +0000 (+0200) Subject: Re: [PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=3275eb040736fb19043fe134ea8aa36770c248d3;p=notmuch-archives.git Re: [PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle --- diff --git a/e3/6855fe86f8e91ec5a72cce6dac4e54b905484e b/e3/6855fe86f8e91ec5a72cce6dac4e54b905484e new file mode 100644 index 000000000..d883d2007 --- /dev/null +++ b/e3/6855fe86f8e91ec5a72cce6dac4e54b905484e @@ -0,0 +1,760 @@ +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 4BC70431FD6 + for ; Thu, 5 Dec 2013 10:18:14 -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 CRdKw+ypM4UV for ; + Thu, 5 Dec 2013 10:18:09 -0800 (PST) +Received: from mail-ea0-f174.google.com (mail-ea0-f174.google.com + [209.85.215.174]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) + (No client certificate requested) + by olra.theworths.org (Postfix) with ESMTPS id 8687D431FD4 + for ; Thu, 5 Dec 2013 10:18:08 -0800 (PST) +Received: by mail-ea0-f174.google.com with SMTP id b10so11395300eae.19 + for ; Thu, 05 Dec 2013 10:18:06 -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:in-reply-to:references + :user-agent:date:message-id:mime-version:content-type; + bh=ZX9YYuobvYtnYfWtN8wCdgoKOmg4nVCloBiHOiuDlrA=; + b=Oap2z79C44rBcEgwIks1L1mokCA3d8QufOL/+1sAOT4C705stdQXevHsx9HRqjIycy + xDt9bs9VcwXToDHvkCw5NISAVpfjkVqNcT6xswn5EBqSrrDiiJs0yAxboTeDaVgobrwo + LE8paOSvRjnxnKvtfSK3JGJWZBqB2wvqHRjNcnk8ghaesS7ENca3eGuECiK3TFQInf1S + 7AfaEROVlljWwk9OjG1DcV3Ee3vfgowz8l5zYjyC4aD1M0Tczr48By1t2f5ChKaozSJ2 + hdARyJyCLxmSfFhtNU9ajs52UwrSHd9SFRq2ehsZAIu3ArgwyzODbRmBVifDCR1WPkox + 5yjw== +X-Gm-Message-State: + ALoCoQmzHAu9BOH0Luoua61cYUZF1KNZQE3NOB6R8vf9wI5BZssdDmsD2rusi1704k2b2ns4KmYV +X-Received: by 10.14.6.5 with SMTP id 5mr8371531eem.51.1386267485780; + Thu, 05 Dec 2013 10:18:05 -0800 (PST) +Received: from localhost (dsl-hkibrasgw2-58c36f-91.dhcp.inet.fi. + [88.195.111.91]) + by mx.google.com with ESMTPSA id e43sm97717001eep.7.2013.12.05.10.18.02 + for + (version=TLSv1.2 cipher=RC4-SHA bits=128/128); + Thu, 05 Dec 2013 10:18:04 -0800 (PST) +From: Jani Nikula +To: Austin Clements +Subject: Re: [PATCH 2/2] lib: introduce notmuch_database_new for initializing + a database handle +In-Reply-To: <20131204231113.GD8854@mit.edu> +References: + + <20131204231113.GD8854@mit.edu> +User-Agent: Notmuch/0.16+145~gebbaa94 (http://notmuchmail.org) Emacs/24.3.1 + (x86_64-pc-linux-gnu) +Date: Thu, 05 Dec 2013 20:17:58 +0200 +Message-ID: <87mwkf40x5.fsf@nikula.org> +MIME-Version: 1.0 +Content-Type: text/plain +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: Thu, 05 Dec 2013 18:18:14 -0000 + +On Thu, 05 Dec 2013, Austin Clements wrote: +> 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.) + +Just to confirm, are you referring to the state between close and +destroy/open? + +Btw what is the use case we have separate close and destroy for? To be +able to access the data cached in memory after the db has been closed? + +> 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"). + +Agreed. + +> 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). + +Agreed. I tried to look into this earlier, but was hitting dead ends +*if* we want to keep reporting user friendly error status in +open/create. Obviously any concrete suggestions would be most welcome! + +>> --- +>> 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). + +Agreed on the naming being unfortunate, though I'll dodge further +bikeshedding. ;) Merging open and create sounds all right, though it's a +minor detail in the bigger picture of this patch. + +The comments below seemed valid too, thanks. + +BR, +Jani. + + +> +>> +{ +>> + /* 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);