* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see http://www.gnu.org/licenses/ .
+ * along with this program. If not, see https://www.gnu.org/licenses/ .
*
* Author: Carl Worth <cworth@cworth.org>
*/
#define STRINGIFY(s) _SUB_STRINGIFY(s)
#define _SUB_STRINGIFY(s) #s
+#if HAVE_XAPIAN_DB_RETRY_LOCK
+#define DB_ACTION (Xapian::DB_CREATE_OR_OPEN | Xapian::DB_RETRY_LOCK)
+#else
+#define DB_ACTION Xapian::DB_CREATE_OR_OPEN
+#endif
+
/* Here's the current schema for our database (for NOTMUCH_DATABASE_VERSION):
*
* We currently have three different types of documents (mail, ghost,
* STRING is the name of a file within that
* directory for this mail message.
*
+ * property: Has a property with key=value
+ * FIXME: if no = is present, should match on any value
+ *
* A mail document also has four values:
*
* TIMESTAMP: The time_t value corresponding to the message's
* generated is 1 and the value will be
* incremented for each thread ID.
*
+ * C* metadata keys starting with C indicate
+ * configuration data. It can be managed with the
+ * n_database_*config* API. There is a convention
+ * of hierarchical keys separated by '.' (e.g.
+ * query.notmuch stores the value for the named
+ * query 'notmuch'), but it is not enforced by the
+ * API.
+ *
* Obsolete metadata
* -----------------
*
/* With these prefix values we follow the conventions published here:
*
- * http://xapian.org/docs/omega/termprefixes.html
+ * https://xapian.org/docs/omega/termprefixes.html
*
* as much as makes sense. Note that I took some liberty in matching
* the reserved prefix values to notmuch concepts, (for example, 'G'
{ "is", "K" },
{ "id", "Q" },
{ "path", "P" },
+ { "property", "XPROPERTY" },
/*
- * Without the ":", since this is a multi-letter prefix, Xapian
- * will add a colon itself if the first letter of the path is
- * upper-case ASCII. Including the ":" forces there to always be a
- * colon, which keeps our own logic simpler.
+ * Unconditionally add ':' to reduce potential ambiguity with
+ * overlapping prefixes and/or terms that start with capital
+ * letters. See Xapian document termprefixes.html for related
+ * discussion.
*/
{ "folder", "XFOLDER:" },
};
talloc_free (notmuch->status_string);
notmuch->status_string = talloc_vasprintf (notmuch, format, va_args);
+ va_end (va_args);
+}
+
+void
+_notmuch_database_log_append (notmuch_database_t *notmuch,
+ const char *format,
+ ...)
+{
+ va_list va_args;
+
+ va_start (va_args, format);
+
+ if (notmuch->status_string)
+ notmuch->status_string = talloc_vasprintf_append (notmuch->status_string, format, va_args);
+ else
+ notmuch->status_string = talloc_vasprintf (notmuch, format, va_args);
va_end (va_args);
}
if (mode == NOTMUCH_DATABASE_MODE_READ_WRITE) {
notmuch->xapian_db = new Xapian::WritableDatabase (xapian_path,
- Xapian::DB_CREATE_OR_OPEN);
+ DB_ACTION);
} else {
notmuch->xapian_db = new Xapian::Database (xapian_path);
}
delete notmuch->last_mod_range_processor;
notmuch->last_mod_range_processor = NULL;
+#if HAVE_XAPIAN_FIELD_PROCESSOR
+ delete notmuch->date_field_processor;
+ notmuch->date_field_processor = NULL;
+ delete notmuch->query_field_processor;
+ notmuch->query_field_processor = NULL;
+#endif
+
return status;
}
-#if HAVE_XAPIAN_COMPACT
static int
unlink_cb (const char *path,
unused (const struct stat *sb),
return ret;
}
-#else
-notmuch_status_t
-notmuch_database_compact (unused (const char *path),
- unused (const char *backup_path),
- unused (notmuch_compact_status_cb_t status_cb),
- unused (void *closure))
-{
- _notmuch_database_log (notmuch, "notmuch was compiled against a xapian version lacking compaction support.\n");
- return NOTMUCH_STATUS_UNSUPPORTED_OPERATION;
-}
-#endif
notmuch_status_t
notmuch_database_destroy (notmuch_database_t *notmuch)
notmuch->atomic_nesting > 0)
goto DONE;
- if (notmuch_database_needs_upgrade(notmuch))
- return NOTMUCH_STATUS_UPGRADE_REQUIRED;
+ if (notmuch_database_needs_upgrade (notmuch))
+ return NOTMUCH_STATUS_UPGRADE_REQUIRED;
try {
(static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db))->begin_transaction (false);
* However, we rely on flushing to test atomicity. */
const char *thresh = getenv ("XAPIAN_FLUSH_THRESHOLD");
if (thresh && atoi (thresh) == 1)
- db->flush ();
+ db->commit ();
} catch (const Xapian::Error &error) {
_notmuch_database_log (notmuch, "A Xapian exception occurred committing transaction: %s.\n",
error.get_msg().c_str());
* References header, if available. If not, fall back to the
* first message ID in the In-Reply-To header. */
if (last_ref_message_id) {
- _notmuch_message_add_term (message, "replyto",
- last_ref_message_id);
+ _notmuch_message_add_term (message, "replyto",
+ last_ref_message_id);
} else if (in_reply_to_message_id) {
_notmuch_message_add_term (message, "replyto",
in_reply_to_message_id);
if (stored_id.empty ()) {
return NULL;
} else {
- Xapian::WritableDatabase *db;
+ Xapian::WritableDatabase *db;
db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
/* Clear the metadata for this message ID. We don't need it
* anymore. */
- db->set_metadata (metadata_key, "");
+ db->set_metadata (metadata_key, "");
- return talloc_strdup (ctx, stored_id.c_str ());
+ return talloc_strdup (ctx, stored_id.c_str ());
}
}