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 *);
320 ret
= tdb_store(ltdb
->idxptr
->itdb
, key
, rec
, TDB_INSERT
);
322 return ltdb_err_map(tdb_error(ltdb
->idxptr
->itdb
));
328 traverse function for storing the in-memory index entries on disk
330 static int ltdb_index_traverse_store(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
332 struct ldb_module
*module
= state
;
333 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
335 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
337 struct dn_list
*list
;
339 list
= ltdb_index_idxptr(module
, data
, true);
341 ltdb
->idxptr
->error
= LDB_ERR_OPERATIONS_ERROR
;
346 v
.length
= strnlen((char *)key
.dptr
, key
.dsize
);
348 dn
= ldb_dn_from_ldb_val(module
, ldb
, &v
);
350 ldb_asprintf_errstring(ldb
, "Failed to parse index key %*.*s as an LDB DN", (int)v
.length
, (int)v
.length
, (const char *)v
.data
);
351 ltdb
->idxptr
->error
= LDB_ERR_OPERATIONS_ERROR
;
355 ltdb
->idxptr
->error
= ltdb_dn_list_store_full(module
, ltdb
,
358 if (ltdb
->idxptr
->error
!= 0) {
364 /* cleanup the idxptr mode when transaction commits */
365 int ltdb_index_transaction_commit(struct ldb_module
*module
)
367 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
370 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
372 ldb_reset_err_string(ldb
);
374 if (ltdb
->idxptr
->itdb
) {
375 tdb_traverse(ltdb
->idxptr
->itdb
, ltdb_index_traverse_store
, module
);
376 tdb_close(ltdb
->idxptr
->itdb
);
379 ret
= ltdb
->idxptr
->error
;
380 if (ret
!= LDB_SUCCESS
) {
381 if (!ldb_errstring(ldb
)) {
382 ldb_set_errstring(ldb
, ldb_strerror(ret
));
384 ldb_asprintf_errstring(ldb
, "Failed to store index records in transaction commit: %s", ldb_errstring(ldb
));
387 talloc_free(ltdb
->idxptr
);
392 /* cleanup the idxptr mode when transaction cancels */
393 int ltdb_index_transaction_cancel(struct ldb_module
*module
)
395 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
396 if (ltdb
->idxptr
&& ltdb
->idxptr
->itdb
) {
397 tdb_close(ltdb
->idxptr
->itdb
);
399 talloc_free(ltdb
->idxptr
);
406 return the dn key to be used for an index
407 the caller is responsible for freeing
409 static struct ldb_dn
*ltdb_index_key(struct ldb_context
*ldb
,
410 const char *attr
, const struct ldb_val
*value
,
411 const struct ldb_schema_attribute
**ap
)
415 const struct ldb_schema_attribute
*a
;
419 attr_folded
= ldb_attr_casefold(ldb
, attr
);
424 a
= ldb_schema_attribute_by_name(ldb
, attr
);
428 r
= a
->syntax
->canonicalise_fn(ldb
, ldb
, value
, &v
);
429 if (r
!= LDB_SUCCESS
) {
430 const char *errstr
= ldb_errstring(ldb
);
431 /* canonicalisation can be refused. For example,
432 a attribute that takes wildcards will refuse to canonicalise
433 if the value contains a wildcard */
434 ldb_asprintf_errstring(ldb
, "Failed to create index key for attribute '%s':%s%s%s",
435 attr
, ldb_strerror(r
), (errstr
?":":""), (errstr
?errstr
:""));
436 talloc_free(attr_folded
);
439 if (ldb_should_b64_encode(ldb
, &v
)) {
440 char *vstr
= ldb_base64_encode(ldb
, (char *)v
.data
, v
.length
);
442 talloc_free(attr_folded
);
445 ret
= ldb_dn_new_fmt(ldb
, ldb
, "%s:%s::%s", LTDB_INDEX
, attr_folded
, vstr
);
448 ret
= ldb_dn_new_fmt(ldb
, ldb
, "%s:%s:%.*s", LTDB_INDEX
, attr_folded
, (int)v
.length
, (char *)v
.data
);
451 if (v
.data
!= value
->data
) {
454 talloc_free(attr_folded
);
460 see if a attribute value is in the list of indexed attributes
462 static bool ltdb_is_indexed(struct ldb_module
*module
,
463 struct ltdb_private
*ltdb
,
466 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
468 struct ldb_message_element
*el
;
470 if (ldb
->schema
.index_handler_override
) {
471 const struct ldb_schema_attribute
*a
472 = ldb_schema_attribute_by_name(ldb
, attr
);
478 if (a
->flags
& LDB_ATTR_FLAG_INDEXED
) {
485 if (!ltdb
->cache
->attribute_indexes
) {
489 el
= ldb_msg_find_element(ltdb
->cache
->indexlist
, LTDB_IDXATTR
);
494 /* TODO: this is too expensive! At least use a binary search */
495 for (i
=0; i
<el
->num_values
; i
++) {
496 if (ldb_attr_cmp((char *)el
->values
[i
].data
, attr
) == 0) {
504 in the following logic functions, the return value is treated as
507 LDB_SUCCESS: we found some matching index values
509 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
511 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
512 we'll need a full search
516 return a list of dn's that might match a simple indexed search (an
517 equality search only)
519 static int ltdb_index_dn_simple(struct ldb_module
*module
,
520 struct ltdb_private
*ltdb
,
521 const struct ldb_parse_tree
*tree
,
522 struct dn_list
*list
)
524 struct ldb_context
*ldb
;
528 ldb
= ldb_module_get_ctx(module
);
533 /* if the attribute isn't in the list of indexed attributes then
534 this node needs a full search */
535 if (!ltdb_is_indexed(module
, ltdb
, tree
->u
.equality
.attr
)) {
536 return LDB_ERR_OPERATIONS_ERROR
;
539 /* the attribute is indexed. Pull the list of DNs that match the
541 dn
= ltdb_index_key(ldb
, tree
->u
.equality
.attr
, &tree
->u
.equality
.value
, NULL
);
542 if (!dn
) return LDB_ERR_OPERATIONS_ERROR
;
544 ret
= ltdb_dn_list_load(module
, dn
, list
);
550 static bool list_union(struct ldb_context
*, struct dn_list
*, const struct dn_list
*);
553 return a list of dn's that might match a leaf indexed search
555 static int ltdb_index_dn_leaf(struct ldb_module
*module
,
556 struct ltdb_private
*ltdb
,
557 const struct ldb_parse_tree
*tree
,
558 struct dn_list
*list
)
560 if (ltdb
->disallow_dn_filter
&&
561 (ldb_attr_cmp(tree
->u
.equality
.attr
, "dn") == 0)) {
562 /* in AD mode we do not support "(dn=...)" search filters */
567 if (ldb_attr_dn(tree
->u
.equality
.attr
) == 0) {
568 list
->dn
= talloc_array(list
, struct ldb_val
, 1);
569 if (list
->dn
== NULL
) {
570 ldb_module_oom(module
);
571 return LDB_ERR_OPERATIONS_ERROR
;
573 list
->dn
[0] = tree
->u
.equality
.value
;
577 return ltdb_index_dn_simple(module
, ltdb
, tree
, list
);
585 static bool list_intersect(struct ldb_context
*ldb
,
586 struct ltdb_private
*ltdb
,
587 struct dn_list
*list
, const struct dn_list
*list2
)
589 struct dn_list
*list3
;
592 if (list
->count
== 0) {
596 if (list2
->count
== 0) {
603 /* the indexing code is allowed to return a longer list than
604 what really matches, as all results are filtered by the
605 full expression at the end - this shortcut avoids a lot of
606 work in some cases */
607 if (list
->count
< 2 && list2
->count
> 10) {
610 if (list2
->count
< 2 && list
->count
> 10) {
611 list
->count
= list2
->count
;
612 list
->dn
= list2
->dn
;
613 /* note that list2 may not be the parent of list2->dn,
614 as list2->dn may be owned by ltdb->idxptr. In that
615 case we expect this reparent call to fail, which is
617 talloc_reparent(list2
, list
, list2
->dn
);
621 list3
= talloc_zero(list
, struct dn_list
);
626 list3
->dn
= talloc_array(list3
, struct ldb_val
, list
->count
);
633 for (i
=0;i
<list
->count
;i
++) {
634 if (ltdb_dn_list_find_val(ltdb
, list2
,
635 &list
->dn
[i
]) != -1) {
636 list3
->dn
[list3
->count
] = list
->dn
[i
];
641 list
->dn
= talloc_steal(list
, list3
->dn
);
642 list
->count
= list3
->count
;
653 static bool list_union(struct ldb_context
*ldb
,
654 struct dn_list
*list
, const struct dn_list
*list2
)
658 if (list2
->count
== 0) {
663 if (list
->count
== 0) {
665 list
->count
= list2
->count
;
666 list
->dn
= list2
->dn
;
667 /* note that list2 may not be the parent of list2->dn,
668 as list2->dn may be owned by ltdb->idxptr. In that
669 case we expect this reparent call to fail, which is
671 talloc_reparent(list2
, list
, list2
->dn
);
675 dn3
= talloc_array(list
, struct ldb_val
, list
->count
+ list2
->count
);
681 /* we allow for duplicates here, and get rid of them later */
682 memcpy(dn3
, list
->dn
, sizeof(list
->dn
[0])*list
->count
);
683 memcpy(dn3
+list
->count
, list2
->dn
, sizeof(list2
->dn
[0])*list2
->count
);
686 list
->count
+= list2
->count
;
691 static int ltdb_index_dn(struct ldb_module
*module
,
692 struct ltdb_private
*ltdb
,
693 const struct ldb_parse_tree
*tree
,
694 struct dn_list
*list
);
698 process an OR list (a union)
700 static int ltdb_index_dn_or(struct ldb_module
*module
,
701 struct ltdb_private
*ltdb
,
702 const struct ldb_parse_tree
*tree
,
703 struct dn_list
*list
)
705 struct ldb_context
*ldb
;
708 ldb
= ldb_module_get_ctx(module
);
713 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
714 struct dn_list
*list2
;
717 list2
= talloc_zero(list
, struct dn_list
);
719 return LDB_ERR_OPERATIONS_ERROR
;
722 ret
= ltdb_index_dn(module
, ltdb
,
723 tree
->u
.list
.elements
[i
], list2
);
725 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
731 if (ret
!= LDB_SUCCESS
) {
737 if (!list_union(ldb
, list
, list2
)) {
739 return LDB_ERR_OPERATIONS_ERROR
;
743 if (list
->count
== 0) {
744 return LDB_ERR_NO_SUCH_OBJECT
;
754 static int ltdb_index_dn_not(struct ldb_module
*module
,
755 struct ltdb_private
*ltdb
,
756 const struct ldb_parse_tree
*tree
,
757 struct dn_list
*list
)
759 /* the only way to do an indexed not would be if we could
760 negate the not via another not or if we knew the total
761 number of database elements so we could know that the
762 existing expression covered the whole database.
764 instead, we just give up, and rely on a full index scan
765 (unless an outer & manages to reduce the list)
767 return LDB_ERR_OPERATIONS_ERROR
;
771 static bool ltdb_index_unique(struct ldb_context
*ldb
,
774 const struct ldb_schema_attribute
*a
;
775 a
= ldb_schema_attribute_by_name(ldb
, attr
);
776 if (a
->flags
& LDB_ATTR_FLAG_UNIQUE_INDEX
) {
783 process an AND expression (intersection)
785 static int ltdb_index_dn_and(struct ldb_module
*module
,
786 struct ltdb_private
*ltdb
,
787 const struct ldb_parse_tree
*tree
,
788 struct dn_list
*list
)
790 struct ldb_context
*ldb
;
794 ldb
= ldb_module_get_ctx(module
);
799 /* in the first pass we only look for unique simple
800 equality tests, in the hope of avoiding having to look
802 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
803 const struct ldb_parse_tree
*subtree
= tree
->u
.list
.elements
[i
];
806 if (subtree
->operation
!= LDB_OP_EQUALITY
||
807 !ltdb_index_unique(ldb
, subtree
->u
.equality
.attr
)) {
811 ret
= ltdb_index_dn(module
, ltdb
, subtree
, list
);
812 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
814 return LDB_ERR_NO_SUCH_OBJECT
;
816 if (ret
== LDB_SUCCESS
) {
817 /* a unique index match means we can
818 * stop. Note that we don't care if we return
819 * a few too many objects, due to later
825 /* now do a full intersection */
828 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
829 const struct ldb_parse_tree
*subtree
= tree
->u
.list
.elements
[i
];
830 struct dn_list
*list2
;
833 list2
= talloc_zero(list
, struct dn_list
);
835 return ldb_module_oom(module
);
838 ret
= ltdb_index_dn(module
, ltdb
, subtree
, list2
);
840 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
845 return LDB_ERR_NO_SUCH_OBJECT
;
848 if (ret
!= LDB_SUCCESS
) {
849 /* this didn't adding anything */
855 talloc_reparent(list2
, list
, list
->dn
);
856 list
->dn
= list2
->dn
;
857 list
->count
= list2
->count
;
859 } else if (!list_intersect(ldb
, ltdb
,
862 return LDB_ERR_OPERATIONS_ERROR
;
865 if (list
->count
== 0) {
867 return LDB_ERR_NO_SUCH_OBJECT
;
870 if (list
->count
< 2) {
871 /* it isn't worth loading the next part of the tree */
877 /* none of the attributes were indexed */
878 return LDB_ERR_OPERATIONS_ERROR
;
885 return a list of matching objects using a one-level index
887 static int ltdb_index_dn_one(struct ldb_module
*module
,
888 struct ldb_dn
*parent_dn
,
889 struct dn_list
*list
)
891 struct ldb_context
*ldb
;
896 ldb
= ldb_module_get_ctx(module
);
898 /* work out the index key from the parent DN */
899 val
.data
= (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn
));
900 val
.length
= strlen((char *)val
.data
);
901 key
= ltdb_index_key(ldb
, LTDB_IDXONE
, &val
, NULL
);
904 return LDB_ERR_OPERATIONS_ERROR
;
907 ret
= ltdb_dn_list_load(module
, key
, list
);
909 if (ret
!= LDB_SUCCESS
) {
913 if (list
->count
== 0) {
914 return LDB_ERR_NO_SUCH_OBJECT
;
921 return a list of dn's that might match a indexed search or
922 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
924 static int ltdb_index_dn(struct ldb_module
*module
,
925 struct ltdb_private
*ltdb
,
926 const struct ldb_parse_tree
*tree
,
927 struct dn_list
*list
)
929 int ret
= LDB_ERR_OPERATIONS_ERROR
;
931 switch (tree
->operation
) {
933 ret
= ltdb_index_dn_and(module
, ltdb
, tree
, list
);
937 ret
= ltdb_index_dn_or(module
, ltdb
, tree
, list
);
941 ret
= ltdb_index_dn_not(module
, ltdb
, tree
, list
);
944 case LDB_OP_EQUALITY
:
945 ret
= ltdb_index_dn_leaf(module
, ltdb
, tree
, list
);
948 case LDB_OP_SUBSTRING
:
953 case LDB_OP_EXTENDED
:
954 /* we can't index with fancy bitops yet */
955 ret
= LDB_ERR_OPERATIONS_ERROR
;
963 filter a candidate dn_list from an indexed search into a set of results
964 extracting just the given attributes
966 static int ltdb_index_filter(struct ltdb_private
*ltdb
,
967 const struct dn_list
*dn_list
,
968 struct ltdb_context
*ac
,
969 uint32_t *match_count
)
971 struct ldb_context
*ldb
;
972 struct ldb_message
*msg
;
973 struct ldb_message
*filtered_msg
;
976 ldb
= ldb_module_get_ctx(ac
->module
);
978 for (i
= 0; i
< dn_list
->count
; i
++) {
983 msg
= ldb_msg_new(ac
);
985 return LDB_ERR_OPERATIONS_ERROR
;
988 dn
= ldb_dn_from_ldb_val(msg
, ldb
, &dn_list
->dn
[i
]);
991 return LDB_ERR_OPERATIONS_ERROR
;
994 ret
= ltdb_search_dn1(ac
->module
, dn
, msg
,
995 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
|
996 LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC
);
998 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
999 /* the record has disappeared? yes, this can happen */
1004 if (ret
!= LDB_SUCCESS
&& ret
!= LDB_ERR_NO_SUCH_OBJECT
) {
1005 /* an internal error */
1007 return LDB_ERR_OPERATIONS_ERROR
;
1010 ret
= ldb_match_msg_error(ldb
, msg
,
1011 ac
->tree
, ac
->base
, ac
->scope
, &matched
);
1012 if (ret
!= LDB_SUCCESS
) {
1021 /* filter the attributes that the user wants */
1022 ret
= ltdb_filter_attrs(ac
, msg
, ac
->attrs
, &filtered_msg
);
1027 return LDB_ERR_OPERATIONS_ERROR
;
1030 ret
= ldb_module_send_entry(ac
->req
, filtered_msg
, NULL
);
1031 if (ret
!= LDB_SUCCESS
) {
1032 /* Regardless of success or failure, the msg
1033 * is the callbacks responsiblity, and should
1034 * not be talloc_free()'ed */
1035 ac
->request_terminated
= true;
1046 remove any duplicated entries in a indexed result
1048 static void ltdb_dn_list_remove_duplicates(struct dn_list
*list
)
1050 unsigned int i
, new_count
;
1052 if (list
->count
< 2) {
1056 TYPESAFE_QSORT(list
->dn
, list
->count
, dn_list_cmp
);
1059 for (i
=1; i
<list
->count
; i
++) {
1060 if (dn_list_cmp(&list
->dn
[i
], &list
->dn
[new_count
-1]) != 0) {
1061 if (new_count
!= i
) {
1062 list
->dn
[new_count
] = list
->dn
[i
];
1068 list
->count
= new_count
;
1072 search the database with a LDAP-like expression using indexes
1073 returns -1 if an indexed search is not possible, in which
1074 case the caller should call ltdb_search_full()
1076 int ltdb_search_indexed(struct ltdb_context
*ac
, uint32_t *match_count
)
1078 struct ldb_context
*ldb
= ldb_module_get_ctx(ac
->module
);
1079 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(ac
->module
), struct ltdb_private
);
1080 struct dn_list
*dn_list
;
1083 /* see if indexing is enabled */
1084 if (!ltdb
->cache
->attribute_indexes
&&
1085 !ltdb
->cache
->one_level_indexes
&&
1086 ac
->scope
!= LDB_SCOPE_BASE
) {
1087 /* fallback to a full search */
1088 return LDB_ERR_OPERATIONS_ERROR
;
1091 dn_list
= talloc_zero(ac
, struct dn_list
);
1092 if (dn_list
== NULL
) {
1093 return ldb_module_oom(ac
->module
);
1096 switch (ac
->scope
) {
1097 case LDB_SCOPE_BASE
:
1098 dn_list
->dn
= talloc_array(dn_list
, struct ldb_val
, 1);
1099 if (dn_list
->dn
== NULL
) {
1100 talloc_free(dn_list
);
1101 return ldb_module_oom(ac
->module
);
1103 dn_list
->dn
[0].data
= discard_const_p(unsigned char, ldb_dn_get_linearized(ac
->base
));
1104 if (dn_list
->dn
[0].data
== NULL
) {
1105 talloc_free(dn_list
);
1106 return ldb_module_oom(ac
->module
);
1108 dn_list
->dn
[0].length
= strlen((char *)dn_list
->dn
[0].data
);
1112 case LDB_SCOPE_ONELEVEL
:
1114 struct dn_list
*idx_one_tree_list
= NULL
;
1115 if (!ltdb
->cache
->one_level_indexes
) {
1116 talloc_free(dn_list
);
1117 return LDB_ERR_OPERATIONS_ERROR
;
1119 ret
= ltdb_index_dn_one(ac
->module
, ac
->base
, dn_list
);
1120 if (ret
!= LDB_SUCCESS
) {
1121 talloc_free(dn_list
);
1126 * If we have too many matches, also try the filter
1127 * tree and do index work there
1129 * We only do this in the GUID index mode, which is
1130 * O(n*log(m)) otherwise the intersection below will
1131 * be too costly at O(n*m).
1134 = talloc_zero(ac
, struct dn_list
);
1135 if (idx_one_tree_list
== NULL
) {
1136 return ldb_module_oom(ac
->module
);
1139 if (!ltdb
->cache
->attribute_indexes
) {
1140 talloc_free(idx_one_tree_list
);
1141 talloc_free(dn_list
);
1142 return LDB_ERR_OPERATIONS_ERROR
;
1145 * Here we load the index for the tree.
1147 ret
= ltdb_index_dn(ac
->module
, ltdb
, ac
->tree
,
1149 if (ret
!= LDB_SUCCESS
) {
1150 talloc_free(idx_one_tree_list
);
1151 talloc_free(dn_list
);
1156 * We have to avoid the O(n*m) behaviour here blowing
1157 * up, so we only intersect the lists if it will
1160 if (idx_one_tree_list
->count
< 10) {
1161 if (!list_intersect(ldb
, ltdb
,
1162 dn_list
, idx_one_tree_list
)) {
1163 talloc_free(idx_one_tree_list
);
1164 talloc_free(dn_list
);
1165 return LDB_ERR_OPERATIONS_ERROR
;
1168 talloc_free(idx_one_tree_list
);
1172 case LDB_SCOPE_SUBTREE
:
1173 case LDB_SCOPE_DEFAULT
:
1174 if (!ltdb
->cache
->attribute_indexes
) {
1175 talloc_free(dn_list
);
1176 return LDB_ERR_OPERATIONS_ERROR
;
1178 ret
= ltdb_index_dn(ac
->module
, ltdb
, ac
->tree
, dn_list
);
1179 if (ret
!= LDB_SUCCESS
) {
1180 talloc_free(dn_list
);
1183 ltdb_dn_list_remove_duplicates(dn_list
);
1187 ret
= ltdb_index_filter(ltdb
, dn_list
, ac
, match_count
);
1188 talloc_free(dn_list
);
1193 * @brief Add a DN in the index list of a given attribute name/value pair
1195 * This function will add the DN in the index list for the index for
1196 * the given attribute name and value.
1198 * @param[in] module A ldb_module structure
1200 * @param[in] dn The string representation of the DN as it
1201 * will be stored in the index entry
1203 * @param[in] el A ldb_message_element array, one of the entry
1204 * referred by the v_idx is the attribute name and
1205 * value pair which will be used to construct the
1208 * @param[in] v_idx The index of element in the el array to use
1210 * @return An ldb error code
1212 static int ltdb_index_add1(struct ldb_module
*module
,
1213 struct ltdb_private
*ltdb
,
1215 struct ldb_message_element
*el
, int v_idx
)
1217 struct ldb_context
*ldb
;
1218 struct ldb_dn
*dn_key
;
1220 const struct ldb_schema_attribute
*a
;
1221 struct dn_list
*list
;
1224 ldb
= ldb_module_get_ctx(module
);
1226 list
= talloc_zero(module
, struct dn_list
);
1228 return LDB_ERR_OPERATIONS_ERROR
;
1231 dn_key
= ltdb_index_key(ldb
, el
->name
, &el
->values
[v_idx
], &a
);
1234 return LDB_ERR_OPERATIONS_ERROR
;
1236 talloc_steal(list
, dn_key
);
1238 ret
= ltdb_dn_list_load(module
, dn_key
, list
);
1239 if (ret
!= LDB_SUCCESS
&& ret
!= LDB_ERR_NO_SUCH_OBJECT
) {
1244 if (list
->count
> 0 &&
1245 a
->flags
& LDB_ATTR_FLAG_UNIQUE_INDEX
) {
1247 * We do not want to print info about a possibly
1248 * confidential DN that the conflict was with in the
1249 * user-visible error string
1251 ldb_debug(ldb
, LDB_DEBUG_WARNING
,
1252 __location__
": unique index violation on %s in %s, "
1253 "conficts with %*.*s in %s",
1255 (int)list
->dn
[0].length
,
1256 (int)list
->dn
[0].length
,
1258 ldb_dn_get_linearized(dn_key
));
1259 ldb_asprintf_errstring(ldb
, __location__
": unique index violation on %s in %s",
1262 return LDB_ERR_ENTRY_ALREADY_EXISTS
;
1265 /* overallocate the list a bit, to reduce the number of
1266 * realloc trigered copies */
1267 alloc_len
= ((list
->count
+1)+7) & ~7;
1268 list
->dn
= talloc_realloc(list
, list
->dn
, struct ldb_val
, alloc_len
);
1269 if (list
->dn
== NULL
) {
1271 return LDB_ERR_OPERATIONS_ERROR
;
1274 list
->dn
[list
->count
].data
1275 = (uint8_t *)talloc_strdup(list
->dn
, dn
);
1276 if (list
->dn
[list
->count
].data
== NULL
) {
1278 return LDB_ERR_OPERATIONS_ERROR
;
1280 list
->dn
[list
->count
].length
= strlen(dn
);
1283 ret
= ltdb_dn_list_store(module
, dn_key
, list
);
1291 add index entries for one elements in a message
1293 static int ltdb_index_add_el(struct ldb_module
*module
,
1294 struct ltdb_private
*ltdb
,
1296 struct ldb_message_element
*el
)
1299 for (i
= 0; i
< el
->num_values
; i
++) {
1300 int ret
= ltdb_index_add1(module
, ltdb
,
1302 if (ret
!= LDB_SUCCESS
) {
1311 add index entries for all elements in a message
1313 static int ltdb_index_add_all(struct ldb_module
*module
,
1314 struct ltdb_private
*ltdb
,
1316 struct ldb_message_element
*elements
,
1317 unsigned int num_el
)
1325 if (!ltdb
->cache
->attribute_indexes
) {
1326 /* no indexed fields */
1330 for (i
= 0; i
< num_el
; i
++) {
1332 if (!ltdb_is_indexed(module
, ltdb
, elements
[i
].name
)) {
1335 ret
= ltdb_index_add_el(module
, ltdb
, dn
, &elements
[i
]);
1336 if (ret
!= LDB_SUCCESS
) {
1337 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1338 ldb_asprintf_errstring(ldb
,
1339 __location__
": Failed to re-index %s in %s - %s",
1340 elements
[i
].name
, dn
, ldb_errstring(ldb
));
1350 insert a one level index for a message
1352 static int ltdb_index_onelevel(struct ldb_module
*module
,
1353 const struct ldb_message
*msg
, int add
)
1355 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
),
1356 struct ltdb_private
);
1357 struct ldb_message_element el
;
1363 /* We index for ONE Level only if requested */
1364 if (!ltdb
->cache
->one_level_indexes
) {
1368 pdn
= ldb_dn_get_parent(module
, msg
->dn
);
1370 return LDB_ERR_OPERATIONS_ERROR
;
1373 dn
= ldb_dn_get_linearized(msg
->dn
);
1376 return LDB_ERR_OPERATIONS_ERROR
;
1379 val
.data
= (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn
));
1380 if (val
.data
== NULL
) {
1382 return LDB_ERR_OPERATIONS_ERROR
;
1385 val
.length
= strlen((char *)val
.data
);
1386 el
.name
= LTDB_IDXONE
;
1391 ret
= ltdb_index_add1(module
, ltdb
, dn
, &el
, 0);
1392 } else { /* delete */
1393 ret
= ltdb_index_del_value(module
, ltdb
, msg
->dn
, &el
, 0);
1402 add the index entries for a new element in a record
1403 The caller guarantees that these element values are not yet indexed
1405 int ltdb_index_add_element(struct ldb_module
*module
,
1406 struct ltdb_private
*ltdb
,
1408 struct ldb_message_element
*el
)
1410 if (ldb_dn_is_special(dn
)) {
1413 if (!ltdb_is_indexed(module
, ltdb
, el
->name
)) {
1416 return ltdb_index_add_el(module
, ltdb
,
1417 ldb_dn_get_linearized(dn
), el
);
1421 add the index entries for a new record
1423 int ltdb_index_add_new(struct ldb_module
*module
,
1424 struct ltdb_private
*ltdb
,
1425 const struct ldb_message
*msg
)
1430 if (ldb_dn_is_special(msg
->dn
)) {
1434 dn
= ldb_dn_get_linearized(msg
->dn
);
1436 return LDB_ERR_OPERATIONS_ERROR
;
1439 ret
= ltdb_index_add_all(module
, ltdb
, dn
, msg
->elements
,
1441 if (ret
!= LDB_SUCCESS
) {
1445 return ltdb_index_onelevel(module
, msg
, 1);
1450 delete an index entry for one message element
1452 int ltdb_index_del_value(struct ldb_module
*module
,
1453 struct ltdb_private
*ltdb
,
1455 struct ldb_message_element
*el
, unsigned int v_idx
)
1457 struct ldb_context
*ldb
;
1458 struct ldb_dn
*dn_key
;
1462 struct dn_list
*list
;
1464 ldb
= ldb_module_get_ctx(module
);
1466 dn_str
= ldb_dn_get_linearized(dn
);
1467 if (dn_str
== NULL
) {
1468 return LDB_ERR_OPERATIONS_ERROR
;
1471 if (dn_str
[0] == '@') {
1475 dn_key
= ltdb_index_key(ldb
, el
->name
, &el
->values
[v_idx
], NULL
);
1477 return LDB_ERR_OPERATIONS_ERROR
;
1480 list
= talloc_zero(dn_key
, struct dn_list
);
1482 talloc_free(dn_key
);
1483 return LDB_ERR_OPERATIONS_ERROR
;
1486 ret
= ltdb_dn_list_load(module
, dn_key
, list
);
1487 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
1488 /* it wasn't indexed. Did we have an earlier error? If we did then
1490 talloc_free(dn_key
);
1494 if (ret
!= LDB_SUCCESS
) {
1495 talloc_free(dn_key
);
1499 i
= ltdb_dn_list_find_str(ltdb
, list
, dn_str
);
1501 /* nothing to delete */
1502 talloc_free(dn_key
);
1506 j
= (unsigned int) i
;
1507 if (j
!= list
->count
- 1) {
1508 memmove(&list
->dn
[j
], &list
->dn
[j
+1], sizeof(list
->dn
[0])*(list
->count
- (j
+1)));
1511 if (list
->count
== 0) {
1512 talloc_free(list
->dn
);
1515 list
->dn
= talloc_realloc(list
, list
->dn
, struct ldb_val
, list
->count
);
1518 ret
= ltdb_dn_list_store(module
, dn_key
, list
);
1520 talloc_free(dn_key
);
1526 delete the index entries for a element
1527 return -1 on failure
1529 int ltdb_index_del_element(struct ldb_module
*module
,
1530 struct ltdb_private
*ltdb
,
1532 struct ldb_message_element
*el
)
1538 if (!ltdb
->cache
->attribute_indexes
) {
1539 /* no indexed fields */
1543 dn_str
= ldb_dn_get_linearized(dn
);
1544 if (dn_str
== NULL
) {
1545 return LDB_ERR_OPERATIONS_ERROR
;
1548 if (dn_str
[0] == '@') {
1552 if (!ltdb_is_indexed(module
, ltdb
, el
->name
)) {
1555 for (i
= 0; i
< el
->num_values
; i
++) {
1556 ret
= ltdb_index_del_value(module
, ltdb
, dn
, el
, i
);
1557 if (ret
!= LDB_SUCCESS
) {
1566 delete the index entries for a record
1567 return -1 on failure
1569 int ltdb_index_delete(struct ldb_module
*module
, const struct ldb_message
*msg
)
1571 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1575 if (ldb_dn_is_special(msg
->dn
)) {
1579 ret
= ltdb_index_onelevel(module
, msg
, 0);
1580 if (ret
!= LDB_SUCCESS
) {
1584 if (!ltdb
->cache
->attribute_indexes
) {
1585 /* no indexed fields */
1589 for (i
= 0; i
< msg
->num_elements
; i
++) {
1590 ret
= ltdb_index_del_element(module
, ltdb
,
1591 msg
->dn
, &msg
->elements
[i
]);
1592 if (ret
!= LDB_SUCCESS
) {
1602 traversal function that deletes all @INDEX records
1604 static int delete_index(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1606 struct ldb_module
*module
= state
;
1607 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1608 const char *dnstr
= "DN=" LTDB_INDEX
":";
1609 struct dn_list list
;
1614 if (strncmp((char *)key
.dptr
, dnstr
, strlen(dnstr
)) != 0) {
1617 /* we need to put a empty list in the internal tdb for this
1622 /* the offset of 3 is to remove the DN= prefix. */
1623 v
.data
= key
.dptr
+ 3;
1624 v
.length
= strnlen((char *)key
.dptr
, key
.dsize
) - 3;
1626 dn
= ldb_dn_from_ldb_val(ltdb
, ldb_module_get_ctx(module
), &v
);
1627 ret
= ltdb_dn_list_store(module
, dn
, &list
);
1628 if (ret
!= LDB_SUCCESS
) {
1629 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
1630 "Unable to store null index for %s\n",
1631 ldb_dn_get_linearized(dn
));
1639 struct ltdb_reindex_context
{
1640 struct ldb_module
*module
;
1645 traversal function that adds @INDEX records during a re index
1647 static int re_key(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1649 struct ldb_context
*ldb
;
1650 struct ltdb_reindex_context
*ctx
= (struct ltdb_reindex_context
*)state
;
1651 struct ldb_module
*module
= ctx
->module
;
1652 struct ldb_message
*msg
;
1653 unsigned int nb_elements_in_db
;
1654 const struct ldb_val val
= {
1656 .length
= data
.dsize
,
1662 ldb
= ldb_module_get_ctx(module
);
1664 if (key
.dsize
> 4 &&
1665 memcmp(key
.dptr
, "DN=@", 4) == 0) {
1669 is_record
= ltdb_key_is_record(key
);
1670 if (is_record
== false) {
1674 msg
= ldb_msg_new(module
);
1679 ret
= ldb_unpack_data_only_attr_list_flags(ldb
, &val
,
1682 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
,
1683 &nb_elements_in_db
);
1685 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid data for index %s\n",
1686 ldb_dn_get_linearized(msg
->dn
));
1692 if (msg
->dn
== NULL
) {
1693 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1694 "Refusing to re-index as GUID "
1695 "key %*.*s with no DN\n",
1696 (int)key
.dsize
, (int)key
.dsize
,
1702 /* check if the DN key has changed, perhaps due to the
1703 case insensitivity of an element changing */
1704 key2
= ltdb_key(module
, msg
->dn
);
1705 if (key2
.dptr
== NULL
) {
1706 /* probably a corrupt record ... darn */
1707 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid DN in re_index: %s",
1708 ldb_dn_get_linearized(msg
->dn
));
1712 if (key
.dsize
!= key2
.dsize
||
1713 (memcmp(key
.dptr
, key2
.dptr
, key
.dsize
) != 0)) {
1715 tdb_ret
= tdb_delete(tdb
, key
);
1717 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1718 "Failed to delete %*.*s "
1719 "for rekey as %*.*s: %s",
1720 (int)key
.dsize
, (int)key
.dsize
,
1721 (const char *)key
.dptr
,
1722 (int)key2
.dsize
, (int)key2
.dsize
,
1723 (const char *)key
.dptr
,
1725 ctx
->error
= ltdb_err_map(tdb_error(tdb
));
1728 tdb_ret
= tdb_store(tdb
, key2
, data
, 0);
1730 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1731 "Failed to rekey %*.*s as %*.*s: %s",
1732 (int)key
.dsize
, (int)key
.dsize
,
1733 (const char *)key
.dptr
,
1734 (int)key2
.dsize
, (int)key2
.dsize
,
1735 (const char *)key
.dptr
,
1737 ctx
->error
= ltdb_err_map(tdb_error(tdb
));
1741 talloc_free(key2
.dptr
);
1749 traversal function that adds @INDEX records during a re index
1751 static int re_index(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1753 struct ldb_context
*ldb
;
1754 struct ltdb_reindex_context
*ctx
= (struct ltdb_reindex_context
*)state
;
1755 struct ldb_module
*module
= ctx
->module
;
1756 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
),
1757 struct ltdb_private
);
1758 struct ldb_message
*msg
;
1759 const char *dn
= NULL
;
1760 unsigned int nb_elements_in_db
;
1761 const struct ldb_val val
= {
1763 .length
= data
.dsize
,
1768 ldb
= ldb_module_get_ctx(module
);
1770 if (key
.dsize
> 4 &&
1771 memcmp(key
.dptr
, "DN=@", 4) == 0) {
1775 is_record
= ltdb_key_is_record(key
);
1776 if (is_record
== false) {
1780 msg
= ldb_msg_new(module
);
1785 ret
= ldb_unpack_data_only_attr_list_flags(ldb
, &val
,
1788 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
,
1789 &nb_elements_in_db
);
1791 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid data for index %s\n",
1792 ldb_dn_get_linearized(msg
->dn
));
1798 if (msg
->dn
== NULL
) {
1799 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1800 "Refusing to re-index as GUID "
1801 "key %*.*s with no DN\n",
1802 (int)key
.dsize
, (int)key
.dsize
,
1807 dn
= ldb_dn_get_linearized(msg
->dn
);
1810 ret
= ltdb_index_onelevel(module
, msg
, 1);
1811 if (ret
!= LDB_SUCCESS
) {
1812 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1813 "Adding special ONE LEVEL index failed (%s)!",
1814 ldb_dn_get_linearized(msg
->dn
));
1819 ret
= ltdb_index_add_all(module
, ltdb
, dn
,
1820 msg
->elements
, msg
->num_elements
);
1822 if (ret
!= LDB_SUCCESS
) {
1834 force a complete reindex of the database
1836 int ltdb_reindex(struct ldb_module
*module
)
1838 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1840 struct ltdb_reindex_context ctx
;
1842 if (ltdb_cache_reload(module
) != 0) {
1843 return LDB_ERR_OPERATIONS_ERROR
;
1847 * Ensure we read (and so remove) the entries from the real
1848 * DB, no values stored so far are any use as we want to do a
1851 ltdb_index_transaction_cancel(module
);
1853 ret
= ltdb_index_transaction_start(module
);
1854 if (ret
!= LDB_SUCCESS
) {
1858 /* first traverse the database deleting any @INDEX records by
1859 * putting NULL entries in the in-memory tdb
1861 ret
= tdb_traverse(ltdb
->tdb
, delete_index
, module
);
1863 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1864 ldb_asprintf_errstring(ldb
, "index deletion traverse failed: %s",
1865 ldb_errstring(ldb
));
1866 return LDB_ERR_OPERATIONS_ERROR
;
1869 /* if we don't have indexes we have nothing todo */
1870 if (!ltdb
->cache
->attribute_indexes
) {
1874 ctx
.module
= module
;
1877 /* now traverse adding any indexes for normal LDB records */
1878 ret
= tdb_traverse(ltdb
->tdb
, re_key
, &ctx
);
1880 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1881 ldb_asprintf_errstring(ldb
, "key correction traverse failed: %s",
1882 ldb_errstring(ldb
));
1883 return LDB_ERR_OPERATIONS_ERROR
;
1886 if (ctx
.error
!= LDB_SUCCESS
) {
1887 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1888 ldb_asprintf_errstring(ldb
, "reindexing failed: %s", ldb_errstring(ldb
));
1894 /* now traverse adding any indexes for normal LDB records */
1895 ret
= tdb_traverse(ltdb
->tdb
, re_index
, &ctx
);
1897 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1898 ldb_asprintf_errstring(ldb
, "reindexing traverse failed: %s",
1899 ldb_errstring(ldb
));
1900 return LDB_ERR_OPERATIONS_ERROR
;
1903 if (ctx
.error
!= LDB_SUCCESS
) {
1904 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1905 ldb_asprintf_errstring(ldb
, "reindexing failed: %s", ldb_errstring(ldb
));