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
42 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
);
60 /* compare two DN entries in a dn_list. Take account of possible
61 * differences in string termination */
62 static int dn_list_cmp(const struct ldb_val
*v1
, const struct ldb_val
*v2
)
64 int ret
= strncmp((char *)v1
->data
, (char *)v2
->data
, v1
->length
);
65 if (ret
!= 0) return ret
;
66 if (v2
->length
> v1
->length
&& v2
->data
[v1
->length
] != 0) {
74 find a entry in a dn_list, using a ldb_val. Uses a case sensitive
75 comparison with the dn returns -1 if not found
77 static int ltdb_dn_list_find_val(const struct dn_list
*list
, const struct ldb_val
*v
)
80 for (i
=0; i
<list
->count
; i
++) {
81 if (dn_list_cmp(&list
->dn
[i
], v
) == 0) return i
;
87 find a entry in a dn_list. Uses a case sensitive comparison with the dn
88 returns -1 if not found
90 static int ltdb_dn_list_find_str(struct dn_list
*list
, const char *dn
)
93 v
.data
= discard_const_p(unsigned char, dn
);
94 v
.length
= strlen(dn
);
95 return ltdb_dn_list_find_val(list
, &v
);
99 return the @IDX list in an index entry for a dn as a
102 static int ltdb_dn_list_load(struct ldb_module
*module
,
103 struct ldb_dn
*dn
, struct dn_list
*list
)
105 struct ldb_message
*msg
;
107 struct ldb_message_element
*el
;
108 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
110 struct dn_list
*list2
;
116 /* see if we have any in-memory index entries */
117 if (ltdb
->idxptr
== NULL
||
118 ltdb
->idxptr
->itdb
== NULL
) {
122 key
.dptr
= discard_const_p(unsigned char, ldb_dn_get_linearized(dn
));
123 key
.dsize
= strlen((char *)key
.dptr
);
125 rec
= tdb_fetch(ltdb
->idxptr
->itdb
, key
);
126 if (rec
.dptr
== NULL
) {
130 /* we've found an in-memory index entry */
131 if (rec
.dsize
!= sizeof(void *)) {
133 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
134 "Bad internal index size %u", (unsigned)rec
.dsize
);
135 return LDB_ERR_OPERATIONS_ERROR
;
137 list2
= *(struct dn_list
**)rec
.dptr
;
144 msg
= ldb_msg_new(list
);
146 return LDB_ERR_OPERATIONS_ERROR
;
149 ret
= ltdb_search_dn1(module
, dn
, msg
);
150 if (ret
!= LDB_SUCCESS
) {
154 /* TODO: check indexing version number */
156 el
= ldb_msg_find_element(msg
, LTDB_IDX
);
162 /* we avoid copying the strings by stealing the list */
163 list
->dn
= talloc_steal(list
, el
->values
);
164 list
->count
= el
->num_values
;
171 save a dn_list into a full @IDX style record
173 static int ltdb_dn_list_store_full(struct ldb_module
*module
, struct ldb_dn
*dn
,
174 struct dn_list
*list
)
176 struct ldb_message
*msg
;
179 msg
= ldb_msg_new(module
);
181 ldb_module_oom(module
);
182 return LDB_ERR_OPERATIONS_ERROR
;
185 ret
= ldb_msg_add_fmt(msg
, LTDB_IDXVERSION
, "%u", LTDB_INDEXING_VERSION
);
186 if (ret
!= LDB_SUCCESS
) {
187 ldb_module_oom(module
);
188 return LDB_ERR_OPERATIONS_ERROR
;
192 if (list
->count
> 0) {
193 struct ldb_message_element
*el
;
195 ret
= ldb_msg_add_empty(msg
, LTDB_IDX
, LDB_FLAG_MOD_ADD
, &el
);
196 if (ret
!= LDB_SUCCESS
) {
197 ldb_module_oom(module
);
199 return LDB_ERR_OPERATIONS_ERROR
;
201 el
->values
= list
->dn
;
202 el
->num_values
= list
->count
;
205 ret
= ltdb_store(module
, msg
, TDB_REPLACE
);
211 save a dn_list into the database, in either @IDX or internal format
213 static int ltdb_dn_list_store(struct ldb_module
*module
, struct ldb_dn
*dn
,
214 struct dn_list
*list
)
216 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
219 struct dn_list
*list2
;
221 if (ltdb
->idxptr
== NULL
) {
222 return ltdb_dn_list_store_full(module
, dn
, list
);
225 if (ltdb
->idxptr
->itdb
== NULL
) {
226 ltdb
->idxptr
->itdb
= tdb_open(NULL
, 1000, TDB_INTERNAL
, O_RDWR
, 0);
227 if (ltdb
->idxptr
->itdb
== NULL
) {
228 return LDB_ERR_OPERATIONS_ERROR
;
232 key
.dptr
= discard_const_p(unsigned char, ldb_dn_get_linearized(dn
));
233 key
.dsize
= strlen((char *)key
.dptr
);
235 rec
= tdb_fetch(ltdb
->idxptr
->itdb
, key
);
236 if (rec
.dptr
!= NULL
) {
237 if (rec
.dsize
!= sizeof(void *)) {
239 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
240 "Bad internal index size %u", (unsigned)rec
.dsize
);
241 return LDB_ERR_OPERATIONS_ERROR
;
243 list2
= *(struct dn_list
**)rec
.dptr
;
245 list2
->dn
= talloc_steal(list2
, list
->dn
);
246 list2
->count
= list
->count
;
250 list2
= talloc(ltdb
->idxptr
, struct dn_list
);
252 return LDB_ERR_OPERATIONS_ERROR
;
254 list2
->dn
= talloc_steal(list2
, list
->dn
);
255 list2
->count
= list
->count
;
257 rec
.dptr
= (uint8_t *)&list2
;
258 rec
.dsize
= sizeof(void *);
260 ret
= tdb_store(ltdb
->idxptr
->itdb
, key
, rec
, TDB_INSERT
);
266 traverse function for storing the in-memory index entries on disk
268 static int ltdb_index_traverse_store(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
270 struct ldb_module
*module
= state
;
271 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
273 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
275 struct dn_list
*list
;
277 if (data
.dsize
!= sizeof(void *)) {
278 ldb_asprintf_errstring(ldb
, "Bad internal index size %u", (unsigned)data
.dsize
);
279 ltdb
->idxptr
->error
= LDB_ERR_OPERATIONS_ERROR
;
283 list
= *(struct dn_list
**)data
.dptr
;
286 v
.length
= key
.dsize
;
288 dn
= ldb_dn_from_ldb_val(module
, ldb
, &v
);
290 ltdb
->idxptr
->error
= LDB_ERR_OPERATIONS_ERROR
;
294 ltdb
->idxptr
->error
= ltdb_dn_list_store_full(module
, dn
, list
);
296 return ltdb
->idxptr
->error
;
299 /* cleanup the idxptr mode when transaction commits */
300 int ltdb_index_transaction_commit(struct ldb_module
*module
)
302 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
305 if (ltdb
->idxptr
->itdb
) {
306 tdb_traverse(ltdb
->idxptr
->itdb
, ltdb_index_traverse_store
, module
);
307 tdb_close(ltdb
->idxptr
->itdb
);
310 ret
= ltdb
->idxptr
->error
;
312 if (ret
!= LDB_SUCCESS
) {
313 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
314 ldb_asprintf_errstring(ldb
, "Failed to store index records in transaction commit");
317 talloc_free(ltdb
->idxptr
);
322 /* cleanup the idxptr mode when transaction cancels */
323 int ltdb_index_transaction_cancel(struct ldb_module
*module
)
325 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
326 if (ltdb
->idxptr
&& ltdb
->idxptr
->itdb
) {
327 tdb_close(ltdb
->idxptr
->itdb
);
329 talloc_free(ltdb
->idxptr
);
336 return the dn key to be used for an index
337 the caller is responsible for freeing
339 static struct ldb_dn
*ltdb_index_key(struct ldb_context
*ldb
,
340 const char *attr
, const struct ldb_val
*value
,
341 const struct ldb_schema_attribute
**ap
)
345 const struct ldb_schema_attribute
*a
;
349 attr_folded
= ldb_attr_casefold(ldb
, attr
);
354 a
= ldb_schema_attribute_by_name(ldb
, attr
);
358 r
= a
->syntax
->canonicalise_fn(ldb
, ldb
, value
, &v
);
359 if (r
!= LDB_SUCCESS
) {
360 const char *errstr
= ldb_errstring(ldb
);
361 /* canonicalisation can be refused. For example,
362 a attribute that takes wildcards will refuse to canonicalise
363 if the value contains a wildcard */
364 ldb_asprintf_errstring(ldb
, "Failed to create index key for attribute '%s':%s%s%s",
365 attr
, ldb_strerror(r
), (errstr
?":":""), (errstr
?errstr
:""));
366 talloc_free(attr_folded
);
369 if (ldb_should_b64_encode(ldb
, &v
)) {
370 char *vstr
= ldb_base64_encode(ldb
, (char *)v
.data
, v
.length
);
371 if (!vstr
) return NULL
;
372 ret
= ldb_dn_new_fmt(ldb
, ldb
, "%s:%s::%s", LTDB_INDEX
, attr_folded
, vstr
);
375 ret
= ldb_dn_new_fmt(ldb
, ldb
, "%s:%s:%.*s", LTDB_INDEX
, attr_folded
, (int)v
.length
, (char *)v
.data
);
378 if (v
.data
!= value
->data
) {
381 talloc_free(attr_folded
);
387 see if a attribute value is in the list of indexed attributes
389 static bool ltdb_is_indexed(const struct ldb_message
*index_list
, const char *attr
)
392 struct ldb_message_element
*el
;
394 el
= ldb_msg_find_element(index_list
, LTDB_IDXATTR
);
398 for (i
=0; i
<el
->num_values
; i
++) {
399 if (ldb_attr_cmp((char *)el
->values
[i
].data
, attr
) == 0) {
407 in the following logic functions, the return value is treated as
410 LDB_SUCCESS: we found some matching index values
412 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
414 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
415 we'll need a full search
419 return a list of dn's that might match a simple indexed search (an
420 equality search only)
422 static int ltdb_index_dn_simple(struct ldb_module
*module
,
423 const struct ldb_parse_tree
*tree
,
424 const struct ldb_message
*index_list
,
425 struct dn_list
*list
)
427 struct ldb_context
*ldb
;
431 ldb
= ldb_module_get_ctx(module
);
436 /* if the attribute isn't in the list of indexed attributes then
437 this node needs a full search */
438 if (!ltdb_is_indexed(index_list
, tree
->u
.equality
.attr
)) {
439 return LDB_ERR_OPERATIONS_ERROR
;
442 /* the attribute is indexed. Pull the list of DNs that match the
444 dn
= ltdb_index_key(ldb
, tree
->u
.equality
.attr
, &tree
->u
.equality
.value
, NULL
);
445 if (!dn
) return LDB_ERR_OPERATIONS_ERROR
;
447 ret
= ltdb_dn_list_load(module
, dn
, list
);
453 static bool list_union(struct ldb_context
*, struct dn_list
*, const struct dn_list
*);
456 return a list of dn's that might match a leaf indexed search
458 static int ltdb_index_dn_leaf(struct ldb_module
*module
,
459 const struct ldb_parse_tree
*tree
,
460 const struct ldb_message
*index_list
,
461 struct dn_list
*list
)
463 if (ldb_attr_dn(tree
->u
.equality
.attr
) == 0) {
464 list
->dn
= talloc_array(list
, struct ldb_val
, 1);
465 if (list
->dn
== NULL
) {
466 ldb_module_oom(module
);
467 return LDB_ERR_OPERATIONS_ERROR
;
469 list
->dn
[0] = tree
->u
.equality
.value
;
473 return ltdb_index_dn_simple(module
, tree
, index_list
, list
);
481 static bool list_intersect(struct ldb_context
*ldb
,
482 struct dn_list
*list
, const struct dn_list
*list2
)
484 struct dn_list
*list3
;
487 if (list
->count
== 0) {
491 if (list2
->count
== 0) {
498 /* the indexing code is allowed to return a longer list than
499 what really matches, as all results are filtered by the
500 full expression at the end - this shortcut avoids a lot of
501 work in some cases */
502 if (list
->count
< 2 && list2
->count
> 10) {
505 if (list2
->count
< 2 && list
->count
> 10) {
506 list
->count
= list2
->count
;
507 list
->dn
= list2
->dn
;
508 /* note that list2 may not be the parent of list2->dn,
509 as list2->dn may be owned by ltdb->idxptr. In that
510 case we expect this reparent call to fail, which is
512 talloc_reparent(list2
, list
, list2
->dn
);
516 list3
= talloc_zero(list
, struct dn_list
);
521 list3
->dn
= talloc_array(list3
, struct ldb_val
, list
->count
);
528 for (i
=0;i
<list
->count
;i
++) {
529 if (ltdb_dn_list_find_val(list2
, &list
->dn
[i
]) != -1) {
530 list3
->dn
[list3
->count
] = list
->dn
[i
];
535 list
->dn
= talloc_steal(list
, list3
->dn
);
536 list
->count
= list3
->count
;
547 static bool list_union(struct ldb_context
*ldb
,
548 struct dn_list
*list
, const struct dn_list
*list2
)
552 if (list2
->count
== 0) {
557 if (list
->count
== 0) {
559 list
->count
= list2
->count
;
560 list
->dn
= list2
->dn
;
561 /* note that list2 may not be the parent of list2->dn,
562 as list2->dn may be owned by ltdb->idxptr. In that
563 case we expect this reparent call to fail, which is
565 talloc_reparent(list2
, list
, list2
->dn
);
569 dn3
= talloc_array(list
, struct ldb_val
, list
->count
+ list2
->count
);
575 /* we allow for duplicates here, and get rid of them later */
576 memcpy(dn3
, list
->dn
, sizeof(list
->dn
[0])*list
->count
);
577 memcpy(dn3
+list
->count
, list2
->dn
, sizeof(list2
->dn
[0])*list2
->count
);
580 list
->count
+= list2
->count
;
585 static int ltdb_index_dn(struct ldb_module
*module
,
586 const struct ldb_parse_tree
*tree
,
587 const struct ldb_message
*index_list
,
588 struct dn_list
*list
);
592 process an OR list (a union)
594 static int ltdb_index_dn_or(struct ldb_module
*module
,
595 const struct ldb_parse_tree
*tree
,
596 const struct ldb_message
*index_list
,
597 struct dn_list
*list
)
599 struct ldb_context
*ldb
;
602 ldb
= ldb_module_get_ctx(module
);
607 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
608 struct dn_list
*list2
;
611 list2
= talloc_zero(list
, struct dn_list
);
613 return LDB_ERR_OPERATIONS_ERROR
;
616 ret
= ltdb_index_dn(module
, tree
->u
.list
.elements
[i
], index_list
, list2
);
618 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
624 if (ret
!= LDB_SUCCESS
) {
630 if (!list_union(ldb
, list
, list2
)) {
632 return LDB_ERR_OPERATIONS_ERROR
;
636 if (list
->count
== 0) {
637 return LDB_ERR_NO_SUCH_OBJECT
;
647 static int ltdb_index_dn_not(struct ldb_module
*module
,
648 const struct ldb_parse_tree
*tree
,
649 const struct ldb_message
*index_list
,
650 struct dn_list
*list
)
652 /* the only way to do an indexed not would be if we could
653 negate the not via another not or if we knew the total
654 number of database elements so we could know that the
655 existing expression covered the whole database.
657 instead, we just give up, and rely on a full index scan
658 (unless an outer & manages to reduce the list)
660 return LDB_ERR_OPERATIONS_ERROR
;
664 static bool ltdb_index_unique(struct ldb_context
*ldb
,
667 const struct ldb_schema_attribute
*a
;
668 a
= ldb_schema_attribute_by_name(ldb
, attr
);
669 if (a
->flags
& LDB_ATTR_FLAG_UNIQUE_INDEX
) {
676 process an AND expression (intersection)
678 static int ltdb_index_dn_and(struct ldb_module
*module
,
679 const struct ldb_parse_tree
*tree
,
680 const struct ldb_message
*index_list
,
681 struct dn_list
*list
)
683 struct ldb_context
*ldb
;
687 ldb
= ldb_module_get_ctx(module
);
692 /* in the first pass we only look for unique simple
693 equality tests, in the hope of avoiding having to look
695 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
696 const struct ldb_parse_tree
*subtree
= tree
->u
.list
.elements
[i
];
699 if (subtree
->operation
!= LDB_OP_EQUALITY
||
700 !ltdb_index_unique(ldb
, subtree
->u
.equality
.attr
)) {
704 ret
= ltdb_index_dn(module
, subtree
, index_list
, list
);
705 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
707 return LDB_ERR_NO_SUCH_OBJECT
;
709 if (ret
== LDB_SUCCESS
) {
710 /* a unique index match means we can
711 * stop. Note that we don't care if we return
712 * a few too many objects, due to later
718 /* now do a full intersection */
721 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
722 const struct ldb_parse_tree
*subtree
= tree
->u
.list
.elements
[i
];
723 struct dn_list
*list2
;
726 list2
= talloc_zero(list
, struct dn_list
);
728 ldb_module_oom(module
);
729 return LDB_ERR_OPERATIONS_ERROR
;
732 ret
= ltdb_index_dn(module
, subtree
, index_list
, list2
);
734 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
739 return LDB_ERR_NO_SUCH_OBJECT
;
742 if (ret
!= LDB_SUCCESS
) {
743 /* this didn't adding anything */
749 talloc_reparent(list2
, list
, list
->dn
);
750 list
->dn
= list2
->dn
;
751 list
->count
= list2
->count
;
753 } else if (!list_intersect(ldb
, list
, list2
)) {
755 return LDB_ERR_OPERATIONS_ERROR
;
758 if (list
->count
== 0) {
760 return LDB_ERR_NO_SUCH_OBJECT
;
763 if (list
->count
< 2) {
764 /* it isn't worth loading the next part of the tree */
770 /* none of the attributes were indexed */
771 return LDB_ERR_OPERATIONS_ERROR
;
778 return a list of matching objects using a one-level index
780 static int ltdb_index_dn_one(struct ldb_module
*module
,
781 struct ldb_dn
*parent_dn
,
782 struct dn_list
*list
)
784 struct ldb_context
*ldb
;
789 ldb
= ldb_module_get_ctx(module
);
791 /* work out the index key from the parent DN */
792 val
.data
= (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn
));
793 val
.length
= strlen((char *)val
.data
);
794 key
= ltdb_index_key(ldb
, LTDB_IDXONE
, &val
, NULL
);
797 return LDB_ERR_OPERATIONS_ERROR
;
800 ret
= ltdb_dn_list_load(module
, key
, list
);
802 if (ret
!= LDB_SUCCESS
) {
806 if (list
->count
== 0) {
807 return LDB_ERR_NO_SUCH_OBJECT
;
814 return a list of dn's that might match a indexed search or
815 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
817 static int ltdb_index_dn(struct ldb_module
*module
,
818 const struct ldb_parse_tree
*tree
,
819 const struct ldb_message
*index_list
,
820 struct dn_list
*list
)
822 int ret
= LDB_ERR_OPERATIONS_ERROR
;
824 switch (tree
->operation
) {
826 ret
= ltdb_index_dn_and(module
, tree
, index_list
, list
);
830 ret
= ltdb_index_dn_or(module
, tree
, index_list
, list
);
834 ret
= ltdb_index_dn_not(module
, tree
, index_list
, list
);
837 case LDB_OP_EQUALITY
:
838 ret
= ltdb_index_dn_leaf(module
, tree
, index_list
, list
);
841 case LDB_OP_SUBSTRING
:
846 case LDB_OP_EXTENDED
:
847 /* we can't index with fancy bitops yet */
848 ret
= LDB_ERR_OPERATIONS_ERROR
;
856 filter a candidate dn_list from an indexed search into a set of results
857 extracting just the given attributes
859 static int ltdb_index_filter(const struct dn_list
*dn_list
,
860 struct ltdb_context
*ac
,
861 uint32_t *match_count
)
863 struct ldb_context
*ldb
;
864 struct ldb_message
*msg
;
867 ldb
= ldb_module_get_ctx(ac
->module
);
869 for (i
= 0; i
< dn_list
->count
; i
++) {
873 msg
= ldb_msg_new(ac
);
875 return LDB_ERR_OPERATIONS_ERROR
;
878 dn
= ldb_dn_from_ldb_val(msg
, ldb
, &dn_list
->dn
[i
]);
881 return LDB_ERR_OPERATIONS_ERROR
;
884 ret
= ltdb_search_dn1(ac
->module
, dn
, msg
);
886 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
887 /* the record has disappeared? yes, this can happen */
892 if (ret
!= LDB_SUCCESS
&& ret
!= LDB_ERR_NO_SUCH_OBJECT
) {
893 /* an internal error */
895 return LDB_ERR_OPERATIONS_ERROR
;
898 if (!ldb_match_msg(ldb
, msg
,
899 ac
->tree
, ac
->base
, ac
->scope
)) {
904 /* filter the attributes that the user wants */
905 ret
= ltdb_filter_attrs(msg
, ac
->attrs
);
909 return LDB_ERR_OPERATIONS_ERROR
;
912 ret
= ldb_module_send_entry(ac
->req
, msg
, NULL
);
913 if (ret
!= LDB_SUCCESS
) {
914 ac
->request_terminated
= true;
925 remove any duplicated entries in a indexed result
927 static void ltdb_dn_list_remove_duplicates(struct dn_list
*list
)
931 if (list
->count
< 2) {
935 qsort(list
->dn
, list
->count
, sizeof(struct ldb_val
), (comparison_fn_t
) dn_list_cmp
);
938 for (i
=1; i
<list
->count
; i
++) {
939 if (dn_list_cmp(&list
->dn
[i
], &list
->dn
[new_count
-1]) != 0) {
940 if (new_count
!= i
) {
941 list
->dn
[new_count
] = list
->dn
[i
];
947 list
->count
= new_count
;
951 search the database with a LDAP-like expression using indexes
952 returns -1 if an indexed search is not possible, in which
953 case the caller should call ltdb_search_full()
955 int ltdb_search_indexed(struct ltdb_context
*ac
, uint32_t *match_count
)
957 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(ac
->module
), struct ltdb_private
);
958 struct dn_list
*dn_list
;
961 /* see if indexing is enabled */
962 if (!ltdb
->cache
->attribute_indexes
&&
963 !ltdb
->cache
->one_level_indexes
&&
964 ac
->scope
!= LDB_SCOPE_BASE
) {
965 /* fallback to a full search */
966 return LDB_ERR_OPERATIONS_ERROR
;
969 dn_list
= talloc_zero(ac
, struct dn_list
);
970 if (dn_list
== NULL
) {
971 ldb_module_oom(ac
->module
);
972 return LDB_ERR_OPERATIONS_ERROR
;
977 dn_list
->dn
= talloc_array(dn_list
, struct ldb_val
, 1);
978 if (dn_list
->dn
== NULL
) {
979 ldb_module_oom(ac
->module
);
980 talloc_free(dn_list
);
981 return LDB_ERR_OPERATIONS_ERROR
;
983 dn_list
->dn
[0].data
= discard_const_p(unsigned char, ldb_dn_get_linearized(ac
->base
));
984 if (dn_list
->dn
[0].data
== NULL
) {
985 ldb_module_oom(ac
->module
);
986 talloc_free(dn_list
);
987 return LDB_ERR_OPERATIONS_ERROR
;
989 dn_list
->dn
[0].length
= strlen((char *)dn_list
->dn
[0].data
);
993 case LDB_SCOPE_ONELEVEL
:
994 if (!ltdb
->cache
->one_level_indexes
) {
995 talloc_free(dn_list
);
996 return LDB_ERR_OPERATIONS_ERROR
;
998 ret
= ltdb_index_dn_one(ac
->module
, ac
->base
, dn_list
);
999 if (ret
!= LDB_SUCCESS
) {
1000 talloc_free(dn_list
);
1005 case LDB_SCOPE_SUBTREE
:
1006 case LDB_SCOPE_DEFAULT
:
1007 if (!ltdb
->cache
->attribute_indexes
) {
1008 talloc_free(dn_list
);
1009 return LDB_ERR_OPERATIONS_ERROR
;
1011 ret
= ltdb_index_dn(ac
->module
, ac
->tree
, ltdb
->cache
->indexlist
, dn_list
);
1012 if (ret
!= LDB_SUCCESS
) {
1013 talloc_free(dn_list
);
1016 ltdb_dn_list_remove_duplicates(dn_list
);
1020 ret
= ltdb_index_filter(dn_list
, ac
, match_count
);
1021 talloc_free(dn_list
);
1026 add an index entry for one message element
1028 static int ltdb_index_add1(struct ldb_module
*module
, const char *dn
,
1029 struct ldb_message_element
*el
, int v_idx
)
1031 struct ldb_context
*ldb
;
1032 struct ldb_dn
*dn_key
;
1034 const struct ldb_schema_attribute
*a
;
1035 struct dn_list
*list
;
1037 ldb
= ldb_module_get_ctx(module
);
1039 list
= talloc_zero(module
, struct dn_list
);
1041 return LDB_ERR_OPERATIONS_ERROR
;
1044 dn_key
= ltdb_index_key(ldb
, el
->name
, &el
->values
[v_idx
], &a
);
1047 return LDB_ERR_OPERATIONS_ERROR
;
1049 talloc_steal(list
, dn_key
);
1051 ret
= ltdb_dn_list_load(module
, dn_key
, list
);
1052 if (ret
!= LDB_SUCCESS
&& ret
!= LDB_ERR_NO_SUCH_OBJECT
) {
1057 if (ltdb_dn_list_find_str(list
, dn
) != -1) {
1062 if (list
->count
> 0 &&
1063 a
->flags
& LDB_ATTR_FLAG_UNIQUE_INDEX
) {
1064 return LDB_ERR_ENTRY_ALREADY_EXISTS
;
1067 list
->dn
= talloc_realloc(list
, list
->dn
, struct ldb_val
, list
->count
+1);
1068 if (list
->dn
== NULL
) {
1070 return LDB_ERR_OPERATIONS_ERROR
;
1072 list
->dn
[list
->count
].data
= discard_const_p(unsigned char, dn
);
1073 list
->dn
[list
->count
].length
= strlen(dn
);
1076 ret
= ltdb_dn_list_store(module
, dn_key
, list
);
1084 add index entries for one elements in a message
1086 static int ltdb_index_add_el(struct ldb_module
*module
, const char *dn
,
1087 struct ldb_message_element
*el
)
1090 for (i
= 0; i
< el
->num_values
; i
++) {
1091 int ret
= ltdb_index_add1(module
, dn
, el
, i
);
1092 if (ret
!= LDB_SUCCESS
) {
1101 add index entries for all elements in a message
1103 static int ltdb_index_add_all(struct ldb_module
*module
, const char *dn
,
1104 struct ldb_message_element
*elements
, int num_el
)
1106 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1113 if (ltdb
->cache
->indexlist
->num_elements
== 0) {
1114 /* no indexed fields */
1118 for (i
= 0; i
< num_el
; i
++) {
1120 if (!ltdb_is_indexed(ltdb
->cache
->indexlist
, elements
[i
].name
)) {
1123 ret
= ltdb_index_add_el(module
, dn
, &elements
[i
]);
1124 if (ret
!= LDB_SUCCESS
) {
1134 insert a one level index for a message
1136 static int ltdb_index_onelevel(struct ldb_module
*module
, const struct ldb_message
*msg
, int add
)
1138 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1139 struct ldb_message_element el
;
1145 /* We index for ONE Level only if requested */
1146 if (!ltdb
->cache
->one_level_indexes
) {
1150 pdn
= ldb_dn_get_parent(module
, msg
->dn
);
1152 return LDB_ERR_OPERATIONS_ERROR
;
1155 dn
= ldb_dn_get_linearized(msg
->dn
);
1158 return LDB_ERR_OPERATIONS_ERROR
;
1161 val
.data
= (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn
));
1162 if (val
.data
== NULL
) {
1164 return LDB_ERR_OPERATIONS_ERROR
;
1167 val
.length
= strlen((char *)val
.data
);
1168 el
.name
= LTDB_IDXONE
;
1173 ret
= ltdb_index_add1(module
, dn
, &el
, 0);
1174 } else { /* delete */
1175 ret
= ltdb_index_del_value(module
, dn
, &el
, 0);
1184 add the index entries for a new element in a record
1185 The caller guarantees that these element values are not yet indexed
1187 int ltdb_index_add_element(struct ldb_module
*module
, struct ldb_dn
*dn
,
1188 struct ldb_message_element
*el
)
1190 if (ldb_dn_is_special(dn
)) {
1193 return ltdb_index_add_el(module
, ldb_dn_get_linearized(dn
), el
);
1197 add the index entries for a new record
1199 int ltdb_index_add_new(struct ldb_module
*module
, const struct ldb_message
*msg
)
1204 if (ldb_dn_is_special(msg
->dn
)) {
1208 dn
= ldb_dn_get_linearized(msg
->dn
);
1210 return LDB_ERR_OPERATIONS_ERROR
;
1213 ret
= ltdb_index_add_all(module
, dn
, msg
->elements
, msg
->num_elements
);
1214 if (ret
!= LDB_SUCCESS
) {
1218 return ltdb_index_onelevel(module
, msg
, 1);
1223 delete an index entry for one message element
1225 int ltdb_index_del_value(struct ldb_module
*module
, const char *dn
,
1226 struct ldb_message_element
*el
, int v_idx
)
1228 struct ldb_context
*ldb
;
1229 struct ldb_dn
*dn_key
;
1231 struct dn_list
*list
;
1233 ldb
= ldb_module_get_ctx(module
);
1239 dn_key
= ltdb_index_key(ldb
, el
->name
, &el
->values
[v_idx
], NULL
);
1241 return LDB_ERR_OPERATIONS_ERROR
;
1244 list
= talloc_zero(dn_key
, struct dn_list
);
1246 talloc_free(dn_key
);
1247 return LDB_ERR_OPERATIONS_ERROR
;
1250 ret
= ltdb_dn_list_load(module
, dn_key
, list
);
1251 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
1252 /* it wasn't indexed. Did we have an earlier error? If we did then
1254 talloc_free(dn_key
);
1258 if (ret
!= LDB_SUCCESS
) {
1259 talloc_free(dn_key
);
1263 i
= ltdb_dn_list_find_str(list
, dn
);
1265 /* nothing to delete */
1266 talloc_free(dn_key
);
1270 if (i
!= list
->count
-1) {
1271 memmove(&list
->dn
[i
], &list
->dn
[i
+1], sizeof(list
->dn
[0])*(list
->count
- (i
+1)));
1274 list
->dn
= talloc_realloc(list
, list
->dn
, struct ldb_val
, list
->count
);
1276 ret
= ltdb_dn_list_store(module
, dn_key
, list
);
1278 talloc_free(dn_key
);
1284 delete the index entries for a element
1285 return -1 on failure
1287 int ltdb_index_del_element(struct ldb_module
*module
, const char *dn
, struct ldb_message_element
*el
)
1289 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1293 if (!ltdb
->cache
->attribute_indexes
) {
1294 /* no indexed fields */
1302 if (!ltdb_is_indexed(ltdb
->cache
->indexlist
, el
->name
)) {
1305 for (i
= 0; i
< el
->num_values
; i
++) {
1306 ret
= ltdb_index_del_value(module
, dn
, el
, i
);
1307 if (ret
!= LDB_SUCCESS
) {
1316 delete the index entries for a record
1317 return -1 on failure
1319 int ltdb_index_delete(struct ldb_module
*module
, const struct ldb_message
*msg
)
1321 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1326 if (ldb_dn_is_special(msg
->dn
)) {
1330 ret
= ltdb_index_onelevel(module
, msg
, 0);
1331 if (ret
!= LDB_SUCCESS
) {
1335 if (!ltdb
->cache
->attribute_indexes
) {
1336 /* no indexed fields */
1340 dn
= ldb_dn_get_linearized(msg
->dn
);
1342 return LDB_ERR_OPERATIONS_ERROR
;
1345 for (i
= 0; i
< msg
->num_elements
; i
++) {
1346 ret
= ltdb_index_del_element(module
, dn
, &msg
->elements
[i
]);
1347 if (ret
!= LDB_SUCCESS
) {
1357 traversal function that deletes all @INDEX records
1359 static int delete_index(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1361 const char *dn
= "DN=" LTDB_INDEX
":";
1362 if (strncmp((char *)key
.dptr
, dn
, strlen(dn
)) == 0) {
1363 return tdb_delete(tdb
, key
);
1369 traversal function that adds @INDEX records during a re index
1371 static int re_index(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1373 struct ldb_context
*ldb
;
1374 struct ldb_module
*module
= (struct ldb_module
*)state
;
1375 struct ldb_message
*msg
;
1376 const char *dn
= NULL
;
1380 ldb
= ldb_module_get_ctx(module
);
1382 if (strncmp((char *)key
.dptr
, "DN=@", 4) == 0 ||
1383 strncmp((char *)key
.dptr
, "DN=", 3) != 0) {
1387 msg
= talloc(module
, struct ldb_message
);
1392 ret
= ltdb_unpack_data(module
, &data
, msg
);
1394 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid data for index %s\n",
1395 ldb_dn_get_linearized(msg
->dn
));
1400 /* check if the DN key has changed, perhaps due to the
1401 case insensitivity of an element changing */
1402 key2
= ltdb_key(module
, msg
->dn
);
1403 if (key2
.dptr
== NULL
) {
1404 /* probably a corrupt record ... darn */
1405 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid DN in re_index: %s",
1406 ldb_dn_get_linearized(msg
->dn
));
1410 if (strcmp((char *)key2
.dptr
, (char *)key
.dptr
) != 0) {
1411 tdb_delete(tdb
, key
);
1412 tdb_store(tdb
, key2
, data
, 0);
1414 talloc_free(key2
.dptr
);
1416 if (msg
->dn
== NULL
) {
1417 dn
= (char *)key
.dptr
+ 3;
1419 dn
= ldb_dn_get_linearized(msg
->dn
);
1422 ret
= ltdb_index_onelevel(module
, msg
, 1);
1423 if (ret
!= LDB_SUCCESS
) {
1424 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1425 "Adding special ONE LEVEL index failed (%s)!",
1426 ldb_dn_get_linearized(msg
->dn
));
1431 ret
= ltdb_index_add_all(module
, dn
, msg
->elements
, msg
->num_elements
);
1435 if (ret
!= LDB_SUCCESS
) return -1;
1441 force a complete reindex of the database
1443 int ltdb_reindex(struct ldb_module
*module
)
1445 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1448 if (ltdb_cache_reload(module
) != 0) {
1449 return LDB_ERR_OPERATIONS_ERROR
;
1452 /* first traverse the database deleting any @INDEX records */
1453 ret
= tdb_traverse(ltdb
->tdb
, delete_index
, NULL
);
1455 return LDB_ERR_OPERATIONS_ERROR
;
1458 /* if we don't have indexes we have nothing todo */
1459 if (ltdb
->cache
->indexlist
->num_elements
== 0) {
1463 /* now traverse adding any indexes for normal LDB records */
1464 ret
= tdb_traverse(ltdb
->tdb
, re_index
, module
);
1466 return LDB_ERR_OPERATIONS_ERROR
;
1470 ltdb
->idxptr
->repack
= true;