aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib/database-private.h
diff options
context:
space:
mode:
authorGravatar Austin Clements <amdragon@mit.edu>2014-08-25 13:26:00 -0400
committerGravatar David Bremner <david@tethera.net>2014-08-30 10:42:08 -0700
commit8363c9053152d349022b821a4a343f0ee2ade318 (patch)
treeb6b904ff63d47c0f20f26ee042d8754b76e338f9 /lib/database-private.h
parent344e4c65a43e0755506e065ec001df8b1eae91f7 (diff)
lib: Database version 3: Introduce fine-grained "features"
Previously, our database schema was versioned by a single number. Each database schema change had to occur "atomically" in Notmuch's development history: before some commit, Notmuch used version N, after that commit, it used version N+1. Hence, each new schema version could introduce only one change, the task of developing a schema change fell on a single person, and it all had to happen and be perfect in a single commit series. This made introducing a new schema version hard. We've seen only two schema changes in the history of Notmuch. This commit introduces database schema version 3; hopefully the last schema version we'll need for a while. With this version, we switch from a single version number to "features": a set of named, independent aspects of the database schema. Features should make backwards compatibility easier. For many things, it should be easy to support databases both with and without a feature, which will allow us to make upgrades optional and will enable "unstable" features that can be developed and tested over time. Features also make forwards compatibility easier. The features recorded in a database include "compatibility flags," which can indicate to an older version of Notmuch when it must support a given feature to open the database for read or for write. This lets us replace the old vague "I don't recognize this version, so something might go wrong, but I promise to try my best" warnings upon opening a database with an unknown version with precise errors. If a database is safe to open for read/write despite unknown features, an older version will know that and issue no message at all. If the database is not safe to open for read/write because of unknown features, an older version will know that, too, and can tell the user exactly which required features it lacks support for.
Diffstat (limited to 'lib/database-private.h')
-rw-r--r--lib/database-private.h108
1 files changed, 107 insertions, 1 deletions
diff --git a/lib/database-private.h b/lib/database-private.h
index d3e65fd6..ca0751cf 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -36,16 +36,106 @@
#pragma GCC visibility push(hidden)
+/* Bit masks for _notmuch_database::features. Features are named,
+ * independent aspects of the database schema.
+ *
+ * A database stores the set of features that it "uses" (implicitly
+ * before database version 3 and explicitly as of version 3).
+ *
+ * A given library version will "recognize" a particular set of
+ * features; if a database uses a feature that the library does not
+ * recognize, the library will refuse to open it. It is assumed the
+ * set of recognized features grows monotonically over time. A
+ * library version will "implement" some subset of the recognized
+ * features: some operations may require that the database use (or not
+ * use) some feature, while other operations may support both
+ * databases that use and that don't use some feature.
+ *
+ * On disk, the database stores string names for these features (see
+ * the feature_names array). These enum bit values are never
+ * persisted to disk and may change freely.
+ */
+enum _notmuch_features {
+ /* If set, file names are stored in "file-direntry" terms. If
+ * unset, file names are stored in document data.
+ *
+ * Introduced: version 1. */
+ NOTMUCH_FEATURE_FILE_TERMS = 1 << 0,
+
+ /* If set, directory timestamps are stored in documents with
+ * XDIRECTORY terms and relative paths. If unset, directory
+ * timestamps are stored in documents with XTIMESTAMP terms and
+ * absolute paths.
+ *
+ * Introduced: version 1. */
+ NOTMUCH_FEATURE_DIRECTORY_DOCS = 1 << 1,
+
+ /* If set, the from, subject, and message-id headers are stored in
+ * message document values. If unset, message documents *may*
+ * have these values, but if the value is empty, it must be
+ * retrieved from the message file.
+ *
+ * Introduced: optional in version 1, required as of version 3.
+ */
+ NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES = 1 << 2,
+
+ /* If set, folder terms are boolean and path terms exist. If
+ * unset, folder terms are probabilistic and stemmed and path
+ * terms do not exist.
+ *
+ * Introduced: version 2. */
+ NOTMUCH_FEATURE_BOOL_FOLDER = 1 << 3,
+};
+
+/* In C++, a named enum is its own type, so define bitwise operators
+ * on _notmuch_features. */
+inline _notmuch_features
+operator|(_notmuch_features a, _notmuch_features b)
+{
+ return static_cast<_notmuch_features>(
+ static_cast<unsigned>(a) | static_cast<unsigned>(b));
+}
+
+inline _notmuch_features
+operator&(_notmuch_features a, _notmuch_features b)
+{
+ return static_cast<_notmuch_features>(
+ static_cast<unsigned>(a) & static_cast<unsigned>(b));
+}
+
+inline _notmuch_features
+operator~(_notmuch_features a)
+{
+ return static_cast<_notmuch_features>(~static_cast<unsigned>(a));
+}
+
+inline _notmuch_features&
+operator|=(_notmuch_features &a, _notmuch_features b)
+{
+ a = a | b;
+ return a;
+}
+
+inline _notmuch_features&
+operator&=(_notmuch_features &a, _notmuch_features b)
+{
+ a = a & b;
+ return a;
+}
+
struct _notmuch_database {
notmuch_bool_t exception_reported;
char *path;
- notmuch_bool_t needs_upgrade;
notmuch_database_mode_t mode;
int atomic_nesting;
Xapian::Database *xapian_db;
+ /* Bit mask of features used by this database. This is a
+ * bitwise-OR of NOTMUCH_FEATURE_* values (above). */
+ enum _notmuch_features features;
+
unsigned int last_doc_id;
uint64_t last_thread_id;
@@ -55,6 +145,22 @@ struct _notmuch_database {
Xapian::ValueRangeProcessor *date_range_processor;
};
+/* Prior to database version 3, features were implied by the database
+ * version number, so hard-code them for earlier versions. */
+#define NOTMUCH_FEATURES_V0 ((enum _notmuch_features)0)
+#define NOTMUCH_FEATURES_V1 (NOTMUCH_FEATURES_V0 | NOTMUCH_FEATURE_FILE_TERMS | \
+ NOTMUCH_FEATURE_DIRECTORY_DOCS)
+#define NOTMUCH_FEATURES_V2 (NOTMUCH_FEATURES_V1 | NOTMUCH_FEATURE_BOOL_FOLDER)
+
+/* Current database features. If any of these are missing from a
+ * database, request an upgrade.
+ * NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES is not included because
+ * upgrade doesn't currently introduce the feature (though brand new
+ * databases will have it). */
+#define NOTMUCH_FEATURES_CURRENT \
+ (NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_DIRECTORY_DOCS | \
+ NOTMUCH_FEATURE_BOOL_FOLDER)
+
/* Return the list of terms from the given iterator matching a prefix.
* The prefix will be stripped from the strings in the returned list.
* The list will be allocated using ctx as the talloc context.