d2c253136d146db6cca03f2ed2b220526ab07cfb
[notmuch] / lib / database-private.h
1 /* database-private.h - For peeking into the internals of notmuch_database_t
2  *
3  * Copyright © 2009 Carl Worth
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see https://www.gnu.org/licenses/ .
17  *
18  * Author: Carl Worth <cworth@cworth.org>
19  */
20
21 #ifndef NOTMUCH_DATABASE_PRIVATE_H
22 #define NOTMUCH_DATABASE_PRIVATE_H
23
24 /* According to WG14/N1124, a C++ implementation won't provide us a
25  * macro like PRIx64 (which gives a printf format string for
26  * formatting a uint64_t as hexadecimal) unless we define
27  * __STDC_FORMAT_MACROS before including inttypes.h. That's annoying,
28  * but there it is.
29  */
30 #define __STDC_FORMAT_MACROS
31 #include <inttypes.h>
32
33 #include "notmuch-private.h"
34
35 #ifdef SILENCE_XAPIAN_DEPRECATION_WARNINGS
36 #define XAPIAN_DEPRECATED(D) D
37 #endif
38
39 #include <xapian.h>
40
41 /* Bit masks for _notmuch_database::features.  Features are named,
42  * independent aspects of the database schema.
43  *
44  * A database stores the set of features that it "uses" (implicitly
45  * before database version 3 and explicitly as of version 3).
46  *
47  * A given library version will "recognize" a particular set of
48  * features; if a database uses a feature that the library does not
49  * recognize, the library will refuse to open it.  It is assumed the
50  * set of recognized features grows monotonically over time.  A
51  * library version will "implement" some subset of the recognized
52  * features: some operations may require that the database use (or not
53  * use) some feature, while other operations may support both
54  * databases that use and that don't use some feature.
55  *
56  * On disk, the database stores string names for these features (see
57  * the feature_names array).  These enum bit values are never
58  * persisted to disk and may change freely.
59  */
60 enum _notmuch_features {
61     /* If set, file names are stored in "file-direntry" terms.  If
62      * unset, file names are stored in document data.
63      *
64      * Introduced: version 1. */
65     NOTMUCH_FEATURE_FILE_TERMS                  = 1 << 0,
66
67     /* If set, directory timestamps are stored in documents with
68      * XDIRECTORY terms and relative paths.  If unset, directory
69      * timestamps are stored in documents with XTIMESTAMP terms and
70      * absolute paths.
71      *
72      * Introduced: version 1. */
73     NOTMUCH_FEATURE_DIRECTORY_DOCS              = 1 << 1,
74
75     /* If set, the from, subject, and message-id headers are stored in
76      * message document values.  If unset, message documents *may*
77      * have these values, but if the value is empty, it must be
78      * retrieved from the message file.
79      *
80      * Introduced: optional in version 1, required as of version 3.
81      */
82     NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES      = 1 << 2,
83
84     /* If set, folder terms are boolean and path terms exist.  If
85      * unset, folder terms are probabilistic and stemmed and path
86      * terms do not exist.
87      *
88      * Introduced: version 2. */
89     NOTMUCH_FEATURE_BOOL_FOLDER                 = 1 << 3,
90
91     /* If set, missing messages are stored in ghost mail documents.
92      * If unset, thread IDs of ghost messages are stored as database
93      * metadata instead of in ghost documents.
94      *
95      * Introduced: version 3. */
96     NOTMUCH_FEATURE_GHOSTS                      = 1 << 4,
97
98
99     /* If set, then the database was created after the introduction of
100      * indexed mime types. If unset, then the database may contain a
101      * mixture of messages with indexed and non-indexed mime types.
102      *
103      * Introduced: version 3. */
104     NOTMUCH_FEATURE_INDEXED_MIMETYPES           = 1 << 5,
105
106     /* If set, messages store the revision number of the last
107      * modification in NOTMUCH_VALUE_LAST_MOD.
108      *
109      * Introduced: version 3. */
110     NOTMUCH_FEATURE_LAST_MOD                    = 1 << 6,
111
112     /* If set, unprefixed terms are stored only for the message body,
113      * not for headers.
114      *
115      * Introduced: version 3. */
116     NOTMUCH_FEATURE_UNPREFIX_BODY_ONLY          = 1 << 7,
117 };
118
119 /* In C++, a named enum is its own type, so define bitwise operators
120  * on _notmuch_features. */
121 inline _notmuch_features
122 operator| (_notmuch_features a, _notmuch_features b)
123 {
124     return static_cast<_notmuch_features>(
125         static_cast<unsigned>(a) | static_cast<unsigned>(b));
126 }
127
128 inline _notmuch_features
129 operator& (_notmuch_features a, _notmuch_features b)
130 {
131     return static_cast<_notmuch_features>(
132         static_cast<unsigned>(a) & static_cast<unsigned>(b));
133 }
134
135 inline _notmuch_features
136 operator~ (_notmuch_features a)
137 {
138     return static_cast<_notmuch_features>(~static_cast<unsigned>(a));
139 }
140
141 inline _notmuch_features&
142 operator|= (_notmuch_features &a, _notmuch_features b)
143 {
144     a = a | b;
145     return a;
146 }
147
148 inline _notmuch_features&
149 operator&= (_notmuch_features &a, _notmuch_features b)
150 {
151     a = a & b;
152     return a;
153 }
154
155 /*
156  * Configuration options for xapian database fields */
157 typedef enum notmuch_field_flags {
158     NOTMUCH_FIELD_NO_FLAGS      = 0,
159     NOTMUCH_FIELD_EXTERNAL      = 1 << 0,
160     NOTMUCH_FIELD_PROBABILISTIC = 1 << 1,
161     NOTMUCH_FIELD_PROCESSOR     = 1 << 2,
162 } notmuch_field_flag_t;
163
164 /*
165  * define bitwise operators to hide casts */
166 inline notmuch_field_flag_t
167 operator| (notmuch_field_flag_t a, notmuch_field_flag_t b)
168 {
169     return static_cast<notmuch_field_flag_t>(
170         static_cast<unsigned>(a) | static_cast<unsigned>(b));
171 }
172
173 inline notmuch_field_flag_t
174 operator& (notmuch_field_flag_t a, notmuch_field_flag_t b)
175 {
176     return static_cast<notmuch_field_flag_t>(
177         static_cast<unsigned>(a) & static_cast<unsigned>(b));
178 }
179
180 #define NOTMUCH_QUERY_PARSER_FLAGS (Xapian::QueryParser::FLAG_BOOLEAN | \
181                                     Xapian::QueryParser::FLAG_PHRASE | \
182                                     Xapian::QueryParser::FLAG_LOVEHATE | \
183                                     Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE | \
184                                     Xapian::QueryParser::FLAG_WILDCARD | \
185                                     Xapian::QueryParser::FLAG_PURE_NOT)
186
187 struct _notmuch_database {
188     bool exception_reported;
189
190     char *path;
191
192     notmuch_database_mode_t mode;
193     int atomic_nesting;
194     /* true if changes have been made in this atomic section */
195     bool atomic_dirty;
196     Xapian::Database *xapian_db;
197     bool open;
198     /* Bit mask of features used by this database.  This is a
199      * bitwise-OR of NOTMUCH_FEATURE_* values (above). */
200     enum _notmuch_features features;
201
202     unsigned int last_doc_id;
203     uint64_t last_thread_id;
204
205     /* error reporting; this value persists only until the
206      * next library call. May be NULL */
207     char *status_string;
208
209     /* Highest committed revision number.  Modifications are recorded
210      * under a higher revision number, which can be generated with
211      * notmuch_database_new_revision. */
212     unsigned long revision;
213     const char *uuid;
214
215     /* Keep track of the number of times the database has been re-opened
216      * (or other global invalidations of notmuch's caching)
217      */
218     unsigned long view;
219     Xapian::QueryParser *query_parser;
220     Xapian::TermGenerator *term_gen;
221     Xapian::RangeProcessor *value_range_processor;
222     Xapian::RangeProcessor *date_range_processor;
223     Xapian::RangeProcessor *last_mod_range_processor;
224
225     /* XXX it's slightly gross to use two parallel string->string maps
226      * here, but at least they are small */
227     notmuch_string_map_t *user_prefix;
228     notmuch_string_map_t *user_header;
229 };
230
231 /* Prior to database version 3, features were implied by the database
232  * version number, so hard-code them for earlier versions. */
233 #define NOTMUCH_FEATURES_V0 ((enum _notmuch_features) 0)
234 #define NOTMUCH_FEATURES_V1 (NOTMUCH_FEATURES_V0 | NOTMUCH_FEATURE_FILE_TERMS | \
235                              NOTMUCH_FEATURE_DIRECTORY_DOCS)
236 #define NOTMUCH_FEATURES_V2 (NOTMUCH_FEATURES_V1 | NOTMUCH_FEATURE_BOOL_FOLDER)
237
238 /* Current database features.  If any of these are missing from a
239  * database, request an upgrade.
240  * NOTMUCH_FEATURE_FROM_SUBJECT_ID_VALUES and
241  * NOTMUCH_FEATURE_INDEXED_MIMETYPES are not included because upgrade
242  * doesn't currently introduce the features (though brand new databases
243  * will have it). */
244 #define NOTMUCH_FEATURES_CURRENT \
245     (NOTMUCH_FEATURE_FILE_TERMS | NOTMUCH_FEATURE_DIRECTORY_DOCS | \
246      NOTMUCH_FEATURE_BOOL_FOLDER | NOTMUCH_FEATURE_GHOSTS | \
247      NOTMUCH_FEATURE_LAST_MOD)
248
249 /* Return the list of terms from the given iterator matching a prefix.
250  * The prefix will be stripped from the strings in the returned list.
251  * The list will be allocated using ctx as the talloc context.
252  *
253  * The function returns NULL on failure.
254  */
255 notmuch_string_list_t *
256 _notmuch_database_get_terms_with_prefix (void *ctx, Xapian::TermIterator &i,
257                                          Xapian::TermIterator &end,
258                                          const char *prefix);
259
260 void
261 _notmuch_database_find_doc_ids (notmuch_database_t *notmuch,
262                                 const char *prefix_name,
263                                 const char *value,
264                                 Xapian::PostingIterator *begin,
265                                 Xapian::PostingIterator *end);
266 #endif