~ubuntu-branches/ubuntu/quantal/maildir-utils/quantal

« back to all changes in this revision

Viewing changes to index/mu-index.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2010-01-19 20:12:43 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100119201243-d8qmzgxgexhy1bs0
Tags: 0.6~beta1-1
* new upstream release 0.6-beta
  - that merges the several different programs under one binary mu
  - no sqlite storage is used anymore
* debian packaging changes:
  - debian/patches
    . remove all patches
  - remove debian/HOWTO (upstream document) it is completely outdated
  - debian/control:
    . adjust build-dep for gmime-2.4
    . remove build-dep on quilt and sqlite
    . adjust the description to new reality
  - debian/rules:
    . do not try to install doc files that are not present anymore
    . disable quilt adaptions
  - add debian/NEWS that explains that the separate programs are gone

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
** Copyright (C) 2008 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
3
 
**
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.
8
 
**  
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.
13
 
**  
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.  
17
 
**  
18
 
*/
19
 
 
20
 
#ifdef HAVE_CONFIG_H
21
 
#include "config.h"
22
 
#endif /*HAVE_CONFIG_H*/
23
 
 
24
 
#include <stdlib.h>
25
 
#include <string.h>
26
 
#include <unistd.h>
27
 
#include <glib.h>
28
 
#include <glib/gstdio.h>
29
 
#include <errno.h>
30
 
 
31
 
#include "mu/mu.h"
32
 
#include "path/mu-path.h"
33
 
 
34
 
#include "mu-storage-sqlite.h"
35
 
 
36
 
#ifdef MU_HAVE_XAPIAN
37
 
#include "mu-storage-xapian.h"
38
 
struct _MuIndex {
39
 
        MuStorageSQLite  *_sqlite;
40
 
        MuStorageXapian  *_xapian;
41
 
        gboolean _sort_inodes;
42
 
};
43
 
# else
44
 
struct _MuIndex {
45
 
        MuStorageSQLite  *_sqlite;
46
 
        gboolean _sort_inodes;
47
 
 
48
 
};
49
 
#endif /*!MU_HAVE_XAPIAN*/
50
 
 
51
 
#include "mu-index.h"
52
 
 
53
 
MuIndex* 
54
 
mu_index_new (const char* mpath, const char *cpath)
55
 
{
56
 
        MuIndex *index;
57
 
        
58
 
        g_return_val_if_fail (mpath, NULL);
59
 
        g_return_val_if_fail (cpath, NULL);
60
 
 
61
 
        do {
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__); 
66
 
                        break;
67
 
                }
68
 
                
69
 
#ifdef MU_HAVE_XAPIAN
70
 
                index->_xapian = mu_storage_xapian_new (cpath);
71
 
                if (!index->_xapian) {
72
 
                        g_warning ("%s: failed to get xapian storage", __FUNCTION__); 
73
 
                        break;
74
 
                }
75
 
#endif /*MU_HAVE_XAPIAN*/
76
 
 
77
 
                index->_sort_inodes = FALSE;
78
 
                g_debug ("created index object");
79
 
 
80
 
                return index;
81
 
        
82
 
        } while (0);
83
 
        
84
 
        mu_index_destroy (index);
85
 
 
86
 
        return NULL;
87
 
}
88
 
 
89
 
 
90
 
void 
91
 
mu_index_destroy (MuIndex *index)
92
 
{
93
 
        if (index) {
94
 
                mu_storage_sqlite_destroy (index->_sqlite);
95
 
#ifdef MU_HAVE_XAPIAN
96
 
                mu_storage_xapian_destroy (index->_xapian);
97
 
#endif /*MU_HAVE_XAPIAN*/
98
 
 
99
 
                g_free (index);
100
 
                g_debug ("destroyed index object");
101
 
        }
102
 
}
103
 
 
104
 
void
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)
111
 
{
112
 
        g_return_if_fail (index);
113
 
        
114
 
        mu_storage_sqlite_tune (index->_sqlite, 
115
 
                                sqlite_tx_size,
116
 
                                synchronous,
117
 
                                temp_store);
118
 
#ifdef MU_HAVE_XAPIAN
119
 
        mu_storage_xapian_tune (index->_xapian,
120
 
                                xapian_tx_size);
121
 
#endif /*MU_HAVE_XAPIAN*/
122
 
        index->_sort_inodes = sort_inodes;
123
 
}
124
 
 
125
 
 
126
 
struct _MuIndexCallbackData {
127
 
        MuIndexCallback       _cb;
128
 
        MuStorageSQLite*      _sqlite;
129
 
#ifdef MU_HAVE_XAPIAN
130
 
        MuStorageXapian*      _xapian;
131
 
#endif /*MU_HAVE_XAPIAN*/
132
 
        void*                 _user_data;
133
 
        MuIndexStats*         _stats;
134
 
        gboolean              _force;
135
 
};
136
 
typedef struct _MuIndexCallbackData MuIndexCallbackData;
137
 
 
138
 
static MuResult
139
 
insert_or_update (const char* fullpath, MuIndexCallbackData *data)
140
 
141
 
        MuMsgGMime *msg;
142
 
        int64_t id; /* the id in the db */
143
 
 
144
 
        if (!(msg = mu_msg_gmime_new (fullpath))) {
145
 
                g_warning ("%s: failed to create mu_msg for %s",
146
 
                           __FUNCTION__, fullpath);
147
 
                return MU_ERROR;
148
 
        }
149
 
        
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);
153
 
                return MU_ERROR;
154
 
        } 
155
 
        
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__, 
160
 
                           fullpath);
161
 
                /* ignore...*/
162
 
        } 
163
 
#endif /*MU_HAVE_XAPIAN*/
164
 
 
165
 
        mu_msg_gmime_destroy (msg);
166
 
        return MU_OK;   
167
 
}
168
 
 
169
 
 
170
 
 
171
 
 
172
 
static MuResult
173
 
run_callback_maybe ( MuIndexCallbackData *data)
174
 
{
175
 
        if (data && data->_cb) {
176
 
                MuResult result = 
177
 
                        data->_cb (data->_stats, data->_user_data);
178
 
                if (result != MU_OK)
179
 
                        g_debug ("%s: callback said %d", __FUNCTION__, result);
180
 
        }
181
 
        return MU_OK;
182
 
}
183
 
 
184
 
 
185
 
static MuResult
186
 
on_run_maildir_file (const char* fullpath, time_t filestamp, 
187
 
                     MuIndexCallbackData *data)
188
 
{
189
 
        MuResult result;
190
 
        time_t dbstamp;
191
 
        gboolean uptodate;
192
 
        
193
 
        g_return_val_if_fail (fullpath, MU_ERROR);
194
 
 
195
 
        result = run_callback_maybe (data);
196
 
        if (result != MU_OK)
197
 
                return result;
198
 
        
199
 
        ++data->_stats->_processed;
200
 
                
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 */
204
 
                uptodate = TRUE;
205
 
                result = MU_OK;
206
 
        } else {
207
 
                uptodate = FALSE;
208
 
                result = insert_or_update(fullpath, data);
209
 
        }
210
 
        
211
 
        /* update statistics */
212
 
        if (result == MU_OK && data && data->_stats) {
213
 
                if (uptodate)
214
 
                        ++data->_stats->_uptodate;
215
 
                else if (dbstamp == 0)  /* 0 means no stamp, ie. a new msg */
216
 
                        ++data->_stats->_added;
217
 
                else
218
 
                        ++data->_stats->_updated;
219
 
        }       
220
 
        return result;
221
 
}
222
 
 
223
 
 
224
 
static gboolean
225
 
check_path (const char* path)
226
 
{
227
 
        g_return_val_if_fail (path, FALSE);
228
 
 
229
 
        if (!g_path_is_absolute (path)) {
230
 
                g_warning ("%s: path is not absolute '%s'", 
231
 
                           __FUNCTION__, path);
232
 
                return FALSE;
233
 
        }
234
 
        
235
 
        if (access (path, R_OK) != 0) {
236
 
                g_warning ("%s: cannot open '%s': %s", 
237
 
                           __FUNCTION__, path, strerror (errno));
238
 
                return FALSE;
239
 
        }
240
 
        
241
 
        return TRUE;
242
 
}
243
 
 
244
 
 
245
 
MuResult
246
 
mu_index_run (MuIndex *index, const char* path,
247
 
              gboolean force, MuIndexStats *stats,
248
 
              MuIndexCallback cb, void *user_data)
249
 
{
250
 
        MuIndexCallbackData cb_data;
251
 
        
252
 
        g_return_val_if_fail (index && index->_sqlite,
253
 
                              MU_ERROR);
254
 
#ifdef MU_HAVE_XAPIAN
255
 
        g_return_val_if_fail (index->_xapian,
256
 
                              MU_ERROR);
257
 
#endif /*MU_HAVE_XAPIAN*/
258
 
        g_return_val_if_fail (check_path (path), MU_ERROR);
259
 
 
260
 
        cb_data._cb        = cb;
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;
268
 
 
269
 
        return mu_path_walk_maildir (path, index->_sort_inodes,
270
 
                                     (MuWalkCallback)on_run_maildir_file,
271
 
                                     &cb_data);
272
 
}
273
 
 
274
 
static MuResult
275
 
on_stats_maildir_file (const char *fullpath, time_t timestamp, 
276
 
                       MuIndexCallbackData *cb_data)
277
 
{
278
 
        
279
 
        MuResult result;
280
 
        
281
 
        if (cb_data && cb_data->_cb)
282
 
                result = cb_data->_cb (cb_data->_stats, cb_data->_user_data);
283
 
        else
284
 
                result = MU_OK;
285
 
 
286
 
        if (result == MU_OK) { 
287
 
                if (cb_data->_stats)
288
 
                        ++cb_data->_stats->_processed;
289
 
                return MU_OK;
290
 
        } else 
291
 
                return result; /* MU_STOP or MU_OK */
292
 
}
293
 
 
294
 
 
295
 
MuResult
296
 
mu_index_stats (MuIndex *index, const char* path,
297
 
                MuIndexStats *stats, MuIndexCallback cb, 
298
 
                void *user_data)
299
 
{
300
 
        MuIndexCallbackData cb_data;
301
 
        
302
 
        g_return_val_if_fail (index, MU_ERROR);
303
 
        g_return_val_if_fail (check_path (path), MU_ERROR);
304
 
 
305
 
        cb_data._cb        = cb;
306
 
        cb_data._stats     = stats;
307
 
        cb_data._user_data = user_data;
308
 
 
309
 
        return mu_path_walk_maildir (path, index->_sort_inodes,
310
 
                                     (MuWalkCallback)on_stats_maildir_file,
311
 
                                     &cb_data);
312
 
}
313
 
 
314
 
 
315
 
 
316
 
static MuResult
317
 
sqlite_remove_callback (MuMsgStatus status, const char* path, 
318
 
                        MuIndexCallbackData *cb_data)
319
 
{
320
 
        MuResult result;
321
 
        
322
 
        if (cb_data && cb_data->_cb)
323
 
                result = cb_data->_cb (cb_data->_stats, cb_data->_user_data);
324
 
        else
325
 
                result = MU_OK;
326
 
 
327
 
        switch (status) {
328
 
                
329
 
        /* callback is just a fyi; file still exists and will not be deleted */
330
 
        case MU_MSG_STATUS_EXISTS: 
331
 
                return MU_OK;
332
 
                
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 */
338
 
 
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; 
343
 
                break;
344
 
                
345
 
        default:
346
 
                g_warning ("%s: unexpected status %d", 
347
 
                           __FUNCTION__, status);
348
 
                return MU_ERROR;
349
 
        }
350
 
 
351
 
        return result;
352
 
}
353
 
 
354
 
MuResult
355
 
mu_index_cleanup (MuIndex *index, MuIndexStats *stats, MuIndexCallback cb, 
356
 
                  void *user_data)
357
 
{
358
 
        MuIndexCallbackData cb_data;
359
 
        MuResult result = MU_OK;
360
 
        
361
 
        g_return_val_if_fail (index, MU_ERROR);
362
 
        memset (&cb_data, 0, sizeof(MuIndexCallbackData));
363
 
        
364
 
        cb_data._cb        = cb;
365
 
        cb_data._user_data = user_data;
366
 
#ifdef MU_HAVE_XAPIAN
367
 
        cb_data._xapian    = index->_xapian;
368
 
#endif /*MU_HAVE_XAPIAN*/
369
 
                
370
 
        cb_data._stats     = stats;
371
 
        result = mu_storage_sqlite_cleanup 
372
 
                (index->_sqlite,
373
 
                 (MuStorageSQLiteCleanupCallback)sqlite_remove_callback,
374
 
                 &cb_data);
375
 
        
376
 
        return result;
377
 
}