[PATCH 2/2] lib: introduce notmuch_database_new for initializing a database handle

2014-01-15 Thread David Bremner
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

2014-01-15 Thread David Bremner
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

2014-01-14 Thread David Bremner
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

2014-01-14 Thread David Bremner
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

2013-12-05 Thread Jani Nikula
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

2013-12-05 Thread Jani Nikula
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

2013-12-04 Thread Austin Clements
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

2013-12-03 Thread Tomi Ollila
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

2013-12-03 Thread Jani Nikula
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

2013-12-03 Thread Jani Nikula
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

2013-12-03 Thread Tomi Ollila
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

2013-12-03 Thread David Bremner

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

2013-12-03 Thread David Bremner

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

2013-12-03 Thread Jani Nikula
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

2013-12-03 Thread Tomi Ollila
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

2013-12-01 Thread Jani Nikula
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

2013-12-01 Thread Jani Nikula
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
-