lib: Make directory document creation optional for _notmuch_directory_create

Previously this function would create directory documents if they
didn't exist.  As a result, it could only be used on writable
databases.  This adds an argument to make creation optional and to
make this function work on read-only databases.  We use a flag
argument to avoid a bare boolean and to permit future expansion.

Both callers have been updated, but currently retain the old behavior.
We'll take advantage of the new argument in the following patches.
This commit is contained in:
Austin Clements 2012-05-18 00:13:34 -04:00 committed by David Bremner
parent 70ca3444c7
commit f69314fbd3
3 changed files with 39 additions and 8 deletions

View file

@ -956,7 +956,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
document.get_value (NOTMUCH_VALUE_TIMESTAMP)); document.get_value (NOTMUCH_VALUE_TIMESTAMP));
directory = _notmuch_directory_create (notmuch, term.c_str() + 10, directory = _notmuch_directory_create (notmuch, term.c_str() + 10,
&status); NOTMUCH_FIND_CREATE, &status);
notmuch_directory_set_mtime (directory, mtime); notmuch_directory_set_mtime (directory, mtime);
notmuch_directory_destroy (directory); notmuch_directory_destroy (directory);
} }
@ -1210,7 +1210,7 @@ _notmuch_database_find_directory_id (notmuch_database_t *notmuch,
return NOTMUCH_STATUS_SUCCESS; return NOTMUCH_STATUS_SUCCESS;
} }
directory = _notmuch_directory_create (notmuch, path, &status); directory = _notmuch_directory_create (notmuch, path, NOTMUCH_FIND_CREATE, &status);
if (status) { if (status) {
*directory_id = -1; *directory_id = -1;
return status; return status;
@ -1320,7 +1320,7 @@ notmuch_database_get_directory (notmuch_database_t *notmuch,
return NOTMUCH_STATUS_READ_ONLY_DATABASE; return NOTMUCH_STATUS_READ_ONLY_DATABASE;
try { try {
*directory = _notmuch_directory_create (notmuch, path, &status); *directory = _notmuch_directory_create (notmuch, path, NOTMUCH_FIND_CREATE, &status);
} catch (const Xapian::Error &error) { } catch (const Xapian::Error &error) {
fprintf (stderr, "A Xapian exception occurred getting directory: %s.\n", fprintf (stderr, "A Xapian exception occurred getting directory: %s.\n",
error.get_msg().c_str()); error.get_msg().c_str());

View file

@ -82,28 +82,41 @@ find_directory_document (notmuch_database_t *notmuch,
return NOTMUCH_PRIVATE_STATUS_SUCCESS; return NOTMUCH_PRIVATE_STATUS_SUCCESS;
} }
/* Find or create a directory document.
*
* 'path' should be a path relative to the path of 'database', or else
* should be an absolute path with initial components that match the
* path of 'database'.
*
* If (flags & NOTMUCH_FIND_CREATE), then the directory document will
* be created if it does not exist. Otherwise, if the directory
* document does not exist, *status_ret is set to
* NOTMUCH_STATUS_SUCCESS and this returns NULL.
*/
notmuch_directory_t * notmuch_directory_t *
_notmuch_directory_create (notmuch_database_t *notmuch, _notmuch_directory_create (notmuch_database_t *notmuch,
const char *path, const char *path,
notmuch_find_flags_t flags,
notmuch_status_t *status_ret) notmuch_status_t *status_ret)
{ {
Xapian::WritableDatabase *db; Xapian::WritableDatabase *db;
notmuch_directory_t *directory; notmuch_directory_t *directory;
notmuch_private_status_t private_status; notmuch_private_status_t private_status;
const char *db_path; const char *db_path;
notmuch_bool_t create = (flags & NOTMUCH_FIND_CREATE);
*status_ret = NOTMUCH_STATUS_SUCCESS; *status_ret = NOTMUCH_STATUS_SUCCESS;
path = _notmuch_database_relative_path (notmuch, path); path = _notmuch_database_relative_path (notmuch, path);
if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY) if (create && notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
INTERNAL_ERROR ("Failure to ensure database is writable"); INTERNAL_ERROR ("Failure to ensure database is writable");
db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
directory = talloc (notmuch, notmuch_directory_t); directory = talloc (notmuch, notmuch_directory_t);
if (unlikely (directory == NULL)) if (unlikely (directory == NULL)) {
*status_ret = NOTMUCH_STATUS_OUT_OF_MEMORY;
return NULL; return NULL;
}
directory->notmuch = notmuch; directory->notmuch = notmuch;
@ -122,6 +135,13 @@ _notmuch_directory_create (notmuch_database_t *notmuch,
directory->document_id = directory->doc.get_docid (); directory->document_id = directory->doc.get_docid ();
if (private_status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) { if (private_status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) {
if (!create) {
notmuch_directory_destroy (directory);
directory = NULL;
*status_ret = NOTMUCH_STATUS_SUCCESS;
goto DONE;
}
void *local = talloc_new (directory); void *local = talloc_new (directory);
const char *parent, *basename; const char *parent, *basename;
Xapian::docid parent_id; Xapian::docid parent_id;
@ -145,6 +165,8 @@ _notmuch_directory_create (notmuch_database_t *notmuch,
directory->doc.add_value (NOTMUCH_VALUE_TIMESTAMP, directory->doc.add_value (NOTMUCH_VALUE_TIMESTAMP,
Xapian::sortable_serialise (0)); Xapian::sortable_serialise (0));
db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
directory->document_id = _notmuch_database_generate_doc_id (notmuch); directory->document_id = _notmuch_database_generate_doc_id (notmuch);
db->replace_document (directory->document_id, directory->doc); db->replace_document (directory->document_id, directory->doc);
talloc_free (local); talloc_free (local);
@ -158,10 +180,11 @@ _notmuch_directory_create (notmuch_database_t *notmuch,
error.get_msg().c_str()); error.get_msg().c_str());
notmuch->exception_reported = TRUE; notmuch->exception_reported = TRUE;
notmuch_directory_destroy (directory); notmuch_directory_destroy (directory);
directory = NULL;
*status_ret = NOTMUCH_STATUS_XAPIAN_EXCEPTION; *status_ret = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
return NULL;
} }
DONE:
if (db_path != path) if (db_path != path)
free ((char *) db_path); free ((char *) db_path);

View file

@ -146,6 +146,13 @@ typedef enum _notmuch_private_status {
: \ : \
(notmuch_status_t) private_status) (notmuch_status_t) private_status)
/* Flags shared by various lookup functions. */
typedef enum _notmuch_find_flags {
/* If set, create the necessary document (or documents) if they
* are missing. Requires a read/write database. */
NOTMUCH_FIND_CREATE = 1<<0,
} notmuch_find_flags_t;
typedef struct _notmuch_doc_id_set notmuch_doc_id_set_t; typedef struct _notmuch_doc_id_set notmuch_doc_id_set_t;
typedef struct _notmuch_string_list notmuch_string_list_t; typedef struct _notmuch_string_list notmuch_string_list_t;
@ -206,6 +213,7 @@ _notmuch_database_filename_to_direntry (void *ctx,
notmuch_directory_t * notmuch_directory_t *
_notmuch_directory_create (notmuch_database_t *notmuch, _notmuch_directory_create (notmuch_database_t *notmuch,
const char *path, const char *path,
notmuch_find_flags_t flags,
notmuch_status_t *status_ret); notmuch_status_t *status_ret);
unsigned int unsigned int