4
Copyright (C) Andrew Tridgell 2004
6
** NOTE! The following LGPL license applies to the ldb
7
** library. This does NOT imply that all of Samba is released
10
This library is free software; you can redistribute it and/or
11
modify it under the terms of the GNU Lesser General Public
12
License as published by the Free Software Foundation; either
13
version 3 of the License, or (at your option) any later version.
15
This library is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
Lesser General Public License for more details.
20
You should have received a copy of the GNU Lesser General Public
21
License along with this library; if not, see <http://www.gnu.org/licenses/>.
27
* Component: ldb tdb backend - indexing
29
* Description: indexing routines for ldb tdb backend
31
* Author: Andrew Tridgell
35
#include "dlinklist.h"
38
the idxptr code is a bit unusual. The way it works is to replace
39
@IDX elements in records during a transaction with @IDXPTR
40
elements. The @IDXPTR elements don't contain the actual index entry
41
values, but contain a pointer to a linked list of values.
43
This means we are storing pointers in a database, which is normally
44
not allowed, but in this case we are storing them only for the
45
duration of a transaction, and re-writing them into the normal @IDX
46
format at the end of the transaction. That means no other processes
47
are ever exposed to the @IDXPTR values.
49
The advantage is that the linked list doesn't cause huge
50
fragmentation during a transaction. Without the @IDXPTR method we
51
often ended up with a ldb that was between 10x and 100x larger then
52
it needs to be due to massive fragmentation caused by re-writing
53
@INDEX records many times during indexing.
55
struct ldb_index_pointer {
56
struct ldb_index_pointer *next, *prev;
67
add to the list of DNs that need to be fixed on transaction end
69
static int ltdb_idxptr_add(struct ldb_module *module, const struct ldb_message *msg)
71
void *data = ldb_module_get_private(module);
72
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
73
ltdb->idxptr->dn_list = talloc_realloc(ltdb->idxptr, ltdb->idxptr->dn_list,
74
const char *, ltdb->idxptr->num_dns+1);
75
if (ltdb->idxptr->dn_list == NULL) {
76
ltdb->idxptr->num_dns = 0;
77
return LDB_ERR_OPERATIONS_ERROR;
79
ltdb->idxptr->dn_list[ltdb->idxptr->num_dns] =
80
talloc_strdup(ltdb->idxptr->dn_list, ldb_dn_get_linearized(msg->dn));
81
if (ltdb->idxptr->dn_list[ltdb->idxptr->num_dns] == NULL) {
82
return LDB_ERR_OPERATIONS_ERROR;
84
ltdb->idxptr->num_dns++;
88
/* free an idxptr record */
89
static int ltdb_free_idxptr(struct ldb_module *module, struct ldb_message_element *el)
92
struct ldb_index_pointer *ptr;
94
if (el->num_values != 1) {
95
return LDB_ERR_OPERATIONS_ERROR;
99
if (val.length != sizeof(void *)) {
100
return LDB_ERR_OPERATIONS_ERROR;
103
ptr = *(struct ldb_index_pointer **)val.data;
104
if (talloc_get_type(ptr, struct ldb_index_pointer) != ptr) {
105
return LDB_ERR_OPERATIONS_ERROR;
109
struct ldb_index_pointer *tmp = ptr;
110
DLIST_REMOVE(ptr, ptr);
118
/* convert from the IDXPTR format to a ldb_message_element format */
119
static int ltdb_convert_from_idxptr(struct ldb_module *module, struct ldb_message_element *el)
122
struct ldb_index_pointer *ptr, *tmp;
124
struct ldb_val *val2;
126
if (el->num_values != 1) {
127
return LDB_ERR_OPERATIONS_ERROR;
131
if (val.length != sizeof(void *)) {
132
return LDB_ERR_OPERATIONS_ERROR;
135
ptr = *(struct ldb_index_pointer **)val.data;
136
if (talloc_get_type(ptr, struct ldb_index_pointer) != ptr) {
137
return LDB_ERR_OPERATIONS_ERROR;
140
/* count the length of the list */
141
for (i=0, tmp = ptr; tmp; tmp=tmp->next) {
145
/* allocate the new values array */
146
val2 = talloc_realloc(NULL, el->values, struct ldb_val, i);
148
return LDB_ERR_OPERATIONS_ERROR;
153
/* populate the values array */
154
for (i=0, tmp = ptr; tmp; tmp=tmp->next, i++) {
155
el->values[i].length = tmp->value.length;
156
/* we need to over-allocate here as there are still some places
157
in ldb that rely on null termination. */
158
el->values[i].data = talloc_size(el->values, tmp->value.length+1);
159
if (el->values[i].data == NULL) {
160
return LDB_ERR_OPERATIONS_ERROR;
162
memcpy(el->values[i].data, tmp->value.data, tmp->value.length);
163
el->values[i].data[tmp->value.length] = 0;
166
/* update the name */
173
/* convert to the IDXPTR format from a ldb_message_element format */
174
static int ltdb_convert_to_idxptr(struct ldb_module *module, struct ldb_message_element *el)
176
struct ldb_index_pointer *ptr, *tmp;
178
struct ldb_val *val2;
179
void *data = ldb_module_get_private(module);
180
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
184
for (i=0;i<el->num_values;i++) {
185
tmp = talloc(ltdb->idxptr, struct ldb_index_pointer);
187
return LDB_ERR_OPERATIONS_ERROR;
189
tmp->value = el->values[i];
190
tmp->value.data = talloc_memdup(tmp, tmp->value.data, tmp->value.length);
191
if (tmp->value.data == NULL) {
192
return LDB_ERR_OPERATIONS_ERROR;
197
/* allocate the new values array */
198
val2 = talloc_realloc(NULL, el->values, struct ldb_val, 1);
200
return LDB_ERR_OPERATIONS_ERROR;
205
el->values[0].data = talloc_memdup(el->values, &ptr, sizeof(ptr));
206
el->values[0].length = sizeof(ptr);
208
/* update the name */
209
el->name = LTDB_IDXPTR;
215
/* enable the idxptr mode when transactions start */
216
int ltdb_index_transaction_start(struct ldb_module *module)
218
void *data = ldb_module_get_private(module);
219
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
220
ltdb->idxptr = talloc_zero(module, struct ltdb_idxptr);
225
a wrapper around ltdb_search_dn1() which translates pointer based index records
226
and maps them into normal ldb message structures
228
static int ltdb_search_dn1_index(struct ldb_module *module,
229
struct ldb_dn *dn, struct ldb_message *msg)
232
ret = ltdb_search_dn1(module, dn, msg);
233
if (ret != LDB_SUCCESS) {
237
/* if this isn't a @INDEX record then don't munge it */
238
if (strncmp(ldb_dn_get_linearized(msg->dn), LTDB_INDEX ":", strlen(LTDB_INDEX) + 1) != 0) {
239
return LDB_ERR_OPERATIONS_ERROR;
242
for (i=0;i<msg->num_elements;i++) {
243
struct ldb_message_element *el = &msg->elements[i];
244
if (strcmp(el->name, LTDB_IDXPTR) == 0) {
245
ret = ltdb_convert_from_idxptr(module, el);
246
if (ret != LDB_SUCCESS) {
258
fixup the idxptr for one DN
260
static int ltdb_idxptr_fix_dn(struct ldb_module *module, const char *strdn)
262
struct ldb_context *ldb;
264
struct ldb_message *msg = ldb_msg_new(module);
267
ldb = ldb_module_get_ctx(module);
269
dn = ldb_dn_new(msg, ldb, strdn);
270
if (ltdb_search_dn1_index(module, dn, msg) == LDB_SUCCESS) {
271
ret = ltdb_store(module, msg, TDB_REPLACE);
277
/* cleanup the idxptr mode when transaction commits */
278
int ltdb_index_transaction_commit(struct ldb_module *module)
281
void *data = ldb_module_get_private(module);
282
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
284
/* fix all the DNs that we have modified */
286
for (i=0;i<ltdb->idxptr->num_dns;i++) {
287
ltdb_idxptr_fix_dn(module, ltdb->idxptr->dn_list[i]);
290
if (ltdb->idxptr->repack) {
291
tdb_repack(ltdb->tdb);
295
talloc_free(ltdb->idxptr);
300
/* cleanup the idxptr mode when transaction cancels */
301
int ltdb_index_transaction_cancel(struct ldb_module *module)
303
void *data = ldb_module_get_private(module);
304
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
305
talloc_free(ltdb->idxptr);
312
/* a wrapper around ltdb_store() for the index code which
313
stores in IDXPTR format when idxptr mode is enabled
315
WARNING: This modifies the msg which is passed in
317
int ltdb_store_idxptr(struct ldb_module *module, const struct ldb_message *msg, int flgs)
319
void *data = ldb_module_get_private(module);
320
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
325
struct ldb_message *msg2 = ldb_msg_new(module);
327
/* free any old pointer */
328
ret = ltdb_search_dn1(module, msg->dn, msg2);
330
for (i=0;i<msg2->num_elements;i++) {
331
struct ldb_message_element *el = &msg2->elements[i];
332
if (strcmp(el->name, LTDB_IDXPTR) == 0) {
333
ret = ltdb_free_idxptr(module, el);
334
if (ret != LDB_SUCCESS) {
342
for (i=0;i<msg->num_elements;i++) {
343
struct ldb_message_element *el = &msg->elements[i];
344
if (strcmp(el->name, LTDB_IDX) == 0) {
345
ret = ltdb_convert_to_idxptr(module, el);
346
if (ret != LDB_SUCCESS) {
352
if (ltdb_idxptr_add(module, msg) != 0) {
353
return LDB_ERR_OPERATIONS_ERROR;
357
ret = ltdb_store(module, msg, flgs);
363
find an element in a list, using the given comparison function and
364
assuming that the list is already sorted using comp_fn
366
return -1 if not found, or the index of the first occurance of needle if found
368
static int ldb_list_find(const void *needle,
369
const void *base, size_t nmemb, size_t size,
370
comparison_fn_t comp_fn)
372
const char *base_p = (const char *)base;
373
size_t min_i, max_i, test_i;
382
while (min_i < max_i) {
385
test_i = (min_i + max_i) / 2;
386
/* the following cast looks strange, but is
387
correct. The key to understanding it is that base_p
388
is a pointer to an array of pointers, so we have to
389
dereference it after casting to void **. The strange
390
const in the middle gives us the right type of pointer
391
after the dereference (tridge) */
392
r = comp_fn(needle, *(void * const *)(base_p + (size * test_i)));
394
/* scan back for first element */
396
comp_fn(needle, *(void * const *)(base_p + (size * (test_i-1)))) == 0) {
412
if (comp_fn(needle, *(void * const *)(base_p + (size * min_i))) == 0) {
425
return the dn key to be used for an index
428
static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
429
const char *attr, const struct ldb_val *value)
433
const struct ldb_schema_attribute *a;
437
attr_folded = ldb_attr_casefold(ldb, attr);
442
a = ldb_schema_attribute_by_name(ldb, attr);
443
r = a->syntax->canonicalise_fn(ldb, ldb, value, &v);
444
if (r != LDB_SUCCESS) {
445
const char *errstr = ldb_errstring(ldb);
446
/* canonicalisation can be refused. For example,
447
a attribute that takes wildcards will refuse to canonicalise
448
if the value contains a wildcard */
449
ldb_asprintf_errstring(ldb, "Failed to create index key for attribute '%s':%s%s%s",
450
attr, ldb_strerror(r), (errstr?":":""), (errstr?errstr:""));
451
talloc_free(attr_folded);
454
if (ldb_should_b64_encode(&v)) {
455
char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length);
456
if (!vstr) return NULL;
457
ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr);
460
ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s:%.*s", LTDB_INDEX, attr_folded, (int)v.length, (char *)v.data);
463
if (v.data != value->data) {
466
talloc_free(attr_folded);
472
see if a attribute value is in the list of indexed attributes
474
static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr,
475
unsigned int *v_idx, const char *key)
478
for (i=0;i<msg->num_elements;i++) {
479
if (ldb_attr_cmp(msg->elements[i].name, key) == 0) {
480
const struct ldb_message_element *el = &msg->elements[i];
483
/* in this case we are just looking to see if key is present,
484
we are not spearching for a specific index */
488
for (j=0;j<el->num_values;j++) {
489
if (ldb_attr_cmp((char *)el->values[j].data, attr) == 0) {
501
/* used in sorting dn lists */
502
static int list_cmp(const char **s1, const char **s2)
504
return strcmp(*s1, *s2);
508
return a list of dn's that might match a simple indexed search or
510
static int ltdb_index_dn_simple(struct ldb_module *module,
511
const struct ldb_parse_tree *tree,
512
const struct ldb_message *index_list,
513
struct dn_list *list)
515
struct ldb_context *ldb;
519
struct ldb_message *msg;
521
ldb = ldb_module_get_ctx(module);
526
/* if the attribute isn't in the list of indexed attributes then
527
this node needs a full search */
528
if (ldb_msg_find_idx(index_list, tree->u.equality.attr, NULL, LTDB_IDXATTR) == -1) {
529
return LDB_ERR_OPERATIONS_ERROR;
532
/* the attribute is indexed. Pull the list of DNs that match the
534
dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value);
535
if (!dn) return LDB_ERR_OPERATIONS_ERROR;
537
msg = talloc(list, struct ldb_message);
539
return LDB_ERR_OPERATIONS_ERROR;
542
ret = ltdb_search_dn1_index(module, dn, msg);
544
if (ret != LDB_SUCCESS) {
548
for (i=0;i<msg->num_elements;i++) {
549
struct ldb_message_element *el;
551
if (strcmp(msg->elements[i].name, LTDB_IDX) != 0) {
555
el = &msg->elements[i];
557
list->dn = talloc_array(list, char *, el->num_values);
560
return LDB_ERR_OPERATIONS_ERROR;
563
for (j=0;j<el->num_values;j++) {
564
list->dn[list->count] =
565
talloc_strdup(list->dn, (char *)el->values[j].data);
566
if (!list->dn[list->count]) {
568
return LDB_ERR_OPERATIONS_ERROR;
576
if (list->count > 1) {
577
qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t) list_cmp);
584
static int list_union(struct ldb_context *, struct dn_list *, const struct dn_list *);
587
return a list of dn's that might match a leaf indexed search
589
static int ltdb_index_dn_leaf(struct ldb_module *module,
590
const struct ldb_parse_tree *tree,
591
const struct ldb_message *index_list,
592
struct dn_list *list)
594
struct ldb_context *ldb;
595
ldb = ldb_module_get_ctx(module);
597
if (ldb_attr_dn(tree->u.equality.attr) == 0) {
598
list->dn = talloc_array(list, char *, 1);
599
if (list->dn == NULL) {
601
return LDB_ERR_OPERATIONS_ERROR;
603
list->dn[0] = talloc_strdup(list->dn, (char *)tree->u.equality.value.data);
604
if (list->dn[0] == NULL) {
606
return LDB_ERR_OPERATIONS_ERROR;
611
return ltdb_index_dn_simple(module, tree, index_list, list);
618
relies on the lists being sorted
620
static int list_intersect(struct ldb_context *ldb,
621
struct dn_list *list, const struct dn_list *list2)
623
struct dn_list *list3;
626
if (list->count == 0 || list2->count == 0) {
628
return LDB_ERR_NO_SUCH_OBJECT;
631
list3 = talloc(ldb, struct dn_list);
633
return LDB_ERR_OPERATIONS_ERROR;
636
list3->dn = talloc_array(list3, char *, list->count);
639
return LDB_ERR_OPERATIONS_ERROR;
643
for (i=0;i<list->count;i++) {
644
if (ldb_list_find(list->dn[i], list2->dn, list2->count,
645
sizeof(char *), (comparison_fn_t)strcmp) != -1) {
646
list3->dn[list3->count] = talloc_move(list3->dn, &list->dn[i]);
649
talloc_free(list->dn[i]);
653
talloc_free(list->dn);
654
list->dn = talloc_move(list, &list3->dn);
655
list->count = list3->count;
658
return LDB_ERR_NO_SUCH_OBJECT;
665
relies on the lists being sorted
667
static int list_union(struct ldb_context *ldb,
668
struct dn_list *list, const struct dn_list *list2)
672
unsigned int count = list->count;
674
if (list->count == 0 && list2->count == 0) {
676
return LDB_ERR_NO_SUCH_OBJECT;
679
d = talloc_realloc(list, list->dn, char *, list->count + list2->count);
681
return LDB_ERR_OPERATIONS_ERROR;
685
for (i=0;i<list2->count;i++) {
686
if (ldb_list_find(list2->dn[i], list->dn, count,
687
sizeof(char *), (comparison_fn_t)strcmp) == -1) {
688
list->dn[list->count] = talloc_strdup(list->dn, list2->dn[i]);
689
if (!list->dn[list->count]) {
690
return LDB_ERR_OPERATIONS_ERROR;
696
if (list->count != count) {
697
qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t)list_cmp);
700
return LDB_ERR_NO_SUCH_OBJECT;
703
static int ltdb_index_dn(struct ldb_module *module,
704
const struct ldb_parse_tree *tree,
705
const struct ldb_message *index_list,
706
struct dn_list *list);
712
static int ltdb_index_dn_or(struct ldb_module *module,
713
const struct ldb_parse_tree *tree,
714
const struct ldb_message *index_list,
715
struct dn_list *list)
717
struct ldb_context *ldb;
721
ldb = ldb_module_get_ctx(module);
723
ret = LDB_ERR_OPERATIONS_ERROR;
727
for (i=0;i<tree->u.list.num_elements;i++) {
728
struct dn_list *list2;
731
list2 = talloc(module, struct dn_list);
733
return LDB_ERR_OPERATIONS_ERROR;
736
v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2);
738
if (v == LDB_ERR_NO_SUCH_OBJECT) {
740
if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
747
if (v != LDB_SUCCESS && v != LDB_ERR_NO_SUCH_OBJECT) {
749
talloc_free(list->dn);
754
if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
756
list->dn = talloc_move(list, &list2->dn);
757
list->count = list2->count;
759
if (list_union(ldb, list, list2) == -1) {
761
return LDB_ERR_OPERATIONS_ERROR;
768
if (list->count == 0) {
769
return LDB_ERR_NO_SUCH_OBJECT;
779
static int ltdb_index_dn_not(struct ldb_module *module,
780
const struct ldb_parse_tree *tree,
781
const struct ldb_message *index_list,
782
struct dn_list *list)
784
/* the only way to do an indexed not would be if we could
785
negate the not via another not or if we knew the total
786
number of database elements so we could know that the
787
existing expression covered the whole database.
789
instead, we just give up, and rely on a full index scan
790
(unless an outer & manages to reduce the list)
792
return LDB_ERR_OPERATIONS_ERROR;
796
AND two index results
798
static int ltdb_index_dn_and(struct ldb_module *module,
799
const struct ldb_parse_tree *tree,
800
const struct ldb_message *index_list,
801
struct dn_list *list)
803
struct ldb_context *ldb;
807
ldb = ldb_module_get_ctx(module);
809
ret = LDB_ERR_OPERATIONS_ERROR;
813
for (i=0;i<tree->u.list.num_elements;i++) {
814
struct dn_list *list2;
817
list2 = talloc(module, struct dn_list);
819
return LDB_ERR_OPERATIONS_ERROR;
822
v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2);
824
if (v == LDB_ERR_NO_SUCH_OBJECT) {
826
talloc_free(list->dn);
828
return LDB_ERR_NO_SUCH_OBJECT;
831
if (v != LDB_SUCCESS && v != LDB_ERR_NO_SUCH_OBJECT) {
836
if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
838
talloc_free(list->dn);
839
list->dn = talloc_move(list, &list2->dn);
840
list->count = list2->count;
842
if (list_intersect(ldb, list, list2) == -1) {
844
return LDB_ERR_OPERATIONS_ERROR;
850
if (list->count == 0) {
851
talloc_free(list->dn);
852
return LDB_ERR_NO_SUCH_OBJECT;
860
AND index results and ONE level special index
862
static int ltdb_index_dn_one(struct ldb_module *module,
863
struct ldb_dn *parent_dn,
864
struct dn_list *list)
866
struct ldb_context *ldb;
867
struct dn_list *list2;
868
struct ldb_message *msg;
874
ldb = ldb_module_get_ctx(module);
876
list2 = talloc_zero(module, struct dn_list);
878
return LDB_ERR_OPERATIONS_ERROR;
881
/* the attribute is indexed. Pull the list of DNs that match the
883
val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn));
884
val.length = strlen((char *)val.data);
885
key = ltdb_index_key(ldb, LTDB_IDXONE, &val);
888
return LDB_ERR_OPERATIONS_ERROR;
891
msg = talloc(list2, struct ldb_message);
894
return LDB_ERR_OPERATIONS_ERROR;
897
ret = ltdb_search_dn1_index(module, key, msg);
899
if (ret != LDB_SUCCESS) {
903
for (i = 0; i < msg->num_elements; i++) {
904
struct ldb_message_element *el;
906
if (strcmp(msg->elements[i].name, LTDB_IDX) != 0) {
910
el = &msg->elements[i];
912
list2->dn = talloc_array(list2, char *, el->num_values);
915
return LDB_ERR_OPERATIONS_ERROR;
918
for (j = 0; j < el->num_values; j++) {
919
list2->dn[list2->count] = talloc_strdup(list2->dn, (char *)el->values[j].data);
920
if (!list2->dn[list2->count]) {
922
return LDB_ERR_OPERATIONS_ERROR;
928
if (list2->count == 0) {
930
return LDB_ERR_NO_SUCH_OBJECT;
933
if (list2->count > 1) {
934
qsort(list2->dn, list2->count, sizeof(char *), (comparison_fn_t) list_cmp);
937
if (list->count > 0) {
938
if (list_intersect(ldb, list, list2) == -1) {
940
return LDB_ERR_OPERATIONS_ERROR;
943
if (list->count == 0) {
944
talloc_free(list->dn);
946
return LDB_ERR_NO_SUCH_OBJECT;
949
list->dn = talloc_move(list, &list2->dn);
950
list->count = list2->count;
959
return a list of dn's that might match a indexed search or
960
an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
962
static int ltdb_index_dn(struct ldb_module *module,
963
const struct ldb_parse_tree *tree,
964
const struct ldb_message *index_list,
965
struct dn_list *list)
967
int ret = LDB_ERR_OPERATIONS_ERROR;
969
switch (tree->operation) {
971
ret = ltdb_index_dn_and(module, tree, index_list, list);
975
ret = ltdb_index_dn_or(module, tree, index_list, list);
979
ret = ltdb_index_dn_not(module, tree, index_list, list);
982
case LDB_OP_EQUALITY:
983
ret = ltdb_index_dn_leaf(module, tree, index_list, list);
986
case LDB_OP_SUBSTRING:
991
case LDB_OP_EXTENDED:
992
/* we can't index with fancy bitops yet */
993
ret = LDB_ERR_OPERATIONS_ERROR;
1001
filter a candidate dn_list from an indexed search into a set of results
1002
extracting just the given attributes
1004
static int ltdb_index_filter(const struct dn_list *dn_list,
1005
struct ltdb_context *ac)
1007
struct ldb_context *ldb;
1008
struct ldb_message *msg;
1011
ldb = ldb_module_get_ctx(ac->module);
1013
for (i = 0; i < dn_list->count; i++) {
1017
msg = ldb_msg_new(ac);
1019
return LDB_ERR_OPERATIONS_ERROR;
1022
dn = ldb_dn_new(msg, ldb, dn_list->dn[i]);
1025
return LDB_ERR_OPERATIONS_ERROR;
1028
ret = ltdb_search_dn1(ac->module, dn, msg);
1030
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1031
/* the record has disappeared? yes, this can happen */
1036
if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1037
/* an internal error */
1039
return LDB_ERR_OPERATIONS_ERROR;
1042
if (!ldb_match_msg(ldb, msg,
1043
ac->tree, ac->base, ac->scope)) {
1048
/* filter the attributes that the user wants */
1049
ret = ltdb_filter_attrs(msg, ac->attrs);
1053
return LDB_ERR_OPERATIONS_ERROR;
1056
ret = ldb_module_send_entry(ac->req, msg, NULL);
1057
if (ret != LDB_SUCCESS) {
1058
ac->request_terminated = true;
1067
search the database with a LDAP-like expression using indexes
1068
returns -1 if an indexed search is not possible, in which
1069
case the caller should call ltdb_search_full()
1071
int ltdb_search_indexed(struct ltdb_context *ac)
1073
struct ldb_context *ldb;
1074
void *data = ldb_module_get_private(ac->module);
1075
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1076
struct dn_list *dn_list;
1077
int ret, idxattr, idxone;
1079
ldb = ldb_module_get_ctx(ac->module);
1081
idxattr = idxone = 0;
1082
ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXATTR);
1087
/* We do one level indexing only if requested */
1088
ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXONE);
1093
if ((ac->scope == LDB_SCOPE_ONELEVEL && (idxattr+idxone == 0)) ||
1094
(ac->scope == LDB_SCOPE_SUBTREE && idxattr == 0)) {
1095
/* no indexes? must do full search */
1096
return LDB_ERR_OPERATIONS_ERROR;
1099
ret = LDB_ERR_OPERATIONS_ERROR;
1101
dn_list = talloc_zero(ac, struct dn_list);
1102
if (dn_list == NULL) {
1103
return LDB_ERR_OPERATIONS_ERROR;
1106
if (ac->scope == LDB_SCOPE_BASE) {
1107
/* with BASE searches only one DN can match */
1108
dn_list->dn = talloc_array(dn_list, char *, 1);
1109
if (dn_list->dn == NULL) {
1111
return LDB_ERR_OPERATIONS_ERROR;
1113
dn_list->dn[0] = ldb_dn_alloc_linearized(dn_list, ac->base);
1114
if (dn_list->dn[0] == NULL) {
1116
return LDB_ERR_OPERATIONS_ERROR;
1122
if (ac->scope != LDB_SCOPE_BASE && idxattr == 1) {
1123
ret = ltdb_index_dn(ac->module, ac->tree, ltdb->cache->indexlist, dn_list);
1125
if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1126
talloc_free(dn_list);
1131
if (ac->scope == LDB_SCOPE_ONELEVEL && idxone == 1) {
1132
ret = ltdb_index_dn_one(ac->module, ac->base, dn_list);
1135
if (ret == LDB_SUCCESS) {
1136
/* we've got a candidate list - now filter by the full tree
1137
and extract the needed attributes */
1138
ret = ltdb_index_filter(dn_list, ac);
1141
talloc_free(dn_list);
1147
add a index element where this is the first indexed DN for this value
1149
static int ltdb_index_add1_new(struct ldb_context *ldb,
1150
struct ldb_message *msg,
1153
struct ldb_message_element *el;
1155
/* add another entry */
1156
el = talloc_realloc(msg, msg->elements,
1157
struct ldb_message_element, msg->num_elements+1);
1159
return LDB_ERR_OPERATIONS_ERROR;
1163
msg->elements[msg->num_elements].name = talloc_strdup(msg->elements, LTDB_IDX);
1164
if (!msg->elements[msg->num_elements].name) {
1165
return LDB_ERR_OPERATIONS_ERROR;
1167
msg->elements[msg->num_elements].num_values = 0;
1168
msg->elements[msg->num_elements].values = talloc(msg->elements, struct ldb_val);
1169
if (!msg->elements[msg->num_elements].values) {
1170
return LDB_ERR_OPERATIONS_ERROR;
1172
msg->elements[msg->num_elements].values[0].length = strlen(dn);
1173
msg->elements[msg->num_elements].values[0].data = discard_const_p(uint8_t, dn);
1174
msg->elements[msg->num_elements].num_values = 1;
1175
msg->num_elements++;
1182
add a index element where this is not the first indexed DN for this
1185
static int ltdb_index_add1_add(struct ldb_context *ldb,
1186
struct ldb_message *msg,
1193
/* for multi-valued attributes we can end up with repeats */
1194
for (i=0;i<msg->elements[idx].num_values;i++) {
1195
if (strcmp(dn, (char *)msg->elements[idx].values[i].data) == 0) {
1200
v2 = talloc_realloc(msg->elements, msg->elements[idx].values,
1202
msg->elements[idx].num_values+1);
1204
return LDB_ERR_OPERATIONS_ERROR;
1206
msg->elements[idx].values = v2;
1208
msg->elements[idx].values[msg->elements[idx].num_values].length = strlen(dn);
1209
msg->elements[idx].values[msg->elements[idx].num_values].data = discard_const_p(uint8_t, dn);
1210
msg->elements[idx].num_values++;
1216
add an index entry for one message element
1218
static int ltdb_index_add1(struct ldb_module *module, const char *dn,
1219
struct ldb_message_element *el, int v_idx)
1221
struct ldb_context *ldb;
1222
struct ldb_message *msg;
1223
struct ldb_dn *dn_key;
1227
ldb = ldb_module_get_ctx(module);
1229
msg = talloc(module, struct ldb_message);
1232
return LDB_ERR_OPERATIONS_ERROR;
1235
dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx]);
1238
return LDB_ERR_OPERATIONS_ERROR;
1240
talloc_steal(msg, dn_key);
1242
ret = ltdb_search_dn1_index(module, dn_key, msg);
1243
if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1248
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1250
msg->num_elements = 0;
1251
msg->elements = NULL;
1254
for (i=0;i<msg->num_elements;i++) {
1255
if (strcmp(LTDB_IDX, msg->elements[i].name) == 0) {
1260
if (i == msg->num_elements) {
1261
ret = ltdb_index_add1_new(ldb, msg, dn);
1263
ret = ltdb_index_add1_add(ldb, msg, i, dn);
1266
if (ret == LDB_SUCCESS) {
1267
ret = ltdb_store_idxptr(module, msg, TDB_REPLACE);
1275
static int ltdb_index_add0(struct ldb_module *module, const char *dn,
1276
struct ldb_message_element *elements, int num_el)
1278
void *data = ldb_module_get_private(module);
1279
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1287
if (ltdb->cache->indexlist->num_elements == 0) {
1288
/* no indexed fields */
1292
for (i = 0; i < num_el; i++) {
1293
ret = ldb_msg_find_idx(ltdb->cache->indexlist, elements[i].name,
1294
NULL, LTDB_IDXATTR);
1298
for (j = 0; j < elements[i].num_values; j++) {
1299
ret = ltdb_index_add1(module, dn, &elements[i], j);
1300
if (ret != LDB_SUCCESS) {
1310
add the index entries for a new record
1312
int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg)
1317
dn = ldb_dn_get_linearized(msg->dn);
1319
return LDB_ERR_OPERATIONS_ERROR;
1322
ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements);
1329
delete an index entry for one message element
1331
int ltdb_index_del_value(struct ldb_module *module, const char *dn,
1332
struct ldb_message_element *el, int v_idx)
1334
struct ldb_context *ldb;
1335
struct ldb_message *msg;
1336
struct ldb_dn *dn_key;
1340
ldb = ldb_module_get_ctx(module);
1346
dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx]);
1348
return LDB_ERR_OPERATIONS_ERROR;
1351
msg = talloc(dn_key, struct ldb_message);
1353
talloc_free(dn_key);
1354
return LDB_ERR_OPERATIONS_ERROR;
1357
ret = ltdb_search_dn1_index(module, dn_key, msg);
1358
if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1359
talloc_free(dn_key);
1363
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1364
/* it wasn't indexed. Did we have an earlier error? If we did then
1366
talloc_free(dn_key);
1370
i = ldb_msg_find_idx(msg, dn, &j, LTDB_IDX);
1372
struct ldb_ldif ldif;
1374
ldb_debug(ldb, LDB_DEBUG_ERROR,
1375
"ERROR: dn %s not found in %s\n", dn,
1376
ldb_dn_get_linearized(dn_key));
1377
ldif.changetype = LDB_CHANGETYPE_NONE;
1379
ldb_ldif_write_file(ldb, stdout, &ldif);
1381
/* it ain't there. hmmm */
1382
talloc_free(dn_key);
1386
if (j != msg->elements[i].num_values - 1) {
1387
memmove(&msg->elements[i].values[j],
1388
&msg->elements[i].values[j+1],
1389
(msg->elements[i].num_values-(j+1)) *
1390
sizeof(msg->elements[i].values[0]));
1392
msg->elements[i].num_values--;
1394
if (msg->elements[i].num_values == 0) {
1395
ret = ltdb_delete_noindex(module, dn_key);
1397
ret = ltdb_store_idxptr(module, msg, TDB_REPLACE);
1400
talloc_free(dn_key);
1406
delete the index entries for a record
1407
return -1 on failure
1409
int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg)
1411
void *data = ldb_module_get_private(module);
1412
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1417
/* find the list of indexed fields */
1418
if (ltdb->cache->indexlist->num_elements == 0) {
1419
/* no indexed fields */
1423
if (ldb_dn_is_special(msg->dn)) {
1427
dn = ldb_dn_get_linearized(msg->dn);
1429
return LDB_ERR_OPERATIONS_ERROR;
1432
for (i = 0; i < msg->num_elements; i++) {
1433
ret = ldb_msg_find_idx(ltdb->cache->indexlist, msg->elements[i].name,
1434
NULL, LTDB_IDXATTR);
1438
for (j = 0; j < msg->elements[i].num_values; j++) {
1439
ret = ltdb_index_del_value(module, dn, &msg->elements[i], j);
1440
if (ret != LDB_SUCCESS) {
1450
handle special index for one level searches
1452
int ltdb_index_one(struct ldb_module *module, const struct ldb_message *msg, int add)
1454
void *data = ldb_module_get_private(module);
1455
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1456
struct ldb_message_element el;
1462
/* We index for ONE Level only if requested */
1463
ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXONE);
1468
pdn = ldb_dn_get_parent(module, msg->dn);
1470
return LDB_ERR_OPERATIONS_ERROR;
1473
dn = ldb_dn_get_linearized(msg->dn);
1476
return LDB_ERR_OPERATIONS_ERROR;
1479
val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn));
1480
if (val.data == NULL) {
1482
return LDB_ERR_OPERATIONS_ERROR;
1485
val.length = strlen((char *)val.data);
1486
el.name = LTDB_IDXONE;
1491
ret = ltdb_index_add1(module, dn, &el, 0);
1492
} else { /* delete */
1493
ret = ltdb_index_del_value(module, dn, &el, 0);
1503
traversal function that deletes all @INDEX records
1505
static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1507
const char *dn = "DN=" LTDB_INDEX ":";
1508
if (strncmp((char *)key.dptr, dn, strlen(dn)) == 0) {
1509
return tdb_delete(tdb, key);
1515
traversal function that adds @INDEX records during a re index
1517
static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1519
struct ldb_context *ldb;
1520
struct ldb_module *module = (struct ldb_module *)state;
1521
struct ldb_message *msg;
1522
const char *dn = NULL;
1526
ldb = ldb_module_get_ctx(module);
1528
if (strncmp((char *)key.dptr, "DN=@", 4) == 0 ||
1529
strncmp((char *)key.dptr, "DN=", 3) != 0) {
1533
msg = talloc(module, struct ldb_message);
1538
ret = ltdb_unpack_data(module, &data, msg);
1544
/* check if the DN key has changed, perhaps due to the
1545
case insensitivity of an element changing */
1546
key2 = ltdb_key(module, msg->dn);
1547
if (key2.dptr == NULL) {
1548
/* probably a corrupt record ... darn */
1549
ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s\n",
1550
ldb_dn_get_linearized(msg->dn));
1554
if (strcmp((char *)key2.dptr, (char *)key.dptr) != 0) {
1555
tdb_delete(tdb, key);
1556
tdb_store(tdb, key2, data, 0);
1558
talloc_free(key2.dptr);
1560
if (msg->dn == NULL) {
1561
dn = (char *)key.dptr + 3;
1563
dn = ldb_dn_get_linearized(msg->dn);
1566
ret = ltdb_index_one(module, msg, 1);
1567
if (ret == LDB_SUCCESS) {
1568
ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements);
1570
ldb_debug(ldb, LDB_DEBUG_ERROR,
1571
"Adding special ONE LEVEL index failed (%s)!\n",
1572
ldb_dn_get_linearized(msg->dn));
1577
if (ret != LDB_SUCCESS) return -1;
1583
force a complete reindex of the database
1585
int ltdb_reindex(struct ldb_module *module)
1587
void *data = ldb_module_get_private(module);
1588
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1591
if (ltdb_cache_reload(module) != 0) {
1592
return LDB_ERR_OPERATIONS_ERROR;
1595
/* first traverse the database deleting any @INDEX records */
1596
ret = tdb_traverse(ltdb->tdb, delete_index, NULL);
1598
return LDB_ERR_OPERATIONS_ERROR;
1601
/* if we don't have indexes we have nothing todo */
1602
if (ltdb->cache->indexlist->num_elements == 0) {
1606
/* now traverse adding any indexes for normal LDB records */
1607
ret = tdb_traverse(ltdb->tdb, re_index, module);
1609
return LDB_ERR_OPERATIONS_ERROR;
1613
ltdb->idxptr->repack = true;