[PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
David Bremner writes: > I'm not sure if this is also a dead end, but I was trying to sketch out > an api that returned something more detailed as status and came up with > the following. The general idea is to replace notmuch_status_t with a > pointer to struct. This will require pretty noisy source changes, > unless we're comfortable with using NULL pointer to indicate success. > In either case we'd rename the existing enum to something like > notmuch_status_code_t. > > /* pseudo-C follows */ > > typedef struct notmuch_status_struct * notmuch_status_t; > A less API disruptive change would be to continue returning codes, but provide functions to interrogate the main types (database, message, etc) for "last-error". We'd still need to special case database_(open|create) d
Re: [PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
David Bremner da...@tethera.net writes: I'm not sure if this is also a dead end, but I was trying to sketch out an api that returned something more detailed as status and came up with the following. The general idea is to replace notmuch_status_t with a pointer to struct. This will require pretty noisy source changes, unless we're comfortable with using NULL pointer to indicate success. In either case we'd rename the existing enum to something like notmuch_status_code_t. /* pseudo-C follows */ typedef struct notmuch_status_struct * notmuch_status_t; A less API disruptive change would be to continue returning codes, but provide functions to interrogate the main types (database, message, etc) for last-error. We'd still need to special case database_(open|create) d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
Jani Nikula writes: >> Austin Wrote: >> >> 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! > I'm not sure if this is also a dead end, but I was trying to sketch out an api that returned something more detailed as status and came up with the following. The general idea is to replace notmuch_status_t with a pointer to struct. This will require pretty noisy source changes, unless we're comfortable with using NULL pointer to indicate success. In either case we'd rename the existing enum to something like notmuch_status_code_t. /* pseudo-C follows */ typedef struct notmuch_status_struct * notmuch_status_t; /* we can just tell external users to pass NULL as the first argument */ notmuch_status_t notmuch_status_new (void *ctx, size_t bufsiz); void notmuch_error_destroy (notuch_error_desc_t *victim); /* printf equivalent */ notmuch_status_t *notmuch_status_format(notmuch_status_t dest, notmuch_status_code_t code, const char *format, ...); /* case 1, caller allocates */ status = notmuch_status_new (BUFSIZ); if (!status) { halt_and_catch_fire(); } /* open could continue to return notmuch_status_code_t, or just 0/1 */ if (notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_WRITE, , status)) { fprintf (stderr, "oops: %s\n", notmuch_status_to_string (status)); notmuch_error_destroy(error_details); return 1; } /* case 2, callee allocates */ status = notmuch_message_freeze (message); if (notmuch_status_to_code (status)) { /* every check needs to be changed, unless NULL=OK */ message_error (message, status, "freezing message"); return status; } /* some existing code is left alone */ fprintf (stderr, "Message-ID: %s\n", notmuch_message_get_message_id (message)); fprintf (stderr, "Status: %s\n", notmuch_status_to_string (status));
Re: [PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
Jani Nikula j...@nikula.org writes: Austin Wrote: 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! I'm not sure if this is also a dead end, but I was trying to sketch out an api that returned something more detailed as status and came up with the following. The general idea is to replace notmuch_status_t with a pointer to struct. This will require pretty noisy source changes, unless we're comfortable with using NULL pointer to indicate success. In either case we'd rename the existing enum to something like notmuch_status_code_t. /* pseudo-C follows */ typedef struct notmuch_status_struct * notmuch_status_t; /* we can just tell external users to pass NULL as the first argument */ notmuch_status_t notmuch_status_new (void *ctx, size_t bufsiz); void notmuch_error_destroy (notuch_error_desc_t *victim); /* printf equivalent */ notmuch_status_t *notmuch_status_format(notmuch_status_t dest, notmuch_status_code_t code, const char *format, ...); /* case 1, caller allocates */ status = notmuch_status_new (BUFSIZ); if (!status) { halt_and_catch_fire(); } /* open could continue to return notmuch_status_code_t, or just 0/1 */ if (notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_WRITE, notmuch, status)) { fprintf (stderr, oops: %s\n, notmuch_status_to_string (status)); notmuch_error_destroy(error_details); return 1; } /* case 2, callee allocates */ status = notmuch_message_freeze (message); if (notmuch_status_to_code (status)) { /* every check needs to be changed, unless NULL=OK */ message_error (message, status, freezing message); return status; } /* some existing code is left alone */ fprintf (stderr, Message-ID: %s\n, notmuch_message_get_message_id (message)); fprintf (stderr, Status: %s\n, notmuch_status_to_string (status)); ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
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. > >> +{ >> +/*
Re: [PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
On Thu, 05 Dec 2013, Austin Clements amdra...@mit.edu 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
Re: [PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
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, - notmuch); +status = notmuch_database_open (notmuch, path, +
[PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
On Tue, Dec 03 2013, Jani Nikula wrote: > On Tue, 03 Dec 2013, Tomi Ollila wrote: >> On Tue, Dec 03 2013, David Bremner wrote: >> >>> The first patch looks ok. I like the new API overall. >>> >>> As far as breaking contrib/notmuch-deliver, I'd rather fix >>> notmuch-insert than put effort into notmuch-deliver at this point. I >>> guess it could be a rough transition for people running notmuch-deliver >>> from git. >>> >>> Jani Nikula writes: >>> +/* + * XXX: error handling should clean up *all* state created! + */ >>> is this a warning to future hackers or some current problem? >>> 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) +/* Initialize a new, empty database handle. + * >>> >>> I wondered about making the new documentation adhere to doxygen? >>> >>> +if (notmuch_database_open (notmuch, + notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_ONLY)) >>> >>> Would it make any sense to migrate the mode argument to an option >>> setting while we're messing with the API? >> >> if that, then also database_path to options ? > > See my reply to David. I agree with your explanation there. > >> I also like this suggestion best of all seen so far, but what if: >> >> #define NOTMUCH_MAJOR_VERSION 0 >> #define NOTMUCH_MINOR_VERSION 17 >> -#define NOTMUCH_MICRO_VERSION 0 >> +#define NOTMUCH_MICRO_VERSION 90 >> >> until changed API/ABI is set into stone (i.e. 0.18.0 at freeze time). > > That would require the user to conditional build with: > > #if NOTMUCH_CHECK_VERSION(0, 17, 90) > /* building against post-0.17 git master or released 0.18 */ > #else > /* building against 0.17 */ > #endif > > instead of the IMHO more natural and accurate: > > #if NOTMUCH_CHECK_VERSION(0, 18, 0) > /* building against post-0.17 git master or released 0.18 */ > #else > /* building against 0.17 */ > #endif True -- I always forget that NOTMUCH_CHECK_VERSION() checks for the value and *newer*. Although there is slight difference I don't think it warrants the use of intermediate values -- the changing API is much bigger issue than this and that is what we have to concentrate on. > > > BR, > Jani. Tomi
[PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
On Tue, 03 Dec 2013, Tomi Ollila wrote: > On Tue, Dec 03 2013, David Bremner wrote: > >> The first patch looks ok. I like the new API overall. >> >> As far as breaking contrib/notmuch-deliver, I'd rather fix >> notmuch-insert than put effort into notmuch-deliver at this point. I >> guess it could be a rough transition for people running notmuch-deliver >> from git. >> >> Jani Nikula writes: >> >>> +/* >>> + * XXX: error handling should clean up *all* state created! >>> + */ >> is this a warning to future hackers or some current problem? >> >>> 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) >>> >>> +/* Initialize a new, empty database handle. >>> + * >> >> I wondered about making the new documentation adhere to doxygen? >> >> >>> +if (notmuch_database_open (notmuch, >>> + notmuch_config_get_database_path (config), >>> + NOTMUCH_DATABASE_MODE_READ_ONLY)) >> >> Would it make any sense to migrate the mode argument to an option >> setting while we're messing with the API? > > if that, then also database_path to options ? See my reply to David. > I also like this suggestion best of all seen so far, but what if: > > #define NOTMUCH_MAJOR_VERSION 0 > #define NOTMUCH_MINOR_VERSION 17 > -#define NOTMUCH_MICRO_VERSION 0 > +#define NOTMUCH_MICRO_VERSION 90 > > until changed API/ABI is set into stone (i.e. 0.18.0 at freeze time). That would require the user to conditional build with: #if NOTMUCH_CHECK_VERSION(0, 17, 90) /* building against post-0.17 git master or released 0.18 */ #else /* building against 0.17 */ #endif instead of the IMHO more natural and accurate: #if NOTMUCH_CHECK_VERSION(0, 18, 0) /* building against post-0.17 git master or released 0.18 */ #else /* building against 0.17 */ #endif BR, Jani.
[PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
On Tue, 03 Dec 2013, David Bremner wrote: > The first patch looks ok. I like the new API overall. Happy to hear that. > As far as breaking contrib/notmuch-deliver, I'd rather fix > notmuch-insert than put effort into notmuch-deliver at this point. I > guess it could be a rough transition for people running notmuch-deliver > from git. Agreed. We could fix notmuch insert with patch 1/2 alone. > Jani Nikula writes: > >> +/* >> + * XXX: error handling should clean up *all* state created! >> + */ > is this a warning to future hackers or some current problem? It's a note to self and reviewers that we need to be sure this happens... I'm just saying I'm not 100% sure we're doing all of that now. >> 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) >> >> +/* Initialize a new, empty database handle. >> + * > > I wondered about making the new documentation adhere to doxygen? I was thinking of fixing either series depending on them getting merged. I wasn't sure we'd reached consensus on doxygen yet. >> +if (notmuch_database_open (notmuch, >> + notmuch_config_get_database_path (config), >> + NOTMUCH_DATABASE_MODE_READ_ONLY)) > > Would it make any sense to migrate the mode argument to an option > setting while we're messing with the API? My gut feeling says no. Same for the path argument suggested by Tomi. What would it mean to change the mode while the database is open? Or the path? I think we'd have to check for this, and fail. Mode is only meaningful for open, and path for open, create and compact. I think adding such state modifiers would make the interface feel more complex, but I'm open to arguments to the contrary. BR, Jani.
[PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
On Tue, Dec 03 2013, David Bremner wrote: > The first patch looks ok. I like the new API overall. > > As far as breaking contrib/notmuch-deliver, I'd rather fix > notmuch-insert than put effort into notmuch-deliver at this point. I > guess it could be a rough transition for people running notmuch-deliver > from git. > > Jani Nikula writes: > >> +/* >> + * XXX: error handling should clean up *all* state created! >> + */ > is this a warning to future hackers or some current problem? > >> 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) >> >> +/* Initialize a new, empty database handle. >> + * > > I wondered about making the new documentation adhere to doxygen? > > >> +if (notmuch_database_open (notmuch, >> + notmuch_config_get_database_path (config), >> + NOTMUCH_DATABASE_MODE_READ_ONLY)) > > Would it make any sense to migrate the mode argument to an option > setting while we're messing with the API? if that, then also database_path to options ? I also like this suggestion best of all seen so far, but what if: #define NOTMUCH_MAJOR_VERSION 0 #define NOTMUCH_MINOR_VERSION 17 -#define NOTMUCH_MICRO_VERSION 0 +#define NOTMUCH_MICRO_VERSION 90 until changed API/ABI is set into stone (i.e. 0.18.0 at freeze time). Tomi
[PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
The first patch looks ok. I like the new API overall. As far as breaking contrib/notmuch-deliver, I'd rather fix notmuch-insert than put effort into notmuch-deliver at this point. I guess it could be a rough transition for people running notmuch-deliver from git. Jani Nikula writes: > +/* > + * XXX: error handling should clean up *all* state created! > + */ is this a warning to future hackers or some current problem? > 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) > > +/* Initialize a new, empty database handle. > + * I wondered about making the new documentation adhere to doxygen? > +if (notmuch_database_open (notmuch, > +notmuch_config_get_database_path (config), > +NOTMUCH_DATABASE_MODE_READ_ONLY)) Would it make any sense to migrate the mode argument to an option setting while we're messing with the API?
Re: [PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
The first patch looks ok. I like the new API overall. As far as breaking contrib/notmuch-deliver, I'd rather fix notmuch-insert than put effort into notmuch-deliver at this point. I guess it could be a rough transition for people running notmuch-deliver from git. Jani Nikula j...@nikula.org writes: +/* + * XXX: error handling should clean up *all* state created! + */ is this a warning to future hackers or some current problem? 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) +/* Initialize a new, empty database handle. + * I wondered about making the new documentation adhere to doxygen? +if (notmuch_database_open (notmuch, +notmuch_config_get_database_path (config), +NOTMUCH_DATABASE_MODE_READ_ONLY)) Would it make any sense to migrate the mode argument to an option setting while we're messing with the API? ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
On Tue, 03 Dec 2013, David Bremner da...@tethera.net wrote: The first patch looks ok. I like the new API overall. Happy to hear that. As far as breaking contrib/notmuch-deliver, I'd rather fix notmuch-insert than put effort into notmuch-deliver at this point. I guess it could be a rough transition for people running notmuch-deliver from git. Agreed. We could fix notmuch insert with patch 1/2 alone. Jani Nikula j...@nikula.org writes: +/* + * XXX: error handling should clean up *all* state created! + */ is this a warning to future hackers or some current problem? It's a note to self and reviewers that we need to be sure this happens... I'm just saying I'm not 100% sure we're doing all of that now. 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) +/* Initialize a new, empty database handle. + * I wondered about making the new documentation adhere to doxygen? I was thinking of fixing either series depending on them getting merged. I wasn't sure we'd reached consensus on doxygen yet. +if (notmuch_database_open (notmuch, + notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_ONLY)) Would it make any sense to migrate the mode argument to an option setting while we're messing with the API? My gut feeling says no. Same for the path argument suggested by Tomi. What would it mean to change the mode while the database is open? Or the path? I think we'd have to check for this, and fail. Mode is only meaningful for open, and path for open, create and compact. I think adding such state modifiers would make the interface feel more complex, but I'm open to arguments to the contrary. BR, Jani. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
On Tue, Dec 03 2013, Jani Nikula j...@nikula.org wrote: On Tue, 03 Dec 2013, Tomi Ollila tomi.oll...@iki.fi wrote: On Tue, Dec 03 2013, David Bremner da...@tethera.net wrote: The first patch looks ok. I like the new API overall. As far as breaking contrib/notmuch-deliver, I'd rather fix notmuch-insert than put effort into notmuch-deliver at this point. I guess it could be a rough transition for people running notmuch-deliver from git. Jani Nikula j...@nikula.org writes: +/* + * XXX: error handling should clean up *all* state created! + */ is this a warning to future hackers or some current problem? 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) +/* Initialize a new, empty database handle. + * I wondered about making the new documentation adhere to doxygen? +if (notmuch_database_open (notmuch, + notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_ONLY)) Would it make any sense to migrate the mode argument to an option setting while we're messing with the API? if that, then also database_path to options ? See my reply to David. I agree with your explanation there. I also like this suggestion best of all seen so far, but what if: #define NOTMUCH_MAJOR_VERSION 0 #define NOTMUCH_MINOR_VERSION 17 -#define NOTMUCH_MICRO_VERSION 0 +#define NOTMUCH_MICRO_VERSION 90 until changed API/ABI is set into stone (i.e. 0.18.0 at freeze time). That would require the user to conditional build with: #if NOTMUCH_CHECK_VERSION(0, 17, 90) /* building against post-0.17 git master or released 0.18 */ #else /* building against 0.17 */ #endif instead of the IMHO more natural and accurate: #if NOTMUCH_CHECK_VERSION(0, 18, 0) /* building against post-0.17 git master or released 0.18 */ #else /* building against 0.17 */ #endif True -- I always forget that NOTMUCH_CHECK_VERSION() checks for the value and *newer*. Although there is slight difference I don't think it warrants the use of intermediate values -- the changing API is much bigger issue than this and that is what we have to concentrate on. BR, Jani. Tomi ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
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, - ); +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 ) { 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 -
[PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle
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, - notmuch); +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 -