~ubuntu-branches/debian/sid/openchange/sid

« back to all changes in this revision

Viewing changes to mapiproxy/libmapistore/indexing/mapistore_indexing.c

  • Committer: Package Import Robot
  • Author(s): Jelmer Vernooij
  • Date: 2012-04-12 20:07:57 UTC
  • mfrom: (11 sid)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20120412200757-k933d9trljmxj1l4
Tags: 1:1.0-4
* openchangeserver: Add dependency on openchangeproxy.
* Rebuild against newer version of Samba 4.
* Use dpkg-buildflags.
* Migrate to Git, update Vcs-Git header.
* Switch to debhelper 9.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
   OpenChange Storage Abstraction Layer library
3
 
 
4
 
   OpenChange Project
5
 
 
6
 
   Copyright (C) Julien Kerihuel 2010-2011
7
 
 
8
 
   This program is free software; you can redistribute it and/or modify
9
 
   it under the terms of the GNU General Public License as published by
10
 
   the Free Software Foundation; either version 3 of the License, or
11
 
   (at your option) any later version.
12
 
   
13
 
   This program is distributed in the hope that it will be useful,
14
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
   GNU General Public License for more details.
17
 
   
18
 
   You should have received a copy of the GNU General Public License
19
 
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 
 */
21
 
 
22
 
#include <errno.h>
23
 
#include <fcntl.h>
24
 
#include <string.h>
25
 
 
26
 
#include "mapistore_errors.h"
27
 
#include "mapistore.h"
28
 
#include "mapistore_common.h"
29
 
#include "mapistore_private.h"
30
 
#include "ndr_mapistore_indexing_db.h"
31
 
 
32
 
#include <dlinklist.h>
33
 
#include <tdb.h>
34
 
 
35
 
/**
36
 
   \file indexing/mapistore_indexing.c
37
 
 
38
 
   \brief Interface API to the mapistore indexing database
39
 
   
40
 
   This database is used to map FID/MID to mapistore URI, plus additional parameters
41
 
 */
42
 
 
43
 
static enum MAPISTORE_ERROR mapistore_indexing_dump_folder_v1(struct mapistore_indexing_entry *entry)
44
 
{
45
 
        /* Sanity checks */
46
 
        MAPISTORE_RETVAL_IF(!entry, MAPISTORE_ERR_INVALID_OBJECT, NULL);
47
 
 
48
 
        DEBUG(0, ("Folder:\n"));
49
 
        DEBUG(0, ("=======\n"));
50
 
        DEBUG(0, ("\t* mapistore_URI:\t%s\n", entry->info.mapistore_indexing_v1.mapistoreURI));
51
 
        DEBUG(0, ("\t* FolderID:\t\t0x%.16"PRIx64"\n", entry->info.mapistore_indexing_v1.FMID));
52
 
        DEBUG(0, ("\t* ParentFolderID:\t0x%.16"PRIx64"\n", entry->info.mapistore_indexing_v1.ParentFolderID));
53
 
        DEBUG(0, ("\t* Allocation ID:\t0x%.16"PRIx64" - 0x%.16"PRIx64"\n", 
54
 
                  entry->info.mapistore_indexing_v1.MessageRangeIDs.range.next_allocation_id,
55
 
                  entry->info.mapistore_indexing_v1.MessageRangeIDs.range.last_allocation_id));
56
 
        DEBUG(0, ("\t* ACLS: (%d)\n", entry->info.mapistore_indexing_v1.Acls.acls_folder.acl_number));
57
 
 
58
 
        return MAPISTORE_SUCCESS;
59
 
}
60
 
 
61
 
enum MAPISTORE_ERROR mapistore_indexing_dump_object(struct mapistore_indexing_entry *entry)
62
 
{
63
 
        /* Sanity checks */
64
 
        MAPISTORE_RETVAL_IF(!entry, MAPISTORE_ERR_INVALID_OBJECT, NULL);
65
 
 
66
 
        switch (entry->info.mapistore_indexing_v1.Type) {
67
 
        case MAPISTORE_INDEXING_FOLDER:
68
 
                return mapistore_indexing_dump_folder_v1(entry);
69
 
                break;
70
 
        default:
71
 
                DEBUG(0, ("Not implemented yet\n"));
72
 
                return MAPISTORE_ERR_NOT_FOUND;
73
 
                break;
74
 
        }
75
 
 
76
 
        return MAPISTORE_ERR_NOT_FOUND;
77
 
}
78
 
 
79
 
 
80
 
enum MAPISTORE_ERROR mapistore_indexing_dump_reverse_entry(struct mapistore_indexing_entry_r *entry)
81
 
{
82
 
        /* Sanity checks */
83
 
        MAPISTORE_RETVAL_IF(!entry, MAPISTORE_ERR_INVALID_OBJECT, NULL);
84
 
 
85
 
        DEBUG(0, ("Indexing Reverse TDB entry:\n"));
86
 
        DEBUG(0, ("===========================\n"));
87
 
        DEBUG(0, ("\t* indexing key = %s\n", entry->indexing_key));
88
 
        DEBUG(0, ("\t* fmid         = 0x%.16"PRIx64"\n", entry->FMID));
89
 
 
90
 
        return MAPISTORE_SUCCESS;
91
 
}
92
 
 
93
 
 
94
 
/**
95
 
   \details Increase the reference counter associated to a given
96
 
   mapistore indexing context
97
 
 
98
 
   \param mictx pointer to the mapistore indexing context
99
 
 
100
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
101
 
 */
102
 
static enum MAPISTORE_ERROR mapistore_indexing_context_add_ref_count(struct mapistore_indexing_context_list *mictx)
103
 
{
104
 
        /* Sanity checks */
105
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERROR, NULL);
106
 
 
107
 
        DEBUG(2, ("* [%s:%d][%s]: ref count was %i, about to increment\n", __FILE__, __LINE__, __FUNCTION__, mictx->ref_count));
108
 
 
109
 
        return MAPISTORE_SUCCESS;
110
 
}
111
 
 
112
 
/**
113
 
   \details Decrease the reference counter associated to a given
114
 
   mapistore indexing context
115
 
 
116
 
   \param mictx pointer to the mapistore indexing context
117
 
 
118
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
119
 
 */
120
 
static enum MAPISTORE_ERROR mapistore_indexing_context_del_ref_count(struct mapistore_indexing_context_list *mictx)
121
 
{
122
 
        /* Sanity checks */
123
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERROR, NULL);
124
 
        MAPISTORE_RETVAL_IF(!mictx->ref_count, MAPISTORE_SUCCESS, NULL);
125
 
        
126
 
        DEBUG(2, ("* [%s:%d][%s]: ref count was %i, about to decrement\n", __FILE__, __LINE__, __FUNCTION__, mictx->ref_count));
127
 
        mictx->ref_count -= 1;
128
 
 
129
 
        return MAPISTORE_SUCCESS;
130
 
}
131
 
 
132
 
/**
133
 
   \details (Accessor) Retrieve the reference counter associated to a
134
 
   given mapistore indexing context
135
 
 
136
 
   \param mictx pointer to the mapistore indexing context
137
 
 
138
 
   \return the reference counter value associated to the mapistore
139
 
   indexing context
140
 
 */
141
 
static uint32_t mapistore_indexing_context_get_ref_count(struct mapistore_indexing_context_list *mictx)
142
 
{
143
 
        return mictx->ref_count;
144
 
}
145
 
 
146
 
/**
147
 
   \details Search the mapistore indexing context list for an existing
148
 
   record matching the specified username
149
 
 
150
 
   \param mstore_ctx pointer to the mapistore context
151
 
   \param username the username to lookup
152
 
 
153
 
   \return pointer to the existing mapistore indexing context list on success, otherwise NULL
154
 
 */
155
 
static struct mapistore_indexing_context_list *mapistore_indexing_context_search(struct mapistore_context *mstore_ctx,
156
 
                                                                                 const char *username)
157
 
{
158
 
        struct mapistore_indexing_context_list  *el;
159
 
 
160
 
        /* Sanity checks */
161
 
        if (!mstore_ctx || !username) return NULL;
162
 
 
163
 
        for (el = mstore_ctx->mapistore_indexing_list; el; el = el->next) {
164
 
                if (el && el->username && !strcmp(el->username, username)) {
165
 
                        return el;
166
 
                }
167
 
        }
168
 
 
169
 
        return NULL;
170
 
}
171
 
 
172
 
/**
173
 
   \details Open a connection context to the indexing database for
174
 
   given user
175
 
 
176
 
   \param mstore_ctx pointer to the mapistore context
177
 
   \param username username of the indexing database owner
178
 
   \param indexing_ctx pointer on pointer to the indexing context to return
179
 
 
180
 
   \return MAPISTORE_SUCCESS on success, otherwise a non-zero MAPISTORE_ERROR value
181
 
 */
182
 
enum MAPISTORE_ERROR mapistore_indexing_context_add(struct mapistore_context *mstore_ctx,
183
 
                                                    const char *username,
184
 
                                                    struct mapistore_indexing_context_list **indexing_ctx)
185
 
{
186
 
        TALLOC_CTX                              *mem_ctx;
187
 
        struct mapistore_indexing_context_list  *mictx;
188
 
        char                                    *dbpath;
189
 
 
190
 
        /* Sanity checks */
191
 
        MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
192
 
        MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
193
 
        MAPISTORE_RETVAL_IF(!indexing_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
194
 
 
195
 
        /* Step 1. Return existing context if available */
196
 
        mictx = mapistore_indexing_context_search(mstore_ctx, username);
197
 
        if (mictx) {
198
 
                DEBUG(2, ("* [%s:%d][%s]: Reusing existing context\n", __FILE__, __LINE__, __FUNCTION__));
199
 
                mapistore_indexing_context_add_ref_count(mictx);
200
 
                *indexing_ctx = mictx;
201
 
                return MAPISTORE_SUCCESS;
202
 
        }
203
 
        
204
 
        /* Step 2. Otherwise create a new context */
205
 
        mem_ctx = talloc_named(NULL, 0, __FUNCTION__);
206
 
        mictx = talloc_zero(mstore_ctx->mapistore_indexing_list, struct mapistore_indexing_context_list);
207
 
 
208
 
        dbpath = talloc_asprintf(mem_ctx, MAPISTORE_INDEXING_DBPATH_TMPL,
209
 
                                 mapistore_get_mapping_path(), username);
210
 
        mictx->tdb_ctx = tdb_wrap_open(mictx, dbpath, 0, 0, O_RDWR|O_CREAT, 0600);
211
 
        talloc_free(dbpath);
212
 
 
213
 
        if (!mictx->tdb_ctx) {
214
 
                DEBUG(3, ("! [%s:%d][%s]: %s\n", __FILE__, __LINE__, __FUNCTION__, strerror(errno)));
215
 
                talloc_free(mictx);
216
 
                talloc_free(mem_ctx);
217
 
 
218
 
                return MAPISTORE_ERR_DATABASE_INIT;
219
 
        }
220
 
 
221
 
        mictx->username = (const char *) talloc_strdup(mictx, username);
222
 
        mictx->ref_count = 1;
223
 
        DEBUG(2, ("* [%s:%d][%s] indexing context value is now %i\n", __FILE__, __LINE__, __FUNCTION__, mictx->ref_count));
224
 
        DLIST_ADD_END(mstore_ctx->mapistore_indexing_list, mictx, struct mapistore_indexing_context_list *);
225
 
 
226
 
        *indexing_ctx = mictx;
227
 
 
228
 
        talloc_free(mem_ctx);
229
 
 
230
 
        return MAPISTORE_SUCCESS;
231
 
}
232
 
 
233
 
 
234
 
/**
235
 
   \details Delete indexing database context for given user
236
 
 
237
 
   \param mstore_ctx pointer to the mapistore context
238
 
   \param username username of the indexing database owner
239
 
 
240
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
241
 
 
242
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
243
 
 */
244
 
enum MAPISTORE_ERROR mapistore_indexing_context_del(struct mapistore_context *mstore_ctx,
245
 
                                                    const char *username)
246
 
{
247
 
        struct mapistore_indexing_context_list  *mictx;
248
 
        enum MAPISTORE_ERROR                    retval;
249
 
 
250
 
        /* Sanity checks */
251
 
        MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
252
 
        MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERROR, NULL);
253
 
 
254
 
        /* Step 1. Search for the context */
255
 
        mictx = mapistore_indexing_context_search(mstore_ctx, username);
256
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERROR, NULL);
257
 
 
258
 
        /* Step 2. Decrement the reference count */
259
 
        retval = mapistore_indexing_context_del_ref_count(mictx);
260
 
 
261
 
        if (mapistore_indexing_context_get_ref_count(mictx)) {
262
 
                /* Step 3. If we still have ref counts, just return */
263
 
                return MAPISTORE_SUCCESS;
264
 
        } else {
265
 
                /* Step 4. If no more associated references, remove and release memory */
266
 
                DLIST_REMOVE(mstore_ctx->mapistore_indexing_list, mictx);
267
 
                talloc_free(mictx);
268
 
        }
269
 
 
270
 
        return MAPISTORE_SUCCESS;
271
 
}
272
 
 
273
 
 
274
 
/**
275
 
   \details Increment the reference counter of the existing context
276
 
   for given user
277
 
 
278
 
   \param mstore_ctx pointer to the mapistore context
279
 
   \param username the user string to lookup
280
 
 
281
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
282
 
 */
283
 
enum MAPISTORE_ERROR mapistore_indexing_context_add_ref(struct mapistore_context *mstore_ctx,
284
 
                                                        const char *username)
285
 
{
286
 
        struct mapistore_indexing_context_list  *mictx;
287
 
        enum MAPISTATUS                         retval;
288
 
 
289
 
        /* Sanity checks */
290
 
        MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
291
 
        MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERROR, NULL);
292
 
 
293
 
        /* Step 1. Search for the context */
294
 
        mictx = mapistore_indexing_context_search(mstore_ctx, username);
295
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERROR, NULL);
296
 
 
297
 
        /* Step 2. Increment the reference counter */
298
 
        retval = mapistore_indexing_context_add_ref_count(mictx);
299
 
 
300
 
        return retval;
301
 
}
302
 
 
303
 
 
304
 
/**
305
 
   \details Retrieve the mapistore indexing entry associated to a
306
 
   folder or message identifier
307
 
 
308
 
   \param mictx pointer to the mapistore indexing context list
309
 
   \param fmid the fmid to lookup
310
 
   \param entry pointer to the mapistore indexing entry to return
311
 
 
312
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
313
 
 */
314
 
static enum MAPISTORE_ERROR mapistore_indexing_get_entry(struct mapistore_indexing_context_list *mictx,
315
 
                                                         uint64_t fmid,
316
 
                                                         struct mapistore_indexing_entry *entry)
317
 
{
318
 
        TDB_DATA                key;
319
 
        TDB_DATA                value;
320
 
        DATA_BLOB               data;
321
 
        enum ndr_err_code       ndr_err;
322
 
 
323
 
        /* Sanity checks */
324
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
325
 
        MAPISTORE_RETVAL_IF(!mictx->tdb_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
326
 
        MAPISTORE_RETVAL_IF(!mictx->tdb_ctx->tdb, MAPISTORE_ERR_DATABASE_INIT, NULL);
327
 
        MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
328
 
        MAPISTORE_RETVAL_IF(!entry, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
329
 
 
330
 
        /* Step 1. Lookup the FID in mapistore indexing database */
331
 
        key.dptr = (unsigned char *)talloc_asprintf(mictx, MAPISTORE_INDEXING_FMID, fmid);
332
 
        key.dsize = strlen((const char *)key.dptr);
333
 
 
334
 
        value = tdb_fetch(mictx->tdb_ctx->tdb, key);
335
 
        talloc_free(key.dptr);
336
 
        MAPISTORE_RETVAL_IF(!value.dptr, MAPISTORE_ERR_NOT_FOUND, NULL);
337
 
 
338
 
        data.data = value.dptr;
339
 
        data.length = value.dsize;
340
 
 
341
 
        /* Step 2. Convert DATA_BLOB to mapistore_indexing entry */
342
 
        ndr_err = ndr_pull_struct_blob(&data, mictx, entry, 
343
 
                                       (ndr_pull_flags_fn_t)ndr_pull_mapistore_indexing_entry);
344
 
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
345
 
                DEBUG(5, ("! [%s:%d][%s]: DATA_BLOB to mapistore indexing entry conversion failed!\n",
346
 
                          __FILE__, __LINE__, __FUNCTION__));
347
 
                talloc_free(value.dptr);
348
 
                return MAPISTORE_ERROR;
349
 
        }
350
 
 
351
 
        DEBUG(5, ("* [%s:%d][%s]: %s loaded correctly!\n", __FILE__, __LINE__, __FUNCTION__,
352
 
                  entry->info.mapistore_indexing_v1.mapistoreURI));
353
 
 
354
 
        return MAPISTORE_SUCCESS;
355
 
}
356
 
 
357
 
 
358
 
/**
359
 
   \details Retrieve the reversed mapistore indexing entry associated to a
360
 
   URI
361
 
 
362
 
   \param mictx pointer to the mapistore indexing context list
363
 
   \param mapistore_uri pointer to the mapistore URI
364
 
   \param entry pointer to the mapistore_indexing_entry_r to return
365
 
 
366
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
367
 
 */
368
 
static enum MAPISTORE_ERROR mapistore_indexing_get_entry_r(struct mapistore_indexing_context_list *mictx,
369
 
                                                           const char *mapistore_uri,
370
 
                                                           struct mapistore_indexing_entry_r *entry)
371
 
{
372
 
        TDB_DATA                key;
373
 
        TDB_DATA                value;
374
 
        DATA_BLOB               data;
375
 
        enum ndr_err_code       ndr_err;
376
 
 
377
 
        /* Sanity checks */
378
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
379
 
        MAPISTORE_RETVAL_IF(!mictx->tdb_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
380
 
        MAPISTORE_RETVAL_IF(!mictx->tdb_ctx->tdb, MAPISTORE_ERR_DATABASE_INIT, NULL);
381
 
        MAPISTORE_RETVAL_IF(!mapistore_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
382
 
        MAPISTORE_RETVAL_IF(!entry, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
383
 
 
384
 
        /* Step 1. Lookup the URI in mapistore indexing database */
385
 
        key.dptr = (unsigned char *)talloc_asprintf(mictx, MAPISTORE_INDEXING_URI, mapistore_uri);
386
 
        key.dsize = strlen((const char *)key.dptr);
387
 
 
388
 
        value = tdb_fetch(mictx->tdb_ctx->tdb, key);
389
 
        talloc_free(key.dptr);
390
 
        MAPISTORE_RETVAL_IF(!value.dptr, MAPISTORE_ERR_NOT_FOUND, NULL);
391
 
 
392
 
        data.data = value.dptr;
393
 
        data.length = value.dsize;
394
 
 
395
 
        /* Step 2. Convert DATA_BLOB to mapistore_indexing entry */
396
 
        ndr_err = ndr_pull_struct_blob(&data, mictx, entry, 
397
 
                                       (ndr_pull_flags_fn_t)ndr_pull_mapistore_indexing_entry_r);
398
 
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
399
 
                DEBUG(5, ("! [%s:%d][%s]: DATA_BLOB to reverse mapistore indexing entry conversion failed!\n",
400
 
                          __FILE__, __LINE__, __FUNCTION__));
401
 
                talloc_free(value.dptr);
402
 
                return MAPISTORE_ERROR;
403
 
        }
404
 
 
405
 
        DEBUG(5, ("* [%s:%d][%s]: %s loaded correctly!\n", __FILE__, __LINE__, __FUNCTION__,
406
 
                  entry->indexing_key));
407
 
 
408
 
        return MAPISTORE_SUCCESS;
409
 
}
410
 
 
411
 
 
412
 
/**
413
 
   \details Search the TDB database and check if the fmid already exists
414
 
 
415
 
   \param mictx pointer to the mapistore indexing context list
416
 
   \param fmid the folder or message identifier to lookup
417
 
 
418
 
   \return MAPISTORE_ERR_NOT_FOUND if the fmid was not found,
419
 
   MAPISTORE_ERR_EXIST if it was found, otherwise different MAPISTORE error
420
 
 */
421
 
static enum MAPISTORE_ERROR mapistore_indexing_record_search_fmid(struct mapistore_indexing_context_list *mictx,
422
 
                                                                  uint64_t fmid)
423
 
{
424
 
        int             ret;
425
 
        TDB_DATA        key;
426
 
 
427
 
        /* Sanity checks */
428
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
429
 
        MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
430
 
 
431
 
        /* Step 1. Set the TDB key for searching */
432
 
        key.dptr = (unsigned char *) talloc_asprintf(mictx, MAPISTORE_INDEXING_FMID, fmid);
433
 
        key.dsize = strlen((const char *)key.dptr);
434
 
 
435
 
        ret = tdb_exists(mictx->tdb_ctx->tdb, key);
436
 
        talloc_free(key.dptr);
437
 
 
438
 
        MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_EXIST, NULL);
439
 
 
440
 
        return MAPISTORE_ERR_NOT_FOUND;
441
 
}
442
 
 
443
 
 
444
 
/**
445
 
   \details Search the TDB database and check if the URI already exists
446
 
 
447
 
   \param mictx pointer to the mapistore indexing context list
448
 
   \param uri the uri to lookup
449
 
 
450
 
   \return MAPISTORE_ERR_NOT_FOUND if the fmid was not found,
451
 
   MAPISTORE_ERR_EXIST if it was found, otherwise different MAPISTORE error
452
 
*/
453
 
enum MAPISTORE_ERROR mapistore_indexing_record_search_uri(struct mapistore_indexing_context_list *mictx,
454
 
                                                          const char *uri)
455
 
{
456
 
        int             ret;
457
 
        TDB_DATA        key;
458
 
 
459
 
        /* Sanity checks */
460
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
461
 
        MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
462
 
 
463
 
        /* Step 1. Set the TDB key for searching */
464
 
        key.dptr = (unsigned char *) talloc_asprintf(mictx, MAPISTORE_INDEXING_URI, uri);
465
 
        key.dsize = strlen((const char *)key.dptr);
466
 
 
467
 
        ret = tdb_exists(mictx->tdb_ctx->tdb, key);
468
 
        talloc_free(key.dptr);
469
 
 
470
 
        MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_EXIST, NULL);
471
 
        
472
 
        return MAPISTORE_ERR_NOT_FOUND;
473
 
}
474
 
 
475
 
 
476
 
/**
477
 
   \details Return FMID associated to a mapistore URI for a given
478
 
   folder or message
479
 
 
480
 
   \param mictx pointer to the mapistore indexing context list
481
 
   \param uri the mapistore URI to lookup
482
 
   \param fmid the folder or message identifier to return
483
 
 
484
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
485
 
 */
486
 
enum MAPISTORE_ERROR mapistore_indexing_get_record_fmid_by_uri(struct mapistore_indexing_context_list *mictx,
487
 
                                                               const char *uri,
488
 
                                                               uint64_t *fmid)
489
 
{
490
 
        enum MAPISTORE_ERROR                    retval;
491
 
        struct mapistore_indexing_entry_r       entry;
492
 
 
493
 
        /* Sanity checks */
494
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
495
 
        MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
496
 
        MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
497
 
 
498
 
        retval = mapistore_indexing_get_entry_r(mictx, uri, &entry);
499
 
        MAPISTORE_RETVAL_IF(retval, retval, NULL);
500
 
 
501
 
        *fmid = entry.FMID;
502
 
 
503
 
        return MAPISTORE_SUCCESS;
504
 
}
505
 
 
506
 
 
507
 
/**
508
 
   \details Return the URI associated to a mapistore FMID for a given
509
 
   folder or message
510
 
 
511
 
   \param mictx pointer to the mapistore indexing context list
512
 
   \param fmid the folder or message identifier to lookup
513
 
   \param uri pointer on pointer to the mapistore URI to return
514
 
 
515
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
516
 
 */
517
 
enum MAPISTORE_ERROR mapistore_indexing_get_record_uri_by_fmid(struct mapistore_indexing_context_list *mictx,
518
 
                                                               uint64_t fmid,
519
 
                                                               char **uri)
520
 
{
521
 
        enum MAPISTORE_ERROR                    retval;
522
 
        struct mapistore_indexing_entry         entry;
523
 
 
524
 
        /* Sanity checks */
525
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
526
 
        MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
527
 
        MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
528
 
 
529
 
        retval = mapistore_indexing_get_entry(mictx, fmid, &entry);
530
 
        MAPISTORE_RETVAL_IF(retval, retval, NULL);
531
 
 
532
 
        *uri = (char *)entry.info.mapistore_indexing_v1.mapistoreURI;
533
 
 
534
 
        return MAPISTORE_SUCCESS;
535
 
}
536
 
 
537
 
 
538
 
static enum MAPISTORE_ERROR mapistore_indexing_update_entry(struct mapistore_indexing_context_list *mictx,
539
 
                                                            uint64_t fmid,
540
 
                                                            struct mapistore_indexing_entry *entry)
541
 
{
542
 
        TALLOC_CTX              *mem_ctx;
543
 
        TDB_DATA                key;
544
 
        TDB_DATA                dbuf;
545
 
        DATA_BLOB               data;
546
 
        int                     ret;
547
 
        enum ndr_err_code       ndr_err;
548
 
 
549
 
        /* Sanity checks */
550
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
551
 
        MAPISTORE_RETVAL_IF(!mictx->tdb_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
552
 
        MAPISTORE_RETVAL_IF(!mictx->tdb_ctx->tdb, MAPISTORE_ERR_DATABASE_INIT, NULL);
553
 
        MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
554
 
        MAPISTORE_RETVAL_IF(!entry, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
555
 
 
556
 
        mem_ctx = talloc_new(mictx);
557
 
 
558
 
        /* Step 1. Make sure the FID exists */
559
 
        key.dptr = (unsigned char *)talloc_asprintf(mem_ctx, MAPISTORE_INDEXING_FMID, fmid);
560
 
        key.dsize = strlen((const char *)key.dptr);
561
 
        
562
 
        ret = tdb_exists(mictx->tdb_ctx->tdb, key);
563
 
        MAPISTORE_RETVAL_IF(!ret, MAPISTORE_ERR_NOT_FOUND, mem_ctx);
564
 
 
565
 
        /* Step 2. Pack the mapistore_indexing_entry into a DATA_BLOB */
566
 
        ndr_err = ndr_push_struct_blob(&data, mem_ctx, entry, (ndr_push_flags_fn_t)ndr_push_mapistore_indexing_entry);
567
 
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
568
 
                DEBUG(0, ("! [%s:%d][%s]: Failed to push mapistore_indexing_entry into NDR blob\n", __FILE__, __LINE__, __FUNCTION__));
569
 
                talloc_free(mem_ctx);
570
 
                return MAPISTORE_ERROR;
571
 
        }
572
 
 
573
 
        dbuf.dptr = data.data;
574
 
        dbuf.dsize = data.length;
575
 
 
576
 
        /* Step 3. Update the record */
577
 
        ret = tdb_store(mictx->tdb_ctx->tdb, key, dbuf, TDB_MODIFY);
578
 
        if (ret == -1) {
579
 
                DEBUG(0, ("[%s:%d][%s]: Unable to update record %s: %s\n", 
580
 
                          __FILE__, __LINE__, __FUNCTION__, (char *)key.dptr,
581
 
                          tdb_errorstr(mictx->tdb_ctx->tdb)));
582
 
                talloc_free(mem_ctx);
583
 
                return MAPISTORE_ERROR;
584
 
        }
585
 
 
586
 
        DEBUG(5, ("* [%s:%d][%s]: Record %s updated successfully\n", __FILE__, __LINE__, __FUNCTION__, (char *)key.dptr));
587
 
 
588
 
        talloc_free(mem_ctx);
589
 
 
590
 
        return MAPISTORE_SUCCESS;
591
 
}
592
 
 
593
 
 
594
 
static enum MAPISTORE_ERROR mapistore_indexing_add_entry_r(struct mapistore_indexing_context_list *mictx,
595
 
                                                           const char *mapistore_uri, uint64_t fmid)
596
 
{
597
 
        TALLOC_CTX                              *mem_ctx;
598
 
        int                                     ret;
599
 
        TDB_DATA                                key;
600
 
        TDB_DATA                                dbuf;
601
 
        DATA_BLOB                               data;
602
 
        enum ndr_err_code                       ndr_err;
603
 
        struct mapistore_indexing_entry_r       entry_r;
604
 
 
605
 
        /* Sanity checks */
606
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
607
 
        MAPISTORE_RETVAL_IF(!mapistore_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
608
 
        MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
609
 
 
610
 
        /* Step 1. Create the key/dbuf record */
611
 
        mem_ctx = talloc_new(mictx);
612
 
 
613
 
        key.dptr = (unsigned char *) talloc_asprintf(mem_ctx, MAPISTORE_INDEXING_URI, mapistore_uri);
614
 
        key.dsize = strlen((const char *)key.dptr);
615
 
 
616
 
        entry_r.indexing_key = (char *) talloc_asprintf(mem_ctx, MAPISTORE_INDEXING_FMID, fmid);
617
 
        entry_r.FMID = fmid;
618
 
 
619
 
        ndr_err = ndr_push_struct_blob(&data, mem_ctx, &entry_r, (ndr_push_flags_fn_t)ndr_push_mapistore_indexing_entry_r);
620
 
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
621
 
                DEBUG(5, ("! [%s:%d][%s]: Failed to push mapistore_indexing_entry_r into NDR blob\n", __FILE__, __LINE__, __FUNCTION__));
622
 
                talloc_free(mem_ctx);
623
 
                return MAPISTORE_ERROR;
624
 
        }
625
 
 
626
 
        dbuf.dptr = data.data;
627
 
        dbuf.dsize = data.length;
628
 
 
629
 
        /* Step 2. Insert the FMID record */
630
 
        ret = tdb_store(mictx->tdb_ctx->tdb, key, dbuf, TDB_INSERT);
631
 
        talloc_free(mem_ctx);
632
 
 
633
 
        if (ret == -1) {
634
 
                DEBUG(3, ("[%s:%d][%s]: Unable to create " MAPISTORE_INDEXING_URI " record: " MAPISTORE_INDEXING_FMID "\n",
635
 
                          __FILE__, __LINE__, __FUNCTION__, mapistore_uri, fmid));
636
 
                return MAPISTORE_ERR_DATABASE_OPS;
637
 
        }
638
 
 
639
 
        return MAPISTORE_SUCCESS;
640
 
}
641
 
 
642
 
 
643
 
static enum MAPISTORE_ERROR mapistore_indexing_del_entry_r(struct mapistore_indexing_context_list *mictx,
644
 
                                                           const char *mapistore_uri)
645
 
{
646
 
        TALLOC_CTX              *mem_ctx;
647
 
        int                     ret;
648
 
        TDB_DATA                key;
649
 
 
650
 
        /* Sanity checks */
651
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
652
 
        MAPISTORE_RETVAL_IF(!mapistore_uri, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
653
 
 
654
 
        mem_ctx = talloc_named(NULL, 0, __FUNCTION__);
655
 
 
656
 
        key.dptr = (unsigned char *)talloc_asprintf(mem_ctx, MAPISTORE_INDEXING_URI, mapistore_uri);
657
 
        key.dsize = strlen((const char *)key.dptr);
658
 
 
659
 
        ret = tdb_delete(mictx->tdb_ctx->tdb, key);
660
 
        if (ret == -1) {
661
 
                DEBUG(3, ("! [%s:%d][%s]: Failed to delete mapistore reverse entry for %s\n", 
662
 
                          __FILE__, __LINE__, __FUNCTION__, (char *)key.dptr));
663
 
                talloc_free(mem_ctx);
664
 
                return MAPISTORE_ERR_DATABASE_OPS;
665
 
        }
666
 
 
667
 
        talloc_free(mem_ctx);
668
 
        return MAPISTORE_SUCCESS;
669
 
}
670
 
 
671
 
 
672
 
/**
673
 
   \details Add a folder or message record to the indexing database
674
 
 
675
 
   \param mictx pointer to the mapistore indexing context
676
 
   \param fmid the Folder or Message identifier to register
677
 
   \param mapistore_uri the mapistore URI to register
678
 
   \param parent_fid the parent folder identifier
679
 
   \param type the element type to add
680
 
 
681
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
682
 
 */
683
 
enum MAPISTORE_ERROR mapistore_indexing_add_fmid_record(struct mapistore_indexing_context_list *mictx,
684
 
                                                        uint64_t fmid,
685
 
                                                        const char *mapistore_uri,
686
 
                                                        uint64_t parent_fid,
687
 
                                                        uint8_t type)
688
 
{
689
 
        enum MAPISTORE_ERROR                    retval;
690
 
        TALLOC_CTX                              *mem_ctx;
691
 
        int                                     ret;
692
 
        struct mapistore_indexing_entry         entry;
693
 
        DATA_BLOB                               data;
694
 
        enum ndr_err_code                       ndr_err;
695
 
        TDB_DATA                                key;
696
 
        TDB_DATA                                dbuf;
697
 
 
698
 
        /* Sanity checks */
699
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
700
 
        MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
701
 
        MAPISTORE_RETVAL_IF(!mapistore_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
702
 
 
703
 
        /* Step 1.a Check if the fid/mid already exists */
704
 
        retval = mapistore_indexing_record_search_fmid(mictx, fmid);
705
 
        if (retval == MAPISTORE_ERR_EXIST) {
706
 
                DEBUG(5, ("! [%s:%d][%s]: FMID 0x%.16"PRIx64" already exists!\n", __FILE__, __LINE__, __FUNCTION__, fmid));
707
 
                return retval;
708
 
        }
709
 
 
710
 
        /* Step 1.b Check if the URI already exists */
711
 
        retval = mapistore_indexing_record_search_uri(mictx, mapistore_uri);
712
 
        if (retval == MAPISTORE_ERR_EXIST) {
713
 
                DEBUG(5, ("! [%s:%d][%s]: URI %s already exists!\n", __FILE__, __LINE__, __FUNCTION__, mapistore_uri));
714
 
                return retval;
715
 
        }
716
 
 
717
 
        /* Step 2. Ensure parent_fid is a valid fid */
718
 
        if (parent_fid) {
719
 
                retval = mapistore_indexing_record_search_fmid(mictx, parent_fid);
720
 
                if (retval == MAPISTORE_ERR_NOT_FOUND) {
721
 
                        DEBUG(5, ("! [%s:%d][%s]: Parent folder 0x%.16"PRIx64" doesn't exist!\n", __FILE__, __LINE__, __FUNCTION__, parent_fid));
722
 
                        return retval;
723
 
                }
724
 
        } else {
725
 
                DEBUG(5, ("* [%s:%d][%s]: Registering root mailbox entry\n", __FILE__, __LINE__, __FUNCTION__));
726
 
        }
727
 
 
728
 
        /* Step 3. Create the key/dbuf record */
729
 
        mem_ctx = talloc_new(mictx);
730
 
        key.dptr = (unsigned char *) talloc_asprintf(mem_ctx, MAPISTORE_INDEXING_FMID, fmid);
731
 
        key.dsize = strlen((const char *)key.dptr);
732
 
 
733
 
        entry.version = 1;
734
 
        entry.info.mapistore_indexing_v1.mapistoreURI = mapistore_uri;
735
 
        entry.info.mapistore_indexing_v1.Type = type;
736
 
        entry.info.mapistore_indexing_v1.FMID = fmid;
737
 
        entry.info.mapistore_indexing_v1.ParentFolderID = parent_fid;
738
 
        if (type == MAPISTORE_INDEXING_FOLDER) {
739
 
                entry.info.mapistore_indexing_v1.MessageRangeIDs.range.next_allocation_id = 0;
740
 
                entry.info.mapistore_indexing_v1.MessageRangeIDs.range.last_allocation_id = 0;
741
 
 
742
 
                entry.info.mapistore_indexing_v1.Acls.acls_folder.acl_number = 0;
743
 
        }
744
 
 
745
 
        ndr_err = ndr_push_struct_blob(&data, mem_ctx, &entry, (ndr_push_flags_fn_t)ndr_push_mapistore_indexing_entry);
746
 
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
747
 
                DEBUG(5, ("! [%s:%d][%s]: Failed to push mapistore_indexing_entry into NDR blob\n", __FILE__, __LINE__, __FUNCTION__));
748
 
                talloc_free(mem_ctx);
749
 
                return MAPISTORE_ERROR;
750
 
        }
751
 
 
752
 
        dbuf.dptr = data.data;
753
 
        dbuf.dsize = data.length;
754
 
 
755
 
        /* Step 4. Insert the FMID record */
756
 
        ret = tdb_store(mictx->tdb_ctx->tdb, key, dbuf, TDB_INSERT);
757
 
 
758
 
        if (ret == -1) {
759
 
                DEBUG(3, ("! [%s:%d][%s]: Unable to create " MAPISTORE_INDEXING_FMID " record: %s\n",
760
 
                          __FILE__, __LINE__, __FUNCTION__, fmid, mapistore_uri));
761
 
                talloc_free(mem_ctx);
762
 
                return MAPISTORE_ERR_DATABASE_OPS;
763
 
        }
764
 
 
765
 
        /* Step 5. Insert the reverse record URI/ indexing record */
766
 
        retval = mapistore_indexing_add_entry_r(mictx, mapistore_uri, fmid);
767
 
 
768
 
        return retval;
769
 
}
770
 
 
771
 
 
772
 
/**
773
 
   \details Add an allocation range for messages to a folder
774
 
 
775
 
   \param mictx pointer to the mapistore indexing context
776
 
   \param fid the folder identifier for which we want to setup the
777
 
   allocation range
778
 
   \param rstart the allocation range ID's start
779
 
   \param rend the allocation range ID's end
780
 
 
781
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
782
 
 */
783
 
enum MAPISTORE_ERROR mapistore_indexing_add_folder_record_allocation_range(struct mapistore_indexing_context_list *mictx,
784
 
                                                                           uint64_t fid,
785
 
                                                                           uint64_t rstart,
786
 
                                                                           uint64_t rend)
787
 
{
788
 
        enum MAPISTORE_ERROR            retval;
789
 
        struct mapistore_indexing_entry entry;
790
 
        uint64_t                        range_start;
791
 
        uint64_t                        range_end;
792
 
 
793
 
        /* Sanity checks */
794
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
795
 
        MAPISTORE_RETVAL_IF(!fid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
796
 
        MAPISTORE_RETVAL_IF(!rstart || !rend, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
797
 
        MAPISTORE_RETVAL_IF(rstart > rend, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
798
 
 
799
 
        /* Step 1. Retrieve the mapistore_indexing entry associated to the fid */
800
 
        retval = mapistore_indexing_get_entry(mictx, fid, &entry);
801
 
 
802
 
        MAPISTORE_RETVAL_IF(retval, retval, NULL);
803
 
 
804
 
        /* Step 2. Check if we already consumed the previous allocation range */
805
 
        MAPISTORE_RETVAL_IF(entry.info.mapistore_indexing_v1.Type != MAPISTORE_INDEXING_FOLDER, MAPISTORE_ERR_INVALID_OBJECT, NULL);
806
 
 
807
 
        range_start = entry.info.mapistore_indexing_v1.MessageRangeIDs.range.next_allocation_id;
808
 
        range_end   = entry.info.mapistore_indexing_v1.MessageRangeIDs.range.last_allocation_id;
809
 
        MAPISTORE_RETVAL_IF((range_start && range_end && range_start != range_end), MAPISTORE_ERROR, NULL);
810
 
 
811
 
        /* Step 3. Update record with new allocation range */
812
 
        entry.info.mapistore_indexing_v1.MessageRangeIDs.range.next_allocation_id = rstart;
813
 
        entry.info.mapistore_indexing_v1.MessageRangeIDs.range.last_allocation_id = rend;
814
 
 
815
 
        retval = mapistore_indexing_update_entry(mictx, fid, &entry);
816
 
 
817
 
        return retval;
818
 
}
819
 
 
820
 
 
821
 
/**
822
 
   \details Update the mapistore URI for a given record within the
823
 
   indexing database
824
 
 
825
 
   \param mictx pointer to the mapistore indexing context
826
 
   \param fmid the folder/message identifier for which we want to
827
 
   update the URI
828
 
   \param new_uri the new mapistore URI to set for this record
829
 
 
830
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
831
 
 */
832
 
enum MAPISTORE_ERROR mapistore_indexing_update_mapistore_uri(struct mapistore_indexing_context_list *mictx,
833
 
                                                             uint64_t fmid, const char *new_uri)
834
 
{
835
 
        enum MAPISTORE_ERROR                    retval;
836
 
        TALLOC_CTX                              *mem_ctx;
837
 
        struct mapistore_indexing_entry         entry;
838
 
        const char                              *old_uri;
839
 
 
840
 
        /* Sanity checks */
841
 
        MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
842
 
        MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
843
 
        MAPISTORE_RETVAL_IF(!new_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
844
 
 
845
 
        /* Step 1. Ensure the new_uri is not already registered */
846
 
        retval = mapistore_indexing_record_search_uri(mictx, new_uri);
847
 
        MAPISTORE_RETVAL_IF(retval == MAPISTORE_ERR_EXIST, retval, NULL);
848
 
 
849
 
        /* Step 2. Retrieve the mapistore_indexing entry associated to the fmid */
850
 
        retval = mapistore_indexing_get_entry(mictx, fmid, &entry);
851
 
        MAPISTORE_RETVAL_IF(retval, retval, NULL);
852
 
 
853
 
        mem_ctx = talloc_new(NULL);
854
 
        old_uri = talloc_strdup(mem_ctx, entry.info.mapistore_indexing_v1.mapistoreURI);
855
 
 
856
 
        /* Step 3. Replace the record with the new_uri */
857
 
        entry.info.mapistore_indexing_v1.mapistoreURI = new_uri;
858
 
        retval = mapistore_indexing_update_entry(mictx, fmid, &entry);
859
 
        MAPISTORE_RETVAL_IF(retval, retval, mem_ctx);
860
 
 
861
 
        /* Step 4. Create the new reversed index entry */
862
 
        retval = mapistore_indexing_add_entry_r(mictx, new_uri, fmid);
863
 
        MAPISTORE_RETVAL_IF(retval, retval, mem_ctx);
864
 
        
865
 
        /* Step 5. Delete the old reversed indexed entry */
866
 
        retval = mapistore_indexing_del_entry_r(mictx, old_uri);
867
 
        MAPISTORE_RETVAL_IF(retval, retval, mem_ctx);
868
 
 
869
 
        talloc_free(mem_ctx);
870
 
 
871
 
        return MAPISTORE_SUCCESS;
872
 
}