2
OpenChange Storage Abstraction Layer library
6
Copyright (C) Julien Kerihuel 2010-2011
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.
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.
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/>.
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"
32
#include <dlinklist.h>
36
\file indexing/mapistore_indexing.c
38
\brief Interface API to the mapistore indexing database
40
This database is used to map FID/MID to mapistore URI, plus additional parameters
43
static enum MAPISTORE_ERROR mapistore_indexing_dump_folder_v1(struct mapistore_indexing_entry *entry)
46
MAPISTORE_RETVAL_IF(!entry, MAPISTORE_ERR_INVALID_OBJECT, NULL);
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));
58
return MAPISTORE_SUCCESS;
61
enum MAPISTORE_ERROR mapistore_indexing_dump_object(struct mapistore_indexing_entry *entry)
64
MAPISTORE_RETVAL_IF(!entry, MAPISTORE_ERR_INVALID_OBJECT, NULL);
66
switch (entry->info.mapistore_indexing_v1.Type) {
67
case MAPISTORE_INDEXING_FOLDER:
68
return mapistore_indexing_dump_folder_v1(entry);
71
DEBUG(0, ("Not implemented yet\n"));
72
return MAPISTORE_ERR_NOT_FOUND;
76
return MAPISTORE_ERR_NOT_FOUND;
80
enum MAPISTORE_ERROR mapistore_indexing_dump_reverse_entry(struct mapistore_indexing_entry_r *entry)
83
MAPISTORE_RETVAL_IF(!entry, MAPISTORE_ERR_INVALID_OBJECT, NULL);
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));
90
return MAPISTORE_SUCCESS;
95
\details Increase the reference counter associated to a given
96
mapistore indexing context
98
\param mictx pointer to the mapistore indexing context
100
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
102
static enum MAPISTORE_ERROR mapistore_indexing_context_add_ref_count(struct mapistore_indexing_context_list *mictx)
105
MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERROR, NULL);
107
DEBUG(2, ("* [%s:%d][%s]: ref count was %i, about to increment\n", __FILE__, __LINE__, __FUNCTION__, mictx->ref_count));
109
return MAPISTORE_SUCCESS;
113
\details Decrease the reference counter associated to a given
114
mapistore indexing context
116
\param mictx pointer to the mapistore indexing context
118
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
120
static enum MAPISTORE_ERROR mapistore_indexing_context_del_ref_count(struct mapistore_indexing_context_list *mictx)
123
MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERROR, NULL);
124
MAPISTORE_RETVAL_IF(!mictx->ref_count, MAPISTORE_SUCCESS, NULL);
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;
129
return MAPISTORE_SUCCESS;
133
\details (Accessor) Retrieve the reference counter associated to a
134
given mapistore indexing context
136
\param mictx pointer to the mapistore indexing context
138
\return the reference counter value associated to the mapistore
141
static uint32_t mapistore_indexing_context_get_ref_count(struct mapistore_indexing_context_list *mictx)
143
return mictx->ref_count;
147
\details Search the mapistore indexing context list for an existing
148
record matching the specified username
150
\param mstore_ctx pointer to the mapistore context
151
\param username the username to lookup
153
\return pointer to the existing mapistore indexing context list on success, otherwise NULL
155
static struct mapistore_indexing_context_list *mapistore_indexing_context_search(struct mapistore_context *mstore_ctx,
156
const char *username)
158
struct mapistore_indexing_context_list *el;
161
if (!mstore_ctx || !username) return NULL;
163
for (el = mstore_ctx->mapistore_indexing_list; el; el = el->next) {
164
if (el && el->username && !strcmp(el->username, username)) {
173
\details Open a connection context to the indexing database for
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
180
\return MAPISTORE_SUCCESS on success, otherwise a non-zero MAPISTORE_ERROR value
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)
187
struct mapistore_indexing_context_list *mictx;
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);
195
/* Step 1. Return existing context if available */
196
mictx = mapistore_indexing_context_search(mstore_ctx, username);
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;
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);
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);
213
if (!mictx->tdb_ctx) {
214
DEBUG(3, ("! [%s:%d][%s]: %s\n", __FILE__, __LINE__, __FUNCTION__, strerror(errno)));
216
talloc_free(mem_ctx);
218
return MAPISTORE_ERR_DATABASE_INIT;
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 *);
226
*indexing_ctx = mictx;
228
talloc_free(mem_ctx);
230
return MAPISTORE_SUCCESS;
235
\details Delete indexing database context for given user
237
\param mstore_ctx pointer to the mapistore context
238
\param username username of the indexing database owner
240
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
242
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
244
enum MAPISTORE_ERROR mapistore_indexing_context_del(struct mapistore_context *mstore_ctx,
245
const char *username)
247
struct mapistore_indexing_context_list *mictx;
248
enum MAPISTORE_ERROR retval;
251
MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
252
MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERROR, NULL);
254
/* Step 1. Search for the context */
255
mictx = mapistore_indexing_context_search(mstore_ctx, username);
256
MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERROR, NULL);
258
/* Step 2. Decrement the reference count */
259
retval = mapistore_indexing_context_del_ref_count(mictx);
261
if (mapistore_indexing_context_get_ref_count(mictx)) {
262
/* Step 3. If we still have ref counts, just return */
263
return MAPISTORE_SUCCESS;
265
/* Step 4. If no more associated references, remove and release memory */
266
DLIST_REMOVE(mstore_ctx->mapistore_indexing_list, mictx);
270
return MAPISTORE_SUCCESS;
275
\details Increment the reference counter of the existing context
278
\param mstore_ctx pointer to the mapistore context
279
\param username the user string to lookup
281
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
283
enum MAPISTORE_ERROR mapistore_indexing_context_add_ref(struct mapistore_context *mstore_ctx,
284
const char *username)
286
struct mapistore_indexing_context_list *mictx;
287
enum MAPISTATUS retval;
290
MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
291
MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERROR, NULL);
293
/* Step 1. Search for the context */
294
mictx = mapistore_indexing_context_search(mstore_ctx, username);
295
MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERROR, NULL);
297
/* Step 2. Increment the reference counter */
298
retval = mapistore_indexing_context_add_ref_count(mictx);
305
\details Retrieve the mapistore indexing entry associated to a
306
folder or message identifier
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
312
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
314
static enum MAPISTORE_ERROR mapistore_indexing_get_entry(struct mapistore_indexing_context_list *mictx,
316
struct mapistore_indexing_entry *entry)
321
enum ndr_err_code ndr_err;
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);
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);
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);
338
data.data = value.dptr;
339
data.length = value.dsize;
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;
351
DEBUG(5, ("* [%s:%d][%s]: %s loaded correctly!\n", __FILE__, __LINE__, __FUNCTION__,
352
entry->info.mapistore_indexing_v1.mapistoreURI));
354
return MAPISTORE_SUCCESS;
359
\details Retrieve the reversed mapistore indexing entry associated to a
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
366
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
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)
375
enum ndr_err_code ndr_err;
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);
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);
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);
392
data.data = value.dptr;
393
data.length = value.dsize;
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;
405
DEBUG(5, ("* [%s:%d][%s]: %s loaded correctly!\n", __FILE__, __LINE__, __FUNCTION__,
406
entry->indexing_key));
408
return MAPISTORE_SUCCESS;
413
\details Search the TDB database and check if the fmid already exists
415
\param mictx pointer to the mapistore indexing context list
416
\param fmid the folder or message identifier to lookup
418
\return MAPISTORE_ERR_NOT_FOUND if the fmid was not found,
419
MAPISTORE_ERR_EXIST if it was found, otherwise different MAPISTORE error
421
static enum MAPISTORE_ERROR mapistore_indexing_record_search_fmid(struct mapistore_indexing_context_list *mictx,
428
MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
429
MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
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);
435
ret = tdb_exists(mictx->tdb_ctx->tdb, key);
436
talloc_free(key.dptr);
438
MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_EXIST, NULL);
440
return MAPISTORE_ERR_NOT_FOUND;
445
\details Search the TDB database and check if the URI already exists
447
\param mictx pointer to the mapistore indexing context list
448
\param uri the uri to lookup
450
\return MAPISTORE_ERR_NOT_FOUND if the fmid was not found,
451
MAPISTORE_ERR_EXIST if it was found, otherwise different MAPISTORE error
453
enum MAPISTORE_ERROR mapistore_indexing_record_search_uri(struct mapistore_indexing_context_list *mictx,
460
MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
461
MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
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);
467
ret = tdb_exists(mictx->tdb_ctx->tdb, key);
468
talloc_free(key.dptr);
470
MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_EXIST, NULL);
472
return MAPISTORE_ERR_NOT_FOUND;
477
\details Return FMID associated to a mapistore URI for a given
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
484
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
486
enum MAPISTORE_ERROR mapistore_indexing_get_record_fmid_by_uri(struct mapistore_indexing_context_list *mictx,
490
enum MAPISTORE_ERROR retval;
491
struct mapistore_indexing_entry_r entry;
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);
498
retval = mapistore_indexing_get_entry_r(mictx, uri, &entry);
499
MAPISTORE_RETVAL_IF(retval, retval, NULL);
503
return MAPISTORE_SUCCESS;
508
\details Return the URI associated to a mapistore FMID for a given
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
515
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
517
enum MAPISTORE_ERROR mapistore_indexing_get_record_uri_by_fmid(struct mapistore_indexing_context_list *mictx,
521
enum MAPISTORE_ERROR retval;
522
struct mapistore_indexing_entry entry;
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);
529
retval = mapistore_indexing_get_entry(mictx, fmid, &entry);
530
MAPISTORE_RETVAL_IF(retval, retval, NULL);
532
*uri = (char *)entry.info.mapistore_indexing_v1.mapistoreURI;
534
return MAPISTORE_SUCCESS;
538
static enum MAPISTORE_ERROR mapistore_indexing_update_entry(struct mapistore_indexing_context_list *mictx,
540
struct mapistore_indexing_entry *entry)
547
enum ndr_err_code ndr_err;
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);
556
mem_ctx = talloc_new(mictx);
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);
562
ret = tdb_exists(mictx->tdb_ctx->tdb, key);
563
MAPISTORE_RETVAL_IF(!ret, MAPISTORE_ERR_NOT_FOUND, mem_ctx);
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;
573
dbuf.dptr = data.data;
574
dbuf.dsize = data.length;
576
/* Step 3. Update the record */
577
ret = tdb_store(mictx->tdb_ctx->tdb, key, dbuf, TDB_MODIFY);
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;
586
DEBUG(5, ("* [%s:%d][%s]: Record %s updated successfully\n", __FILE__, __LINE__, __FUNCTION__, (char *)key.dptr));
588
talloc_free(mem_ctx);
590
return MAPISTORE_SUCCESS;
594
static enum MAPISTORE_ERROR mapistore_indexing_add_entry_r(struct mapistore_indexing_context_list *mictx,
595
const char *mapistore_uri, uint64_t fmid)
602
enum ndr_err_code ndr_err;
603
struct mapistore_indexing_entry_r entry_r;
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);
610
/* Step 1. Create the key/dbuf record */
611
mem_ctx = talloc_new(mictx);
613
key.dptr = (unsigned char *) talloc_asprintf(mem_ctx, MAPISTORE_INDEXING_URI, mapistore_uri);
614
key.dsize = strlen((const char *)key.dptr);
616
entry_r.indexing_key = (char *) talloc_asprintf(mem_ctx, MAPISTORE_INDEXING_FMID, fmid);
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;
626
dbuf.dptr = data.data;
627
dbuf.dsize = data.length;
629
/* Step 2. Insert the FMID record */
630
ret = tdb_store(mictx->tdb_ctx->tdb, key, dbuf, TDB_INSERT);
631
talloc_free(mem_ctx);
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;
639
return MAPISTORE_SUCCESS;
643
static enum MAPISTORE_ERROR mapistore_indexing_del_entry_r(struct mapistore_indexing_context_list *mictx,
644
const char *mapistore_uri)
651
MAPISTORE_RETVAL_IF(!mictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
652
MAPISTORE_RETVAL_IF(!mapistore_uri, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
654
mem_ctx = talloc_named(NULL, 0, __FUNCTION__);
656
key.dptr = (unsigned char *)talloc_asprintf(mem_ctx, MAPISTORE_INDEXING_URI, mapistore_uri);
657
key.dsize = strlen((const char *)key.dptr);
659
ret = tdb_delete(mictx->tdb_ctx->tdb, key);
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;
667
talloc_free(mem_ctx);
668
return MAPISTORE_SUCCESS;
673
\details Add a folder or message record to the indexing database
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
681
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
683
enum MAPISTORE_ERROR mapistore_indexing_add_fmid_record(struct mapistore_indexing_context_list *mictx,
685
const char *mapistore_uri,
689
enum MAPISTORE_ERROR retval;
692
struct mapistore_indexing_entry entry;
694
enum ndr_err_code ndr_err;
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);
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));
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));
717
/* Step 2. Ensure parent_fid is a valid 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));
725
DEBUG(5, ("* [%s:%d][%s]: Registering root mailbox entry\n", __FILE__, __LINE__, __FUNCTION__));
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);
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;
742
entry.info.mapistore_indexing_v1.Acls.acls_folder.acl_number = 0;
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;
752
dbuf.dptr = data.data;
753
dbuf.dsize = data.length;
755
/* Step 4. Insert the FMID record */
756
ret = tdb_store(mictx->tdb_ctx->tdb, key, dbuf, TDB_INSERT);
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;
765
/* Step 5. Insert the reverse record URI/ indexing record */
766
retval = mapistore_indexing_add_entry_r(mictx, mapistore_uri, fmid);
773
\details Add an allocation range for messages to a folder
775
\param mictx pointer to the mapistore indexing context
776
\param fid the folder identifier for which we want to setup the
778
\param rstart the allocation range ID's start
779
\param rend the allocation range ID's end
781
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
783
enum MAPISTORE_ERROR mapistore_indexing_add_folder_record_allocation_range(struct mapistore_indexing_context_list *mictx,
788
enum MAPISTORE_ERROR retval;
789
struct mapistore_indexing_entry entry;
790
uint64_t range_start;
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);
799
/* Step 1. Retrieve the mapistore_indexing entry associated to the fid */
800
retval = mapistore_indexing_get_entry(mictx, fid, &entry);
802
MAPISTORE_RETVAL_IF(retval, retval, NULL);
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);
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);
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;
815
retval = mapistore_indexing_update_entry(mictx, fid, &entry);
822
\details Update the mapistore URI for a given record within the
825
\param mictx pointer to the mapistore indexing context
826
\param fmid the folder/message identifier for which we want to
828
\param new_uri the new mapistore URI to set for this record
830
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
832
enum MAPISTORE_ERROR mapistore_indexing_update_mapistore_uri(struct mapistore_indexing_context_list *mictx,
833
uint64_t fmid, const char *new_uri)
835
enum MAPISTORE_ERROR retval;
837
struct mapistore_indexing_entry entry;
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);
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);
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);
853
mem_ctx = talloc_new(NULL);
854
old_uri = talloc_strdup(mem_ctx, entry.info.mapistore_indexing_v1.mapistoreURI);
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);
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);
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);
869
talloc_free(mem_ctx);
871
return MAPISTORE_SUCCESS;