2
** Copyright (C) 2008 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
4
** This program is free software; you can redistribute it and/or modify
5
1** it under the terms of the GNU General Public License as published by
6
** the Free Software Foundation; either version 3 of the License, or
7
** (at your option) any later version.
9
** This program is distributed in the hope that it will be useful,
10
** but WITHOUT ANY WARRANTY; without even the implied warranty of
11
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
** GNU General Public License for more details.
14
** You should have received a copy of the GNU General Public License
15
** along with this program; if not, write to the Free Software Foundation,
16
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
#endif /*HAVE_CONFIG_H*/
28
#include <glib/gstdio.h>
32
#include "path/mu-path.h"
34
#include "mu-storage-sqlite.h"
37
#include "mu-storage-xapian.h"
39
MuStorageSQLite *_sqlite;
40
MuStorageXapian *_xapian;
41
gboolean _sort_inodes;
45
MuStorageSQLite *_sqlite;
46
gboolean _sort_inodes;
49
#endif /*!MU_HAVE_XAPIAN*/
54
mu_index_new (const char* mpath, const char *cpath)
58
g_return_val_if_fail (mpath, NULL);
59
g_return_val_if_fail (cpath, NULL);
62
index = g_new0 (MuIndex, 1);
63
index->_sqlite = mu_storage_sqlite_new (mpath);
64
if (!index->_sqlite) {
65
g_warning ("%s: failed to get meta storage", __FUNCTION__);
70
index->_xapian = mu_storage_xapian_new (cpath);
71
if (!index->_xapian) {
72
g_warning ("%s: failed to get xapian storage", __FUNCTION__);
75
#endif /*MU_HAVE_XAPIAN*/
77
index->_sort_inodes = FALSE;
78
g_debug ("created index object");
84
mu_index_destroy (index);
91
mu_index_destroy (MuIndex *index)
94
mu_storage_sqlite_destroy (index->_sqlite);
96
mu_storage_xapian_destroy (index->_xapian);
97
#endif /*MU_HAVE_XAPIAN*/
100
g_debug ("destroyed index object");
105
mu_index_tune (MuIndex *index,
106
unsigned int sqlite_tx_size,
107
unsigned int synchronous,
108
unsigned int temp_store,
109
unsigned int xapian_tx_size,
110
gboolean sort_inodes)
112
g_return_if_fail (index);
114
mu_storage_sqlite_tune (index->_sqlite,
118
#ifdef MU_HAVE_XAPIAN
119
mu_storage_xapian_tune (index->_xapian,
121
#endif /*MU_HAVE_XAPIAN*/
122
index->_sort_inodes = sort_inodes;
126
struct _MuIndexCallbackData {
128
MuStorageSQLite* _sqlite;
129
#ifdef MU_HAVE_XAPIAN
130
MuStorageXapian* _xapian;
131
#endif /*MU_HAVE_XAPIAN*/
133
MuIndexStats* _stats;
136
typedef struct _MuIndexCallbackData MuIndexCallbackData;
139
insert_or_update (const char* fullpath, MuIndexCallbackData *data)
142
int64_t id; /* the id in the db */
144
if (!(msg = mu_msg_gmime_new (fullpath))) {
145
g_warning ("%s: failed to create mu_msg for %s",
146
__FUNCTION__, fullpath);
150
if ((id = mu_storage_sqlite_store (data->_sqlite, msg)) == -1) {
151
g_warning ("%s: storing %s failed", __FUNCTION__, fullpath);
152
mu_msg_gmime_destroy (msg);
156
#ifdef MU_HAVE_XAPIAN
157
/* we got a valid id; scan the message contents as well */
158
if (mu_storage_xapian_store (data->_xapian, id, msg) != MU_OK) {
159
g_warning ("%s: storing content %s failed", __FUNCTION__,
163
#endif /*MU_HAVE_XAPIAN*/
165
mu_msg_gmime_destroy (msg);
173
run_callback_maybe ( MuIndexCallbackData *data)
175
if (data && data->_cb) {
177
data->_cb (data->_stats, data->_user_data);
179
g_debug ("%s: callback said %d", __FUNCTION__, result);
186
on_run_maildir_file (const char* fullpath, time_t filestamp,
187
MuIndexCallbackData *data)
193
g_return_val_if_fail (fullpath, MU_ERROR);
195
result = run_callback_maybe (data);
199
++data->_stats->_processed;
201
/* see if we need to update/insert anything...*/
202
dbstamp = mu_storage_sqlite_message_timestamp (data->_sqlite, fullpath);
203
if (dbstamp >= filestamp && !data->_force) { /* msg is uptodate, no force */
208
result = insert_or_update(fullpath, data);
211
/* update statistics */
212
if (result == MU_OK && data && data->_stats) {
214
++data->_stats->_uptodate;
215
else if (dbstamp == 0) /* 0 means no stamp, ie. a new msg */
216
++data->_stats->_added;
218
++data->_stats->_updated;
225
check_path (const char* path)
227
g_return_val_if_fail (path, FALSE);
229
if (!g_path_is_absolute (path)) {
230
g_warning ("%s: path is not absolute '%s'",
235
if (access (path, R_OK) != 0) {
236
g_warning ("%s: cannot open '%s': %s",
237
__FUNCTION__, path, strerror (errno));
246
mu_index_run (MuIndex *index, const char* path,
247
gboolean force, MuIndexStats *stats,
248
MuIndexCallback cb, void *user_data)
250
MuIndexCallbackData cb_data;
252
g_return_val_if_fail (index && index->_sqlite,
254
#ifdef MU_HAVE_XAPIAN
255
g_return_val_if_fail (index->_xapian,
257
#endif /*MU_HAVE_XAPIAN*/
258
g_return_val_if_fail (check_path (path), MU_ERROR);
261
cb_data._user_data = user_data;
262
cb_data._sqlite = index->_sqlite;
263
#ifdef MU_HAVE_XAPIAN
264
cb_data._xapian = index->_xapian;
265
#endif /*MU_HAVE_XAPIAN*/
266
cb_data._stats = stats;
267
cb_data._force = force;
269
return mu_path_walk_maildir (path, index->_sort_inodes,
270
(MuWalkCallback)on_run_maildir_file,
275
on_stats_maildir_file (const char *fullpath, time_t timestamp,
276
MuIndexCallbackData *cb_data)
281
if (cb_data && cb_data->_cb)
282
result = cb_data->_cb (cb_data->_stats, cb_data->_user_data);
286
if (result == MU_OK) {
288
++cb_data->_stats->_processed;
291
return result; /* MU_STOP or MU_OK */
296
mu_index_stats (MuIndex *index, const char* path,
297
MuIndexStats *stats, MuIndexCallback cb,
300
MuIndexCallbackData cb_data;
302
g_return_val_if_fail (index, MU_ERROR);
303
g_return_val_if_fail (check_path (path), MU_ERROR);
306
cb_data._stats = stats;
307
cb_data._user_data = user_data;
309
return mu_path_walk_maildir (path, index->_sort_inodes,
310
(MuWalkCallback)on_stats_maildir_file,
317
sqlite_remove_callback (MuMsgStatus status, const char* path,
318
MuIndexCallbackData *cb_data)
322
if (cb_data && cb_data->_cb)
323
result = cb_data->_cb (cb_data->_stats, cb_data->_user_data);
329
/* callback is just a fyi; file still exists and will not be deleted */
330
case MU_MSG_STATUS_EXISTS:
333
case MU_MSG_STATUS_CLEANUP:
334
#ifdef MU_HAVE_XAPIAN
335
return mu_storage_xapian_cleanup (cb_data->_xapian, path);
336
#endif /*MU_HAVE_XAPIAN*/
337
return MU_OK; /* message will be removed */
339
case MU_MSG_STATUS_CLEANED_UP:
340
/* message was succesfully cleaned up from db; update stats */
341
if (cb_data && cb_data->_stats)
342
++cb_data->_stats->_cleaned_up;
346
g_warning ("%s: unexpected status %d",
347
__FUNCTION__, status);
355
mu_index_cleanup (MuIndex *index, MuIndexStats *stats, MuIndexCallback cb,
358
MuIndexCallbackData cb_data;
359
MuResult result = MU_OK;
361
g_return_val_if_fail (index, MU_ERROR);
362
memset (&cb_data, 0, sizeof(MuIndexCallbackData));
365
cb_data._user_data = user_data;
366
#ifdef MU_HAVE_XAPIAN
367
cb_data._xapian = index->_xapian;
368
#endif /*MU_HAVE_XAPIAN*/
370
cb_data._stats = stats;
371
result = mu_storage_sqlite_cleanup
373
(MuStorageSQLiteCleanupCallback)sqlite_remove_callback,