Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 281 lines (207 sloc) 6.463 kB
ce97c49 @djcb * mu-store refactoring
authored
1 /* -*-mode: c++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8-*- */
2 /*
3 ** Copyright (C) 2008-2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
4 **
5 ** This program is free software; you can redistribute it and/or modify it
6 ** under the terms of the GNU General Public License as published by the
7 ** Free Software Foundation; either version 3, or (at your option) any
8 ** 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, write to the Free Software Foundation,
17 ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **
19 */
20
21 #if HAVE_CONFIG_H
22 #include "config.h"
23 #endif /*HAVE_CONFIG_H*/
24
25 #include <cstdio>
26 #include <xapian.h>
27 #include <cstring>
28 #include <stdexcept>
57b2625 @djcb * mu-store-read.cc: use realpath when determining path, getting rid of
authored
29 #include <limits.h>
30 #include <stdlib.h>
31 #include <errno.h>
ce97c49 @djcb * mu-store refactoring
authored
32
33 #include "mu-store.h"
34 #include "mu-store-priv.hh" /* _MuStore */
35
36 #include "mu-msg.h"
37 #include "mu-msg-part.h"
38 #include "mu-store.h"
39 #include "mu-util.h"
40 #include "mu-str.h"
41 #include "mu-date.h"
42 #include "mu-flags.h"
43 #include "mu-contacts.h"
44
a984a70 * mu-store-(read|write).cc: cleanups
Dirk-Jan C. Binnema authored
45
46 // note: not re-entrant
6a13866 @djcb * mu-store: many cleanups, fixes
authored
47 const char*
a984a70 * mu-store-(read|write).cc: cleanups
Dirk-Jan C. Binnema authored
48 _MuStore::get_uid_term (const char* path)
49 {
50 // combination of DJB, BKDR hash functions to get a 64 bit
51 // value
52 unsigned djbhash, bkdrhash, bkdrseed;
53 unsigned u;
57b2625 @djcb * mu-store-read.cc: use realpath when determining path, getting rid of
authored
54
55 char real_path[PATH_MAX + 1];
92e543c @djcb * fix unit tests (i.e.. fix re-indexing messages bug)
authored
56 static char hex[18];
d93186e * <many> add support for searching attachment mime-types
djcb authored
57 static const char uid_prefix =
58 mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_UID);
a984a70 * mu-store-(read|write).cc: cleanups
Dirk-Jan C. Binnema authored
59
57b2625 @djcb * mu-store-read.cc: use realpath when determining path, getting rid of
authored
60 /* check profile to see if realpath is expensive; we need
61 * realpath here (and in mu-msg-file) to ensure that the same
62 * messages are only considered ones (ignore e.g. symlinks and
63 * '//' in paths) */
441c5a1 @djcb * mu-store-read: fix realpath checking
authored
64
65 // note: realpath fails when there's no file at path
66 if (!realpath (path, real_path))
67 strcpy (real_path, path);
57b2625 @djcb * mu-store-read.cc: use realpath when determining path, getting rid of
authored
68
a984a70 * mu-store-(read|write).cc: cleanups
Dirk-Jan C. Binnema authored
69 djbhash = 5381;
70 bkdrhash = 0;
71 bkdrseed = 1313;
72
57b2625 @djcb * mu-store-read.cc: use realpath when determining path, getting rid of
authored
73 for(u = 0; real_path[u]; ++u) {
74 djbhash = ((djbhash << 5) + djbhash) + real_path[u];
75 bkdrhash = bkdrhash * bkdrseed + real_path[u];
6a13866 @djcb * mu-store: many cleanups, fixes
authored
76 }
77
d93186e * <many> add support for searching attachment mime-types
djcb authored
78 snprintf (hex, sizeof(hex), "%c%08x%08x",
79 uid_prefix, djbhash, bkdrhash);
6a13866 @djcb * mu-store: many cleanups, fixes
authored
80
a984a70 * mu-store-(read|write).cc: cleanups
Dirk-Jan C. Binnema authored
81 return hex;
82 }
6a13866 @djcb * mu-store: many cleanups, fixes
authored
83
84
ce97c49 @djcb * mu-store refactoring
authored
85 MuStore*
86 mu_store_new_read_only (const char* xpath, GError **err)
87 {
88 g_return_val_if_fail (xpath, NULL);
89
90 try {
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
91 return new _MuStore (xpath);
ce97c49 @djcb * mu-store refactoring
authored
92
6a13866 @djcb * mu-store: many cleanups, fixes
authored
93 } catch (const MuStoreError& merr) {
ece0bc5 @djcb * introduce mu_util_g_set_error, a g_set_error wrapper
authored
94 mu_util_g_set_error (err, merr.mu_error(), "%s",
279f627 @djcb * cosmetics
authored
95 merr.what().c_str());
6a13866 @djcb * mu-store: many cleanups, fixes
authored
96
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
97 } MU_XAPIAN_CATCH_BLOCK_G_ERROR(err, MU_ERROR_XAPIAN);
ce97c49 @djcb * mu-store refactoring
authored
98
99 return NULL;
100 }
101
102
6a13866 @djcb * mu-store: many cleanups, fixes
authored
103 gboolean
104 mu_store_is_read_only (MuStore *store)
105 {
106 g_return_val_if_fail (store, FALSE);
107
108 try {
109 return store->is_read_only() ? TRUE : FALSE;
110
111 } MU_XAPIAN_CATCH_BLOCK_RETURN(FALSE);
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
112
6a13866 @djcb * mu-store: many cleanups, fixes
authored
113 }
114
ce97c49 @djcb * mu-store refactoring
authored
115
116 unsigned
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
117 mu_store_count (MuStore *store, GError **err)
ce97c49 @djcb * mu-store refactoring
authored
118 {
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
119 g_return_val_if_fail (store, (unsigned)-1);
ce97c49 @djcb * mu-store refactoring
authored
120
121 try {
122 return store->db_read_only()->get_doccount();
123
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
124 } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(err, MU_ERROR_XAPIAN,
125 (unsigned)-1);
ce97c49 @djcb * mu-store refactoring
authored
126 }
127
128
129 const char*
130 mu_store_version (MuStore *store)
131 {
132 g_return_val_if_fail (store, NULL);
133 return store->version ();
134 }
135
136
6a13866 @djcb * mu-store: many cleanups, fixes
authored
137 gboolean
138 mu_store_needs_upgrade (MuStore *store)
139 {
140 g_return_val_if_fail (store, TRUE);
141
279f627 @djcb * cosmetics
authored
142 return (g_strcmp0 (mu_store_version (store),
143 MU_STORE_SCHEMA_VERSION) == 0) ? FALSE : TRUE;
6a13866 @djcb * mu-store: many cleanups, fixes
authored
144 }
145
ce97c49 @djcb * mu-store refactoring
authored
146
147 char*
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
148 mu_store_get_metadata (MuStore *store, const char *key, GError **err)
ce97c49 @djcb * mu-store refactoring
authored
149 {
150 g_return_val_if_fail (store, NULL);
151 g_return_val_if_fail (key, NULL);
152
153 try {
154 const std::string val (store->db_read_only()->get_metadata (key));
155 return val.empty() ? NULL : g_strdup (val.c_str());
156
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
157 } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(err, MU_ERROR_XAPIAN, NULL);
ce97c49 @djcb * mu-store refactoring
authored
158 }
159
160
161 XapianDatabase*
162 mu_store_get_read_only_database (MuStore *store)
163 {
164 g_return_val_if_fail (store, NULL);
165 return (XapianWritableDatabase*)store->db_read_only();
166 }
167
168
169
170 gboolean
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
171 mu_store_contains_message (MuStore *store, const char* path, GError **err)
ce97c49 @djcb * mu-store refactoring
authored
172 {
173 g_return_val_if_fail (store, FALSE);
174 g_return_val_if_fail (path, FALSE);
175
176 try {
92e543c @djcb * fix unit tests (i.e.. fix re-indexing messages bug)
authored
177 const std::string term (store->get_uid_term(path));
aa952aa @djcb * mu-stored-read.cc: don't do excessive logging
authored
178 return store->db_read_only()->term_exists (term) ? TRUE: FALSE;
ce97c49 @djcb * mu-store refactoring
authored
179
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
180 } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(err, MU_ERROR_XAPIAN, FALSE);
181
ce97c49 @djcb * mu-store refactoring
authored
182 }
183
184
a984a70 * mu-store-(read|write).cc: cleanups
Dirk-Jan C. Binnema authored
185 unsigned
186 mu_store_get_docid_for_path (MuStore *store, const char* path, GError **err)
187 {
188 g_return_val_if_fail (store, FALSE);
189 g_return_val_if_fail (path, FALSE);
190
191 try {
92e543c @djcb * fix unit tests (i.e.. fix re-indexing messages bug)
authored
192 const std::string term (store->get_uid_term(path));
193 Xapian::Query query (term);
a984a70 * mu-store-(read|write).cc: cleanups
Dirk-Jan C. Binnema authored
194 Xapian::Enquire enq (*store->db_read_only());
195
196 enq.set_query (query);
197
198 Xapian::MSet mset (enq.get_mset (0,1));
199 if (mset.empty())
200 throw MuStoreError (MU_ERROR_NO_MATCHES,
201 "message not found");
202
203 return *mset.begin();
204
205 } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(err, MU_ERROR_XAPIAN,
206 MU_STORE_INVALID_DOCID);
207 }
208
209
ce97c49 @djcb * mu-store refactoring
authored
210
211 time_t
279f627 @djcb * cosmetics
authored
212 mu_store_get_timestamp (MuStore *store, const char *msgpath, GError **err)
ce97c49 @djcb * mu-store refactoring
authored
213 {
214 char *stampstr;
215 time_t rv;
216
217 g_return_val_if_fail (store, 0);
218 g_return_val_if_fail (msgpath, 0);
219
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
220 stampstr = mu_store_get_metadata (store, msgpath, err);
ce97c49 @djcb * mu-store refactoring
authored
221 if (!stampstr)
222 return (time_t)0;
223
224 rv = (time_t) g_ascii_strtoull (stampstr, NULL, 10);
225 g_free (stampstr);
226
227 return rv;
228 }
229
230
231
232 MuError
233 mu_store_foreach (MuStore *self,
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
234 MuStoreForeachFunc func, void *user_data, GError **err)
ce97c49 @djcb * mu-store refactoring
authored
235 {
236 g_return_val_if_fail (self, MU_ERROR);
237 g_return_val_if_fail (func, MU_ERROR);
238
239 try {
240 Xapian::Enquire enq (*self->db_read_only());
241
242 enq.set_query (Xapian::Query::MatchAll);
243 enq.set_cutoff (0,0);
244
245 Xapian::MSet matches
246 (enq.get_mset (0, self->db_read_only()->get_doccount()));
247 if (matches.empty())
248 return MU_OK; /* database is empty */
249
250 for (Xapian::MSet::iterator iter = matches.begin();
251 iter != matches.end(); ++iter) {
252 Xapian::Document doc (iter.get_document());
253 const std::string path(doc.get_value(MU_MSG_FIELD_ID_PATH));
254 MuError res = func (path.c_str(), user_data);
255 if (res != MU_OK)
256 return res;
257 }
258
bd1ae1a @djcb * mu-store*: use GError, stability fixes + cleanups
authored
259 } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(err, MU_ERROR_XAPIAN,
260 MU_ERROR_XAPIAN);
ce97c49 @djcb * mu-store refactoring
authored
261
262 return MU_OK;
263 }
6a13866 @djcb * mu-store: many cleanups, fixes
authored
264
265
1f4e558 @djcb * mu-store-read.cc: add mu_store_get_msg
authored
266
267 MuMsg*
268 mu_store_get_msg (MuStore *self, unsigned docid, GError **err)
269 {
270 g_return_val_if_fail (self, NULL);
271 g_return_val_if_fail (docid != 0, NULL);
272
273 try {
274 Xapian::Document *doc =
6e2c3bf @djcb * mu-store-read.cc: cosmetic
authored
275 new Xapian::Document
276 (self->db_read_only()->get_document (docid));
1f4e558 @djcb * mu-store-read.cc: add mu_store_get_msg
authored
277 return mu_msg_new_from_doc ((XapianDocument*)doc, err);
278
279 } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, 0);
280 }
Something went wrong with that request. Please try again.