1 Return-Path: <jani@nikula.org>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id 3C43D431FB6
\r
6 for <notmuch@notmuchmail.org>; Sat, 23 Aug 2014 09:02:50 -0700 (PDT)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5
\r
12 tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled
\r
13 Received: from olra.theworths.org ([127.0.0.1])
\r
14 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
15 with ESMTP id bPYCnr-aBRuP for <notmuch@notmuchmail.org>;
\r
16 Sat, 23 Aug 2014 09:02:43 -0700 (PDT)
\r
17 Received: from mail-wi0-f171.google.com (mail-wi0-f171.google.com
\r
18 [209.85.212.171]) (using TLSv1 with cipher RC4-SHA (128/128 bits))
\r
19 (No client certificate requested)
\r
20 by olra.theworths.org (Postfix) with ESMTPS id A3418431FAF
\r
21 for <notmuch@notmuchmail.org>; Sat, 23 Aug 2014 09:02:42 -0700 (PDT)
\r
22 Received: by mail-wi0-f171.google.com with SMTP id hi2so844068wib.16
\r
23 for <notmuch@notmuchmail.org>; Sat, 23 Aug 2014 09:02:41 -0700 (PDT)
\r
24 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
\r
25 d=1e100.net; s=20130820;
\r
26 h=x-gm-message-state:from:to:subject:in-reply-to:references
\r
27 :user-agent:date:message-id:mime-version:content-type;
\r
28 bh=UE6h6AnDwL0D9gvGPUnAfS5fKTsOKdPfacIwzt7V7KQ=;
\r
29 b=bzetmBlRlQOizY3PhWhAoo3cE+VP6iv+c+q2bn4CVIYwAXAYHpYueHY96rRRHC3qMQ
\r
30 3El5ND4wAkUXGBCR8I3vbIhXccGeoXiskKsx/yttIoCQkzljuZQficEf/3gOmZ1r1h17
\r
31 W0xB28/GA8DPF3LlC4E9HwuSLYHjxcj89fYbqBqei0lshMUQ5kfWWzvg2eu3OclK9RGI
\r
32 JnS0tyM1VsOZKHK1otA3ujlNbHOQ+NHYIrzTXfByXa8czh1vlXkROoVp+sNavLVNqusL
\r
33 HZbjilh5rssqaMux0tJB3nJXU1/LbDG2dVr32gDkpvcqJXAHct4KJj0ZWUkUCEVWVhhn
\r
36 ALoCoQnXOVuCL3NVkQr9Oi1AaSAVu6EDqFqIxXBXFKLbjPSirI0noI/6Tun+6U6tXGxn8ZDARVBk
\r
37 X-Received: by 10.180.21.101 with SMTP id u5mr4647284wie.68.1408809761398;
\r
38 Sat, 23 Aug 2014 09:02:41 -0700 (PDT)
\r
39 Received: from localhost (dsl-hkibrasgw2-58c374-75.dhcp.inet.fi.
\r
40 [88.195.116.75]) by mx.google.com with ESMTPSA id
\r
41 y10sm10563955wie.18.2014.08.23.09.02.39 for <multiple recipients>
\r
42 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
\r
43 Sat, 23 Aug 2014 09:02:40 -0700 (PDT)
\r
44 From: Jani Nikula <jani@nikula.org>
\r
45 To: Austin Clements <amdragon@MIT.EDU>, notmuch@notmuchmail.org
\r
46 Subject: Re: [PATCH v3 04/13] lib: Database version 3: Introduce
\r
47 fine-grained "features"
\r
48 In-Reply-To: <1406859003-11561-5-git-send-email-amdragon@mit.edu>
\r
49 References: <1406859003-11561-1-git-send-email-amdragon@mit.edu>
\r
50 <1406859003-11561-5-git-send-email-amdragon@mit.edu>
\r
51 User-Agent: Notmuch/0.18.1+65~g9f0f30f (http://notmuchmail.org) Emacs/24.3.1
\r
52 (x86_64-pc-linux-gnu)
\r
53 Date: Sat, 23 Aug 2014 19:02:39 +0300
\r
54 Message-ID: <87r407jisg.fsf@nikula.org>
\r
56 Content-Type: text/plain
\r
57 X-BeenThere: notmuch@notmuchmail.org
\r
58 X-Mailman-Version: 2.1.13
\r
60 List-Id: "Use and development of the notmuch mail system."
\r
61 <notmuch.notmuchmail.org>
\r
62 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
63 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
64 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
65 List-Post: <mailto:notmuch@notmuchmail.org>
\r
66 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
67 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
68 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
69 X-List-Received-Date: Sat, 23 Aug 2014 16:02:50 -0000
\r
71 On Fri, 01 Aug 2014, Austin Clements <amdragon@MIT.EDU> wrote:
\r
72 > Previously, our database schema was versioned by a single number.
\r
73 > Each database schema change had to occur "atomically" in Notmuch's
\r
74 > development history: before some commit, Notmuch used version N, after
\r
75 > that commit, it used version N+1. Hence, each new schema version
\r
76 > could introduce only one change, the task of developing a schema
\r
77 > change fell on a single person, and it all had to happen and be
\r
78 > perfect in a single commit series. This made introducing a new schema
\r
79 > version hard. We've seen only two schema changes in the history of
\r
82 > This commit introduces database schema version 3; hopefully the last
\r
83 > schema version we'll need for a while. With this version, we switch
\r
84 > from a single version number to "features": a set of named,
\r
85 > independent aspects of the database schema.
\r
87 > Features should make backwards compatibility easier. For many things,
\r
88 > it should be easy to support databases both with and without a
\r
89 > feature, which will allow us to make upgrades optional and will enable
\r
90 > "unstable" features that can be developed and tested over time.
\r
92 > Features also make forwards compatibility easier. The features
\r
93 > recorded in a database include "compatibility flags," which can
\r
94 > indicate to an older version of Notmuch when it must support a given
\r
95 > feature to open the database for read or for write. This lets us
\r
96 > replace the old vague "I don't recognize this version, so something
\r
97 > might go wrong, but I promise to try my best" warnings upon opening a
\r
98 > database with an unknown version with precise errors. If a database
\r
99 > is safe to open for read/write despite unknown features, an older
\r
100 > version will know that and issue no message at all. If the database
\r
101 > is not safe to open for read/write because of unknown features, an
\r
102 > older version will know that, too, and can tell the user exactly which
\r
103 > required features it lacks support for.
\r
105 I agree with the change overall; it might be useful to have another set
\r
106 of eyes on the patch though.
\r
109 > lib/database-private.h | 57 ++++++++++++++-
\r
110 > lib/database.cc | 190 ++++++++++++++++++++++++++++++++++++++++---------
\r
111 > 2 files changed, 213 insertions(+), 34 deletions(-)
\r
113 > diff --git a/lib/database-private.h b/lib/database-private.h
\r
114 > index d3e65fd..2ffab33 100644
\r
115 > --- a/lib/database-private.h
\r
116 > +++ b/lib/database-private.h
\r
117 > @@ -41,11 +41,15 @@ struct _notmuch_database {
\r
121 > - notmuch_bool_t needs_upgrade;
\r
122 > notmuch_database_mode_t mode;
\r
123 > int atomic_nesting;
\r
124 > Xapian::Database *xapian_db;
\r
126 > + /* Bit mask of features used by this database. Features are
\r
127 > + * named, independent aspects of the database schema. This is a
\r
128 > + * bitwise-OR of NOTMUCH_FEATURE_* values (below). */
\r
129 > + unsigned int features;
\r
131 > unsigned int last_doc_id;
\r
132 > uint64_t last_thread_id;
\r
134 > @@ -55,6 +59,57 @@ struct _notmuch_database {
\r
135 > Xapian::ValueRangeProcessor *date_range_processor;
\r
138 > +/* Bit masks for _notmuch_database::features. */
\r
140 > + /* If set, file names are stored in "file-direntry" terms. If
\r
141 > + * unset, file names are stored in document data.
\r
143 > + * Introduced: version 1. Implementation support: both for read;
\r
144 > + * required for write. */
\r
146 Maybe I'm dense, but the implementation support comments could be
\r
149 > + NOTMUCH_FEATURE_FILE_TERMS = 1 << 0,
\r
151 > + /* If set, directory timestamps are stored in documents with
\r
152 > + * XDIRECTORY terms and relative paths. If unset, directory
\r
153 > + * timestamps are stored in documents with XTIMESTAMP terms and
\r
154 > + * absolute paths.
\r
156 > + * Introduced: version 1. Implementation support: required. */
\r
157 > + NOTMUCH_FEATURE_DIRECTORY_DOCS = 1 << 1,
\r
159 > + /* If set, the from, subject, and message-id headers are stored in
\r
160 > + * message document values. If unset, message documents *may*
\r
161 > + * have these values, but if the value is empty, it must be
\r
162 > + * retrieved from the message file.
\r
164 > + * Introduced: optional in version 1, required as of version 3.
\r
165 > + * Implementation support: both.
\r
167 > + NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES = 1 << 2,
\r
169 > + /* If set, folder terms are boolean and path terms exist. If
\r
170 > + * unset, folder terms are probabilistic and stemmed and path
\r
171 > + * terms do not exist.
\r
173 > + * Introduced: version 2. Implementation support: required. */
\r
174 > + NOTMUCH_FEATURE_BOOL_FOLDER = 1 << 3,
\r
177 > +/* Prior to database version 3, features were implied by the database
\r
178 > + * version number, so hard-code them for earlier versions. */
\r
179 > +#define NOTMUCH_FEATURES_V0 (0)
\r
180 > +#define NOTMUCH_FEATURES_V1 (NOTMUCH_FEATURES_V0 | NOTMUCH_FEATURE_FILE_TERMS | \
\r
181 > + NOTMUCH_FEATURE_DIRECTORY_DOCS)
\r
182 > +#define NOTMUCH_FEATURES_V2 (NOTMUCH_FEATURES_V1 | NOTMUCH_FEATURE_BOOL_FOLDER)
\r
184 > +/* Current database features. If any of these are missing from a
\r
185 > + * database, request an upgrade.
\r
186 > + * NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES is not included because
\r
187 > + * upgrade doesn't currently introduce the feature (though brand new
\r
188 > + * databases will have it). */
\r
189 > +#define NOTMUCH_FEATURES_CURRENT \
\r
190 > + (NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_DIRECTORY_DOCS | \
\r
191 > + NOTMUCH_FEATURE_BOOL_FOLDER)
\r
193 > /* Return the list of terms from the given iterator matching a prefix.
\r
194 > * The prefix will be stripped from the strings in the returned list.
\r
195 > * The list will be allocated using ctx as the talloc context.
\r
196 > diff --git a/lib/database.cc b/lib/database.cc
\r
197 > index 45c4260..29a56db 100644
\r
198 > --- a/lib/database.cc
\r
199 > +++ b/lib/database.cc
\r
200 > @@ -20,6 +20,7 @@
\r
202 > #include "database-private.h"
\r
203 > #include "parse-time-vrp.h"
\r
204 > +#include "string-util.h"
\r
206 > #include <iostream>
\r
208 > @@ -42,7 +43,7 @@ typedef struct {
\r
209 > const char *prefix;
\r
212 > -#define NOTMUCH_DATABASE_VERSION 2
\r
213 > +#define NOTMUCH_DATABASE_VERSION 3
\r
215 > #define STRINGIFY(s) _SUB_STRINGIFY(s)
\r
216 > #define _SUB_STRINGIFY(s) #s
\r
217 > @@ -151,6 +152,17 @@ typedef struct {
\r
218 > * changes are made to the database (such as by
\r
219 > * indexing new fields).
\r
221 > + * features The set of features supported by this
\r
222 > + * database. This consists of a set of
\r
223 > + * '\n'-separated lines, where each is a feature
\r
224 > + * name, a '\t', and compatibility flags. If the
\r
225 > + * compatibility flags contain 'w', then the
\r
226 > + * opener must support this feature to safely
\r
227 > + * write this database. If the compatibility
\r
228 > + * flags contain 'r', then the opener must
\r
229 > + * support this feature to read this database.
\r
230 > + * Introduced in database version 3.
\r
232 > * last_thread_id The last thread ID generated. This is stored
\r
233 > * as a 16-byte hexadecimal ASCII representation
\r
234 > * of a 64-bit unsigned integer. The first ID
\r
235 > @@ -251,6 +263,25 @@ _find_prefix (const char *name)
\r
239 > +static const struct
\r
242 Brace should be at the end of the previous line.
\r
244 > + /* NOTMUCH_FEATURE_* value. */
\r
245 > + unsigned int value;
\r
246 > + /* Feature name as it appears in the database. This name should
\r
247 > + * be appropriate for displaying to the user if an older version
\r
248 > + * of notmuch doesn't support this feature. */
\r
249 > + const char *name;
\r
250 > + /* Compatibility flags when this feature is declared. */
\r
251 > + const char *flags;
\r
252 > +} feature_names[] = {
\r
253 > + {NOTMUCH_FEATURE_FILE_TERMS, "multiple paths per message", "rw"},
\r
254 > + {NOTMUCH_FEATURE_DIRECTORY_DOCS, "relative directory paths", "rw"},
\r
255 > + /* Header values are not required for reading a database because a
\r
256 > + * reader can just refer to the message file. */
\r
257 > + {NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES, "from/subject/message-ID in database", "w"},
\r
258 > + {NOTMUCH_FEATURE_BOOL_FOLDER, "exact folder:/path: search", "rw"},
\r
260 Spaces missing after the opening braces and before the closing braces.
\r
265 > notmuch_status_to_string (notmuch_status_t status)
\r
267 > @@ -591,6 +622,11 @@ notmuch_database_create (const char *path, notmuch_database_t **database)
\r
272 > + /* Upgrade doesn't add this feature to existing databases, but new
\r
273 > + * databases have it. */
\r
274 > + notmuch->features |= NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES;
\r
276 > status = notmuch_database_upgrade (notmuch, NULL, NULL);
\r
278 > notmuch_database_close(notmuch);
\r
279 > @@ -619,6 +655,80 @@ _notmuch_database_ensure_writable (notmuch_database_t *notmuch)
\r
280 > return NOTMUCH_STATUS_SUCCESS;
\r
283 > +/* Parse a database features string from the given database version.
\r
285 > + * For version < 3, this ignores the features string and returns a
\r
286 > + * hard-coded set of features.
\r
288 > + * If there are unrecognized features that are required to open the
\r
289 > + * database in mode (which should be 'r' or 'w'), return a
\r
290 > + * comma-separated list of unrecognized but required features in
\r
291 > + * *incompat_out, which will be allocated from ctx.
\r
293 Please describe the actual return value.
\r
296 > +static unsigned int
\r
297 > +_parse_features (const void *ctx, const char *features, unsigned int version,
\r
298 > + char mode, char **incompat_out)
\r
300 > + unsigned int res = 0, namelen, i;
\r
301 > + size_t llen = 0;
\r
302 > + const char *flags;
\r
304 > + /* Prior to database version 3, features were implied by the
\r
305 > + * version number. */
\r
306 > + if (version == 0)
\r
307 > + return NOTMUCH_FEATURES_V0;
\r
308 > + else if (version == 1)
\r
309 > + return NOTMUCH_FEATURES_V1;
\r
310 > + else if (version == 2)
\r
311 > + return NOTMUCH_FEATURES_V2;
\r
313 > + /* Parse the features string */
\r
314 > + while ((features = strtok_len_c (features + llen, "\n", &llen)) != NULL) {
\r
315 > + flags = strchr (features, '\t');
\r
316 > + if (! flags || flags > features + llen)
\r
318 > + namelen = flags - features;
\r
320 > + for (i = 0; i < ARRAY_SIZE (feature_names); ++i) {
\r
321 > + if (strlen (feature_names[i].name) == namelen &&
\r
322 > + strncmp (feature_names[i].name, features, namelen) == 0) {
\r
323 > + res |= feature_names[i].value;
\r
328 > + if (i == ARRAY_SIZE (feature_names)) {
\r
329 > + /* Unrecognized feature */
\r
330 > + const char *have = strchr (flags, mode);
\r
331 > + if (have && have < features + llen) {
\r
332 > + /* This feature is required to access this database in
\r
333 > + * 'mode', but we don't understand it. */
\r
334 > + if (! *incompat_out)
\r
335 > + *incompat_out = talloc_strdup (ctx, "");
\r
336 > + *incompat_out = talloc_asprintf_append_buffer (
\r
337 > + *incompat_out, "%s%.*s", **incompat_out ? ", " : "",
\r
338 > + namelen, features);
\r
340 Do we intend the lib user to be able to parse the features? Perhaps we
\r
341 should use '\n' as separator here too? (Although looks like *currently*
\r
342 this is only for printing the message from within the lib.)
\r
352 > +_print_features (const void *ctx, unsigned int features)
\r
354 > + unsigned int i;
\r
355 > + char *res = talloc_strdup (ctx, "");
\r
357 > + for (i = 0; i < ARRAY_SIZE (feature_names); ++i)
\r
358 > + if (features & feature_names[i].value)
\r
359 > + res = talloc_asprintf_append_buffer (
\r
360 > + res, "%s\t%s\n", feature_names[i].name, feature_names[i].flags);
\r
366 > notmuch_database_open (const char *path,
\r
367 > notmuch_database_mode_t mode,
\r
368 > @@ -627,7 +737,7 @@ notmuch_database_open (const char *path,
\r
369 > notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
\r
370 > void *local = talloc_new (NULL);
\r
371 > notmuch_database_t *notmuch = NULL;
\r
372 > - char *notmuch_path, *xapian_path;
\r
373 > + char *notmuch_path, *xapian_path, *incompat_features;
\r
376 > unsigned int i, version;
\r
377 > @@ -677,7 +787,6 @@ notmuch_database_open (const char *path,
\r
378 > if (notmuch->path[strlen (notmuch->path) - 1] == '/')
\r
379 > notmuch->path[strlen (notmuch->path) - 1] = '\0';
\r
381 > - notmuch->needs_upgrade = FALSE;
\r
382 > notmuch->mode = mode;
\r
383 > notmuch->atomic_nesting = 0;
\r
385 > @@ -686,37 +795,44 @@ notmuch_database_open (const char *path,
\r
386 > if (mode == NOTMUCH_DATABASE_MODE_READ_WRITE) {
\r
387 > notmuch->xapian_db = new Xapian::WritableDatabase (xapian_path,
\r
388 > Xapian::DB_CREATE_OR_OPEN);
\r
389 > - version = notmuch_database_get_version (notmuch);
\r
391 > - if (version > NOTMUCH_DATABASE_VERSION) {
\r
392 > - fprintf (stderr,
\r
393 > - "Error: Notmuch database at %s\n"
\r
394 > - " has a newer database format version (%u) than supported by this\n"
\r
395 > - " version of notmuch (%u). Refusing to open this database in\n"
\r
396 > - " read-write mode.\n",
\r
397 > - notmuch_path, version, NOTMUCH_DATABASE_VERSION);
\r
398 > - notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
\r
399 > - notmuch_database_destroy (notmuch);
\r
400 > - notmuch = NULL;
\r
401 > - status = NOTMUCH_STATUS_FILE_ERROR;
\r
405 > - if (version < NOTMUCH_DATABASE_VERSION)
\r
406 > - notmuch->needs_upgrade = TRUE;
\r
408 > notmuch->xapian_db = new Xapian::Database (xapian_path);
\r
409 > - version = notmuch_database_get_version (notmuch);
\r
410 > - if (version > NOTMUCH_DATABASE_VERSION)
\r
412 > - fprintf (stderr,
\r
413 > - "Warning: Notmuch database at %s\n"
\r
414 > - " has a newer database format version (%u) than supported by this\n"
\r
415 > - " version of notmuch (%u). Some operations may behave incorrectly,\n"
\r
416 > - " (but the database will not be harmed since it is being opened\n"
\r
417 > - " in read-only mode).\n",
\r
418 > - notmuch_path, version, NOTMUCH_DATABASE_VERSION);
\r
422 > + /* Check version. As of database version 3, we represent
\r
423 > + * changes in terms of features, so assume a version bump
\r
424 > + * means a dramatically incompatible change. */
\r
425 > + version = notmuch_database_get_version (notmuch);
\r
426 > + if (version > NOTMUCH_DATABASE_VERSION) {
\r
427 > + fprintf (stderr,
\r
428 > + "Error: Notmuch database at %s\n"
\r
429 > + " has a newer database format version (%u) than supported by this\n"
\r
430 > + " version of notmuch (%u).\n",
\r
431 > + notmuch_path, version, NOTMUCH_DATABASE_VERSION);
\r
432 > + notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
\r
433 > + notmuch_database_destroy (notmuch);
\r
434 > + notmuch = NULL;
\r
435 > + status = NOTMUCH_STATUS_FILE_ERROR;
\r
439 > + /* Check features. */
\r
440 > + incompat_features = NULL;
\r
441 > + notmuch->features = _parse_features (
\r
442 > + local, notmuch->xapian_db->get_metadata ("features").c_str (),
\r
443 > + version, mode == NOTMUCH_DATABASE_MODE_READ_WRITE ? 'w' : 'r',
\r
445 Makes me think _parse_features could use notmuch_database_mode_t mode
\r
446 instead of char mode. *shrug*.
\r
448 > + &incompat_features);
\r
449 > + if (incompat_features) {
\r
450 > + fprintf (stderr,
\r
451 > + "Error: Notmuch database at %s\n"
\r
452 > + " requires features (%s)\n"
\r
453 > + " not supported by this version of notmuch.\n",
\r
454 > + notmuch_path, incompat_features);
\r
455 > + notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
\r
456 > + notmuch_database_destroy (notmuch);
\r
457 > + notmuch = NULL;
\r
458 > + status = NOTMUCH_STATUS_FILE_ERROR;
\r
462 > notmuch->last_doc_id = notmuch->xapian_db->get_lastdocid ();
\r
463 > @@ -1048,7 +1164,8 @@ notmuch_database_get_version (notmuch_database_t *notmuch)
\r
465 > notmuch_database_needs_upgrade (notmuch_database_t *notmuch)
\r
467 > - return notmuch->needs_upgrade;
\r
468 > + return notmuch->mode == NOTMUCH_DATABASE_MODE_READ_WRITE &&
\r
469 > + (NOTMUCH_FEATURES_CURRENT & ~notmuch->features);
\r
472 Am I correct that this does not lead to a database upgrade from v2 to v3
\r
473 until we actually change the features?
\r
475 Aside, why don't we return a suitable status code from
\r
476 notmuch_database_open when an upgrade is required?
\r
478 > static volatile sig_atomic_t do_progress_notify = 0;
\r
479 > @@ -1077,6 +1194,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
\r
480 > double progress),
\r
483 > + void *local = talloc_new (NULL);
\r
484 > Xapian::WritableDatabase *db;
\r
485 > struct sigaction action;
\r
486 > struct itimerval timerval;
\r
487 > @@ -1114,6 +1232,10 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
\r
488 > timer_is_active = TRUE;
\r
491 > + /* Set the target features so we write out changes in the desired
\r
493 > + notmuch->features |= NOTMUCH_FEATURES_CURRENT;
\r
495 > /* Before version 1, each message document had its filename in the
\r
496 > * data field. Copy that into the new format by calling
\r
497 > * notmuch_message_add_filename.
\r
498 > @@ -1226,6 +1348,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
\r
499 > notmuch_query_destroy (query);
\r
502 > + db->set_metadata ("features", _print_features (local, notmuch->features));
\r
503 > db->set_metadata ("version", STRINGIFY (NOTMUCH_DATABASE_VERSION));
\r
506 > @@ -1302,6 +1425,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
\r
507 > sigaction (SIGALRM, &action, NULL);
\r
510 > + talloc_free (local);
\r
511 > return NOTMUCH_STATUS_SUCCESS;
\r
517 > _______________________________________________
\r
518 > notmuch mailing list
\r
519 > notmuch@notmuchmail.org
\r
520 > http://notmuchmail.org/mailman/listinfo/notmuch
\r