return status;
}
+static notmuch_status_t
+_db_dir_exists (const char *database_path, char **message)
+{
+ struct stat st;
+ int err;
+
+ err = stat (database_path, &st);
+ if (err) {
+ IGNORE_RESULT (asprintf (message, "Error: Cannot open database at %s: %s.\n",
+ database_path, strerror (errno)));
+ return NOTMUCH_STATUS_FILE_ERROR;
+ }
+
+ if (! S_ISDIR (st.st_mode)) {
+ IGNORE_RESULT (asprintf (message, "Error: Cannot open database at %s: "
+ "Not a directory.\n",
+ database_path));
+ return NOTMUCH_STATUS_FILE_ERROR;
+ }
+
+ return NOTMUCH_STATUS_SUCCESS;
+}
+
static notmuch_status_t
_choose_database_path (void *ctx,
const char *config_path,
return status;
}
+ if (! *database_path) {
+ *database_path = getenv ("NOTMUCH_DATABASE");
+ }
+
if (! *database_path && *key_file) {
char *path = g_key_file_get_value (*key_file, "database", "path", NULL);
if (path) {
return NOTMUCH_STATUS_SUCCESS;
}
-notmuch_status_t
-notmuch_database_open_with_config (const char *database_path,
- notmuch_database_mode_t mode,
- const char *config_path,
- const char *profile,
- notmuch_database_t **database,
- char **status_string)
+notmuch_database_t *
+_alloc_notmuch ()
{
- notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
- void *local = talloc_new (NULL);
- notmuch_database_t *notmuch = NULL;
- char *notmuch_path, *incompat_features;
- char *message = NULL;
- struct stat st;
- int err;
- unsigned int version;
- GKeyFile *key_file = NULL;
- static int initialized = 0;
+ notmuch_database_t *notmuch;
- if ((status = _choose_database_path (local, config_path, profile, &key_file, &database_path,
- &message)))
- goto DONE;
+ notmuch = talloc_zero (NULL, notmuch_database_t);
+ if (! notmuch)
+ return NULL;
- if (! (notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch"))) {
- message = strdup ("Out of memory\n");
- status = NOTMUCH_STATUS_OUT_OF_MEMORY;
- goto DONE;
- }
+ notmuch->exception_reported = false;
+ notmuch->status_string = NULL;
+ notmuch->writable_xapian_db = NULL;
+ notmuch->atomic_nesting = 0;
+ notmuch->view = 1;
+ return notmuch;
+}
- err = stat (notmuch_path, &st);
- if (err) {
- IGNORE_RESULT (asprintf (&message, "Error opening database at %s: %s\n",
- notmuch_path, strerror (errno)));
- status = NOTMUCH_STATUS_FILE_ERROR;
- goto DONE;
- }
+static void
+_set_database_path (notmuch_database_t *notmuch,
+ const char *database_path)
+{
+ char *path = talloc_strdup (notmuch, database_path);
+
+ strip_trailing (path, '/');
+
+ _notmuch_config_cache (notmuch, NOTMUCH_CONFIG_DATABASE_PATH, path);
+}
+
+static void
+_init_libs ()
+{
+
+ static int initialized = 0;
/* Initialize the GLib type system and threads */
#if ! GLIB_CHECK_VERSION (2, 35, 1)
g_mime_init ();
initialized = 1;
}
+}
- notmuch = talloc_zero (NULL, notmuch_database_t);
- notmuch->exception_reported = false;
- notmuch->status_string = NULL;
- notmuch->path = talloc_strdup (notmuch, database_path);
-
- strip_trailing (notmuch->path, '/');
-
- notmuch->writable_xapian_db = NULL;
- notmuch->atomic_nesting = 0;
- notmuch->view = 1;
-
- if (! (notmuch->xapian_path = talloc_asprintf (notmuch, "%s/%s", notmuch_path, "xapian"))) {
- message = strdup ("Out of memory\n");
- status = NOTMUCH_STATUS_OUT_OF_MEMORY;
- goto DONE;
- }
+static notmuch_status_t
+_finish_open (notmuch_database_t *notmuch,
+ const char *profile,
+ notmuch_database_mode_t mode,
+ GKeyFile *key_file,
+ char **message_ptr)
+{
+ notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
+ char *incompat_features;
+ char *message = NULL;
+ unsigned int version;
+ const char *database_path = notmuch_database_get_path (notmuch);
try {
std::string last_thread_id;
"Error: Notmuch database at %s\n"
" has a newer database format version (%u) than supported by this\n"
" version of notmuch (%u).\n",
- notmuch_path, version, NOTMUCH_DATABASE_VERSION));
+ database_path, version, NOTMUCH_DATABASE_VERSION));
notmuch_database_destroy (notmuch);
notmuch = NULL;
status = NOTMUCH_STATUS_FILE_ERROR;
/* Check features. */
incompat_features = NULL;
notmuch->features = _notmuch_database_parse_features (
- local, notmuch->xapian_db->get_metadata ("features").c_str (),
+ notmuch, notmuch->xapian_db->get_metadata ("features").c_str (),
version, mode == NOTMUCH_DATABASE_MODE_READ_WRITE ? 'w' : 'r',
&incompat_features);
if (incompat_features) {
"Error: Notmuch database at %s\n"
" requires features (%s)\n"
" not supported by this version of notmuch.\n",
- notmuch_path, incompat_features));
+ database_path, incompat_features));
notmuch_database_destroy (notmuch);
notmuch = NULL;
status = NOTMUCH_STATUS_FILE_ERROR;
notmuch = NULL;
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
}
+ DONE:
+ if (message_ptr)
+ *message_ptr = message;
+ return status;
+}
+
+notmuch_status_t
+notmuch_database_open_with_config (const char *database_path,
+ notmuch_database_mode_t mode,
+ const char *config_path,
+ const char *profile,
+ notmuch_database_t **database,
+ char **status_string)
+{
+ notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
+ void *local = talloc_new (NULL);
+ notmuch_database_t *notmuch = NULL;
+ char *notmuch_path;
+ char *message = NULL;
+ GKeyFile *key_file = NULL;
+
+ _init_libs ();
+
+ notmuch = _alloc_notmuch ();
+ if (! notmuch) {
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+ goto DONE;
+ }
+
+ if ((status = _choose_database_path (local, config_path, profile, &key_file, &database_path,
+ &message)))
+ goto DONE;
+
+ _set_database_path (notmuch, database_path);
+
+ status = _db_dir_exists (database_path, &message);
+ if (status)
+ goto DONE;
+
+ if (! (notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch"))) {
+ message = strdup ("Out of memory\n");
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+ goto DONE;
+ }
+
+ status = _db_dir_exists (notmuch_path, &message);
+ if (status)
+ goto DONE;
+
+ if (! (notmuch->xapian_path = talloc_asprintf (notmuch, "%s/%s", notmuch_path, "xapian"))) {
+ message = strdup ("Out of memory\n");
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+ goto DONE;
+ }
+
+ status = _finish_open (notmuch, profile, mode, key_file, &message);
DONE:
talloc_free (local);
char *notmuch_path = NULL;
char *message = NULL;
GKeyFile *key_file = NULL;
- struct stat st;
- int err;
void *local = talloc_new (NULL);
+ int err;
- if ((status = _choose_database_path (local, config_path, profile, &key_file, &database_path,
- &message)))
- goto DONE;
+ _init_libs ();
- err = stat (database_path, &st);
- if (err) {
- IGNORE_RESULT (asprintf (&message, "Error: Cannot create database at %s: %s.\n",
- database_path, strerror (errno)));
- status = NOTMUCH_STATUS_FILE_ERROR;
+ notmuch = _alloc_notmuch ();
+ if (! notmuch) {
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;
goto DONE;
}
- if (! S_ISDIR (st.st_mode)) {
- IGNORE_RESULT (asprintf (&message, "Error: Cannot create database at %s: "
- "Not a directory.\n",
- database_path));
- status = NOTMUCH_STATUS_FILE_ERROR;
+ _init_libs ();
+
+ if ((status = _choose_database_path (local, config_path, profile,
+ &key_file, &database_path, &message)))
goto DONE;
- }
+
+ status = _db_dir_exists (database_path, &message);
+ if (status)
+ goto DONE;
+
+ _set_database_path (notmuch, database_path);
notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch");
if (err) {
if (errno == EEXIST) {
status = NOTMUCH_STATUS_DATABASE_EXISTS;
+ talloc_free (notmuch);
+ notmuch = NULL;
} else {
IGNORE_RESULT (asprintf (&message, "Error: Cannot create directory %s: %s.\n",
notmuch_path, strerror (errno)));
talloc_free (notmuch);
return status;
}
+
+notmuch_status_t
+notmuch_database_reopen (notmuch_database_t *notmuch,
+ notmuch_database_mode_t new_mode)
+{
+ notmuch_database_mode_t cur_mode = _notmuch_database_mode (notmuch);
+
+ if (notmuch->xapian_db == NULL) {
+ _notmuch_database_log (notmuch, "Cannot reopen closed or nonexistent database\n");
+ return NOTMUCH_STATUS_ILLEGAL_ARGUMENT;
+ }
+
+ try {
+ if (cur_mode == new_mode &&
+ new_mode == NOTMUCH_DATABASE_MODE_READ_ONLY) {
+ notmuch->xapian_db->reopen ();
+ } else {
+ notmuch->xapian_db->close ();
+
+ delete notmuch->xapian_db;
+ notmuch->xapian_db = NULL;
+ /* no need to free the same object twice */
+ notmuch->writable_xapian_db = NULL;
+
+ if (new_mode == NOTMUCH_DATABASE_MODE_READ_WRITE) {
+ notmuch->writable_xapian_db = new Xapian::WritableDatabase (notmuch->xapian_path,
+ DB_ACTION);
+ notmuch->xapian_db = notmuch->writable_xapian_db;
+ } else {
+ notmuch->xapian_db = new Xapian::Database (notmuch->xapian_path,
+ DB_ACTION);
+ }
+ }
+ } catch (const Xapian::Error &error) {
+ if (! notmuch->exception_reported) {
+ _notmuch_database_log (notmuch, "Error: A Xapian exception reopening database: %s\n",
+ error.get_msg ().c_str ());
+ notmuch->exception_reported = true;
+ }
+ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+ }
+
+ notmuch->view++;
+ notmuch->open = true;
+ return NOTMUCH_STATUS_SUCCESS;
+}