4 Copyright (C) Andrew Tridgell 2004-2009
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 "ldb_private.h"
43 struct tdb_context
*itdb
;
47 /* we put a @IDXVERSION attribute on index entries. This
48 allows us to tell if it was written by an older version
50 #define LTDB_INDEXING_VERSION 2
52 /* enable the idxptr mode when transactions start */
53 int ltdb_index_transaction_start(struct ldb_module
*module
)
55 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
56 ltdb
->idxptr
= talloc_zero(ltdb
, struct ltdb_idxptr
);
57 if (ltdb
->idxptr
== NULL
) {
58 return ldb_oom(ldb_module_get_ctx(module
));
64 /* compare two DN entries in a dn_list. Take account of possible
65 * differences in string termination */
66 static int dn_list_cmp(const struct ldb_val
*v1
, const struct ldb_val
*v2
)
68 if (v1
->length
> v2
->length
&& v1
->data
[v2
->length
] != 0) {
71 if (v1
->length
< v2
->length
&& v2
->data
[v1
->length
] != 0) {
74 return strncmp((char *)v1
->data
, (char *)v2
->data
, v1
->length
);
79 find a entry in a dn_list, using a ldb_val. Uses a case sensitive
80 comparison with the dn returns -1 if not found
82 static int ltdb_dn_list_find_val(struct ltdb_private
*ltdb
,
83 const struct dn_list
*list
,
84 const struct ldb_val
*v
)
87 for (i
=0; i
<list
->count
; i
++) {
88 if (dn_list_cmp(&list
->dn
[i
], v
) == 0) {
96 find a entry in a dn_list. Uses a case sensitive comparison with the dn
97 returns -1 if not found
99 static int ltdb_dn_list_find_str(struct ltdb_private
*ltdb
,
100 struct dn_list
*list
,
104 v
.data
= discard_const_p(unsigned char, dn
);
105 v
.length
= strlen(dn
);
106 return ltdb_dn_list_find_val(ltdb
, list
, &v
);
110 this is effectively a cast function, but with lots of paranoia
111 checks and also copes with CPUs that are fussy about pointer
114 static struct dn_list
*ltdb_index_idxptr(struct ldb_module
*module
, TDB_DATA rec
, bool check_parent
)
116 struct dn_list
*list
;
117 if (rec
.dsize
!= sizeof(void *)) {
118 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
119 "Bad data size for idxptr %u", (unsigned)rec
.dsize
);
122 /* note that we can't just use a cast here, as rec.dptr may
123 not be aligned sufficiently for a pointer. A cast would cause
124 platforms like some ARM CPUs to crash */
125 memcpy(&list
, rec
.dptr
, sizeof(void *));
126 list
= talloc_get_type(list
, struct dn_list
);
128 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
129 "Bad type '%s' for idxptr",
130 talloc_get_name(list
));
133 if (check_parent
&& list
->dn
&& talloc_parent(list
->dn
) != list
) {
134 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
135 "Bad parent '%s' for idxptr",
136 talloc_get_name(talloc_parent(list
->dn
)));
143 return the @IDX list in an index entry for a dn as a
146 static int ltdb_dn_list_load(struct ldb_module
*module
,
147 struct ldb_dn
*dn
, struct dn_list
*list
)
149 struct ldb_message
*msg
;
151 struct ldb_message_element
*el
;
152 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
154 struct dn_list
*list2
;
160 /* see if we have any in-memory index entries */
161 if (ltdb
->idxptr
== NULL
||
162 ltdb
->idxptr
->itdb
== NULL
) {
166 key
.dptr
= discard_const_p(unsigned char, ldb_dn_get_linearized(dn
));
167 key
.dsize
= strlen((char *)key
.dptr
);
169 rec
= tdb_fetch(ltdb
->idxptr
->itdb
, key
);
170 if (rec
.dptr
== NULL
) {
174 /* we've found an in-memory index entry */
175 list2
= ltdb_index_idxptr(module
, rec
, true);
178 return LDB_ERR_OPERATIONS_ERROR
;
186 msg
= ldb_msg_new(list
);
188 return LDB_ERR_OPERATIONS_ERROR
;
191 ret
= ltdb_search_dn1(module
, dn
, msg
,
192 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
193 |LDB_UNPACK_DATA_FLAG_NO_DN
);
194 if (ret
!= LDB_SUCCESS
) {
199 /* TODO: check indexing version number */
201 el
= ldb_msg_find_element(msg
, LTDB_IDX
);
208 * we avoid copying the strings by stealing the list. We have
209 * to steal msg onto el->values (which looks odd) because we
210 * asked for the memory to be allocated on msg, not on each
211 * value with LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC above
213 talloc_steal(el
->values
, msg
);
214 list
->dn
= talloc_steal(list
, el
->values
);
215 list
->count
= el
->num_values
;
217 /* We don't need msg->elements any more */
218 talloc_free(msg
->elements
);
224 save a dn_list into a full @IDX style record
226 static int ltdb_dn_list_store_full(struct ldb_module
*module
,
227 struct ltdb_private
*ltdb
,
229 struct dn_list
*list
)
231 struct ldb_message
*msg
;
234 if (list
->count
== 0) {
235 ret
= ltdb_delete_noindex(module
, dn
);
236 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
242 msg
= ldb_msg_new(module
);
244 return ldb_module_oom(module
);
247 ret
= ldb_msg_add_fmt(msg
, LTDB_IDXVERSION
, "%u", LTDB_INDEXING_VERSION
);
248 if (ret
!= LDB_SUCCESS
) {
250 return ldb_module_oom(module
);
254 if (list
->count
> 0) {
255 struct ldb_message_element
*el
;
257 ret
= ldb_msg_add_empty(msg
, LTDB_IDX
, LDB_FLAG_MOD_ADD
, &el
);
258 if (ret
!= LDB_SUCCESS
) {
260 return ldb_module_oom(module
);
262 el
->values
= list
->dn
;
263 el
->num_values
= list
->count
;
266 ret
= ltdb_store(module
, msg
, TDB_REPLACE
);
272 save a dn_list into the database, in either @IDX or internal format
274 static int ltdb_dn_list_store(struct ldb_module
*module
, struct ldb_dn
*dn
,
275 struct dn_list
*list
)
277 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
280 struct dn_list
*list2
;
282 if (ltdb
->idxptr
== NULL
) {
283 return ltdb_dn_list_store_full(module
, ltdb
,
287 if (ltdb
->idxptr
->itdb
== NULL
) {
288 ltdb
->idxptr
->itdb
= tdb_open(NULL
, 1000, TDB_INTERNAL
, O_RDWR
, 0);
289 if (ltdb
->idxptr
->itdb
== NULL
) {
290 return LDB_ERR_OPERATIONS_ERROR
;
294 key
.dptr
= discard_const_p(unsigned char, ldb_dn_get_linearized(dn
));
295 key
.dsize
= strlen((char *)key
.dptr
);
297 rec
= tdb_fetch(ltdb
->idxptr
->itdb
, key
);
298 if (rec
.dptr
!= NULL
) {
299 list2
= ltdb_index_idxptr(module
, rec
, false);
302 return LDB_ERR_OPERATIONS_ERROR
;
305 list2
->dn
= talloc_steal(list2
, list
->dn
);
306 list2
->count
= list
->count
;
310 list2
= talloc(ltdb
->idxptr
, struct dn_list
);
312 return LDB_ERR_OPERATIONS_ERROR
;
314 list2
->dn
= talloc_steal(list2
, list
->dn
);
315 list2
->count
= list
->count
;
317 rec
.dptr
= (uint8_t *)&list2
;
318 rec
.dsize
= sizeof(void *);
322 * This is not a store into the main DB, but into an in-memory
323 * TDB, so we don't need a guard on ltdb->read_only
325 ret
= tdb_store(ltdb
->idxptr
->itdb
, key
, rec
, TDB_INSERT
);
327 return ltdb_err_map(tdb_error(ltdb
->idxptr
->itdb
));
333 traverse function for storing the in-memory index entries on disk
335 static int ltdb_index_traverse_store(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
337 struct ldb_module
*module
= state
;
338 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
340 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
342 struct dn_list
*list
;
344 list
= ltdb_index_idxptr(module
, data
, true);
346 ltdb
->idxptr
->error
= LDB_ERR_OPERATIONS_ERROR
;
351 v
.length
= strnlen((char *)key
.dptr
, key
.dsize
);
353 dn
= ldb_dn_from_ldb_val(module
, ldb
, &v
);
355 ldb_asprintf_errstring(ldb
, "Failed to parse index key %*.*s as an LDB DN", (int)v
.length
, (int)v
.length
, (const char *)v
.data
);
356 ltdb
->idxptr
->error
= LDB_ERR_OPERATIONS_ERROR
;
360 ltdb
->idxptr
->error
= ltdb_dn_list_store_full(module
, ltdb
,
363 if (ltdb
->idxptr
->error
!= 0) {
369 /* cleanup the idxptr mode when transaction commits */
370 int ltdb_index_transaction_commit(struct ldb_module
*module
)
372 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
375 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
377 ldb_reset_err_string(ldb
);
379 if (ltdb
->idxptr
->itdb
) {
380 tdb_traverse(ltdb
->idxptr
->itdb
, ltdb_index_traverse_store
, module
);
381 tdb_close(ltdb
->idxptr
->itdb
);
384 ret
= ltdb
->idxptr
->error
;
385 if (ret
!= LDB_SUCCESS
) {
386 if (!ldb_errstring(ldb
)) {
387 ldb_set_errstring(ldb
, ldb_strerror(ret
));
389 ldb_asprintf_errstring(ldb
, "Failed to store index records in transaction commit: %s", ldb_errstring(ldb
));
392 talloc_free(ltdb
->idxptr
);
397 /* cleanup the idxptr mode when transaction cancels */
398 int ltdb_index_transaction_cancel(struct ldb_module
*module
)
400 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
401 if (ltdb
->idxptr
&& ltdb
->idxptr
->itdb
) {
402 tdb_close(ltdb
->idxptr
->itdb
);
404 talloc_free(ltdb
->idxptr
);
411 return the dn key to be used for an index
412 the caller is responsible for freeing
414 static struct ldb_dn
*ltdb_index_key(struct ldb_context
*ldb
,
415 const char *attr
, const struct ldb_val
*value
,
416 const struct ldb_schema_attribute
**ap
)
420 const struct ldb_schema_attribute
*a
;
424 attr_folded
= ldb_attr_casefold(ldb
, attr
);
429 a
= ldb_schema_attribute_by_name(ldb
, attr
);
433 r
= a
->syntax
->canonicalise_fn(ldb
, ldb
, value
, &v
);
434 if (r
!= LDB_SUCCESS
) {
435 const char *errstr
= ldb_errstring(ldb
);
436 /* canonicalisation can be refused. For example,
437 a attribute that takes wildcards will refuse to canonicalise
438 if the value contains a wildcard */
439 ldb_asprintf_errstring(ldb
, "Failed to create index key for attribute '%s':%s%s%s",
440 attr
, ldb_strerror(r
), (errstr
?":":""), (errstr
?errstr
:""));
441 talloc_free(attr_folded
);
444 if (ldb_should_b64_encode(ldb
, &v
)) {
445 char *vstr
= ldb_base64_encode(ldb
, (char *)v
.data
, v
.length
);
447 talloc_free(attr_folded
);
450 ret
= ldb_dn_new_fmt(ldb
, ldb
, "%s:%s::%s", LTDB_INDEX
, attr_folded
, vstr
);
453 ret
= ldb_dn_new_fmt(ldb
, ldb
, "%s:%s:%.*s", LTDB_INDEX
, attr_folded
, (int)v
.length
, (char *)v
.data
);
456 if (v
.data
!= value
->data
) {
459 talloc_free(attr_folded
);
465 see if a attribute value is in the list of indexed attributes
467 static bool ltdb_is_indexed(struct ldb_module
*module
,
468 struct ltdb_private
*ltdb
,
471 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
473 struct ldb_message_element
*el
;
475 if (ldb
->schema
.index_handler_override
) {
476 const struct ldb_schema_attribute
*a
477 = ldb_schema_attribute_by_name(ldb
, attr
);
483 if (a
->flags
& LDB_ATTR_FLAG_INDEXED
) {
490 if (!ltdb
->cache
->attribute_indexes
) {
494 el
= ldb_msg_find_element(ltdb
->cache
->indexlist
, LTDB_IDXATTR
);
499 /* TODO: this is too expensive! At least use a binary search */
500 for (i
=0; i
<el
->num_values
; i
++) {
501 if (ldb_attr_cmp((char *)el
->values
[i
].data
, attr
) == 0) {
509 in the following logic functions, the return value is treated as
512 LDB_SUCCESS: we found some matching index values
514 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
516 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
517 we'll need a full search
521 return a list of dn's that might match a simple indexed search (an
522 equality search only)
524 static int ltdb_index_dn_simple(struct ldb_module
*module
,
525 struct ltdb_private
*ltdb
,
526 const struct ldb_parse_tree
*tree
,
527 struct dn_list
*list
)
529 struct ldb_context
*ldb
;
533 ldb
= ldb_module_get_ctx(module
);
538 /* if the attribute isn't in the list of indexed attributes then
539 this node needs a full search */
540 if (!ltdb_is_indexed(module
, ltdb
, tree
->u
.equality
.attr
)) {
541 return LDB_ERR_OPERATIONS_ERROR
;
544 /* the attribute is indexed. Pull the list of DNs that match the
546 dn
= ltdb_index_key(ldb
, tree
->u
.equality
.attr
, &tree
->u
.equality
.value
, NULL
);
547 if (!dn
) return LDB_ERR_OPERATIONS_ERROR
;
549 ret
= ltdb_dn_list_load(module
, dn
, list
);
555 static bool list_union(struct ldb_context
*, struct dn_list
*, const struct dn_list
*);
558 return a list of dn's that might match a leaf indexed search
560 static int ltdb_index_dn_leaf(struct ldb_module
*module
,
561 struct ltdb_private
*ltdb
,
562 const struct ldb_parse_tree
*tree
,
563 struct dn_list
*list
)
565 if (ltdb
->disallow_dn_filter
&&
566 (ldb_attr_cmp(tree
->u
.equality
.attr
, "dn") == 0)) {
567 /* in AD mode we do not support "(dn=...)" search filters */
572 if (ldb_attr_dn(tree
->u
.equality
.attr
) == 0) {
573 list
->dn
= talloc_array(list
, struct ldb_val
, 1);
574 if (list
->dn
== NULL
) {
575 ldb_module_oom(module
);
576 return LDB_ERR_OPERATIONS_ERROR
;
578 list
->dn
[0] = tree
->u
.equality
.value
;
582 return ltdb_index_dn_simple(module
, ltdb
, tree
, list
);
590 static bool list_intersect(struct ldb_context
*ldb
,
591 struct ltdb_private
*ltdb
,
592 struct dn_list
*list
, const struct dn_list
*list2
)
594 struct dn_list
*list3
;
597 if (list
->count
== 0) {
601 if (list2
->count
== 0) {
608 /* the indexing code is allowed to return a longer list than
609 what really matches, as all results are filtered by the
610 full expression at the end - this shortcut avoids a lot of
611 work in some cases */
612 if (list
->count
< 2 && list2
->count
> 10) {
615 if (list2
->count
< 2 && list
->count
> 10) {
616 list
->count
= list2
->count
;
617 list
->dn
= list2
->dn
;
618 /* note that list2 may not be the parent of list2->dn,
619 as list2->dn may be owned by ltdb->idxptr. In that
620 case we expect this reparent call to fail, which is
622 talloc_reparent(list2
, list
, list2
->dn
);
626 list3
= talloc_zero(list
, struct dn_list
);
631 list3
->dn
= talloc_array(list3
, struct ldb_val
, list
->count
);
638 for (i
=0;i
<list
->count
;i
++) {
639 if (ltdb_dn_list_find_val(ltdb
, list2
,
640 &list
->dn
[i
]) != -1) {
641 list3
->dn
[list3
->count
] = list
->dn
[i
];
646 list
->dn
= talloc_steal(list
, list3
->dn
);
647 list
->count
= list3
->count
;
658 static bool list_union(struct ldb_context
*ldb
,
659 struct dn_list
*list
, const struct dn_list
*list2
)
663 if (list2
->count
== 0) {
668 if (list
->count
== 0) {
670 list
->count
= list2
->count
;
671 list
->dn
= list2
->dn
;
672 /* note that list2 may not be the parent of list2->dn,
673 as list2->dn may be owned by ltdb->idxptr. In that
674 case we expect this reparent call to fail, which is
676 talloc_reparent(list2
, list
, list2
->dn
);
680 dn3
= talloc_array(list
, struct ldb_val
, list
->count
+ list2
->count
);
686 /* we allow for duplicates here, and get rid of them later */
687 memcpy(dn3
, list
->dn
, sizeof(list
->dn
[0])*list
->count
);
688 memcpy(dn3
+list
->count
, list2
->dn
, sizeof(list2
->dn
[0])*list2
->count
);
691 list
->count
+= list2
->count
;
696 static int ltdb_index_dn(struct ldb_module
*module
,
697 struct ltdb_private
*ltdb
,
698 const struct ldb_parse_tree
*tree
,
699 struct dn_list
*list
);
703 process an OR list (a union)
705 static int ltdb_index_dn_or(struct ldb_module
*module
,
706 struct ltdb_private
*ltdb
,
707 const struct ldb_parse_tree
*tree
,
708 struct dn_list
*list
)
710 struct ldb_context
*ldb
;
713 ldb
= ldb_module_get_ctx(module
);
718 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
719 struct dn_list
*list2
;
722 list2
= talloc_zero(list
, struct dn_list
);
724 return LDB_ERR_OPERATIONS_ERROR
;
727 ret
= ltdb_index_dn(module
, ltdb
,
728 tree
->u
.list
.elements
[i
], list2
);
730 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
736 if (ret
!= LDB_SUCCESS
) {
742 if (!list_union(ldb
, list
, list2
)) {
744 return LDB_ERR_OPERATIONS_ERROR
;
748 if (list
->count
== 0) {
749 return LDB_ERR_NO_SUCH_OBJECT
;
759 static int ltdb_index_dn_not(struct ldb_module
*module
,
760 struct ltdb_private
*ltdb
,
761 const struct ldb_parse_tree
*tree
,
762 struct dn_list
*list
)
764 /* the only way to do an indexed not would be if we could
765 negate the not via another not or if we knew the total
766 number of database elements so we could know that the
767 existing expression covered the whole database.
769 instead, we just give up, and rely on a full index scan
770 (unless an outer & manages to reduce the list)
772 return LDB_ERR_OPERATIONS_ERROR
;
776 static bool ltdb_index_unique(struct ldb_context
*ldb
,
779 const struct ldb_schema_attribute
*a
;
780 a
= ldb_schema_attribute_by_name(ldb
, attr
);
781 if (a
->flags
& LDB_ATTR_FLAG_UNIQUE_INDEX
) {
788 process an AND expression (intersection)
790 static int ltdb_index_dn_and(struct ldb_module
*module
,
791 struct ltdb_private
*ltdb
,
792 const struct ldb_parse_tree
*tree
,
793 struct dn_list
*list
)
795 struct ldb_context
*ldb
;
799 ldb
= ldb_module_get_ctx(module
);
804 /* in the first pass we only look for unique simple
805 equality tests, in the hope of avoiding having to look
807 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
808 const struct ldb_parse_tree
*subtree
= tree
->u
.list
.elements
[i
];
811 if (subtree
->operation
!= LDB_OP_EQUALITY
||
812 !ltdb_index_unique(ldb
, subtree
->u
.equality
.attr
)) {
816 ret
= ltdb_index_dn(module
, ltdb
, subtree
, list
);
817 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
819 return LDB_ERR_NO_SUCH_OBJECT
;
821 if (ret
== LDB_SUCCESS
) {
822 /* a unique index match means we can
823 * stop. Note that we don't care if we return
824 * a few too many objects, due to later
830 /* now do a full intersection */
833 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
834 const struct ldb_parse_tree
*subtree
= tree
->u
.list
.elements
[i
];
835 struct dn_list
*list2
;
838 list2
= talloc_zero(list
, struct dn_list
);
840 return ldb_module_oom(module
);
843 ret
= ltdb_index_dn(module
, ltdb
, subtree
, list2
);
845 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
850 return LDB_ERR_NO_SUCH_OBJECT
;
853 if (ret
!= LDB_SUCCESS
) {
854 /* this didn't adding anything */
860 talloc_reparent(list2
, list
, list
->dn
);
861 list
->dn
= list2
->dn
;
862 list
->count
= list2
->count
;
864 } else if (!list_intersect(ldb
, ltdb
,
867 return LDB_ERR_OPERATIONS_ERROR
;
870 if (list
->count
== 0) {
872 return LDB_ERR_NO_SUCH_OBJECT
;
875 if (list
->count
< 2) {
876 /* it isn't worth loading the next part of the tree */
882 /* none of the attributes were indexed */
883 return LDB_ERR_OPERATIONS_ERROR
;
890 return a list of matching objects using a one-level index
892 static int ltdb_index_dn_one(struct ldb_module
*module
,
893 struct ldb_dn
*parent_dn
,
894 struct dn_list
*list
)
896 struct ldb_context
*ldb
;
901 ldb
= ldb_module_get_ctx(module
);
903 /* work out the index key from the parent DN */
904 val
.data
= (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn
));
905 val
.length
= strlen((char *)val
.data
);
906 key
= ltdb_index_key(ldb
, LTDB_IDXONE
, &val
, NULL
);
909 return LDB_ERR_OPERATIONS_ERROR
;
912 ret
= ltdb_dn_list_load(module
, key
, list
);
914 if (ret
!= LDB_SUCCESS
) {
918 if (list
->count
== 0) {
919 return LDB_ERR_NO_SUCH_OBJECT
;
926 return a list of dn's that might match a indexed search or
927 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
929 static int ltdb_index_dn(struct ldb_module
*module
,
930 struct ltdb_private
*ltdb
,
931 const struct ldb_parse_tree
*tree
,
932 struct dn_list
*list
)
934 int ret
= LDB_ERR_OPERATIONS_ERROR
;
936 switch (tree
->operation
) {
938 ret
= ltdb_index_dn_and(module
, ltdb
, tree
, list
);
942 ret
= ltdb_index_dn_or(module
, ltdb
, tree
, list
);
946 ret
= ltdb_index_dn_not(module
, ltdb
, tree
, list
);
949 case LDB_OP_EQUALITY
:
950 ret
= ltdb_index_dn_leaf(module
, ltdb
, tree
, list
);
953 case LDB_OP_SUBSTRING
:
958 case LDB_OP_EXTENDED
:
959 /* we can't index with fancy bitops yet */
960 ret
= LDB_ERR_OPERATIONS_ERROR
;
968 filter a candidate dn_list from an indexed search into a set of results
969 extracting just the given attributes
971 static int ltdb_index_filter(struct ltdb_private
*ltdb
,
972 const struct dn_list
*dn_list
,
973 struct ltdb_context
*ac
,
974 uint32_t *match_count
)
976 struct ldb_context
*ldb
;
977 struct ldb_message
*msg
;
978 struct ldb_message
*filtered_msg
;
981 ldb
= ldb_module_get_ctx(ac
->module
);
983 for (i
= 0; i
< dn_list
->count
; i
++) {
988 msg
= ldb_msg_new(ac
);
990 return LDB_ERR_OPERATIONS_ERROR
;
993 dn
= ldb_dn_from_ldb_val(msg
, ldb
, &dn_list
->dn
[i
]);
996 return LDB_ERR_OPERATIONS_ERROR
;
999 ret
= ltdb_search_dn1(ac
->module
, dn
, msg
,
1000 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
|
1001 LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC
);
1003 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
1004 /* the record has disappeared? yes, this can happen */
1009 if (ret
!= LDB_SUCCESS
&& ret
!= LDB_ERR_NO_SUCH_OBJECT
) {
1010 /* an internal error */
1012 return LDB_ERR_OPERATIONS_ERROR
;
1015 ret
= ldb_match_msg_error(ldb
, msg
,
1016 ac
->tree
, ac
->base
, ac
->scope
, &matched
);
1017 if (ret
!= LDB_SUCCESS
) {
1026 /* filter the attributes that the user wants */
1027 ret
= ltdb_filter_attrs(ac
, msg
, ac
->attrs
, &filtered_msg
);
1032 return LDB_ERR_OPERATIONS_ERROR
;
1035 ret
= ldb_module_send_entry(ac
->req
, filtered_msg
, NULL
);
1036 if (ret
!= LDB_SUCCESS
) {
1037 /* Regardless of success or failure, the msg
1038 * is the callbacks responsiblity, and should
1039 * not be talloc_free()'ed */
1040 ac
->request_terminated
= true;
1051 remove any duplicated entries in a indexed result
1053 static void ltdb_dn_list_remove_duplicates(struct dn_list
*list
)
1055 unsigned int i
, new_count
;
1057 if (list
->count
< 2) {
1061 TYPESAFE_QSORT(list
->dn
, list
->count
, dn_list_cmp
);
1064 for (i
=1; i
<list
->count
; i
++) {
1065 if (dn_list_cmp(&list
->dn
[i
], &list
->dn
[new_count
-1]) != 0) {
1066 if (new_count
!= i
) {
1067 list
->dn
[new_count
] = list
->dn
[i
];
1073 list
->count
= new_count
;
1077 search the database with a LDAP-like expression using indexes
1078 returns -1 if an indexed search is not possible, in which
1079 case the caller should call ltdb_search_full()
1081 int ltdb_search_indexed(struct ltdb_context
*ac
, uint32_t *match_count
)
1083 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(ac
->module
), struct ltdb_private
);
1084 struct dn_list
*dn_list
;
1087 /* see if indexing is enabled */
1088 if (!ltdb
->cache
->attribute_indexes
&&
1089 !ltdb
->cache
->one_level_indexes
&&
1090 ac
->scope
!= LDB_SCOPE_BASE
) {
1091 /* fallback to a full search */
1092 return LDB_ERR_OPERATIONS_ERROR
;
1095 dn_list
= talloc_zero(ac
, struct dn_list
);
1096 if (dn_list
== NULL
) {
1097 return ldb_module_oom(ac
->module
);
1100 switch (ac
->scope
) {
1101 case LDB_SCOPE_BASE
:
1102 dn_list
->dn
= talloc_array(dn_list
, struct ldb_val
, 1);
1103 if (dn_list
->dn
== NULL
) {
1104 talloc_free(dn_list
);
1105 return ldb_module_oom(ac
->module
);
1107 dn_list
->dn
[0].data
= discard_const_p(unsigned char, ldb_dn_get_linearized(ac
->base
));
1108 if (dn_list
->dn
[0].data
== NULL
) {
1109 talloc_free(dn_list
);
1110 return ldb_module_oom(ac
->module
);
1112 dn_list
->dn
[0].length
= strlen((char *)dn_list
->dn
[0].data
);
1116 case LDB_SCOPE_ONELEVEL
:
1117 if (!ltdb
->cache
->one_level_indexes
) {
1118 talloc_free(dn_list
);
1119 return LDB_ERR_OPERATIONS_ERROR
;
1121 ret
= ltdb_index_dn_one(ac
->module
, ac
->base
, dn_list
);
1122 if (ret
!= LDB_SUCCESS
) {
1123 talloc_free(dn_list
);
1128 case LDB_SCOPE_SUBTREE
:
1129 case LDB_SCOPE_DEFAULT
:
1130 if (!ltdb
->cache
->attribute_indexes
) {
1131 talloc_free(dn_list
);
1132 return LDB_ERR_OPERATIONS_ERROR
;
1134 ret
= ltdb_index_dn(ac
->module
, ltdb
, ac
->tree
, dn_list
);
1135 if (ret
!= LDB_SUCCESS
) {
1136 talloc_free(dn_list
);
1139 ltdb_dn_list_remove_duplicates(dn_list
);
1143 ret
= ltdb_index_filter(ltdb
, dn_list
, ac
, match_count
);
1144 talloc_free(dn_list
);
1149 * @brief Add a DN in the index list of a given attribute name/value pair
1151 * This function will add the DN in the index list for the index for
1152 * the given attribute name and value.
1154 * @param[in] module A ldb_module structure
1156 * @param[in] dn The string representation of the DN as it
1157 * will be stored in the index entry
1159 * @param[in] el A ldb_message_element array, one of the entry
1160 * referred by the v_idx is the attribute name and
1161 * value pair which will be used to construct the
1164 * @param[in] v_idx The index of element in the el array to use
1166 * @return An ldb error code
1168 static int ltdb_index_add1(struct ldb_module
*module
,
1169 struct ltdb_private
*ltdb
,
1171 struct ldb_message_element
*el
, int v_idx
)
1173 struct ldb_context
*ldb
;
1174 struct ldb_dn
*dn_key
;
1176 const struct ldb_schema_attribute
*a
;
1177 struct dn_list
*list
;
1180 ldb
= ldb_module_get_ctx(module
);
1182 list
= talloc_zero(module
, struct dn_list
);
1184 return LDB_ERR_OPERATIONS_ERROR
;
1187 dn_key
= ltdb_index_key(ldb
, el
->name
, &el
->values
[v_idx
], &a
);
1190 return LDB_ERR_OPERATIONS_ERROR
;
1192 talloc_steal(list
, dn_key
);
1194 ret
= ltdb_dn_list_load(module
, dn_key
, list
);
1195 if (ret
!= LDB_SUCCESS
&& ret
!= LDB_ERR_NO_SUCH_OBJECT
) {
1200 if (list
->count
> 0 &&
1201 a
->flags
& LDB_ATTR_FLAG_UNIQUE_INDEX
) {
1203 * We do not want to print info about a possibly
1204 * confidential DN that the conflict was with in the
1205 * user-visible error string
1207 ldb_debug(ldb
, LDB_DEBUG_WARNING
,
1208 __location__
": unique index violation on %s in %s, "
1209 "conficts with %*.*s in %s",
1211 (int)list
->dn
[0].length
,
1212 (int)list
->dn
[0].length
,
1214 ldb_dn_get_linearized(dn_key
));
1215 ldb_asprintf_errstring(ldb
, __location__
": unique index violation on %s in %s",
1218 return LDB_ERR_ENTRY_ALREADY_EXISTS
;
1221 /* overallocate the list a bit, to reduce the number of
1222 * realloc trigered copies */
1223 alloc_len
= ((list
->count
+1)+7) & ~7;
1224 list
->dn
= talloc_realloc(list
, list
->dn
, struct ldb_val
, alloc_len
);
1225 if (list
->dn
== NULL
) {
1227 return LDB_ERR_OPERATIONS_ERROR
;
1230 list
->dn
[list
->count
].data
1231 = (uint8_t *)talloc_strdup(list
->dn
, dn
);
1232 if (list
->dn
[list
->count
].data
== NULL
) {
1234 return LDB_ERR_OPERATIONS_ERROR
;
1236 list
->dn
[list
->count
].length
= strlen(dn
);
1239 ret
= ltdb_dn_list_store(module
, dn_key
, list
);
1247 add index entries for one elements in a message
1249 static int ltdb_index_add_el(struct ldb_module
*module
,
1250 struct ltdb_private
*ltdb
,
1252 struct ldb_message_element
*el
)
1255 for (i
= 0; i
< el
->num_values
; i
++) {
1256 int ret
= ltdb_index_add1(module
, ltdb
,
1258 if (ret
!= LDB_SUCCESS
) {
1267 add index entries for all elements in a message
1269 static int ltdb_index_add_all(struct ldb_module
*module
,
1270 struct ltdb_private
*ltdb
,
1272 struct ldb_message_element
*elements
,
1273 unsigned int num_el
)
1281 if (!ltdb
->cache
->attribute_indexes
) {
1282 /* no indexed fields */
1286 for (i
= 0; i
< num_el
; i
++) {
1288 if (!ltdb_is_indexed(module
, ltdb
, elements
[i
].name
)) {
1291 ret
= ltdb_index_add_el(module
, ltdb
, dn
, &elements
[i
]);
1292 if (ret
!= LDB_SUCCESS
) {
1293 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1294 ldb_asprintf_errstring(ldb
,
1295 __location__
": Failed to re-index %s in %s - %s",
1296 elements
[i
].name
, dn
, ldb_errstring(ldb
));
1306 insert a one level index for a message
1308 static int ltdb_index_onelevel(struct ldb_module
*module
,
1309 const struct ldb_message
*msg
, int add
)
1311 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
),
1312 struct ltdb_private
);
1313 struct ldb_message_element el
;
1319 /* We index for ONE Level only if requested */
1320 if (!ltdb
->cache
->one_level_indexes
) {
1324 pdn
= ldb_dn_get_parent(module
, msg
->dn
);
1326 return LDB_ERR_OPERATIONS_ERROR
;
1329 dn
= ldb_dn_get_linearized(msg
->dn
);
1332 return LDB_ERR_OPERATIONS_ERROR
;
1335 val
.data
= (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn
));
1336 if (val
.data
== NULL
) {
1338 return LDB_ERR_OPERATIONS_ERROR
;
1341 val
.length
= strlen((char *)val
.data
);
1342 el
.name
= LTDB_IDXONE
;
1347 ret
= ltdb_index_add1(module
, ltdb
, dn
, &el
, 0);
1348 } else { /* delete */
1349 ret
= ltdb_index_del_value(module
, ltdb
, msg
->dn
, &el
, 0);
1358 add the index entries for a new element in a record
1359 The caller guarantees that these element values are not yet indexed
1361 int ltdb_index_add_element(struct ldb_module
*module
,
1362 struct ltdb_private
*ltdb
,
1364 struct ldb_message_element
*el
)
1366 if (ldb_dn_is_special(dn
)) {
1369 if (!ltdb_is_indexed(module
, ltdb
, el
->name
)) {
1372 return ltdb_index_add_el(module
, ltdb
,
1373 ldb_dn_get_linearized(dn
), el
);
1377 add the index entries for a new record
1379 int ltdb_index_add_new(struct ldb_module
*module
,
1380 struct ltdb_private
*ltdb
,
1381 const struct ldb_message
*msg
)
1386 if (ldb_dn_is_special(msg
->dn
)) {
1390 dn
= ldb_dn_get_linearized(msg
->dn
);
1392 return LDB_ERR_OPERATIONS_ERROR
;
1395 ret
= ltdb_index_add_all(module
, ltdb
, dn
, msg
->elements
,
1397 if (ret
!= LDB_SUCCESS
) {
1401 return ltdb_index_onelevel(module
, msg
, 1);
1406 delete an index entry for one message element
1408 int ltdb_index_del_value(struct ldb_module
*module
,
1409 struct ltdb_private
*ltdb
,
1411 struct ldb_message_element
*el
, unsigned int v_idx
)
1413 struct ldb_context
*ldb
;
1414 struct ldb_dn
*dn_key
;
1418 struct dn_list
*list
;
1420 ldb
= ldb_module_get_ctx(module
);
1422 dn_str
= ldb_dn_get_linearized(dn
);
1423 if (dn_str
== NULL
) {
1424 return LDB_ERR_OPERATIONS_ERROR
;
1427 if (dn_str
[0] == '@') {
1431 dn_key
= ltdb_index_key(ldb
, el
->name
, &el
->values
[v_idx
], NULL
);
1433 return LDB_ERR_OPERATIONS_ERROR
;
1436 list
= talloc_zero(dn_key
, struct dn_list
);
1438 talloc_free(dn_key
);
1439 return LDB_ERR_OPERATIONS_ERROR
;
1442 ret
= ltdb_dn_list_load(module
, dn_key
, list
);
1443 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
1444 /* it wasn't indexed. Did we have an earlier error? If we did then
1446 talloc_free(dn_key
);
1450 if (ret
!= LDB_SUCCESS
) {
1451 talloc_free(dn_key
);
1455 i
= ltdb_dn_list_find_str(ltdb
, list
, dn_str
);
1457 /* nothing to delete */
1458 talloc_free(dn_key
);
1462 j
= (unsigned int) i
;
1463 if (j
!= list
->count
- 1) {
1464 memmove(&list
->dn
[j
], &list
->dn
[j
+1], sizeof(list
->dn
[0])*(list
->count
- (j
+1)));
1467 if (list
->count
== 0) {
1468 talloc_free(list
->dn
);
1471 list
->dn
= talloc_realloc(list
, list
->dn
, struct ldb_val
, list
->count
);
1474 ret
= ltdb_dn_list_store(module
, dn_key
, list
);
1476 talloc_free(dn_key
);
1482 delete the index entries for a element
1483 return -1 on failure
1485 int ltdb_index_del_element(struct ldb_module
*module
,
1486 struct ltdb_private
*ltdb
,
1488 struct ldb_message_element
*el
)
1494 if (!ltdb
->cache
->attribute_indexes
) {
1495 /* no indexed fields */
1499 dn_str
= ldb_dn_get_linearized(dn
);
1500 if (dn_str
== NULL
) {
1501 return LDB_ERR_OPERATIONS_ERROR
;
1504 if (dn_str
[0] == '@') {
1508 if (!ltdb_is_indexed(module
, ltdb
, el
->name
)) {
1511 for (i
= 0; i
< el
->num_values
; i
++) {
1512 ret
= ltdb_index_del_value(module
, ltdb
, dn
, el
, i
);
1513 if (ret
!= LDB_SUCCESS
) {
1522 delete the index entries for a record
1523 return -1 on failure
1525 int ltdb_index_delete(struct ldb_module
*module
, const struct ldb_message
*msg
)
1527 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1531 if (ldb_dn_is_special(msg
->dn
)) {
1535 ret
= ltdb_index_onelevel(module
, msg
, 0);
1536 if (ret
!= LDB_SUCCESS
) {
1540 if (!ltdb
->cache
->attribute_indexes
) {
1541 /* no indexed fields */
1545 for (i
= 0; i
< msg
->num_elements
; i
++) {
1546 ret
= ltdb_index_del_element(module
, ltdb
,
1547 msg
->dn
, &msg
->elements
[i
]);
1548 if (ret
!= LDB_SUCCESS
) {
1558 traversal function that deletes all @INDEX records
1560 static int delete_index(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1562 struct ldb_module
*module
= state
;
1563 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1564 const char *dnstr
= "DN=" LTDB_INDEX
":";
1565 struct dn_list list
;
1570 if (strncmp((char *)key
.dptr
, dnstr
, strlen(dnstr
)) != 0) {
1573 /* we need to put a empty list in the internal tdb for this
1578 /* the offset of 3 is to remove the DN= prefix. */
1579 v
.data
= key
.dptr
+ 3;
1580 v
.length
= strnlen((char *)key
.dptr
, key
.dsize
) - 3;
1582 dn
= ldb_dn_from_ldb_val(ltdb
, ldb_module_get_ctx(module
), &v
);
1583 ret
= ltdb_dn_list_store(module
, dn
, &list
);
1584 if (ret
!= LDB_SUCCESS
) {
1585 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
1586 "Unable to store null index for %s\n",
1587 ldb_dn_get_linearized(dn
));
1595 struct ltdb_reindex_context
{
1596 struct ldb_module
*module
;
1601 traversal function that adds @INDEX records during a re index
1603 static int re_key(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1605 struct ldb_context
*ldb
;
1606 struct ltdb_reindex_context
*ctx
= (struct ltdb_reindex_context
*)state
;
1607 struct ldb_module
*module
= ctx
->module
;
1608 struct ldb_message
*msg
;
1609 unsigned int nb_elements_in_db
;
1610 const struct ldb_val val
= {
1612 .length
= data
.dsize
,
1618 ldb
= ldb_module_get_ctx(module
);
1620 if (key
.dsize
> 4 &&
1621 memcmp(key
.dptr
, "DN=@", 4) == 0) {
1625 is_record
= ltdb_key_is_record(key
);
1626 if (is_record
== false) {
1630 msg
= ldb_msg_new(module
);
1635 ret
= ldb_unpack_data_only_attr_list_flags(ldb
, &val
,
1638 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
,
1639 &nb_elements_in_db
);
1641 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid data for index %s\n",
1642 ldb_dn_get_linearized(msg
->dn
));
1648 if (msg
->dn
== NULL
) {
1649 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1650 "Refusing to re-index as GUID "
1651 "key %*.*s with no DN\n",
1652 (int)key
.dsize
, (int)key
.dsize
,
1658 /* check if the DN key has changed, perhaps due to the case
1659 insensitivity of an element changing, or a change from DN
1661 key2
= ltdb_key_msg(module
, msg
);
1662 if (key2
.dptr
== NULL
) {
1663 /* probably a corrupt record ... darn */
1664 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid DN in re_index: %s",
1665 ldb_dn_get_linearized(msg
->dn
));
1669 if (key
.dsize
!= key2
.dsize
||
1670 (memcmp(key
.dptr
, key2
.dptr
, key
.dsize
) != 0)) {
1672 tdb_ret
= tdb_delete(tdb
, key
);
1674 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1675 "Failed to delete %*.*s "
1676 "for rekey as %*.*s: %s",
1677 (int)key
.dsize
, (int)key
.dsize
,
1678 (const char *)key
.dptr
,
1679 (int)key2
.dsize
, (int)key2
.dsize
,
1680 (const char *)key
.dptr
,
1682 ctx
->error
= ltdb_err_map(tdb_error(tdb
));
1685 tdb_ret
= tdb_store(tdb
, key2
, data
, 0);
1687 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1688 "Failed to rekey %*.*s as %*.*s: %s",
1689 (int)key
.dsize
, (int)key
.dsize
,
1690 (const char *)key
.dptr
,
1691 (int)key2
.dsize
, (int)key2
.dsize
,
1692 (const char *)key
.dptr
,
1694 ctx
->error
= ltdb_err_map(tdb_error(tdb
));
1698 talloc_free(key2
.dptr
);
1706 traversal function that adds @INDEX records during a re index
1708 static int re_index(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1710 struct ldb_context
*ldb
;
1711 struct ltdb_reindex_context
*ctx
= (struct ltdb_reindex_context
*)state
;
1712 struct ldb_module
*module
= ctx
->module
;
1713 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
),
1714 struct ltdb_private
);
1715 struct ldb_message
*msg
;
1716 const char *dn
= NULL
;
1717 unsigned int nb_elements_in_db
;
1718 const struct ldb_val val
= {
1720 .length
= data
.dsize
,
1725 ldb
= ldb_module_get_ctx(module
);
1727 if (key
.dsize
> 4 &&
1728 memcmp(key
.dptr
, "DN=@", 4) == 0) {
1732 is_record
= ltdb_key_is_record(key
);
1733 if (is_record
== false) {
1737 msg
= ldb_msg_new(module
);
1742 ret
= ldb_unpack_data_only_attr_list_flags(ldb
, &val
,
1745 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
,
1746 &nb_elements_in_db
);
1748 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid data for index %s\n",
1749 ldb_dn_get_linearized(msg
->dn
));
1755 if (msg
->dn
== NULL
) {
1756 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1757 "Refusing to re-index as GUID "
1758 "key %*.*s with no DN\n",
1759 (int)key
.dsize
, (int)key
.dsize
,
1764 dn
= ldb_dn_get_linearized(msg
->dn
);
1767 ret
= ltdb_index_onelevel(module
, msg
, 1);
1768 if (ret
!= LDB_SUCCESS
) {
1769 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1770 "Adding special ONE LEVEL index failed (%s)!",
1771 ldb_dn_get_linearized(msg
->dn
));
1776 ret
= ltdb_index_add_all(module
, ltdb
, dn
,
1777 msg
->elements
, msg
->num_elements
);
1779 if (ret
!= LDB_SUCCESS
) {
1791 force a complete reindex of the database
1793 int ltdb_reindex(struct ldb_module
*module
)
1795 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1797 struct ltdb_reindex_context ctx
;
1800 * Only triggered after a modification, but make clear we do
1801 * not re-index a read-only DB
1803 if (ltdb
->read_only
) {
1804 return LDB_ERR_UNWILLING_TO_PERFORM
;
1807 if (ltdb_cache_reload(module
) != 0) {
1808 return LDB_ERR_OPERATIONS_ERROR
;
1812 * Ensure we read (and so remove) the entries from the real
1813 * DB, no values stored so far are any use as we want to do a
1816 ltdb_index_transaction_cancel(module
);
1818 ret
= ltdb_index_transaction_start(module
);
1819 if (ret
!= LDB_SUCCESS
) {
1823 /* first traverse the database deleting any @INDEX records by
1824 * putting NULL entries in the in-memory tdb
1826 ret
= tdb_traverse(ltdb
->tdb
, delete_index
, module
);
1828 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1829 ldb_asprintf_errstring(ldb
, "index deletion traverse failed: %s",
1830 ldb_errstring(ldb
));
1831 return LDB_ERR_OPERATIONS_ERROR
;
1834 /* if we don't have indexes we have nothing todo */
1835 if (!ltdb
->cache
->attribute_indexes
) {
1839 ctx
.module
= module
;
1842 /* now traverse adding any indexes for normal LDB records */
1843 ret
= tdb_traverse(ltdb
->tdb
, re_key
, &ctx
);
1845 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1846 ldb_asprintf_errstring(ldb
, "key correction traverse failed: %s",
1847 ldb_errstring(ldb
));
1848 return LDB_ERR_OPERATIONS_ERROR
;
1851 if (ctx
.error
!= LDB_SUCCESS
) {
1852 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1853 ldb_asprintf_errstring(ldb
, "reindexing failed: %s", ldb_errstring(ldb
));
1859 /* now traverse adding any indexes for normal LDB records */
1860 ret
= tdb_traverse(ltdb
->tdb
, re_index
, &ctx
);
1862 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1863 ldb_asprintf_errstring(ldb
, "reindexing traverse failed: %s",
1864 ldb_errstring(ldb
));
1865 return LDB_ERR_OPERATIONS_ERROR
;
1868 if (ctx
.error
!= LDB_SUCCESS
) {
1869 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1870 ldb_asprintf_errstring(ldb
, "reindexing failed: %s", ldb_errstring(ldb
));