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
;
46 /* we put a @IDXVERSION attribute on index entries. This
47 allows us to tell if it was written by an older version
49 #define LTDB_INDEXING_VERSION 2
51 /* enable the idxptr mode when transactions start */
52 int ltdb_index_transaction_start(struct ldb_module
*module
)
54 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
55 ltdb
->idxptr
= talloc_zero(ltdb
, struct ltdb_idxptr
);
59 /* compare two DN entries in a dn_list. Take account of possible
60 * differences in string termination */
61 static int dn_list_cmp(const struct ldb_val
*v1
, const struct ldb_val
*v2
)
63 if (v1
->length
> v2
->length
&& v1
->data
[v2
->length
] != 0) {
66 if (v1
->length
< v2
->length
&& v2
->data
[v1
->length
] != 0) {
69 return strncmp((char *)v1
->data
, (char *)v2
->data
, v1
->length
);
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 this is effectively a cast function, but with lots of paranoia
100 checks and also copes with CPUs that are fussy about pointer
103 static struct dn_list
*ltdb_index_idxptr(struct ldb_module
*module
, TDB_DATA rec
, bool check_parent
)
105 struct dn_list
*list
;
106 if (rec
.dsize
!= sizeof(void *)) {
107 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
108 "Bad data size for idxptr %u", (unsigned)rec
.dsize
);
111 /* note that we can't just use a cast here, as rec.dptr may
112 not be aligned sufficiently for a pointer. A cast would cause
113 platforms like some ARM CPUs to crash */
114 memcpy(&list
, rec
.dptr
, sizeof(void *));
115 list
= talloc_get_type(list
, struct dn_list
);
117 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
118 "Bad type '%s' for idxptr",
119 talloc_get_name(list
));
122 if (check_parent
&& list
->dn
&& talloc_parent(list
->dn
) != list
) {
123 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
124 "Bad parent '%s' for idxptr",
125 talloc_get_name(talloc_parent(list
->dn
)));
132 return the @IDX list in an index entry for a dn as a
135 static int ltdb_dn_list_load(struct ldb_module
*module
,
136 struct ldb_dn
*dn
, struct dn_list
*list
)
138 struct ldb_message
*msg
;
140 struct ldb_message_element
*el
;
141 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
143 struct dn_list
*list2
;
149 /* see if we have any in-memory index entries */
150 if (ltdb
->idxptr
== NULL
||
151 ltdb
->idxptr
->itdb
== NULL
) {
155 key
.dptr
= discard_const_p(unsigned char, ldb_dn_get_linearized(dn
));
156 key
.dsize
= strlen((char *)key
.dptr
);
158 rec
= tdb_fetch_compat(ltdb
->idxptr
->itdb
, key
);
159 if (rec
.dptr
== NULL
) {
163 /* we've found an in-memory index entry */
164 list2
= ltdb_index_idxptr(module
, rec
, true);
167 return LDB_ERR_OPERATIONS_ERROR
;
175 msg
= ldb_msg_new(list
);
177 return LDB_ERR_OPERATIONS_ERROR
;
180 ret
= ltdb_search_dn1(module
, dn
, msg
);
181 if (ret
!= LDB_SUCCESS
) {
186 /* TODO: check indexing version number */
188 el
= ldb_msg_find_element(msg
, LTDB_IDX
);
194 /* we avoid copying the strings by stealing the list */
195 list
->dn
= talloc_steal(list
, el
->values
);
196 list
->count
= el
->num_values
;
203 save a dn_list into a full @IDX style record
205 static int ltdb_dn_list_store_full(struct ldb_module
*module
, struct ldb_dn
*dn
,
206 struct dn_list
*list
)
208 struct ldb_message
*msg
;
211 if (list
->count
== 0) {
212 ret
= ltdb_delete_noindex(module
, dn
);
213 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
219 msg
= ldb_msg_new(module
);
221 return ldb_module_oom(module
);
224 ret
= ldb_msg_add_fmt(msg
, LTDB_IDXVERSION
, "%u", LTDB_INDEXING_VERSION
);
225 if (ret
!= LDB_SUCCESS
) {
227 return ldb_module_oom(module
);
231 if (list
->count
> 0) {
232 struct ldb_message_element
*el
;
234 ret
= ldb_msg_add_empty(msg
, LTDB_IDX
, LDB_FLAG_MOD_ADD
, &el
);
235 if (ret
!= LDB_SUCCESS
) {
237 return ldb_module_oom(module
);
239 el
->values
= list
->dn
;
240 el
->num_values
= list
->count
;
243 ret
= ltdb_store(module
, msg
, TDB_REPLACE
);
249 save a dn_list into the database, in either @IDX or internal format
251 static int ltdb_dn_list_store(struct ldb_module
*module
, struct ldb_dn
*dn
,
252 struct dn_list
*list
)
254 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
257 struct dn_list
*list2
;
259 if (ltdb
->idxptr
== NULL
) {
260 return ltdb_dn_list_store_full(module
, dn
, list
);
263 if (ltdb
->idxptr
->itdb
== NULL
) {
264 ltdb
->idxptr
->itdb
= tdb_open_compat(NULL
, 1000, TDB_INTERNAL
, O_RDWR
, 0, NULL
, NULL
);
265 if (ltdb
->idxptr
->itdb
== NULL
) {
266 return LDB_ERR_OPERATIONS_ERROR
;
270 key
.dptr
= discard_const_p(unsigned char, ldb_dn_get_linearized(dn
));
271 key
.dsize
= strlen((char *)key
.dptr
);
273 rec
= tdb_fetch_compat(ltdb
->idxptr
->itdb
, key
);
274 if (rec
.dptr
!= NULL
) {
275 list2
= ltdb_index_idxptr(module
, rec
, false);
278 return LDB_ERR_OPERATIONS_ERROR
;
281 list2
->dn
= talloc_steal(list2
, list
->dn
);
282 list2
->count
= list
->count
;
286 list2
= talloc(ltdb
->idxptr
, struct dn_list
);
288 return LDB_ERR_OPERATIONS_ERROR
;
290 list2
->dn
= talloc_steal(list2
, list
->dn
);
291 list2
->count
= list
->count
;
293 rec
.dptr
= (uint8_t *)&list2
;
294 rec
.dsize
= sizeof(void *);
296 ret
= tdb_store(ltdb
->idxptr
->itdb
, key
, rec
, TDB_INSERT
);
298 return ltdb_err_map(tdb_error(ltdb
->idxptr
->itdb
));
304 traverse function for storing the in-memory index entries on disk
306 static int ltdb_index_traverse_store(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
308 struct ldb_module
*module
= state
;
309 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
311 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
313 struct dn_list
*list
;
315 list
= ltdb_index_idxptr(module
, data
, true);
317 ltdb
->idxptr
->error
= LDB_ERR_OPERATIONS_ERROR
;
322 v
.length
= strnlen((char *)key
.dptr
, key
.dsize
);
324 dn
= ldb_dn_from_ldb_val(module
, ldb
, &v
);
326 ldb_asprintf_errstring(ldb
, "Failed to parse index key %*.*s as an LDB DN", (int)v
.length
, (int)v
.length
, (const char *)v
.data
);
327 ltdb
->idxptr
->error
= LDB_ERR_OPERATIONS_ERROR
;
331 ltdb
->idxptr
->error
= ltdb_dn_list_store_full(module
, dn
, list
);
333 if (ltdb
->idxptr
->error
!= 0) {
339 /* cleanup the idxptr mode when transaction commits */
340 int ltdb_index_transaction_commit(struct ldb_module
*module
)
342 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
345 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
347 ldb_reset_err_string(ldb
);
349 if (ltdb
->idxptr
->itdb
) {
350 tdb_traverse(ltdb
->idxptr
->itdb
, ltdb_index_traverse_store
, module
);
351 tdb_close(ltdb
->idxptr
->itdb
);
354 ret
= ltdb
->idxptr
->error
;
355 if (ret
!= LDB_SUCCESS
) {
356 if (!ldb_errstring(ldb
)) {
357 ldb_set_errstring(ldb
, ldb_strerror(ret
));
359 ldb_asprintf_errstring(ldb
, "Failed to store index records in transaction commit: %s", ldb_errstring(ldb
));
362 talloc_free(ltdb
->idxptr
);
367 /* cleanup the idxptr mode when transaction cancels */
368 int ltdb_index_transaction_cancel(struct ldb_module
*module
)
370 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
371 if (ltdb
->idxptr
&& ltdb
->idxptr
->itdb
) {
372 tdb_close(ltdb
->idxptr
->itdb
);
374 talloc_free(ltdb
->idxptr
);
381 return the dn key to be used for an index
382 the caller is responsible for freeing
384 static struct ldb_dn
*ltdb_index_key(struct ldb_context
*ldb
,
385 const char *attr
, const struct ldb_val
*value
,
386 const struct ldb_schema_attribute
**ap
)
390 const struct ldb_schema_attribute
*a
;
394 attr_folded
= ldb_attr_casefold(ldb
, attr
);
399 a
= ldb_schema_attribute_by_name(ldb
, attr
);
403 r
= a
->syntax
->canonicalise_fn(ldb
, ldb
, value
, &v
);
404 if (r
!= LDB_SUCCESS
) {
405 const char *errstr
= ldb_errstring(ldb
);
406 /* canonicalisation can be refused. For example,
407 a attribute that takes wildcards will refuse to canonicalise
408 if the value contains a wildcard */
409 ldb_asprintf_errstring(ldb
, "Failed to create index key for attribute '%s':%s%s%s",
410 attr
, ldb_strerror(r
), (errstr
?":":""), (errstr
?errstr
:""));
411 talloc_free(attr_folded
);
414 if (ldb_should_b64_encode(ldb
, &v
)) {
415 char *vstr
= ldb_base64_encode(ldb
, (char *)v
.data
, v
.length
);
417 talloc_free(attr_folded
);
420 ret
= ldb_dn_new_fmt(ldb
, ldb
, "%s:%s::%s", LTDB_INDEX
, attr_folded
, vstr
);
423 ret
= ldb_dn_new_fmt(ldb
, ldb
, "%s:%s:%.*s", LTDB_INDEX
, attr_folded
, (int)v
.length
, (char *)v
.data
);
426 if (v
.data
!= value
->data
) {
429 talloc_free(attr_folded
);
435 see if a attribute value is in the list of indexed attributes
437 static bool ltdb_is_indexed(const struct ldb_message
*index_list
, const char *attr
)
440 struct ldb_message_element
*el
;
442 el
= ldb_msg_find_element(index_list
, LTDB_IDXATTR
);
447 /* TODO: this is too expensive! At least use a binary search */
448 for (i
=0; i
<el
->num_values
; i
++) {
449 if (ldb_attr_cmp((char *)el
->values
[i
].data
, attr
) == 0) {
457 in the following logic functions, the return value is treated as
460 LDB_SUCCESS: we found some matching index values
462 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
464 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
465 we'll need a full search
469 return a list of dn's that might match a simple indexed search (an
470 equality search only)
472 static int ltdb_index_dn_simple(struct ldb_module
*module
,
473 const struct ldb_parse_tree
*tree
,
474 const struct ldb_message
*index_list
,
475 struct dn_list
*list
)
477 struct ldb_context
*ldb
;
481 ldb
= ldb_module_get_ctx(module
);
486 /* if the attribute isn't in the list of indexed attributes then
487 this node needs a full search */
488 if (!ltdb_is_indexed(index_list
, tree
->u
.equality
.attr
)) {
489 return LDB_ERR_OPERATIONS_ERROR
;
492 /* the attribute is indexed. Pull the list of DNs that match the
494 dn
= ltdb_index_key(ldb
, tree
->u
.equality
.attr
, &tree
->u
.equality
.value
, NULL
);
495 if (!dn
) return LDB_ERR_OPERATIONS_ERROR
;
497 ret
= ltdb_dn_list_load(module
, dn
, list
);
503 static bool list_union(struct ldb_context
*, struct dn_list
*, const struct dn_list
*);
506 return a list of dn's that might match a leaf indexed search
508 static int ltdb_index_dn_leaf(struct ldb_module
*module
,
509 const struct ldb_parse_tree
*tree
,
510 const struct ldb_message
*index_list
,
511 struct dn_list
*list
)
513 if (ldb_attr_dn(tree
->u
.equality
.attr
) == 0) {
514 list
->dn
= talloc_array(list
, struct ldb_val
, 1);
515 if (list
->dn
== NULL
) {
516 ldb_module_oom(module
);
517 return LDB_ERR_OPERATIONS_ERROR
;
519 list
->dn
[0] = tree
->u
.equality
.value
;
523 return ltdb_index_dn_simple(module
, tree
, index_list
, list
);
531 static bool list_intersect(struct ldb_context
*ldb
,
532 struct dn_list
*list
, const struct dn_list
*list2
)
534 struct dn_list
*list3
;
537 if (list
->count
== 0) {
541 if (list2
->count
== 0) {
548 /* the indexing code is allowed to return a longer list than
549 what really matches, as all results are filtered by the
550 full expression at the end - this shortcut avoids a lot of
551 work in some cases */
552 if (list
->count
< 2 && list2
->count
> 10) {
555 if (list2
->count
< 2 && list
->count
> 10) {
556 list
->count
= list2
->count
;
557 list
->dn
= list2
->dn
;
558 /* note that list2 may not be the parent of list2->dn,
559 as list2->dn may be owned by ltdb->idxptr. In that
560 case we expect this reparent call to fail, which is
562 talloc_reparent(list2
, list
, list2
->dn
);
566 list3
= talloc_zero(list
, struct dn_list
);
571 list3
->dn
= talloc_array(list3
, struct ldb_val
, list
->count
);
578 for (i
=0;i
<list
->count
;i
++) {
579 if (ltdb_dn_list_find_val(list2
, &list
->dn
[i
]) != -1) {
580 list3
->dn
[list3
->count
] = list
->dn
[i
];
585 list
->dn
= talloc_steal(list
, list3
->dn
);
586 list
->count
= list3
->count
;
597 static bool list_union(struct ldb_context
*ldb
,
598 struct dn_list
*list
, const struct dn_list
*list2
)
602 if (list2
->count
== 0) {
607 if (list
->count
== 0) {
609 list
->count
= list2
->count
;
610 list
->dn
= list2
->dn
;
611 /* note that list2 may not be the parent of list2->dn,
612 as list2->dn may be owned by ltdb->idxptr. In that
613 case we expect this reparent call to fail, which is
615 talloc_reparent(list2
, list
, list2
->dn
);
619 dn3
= talloc_array(list
, struct ldb_val
, list
->count
+ list2
->count
);
625 /* we allow for duplicates here, and get rid of them later */
626 memcpy(dn3
, list
->dn
, sizeof(list
->dn
[0])*list
->count
);
627 memcpy(dn3
+list
->count
, list2
->dn
, sizeof(list2
->dn
[0])*list2
->count
);
630 list
->count
+= list2
->count
;
635 static int ltdb_index_dn(struct ldb_module
*module
,
636 const struct ldb_parse_tree
*tree
,
637 const struct ldb_message
*index_list
,
638 struct dn_list
*list
);
642 process an OR list (a union)
644 static int ltdb_index_dn_or(struct ldb_module
*module
,
645 const struct ldb_parse_tree
*tree
,
646 const struct ldb_message
*index_list
,
647 struct dn_list
*list
)
649 struct ldb_context
*ldb
;
652 ldb
= ldb_module_get_ctx(module
);
657 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
658 struct dn_list
*list2
;
661 list2
= talloc_zero(list
, struct dn_list
);
663 return LDB_ERR_OPERATIONS_ERROR
;
666 ret
= ltdb_index_dn(module
, tree
->u
.list
.elements
[i
], index_list
, list2
);
668 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
674 if (ret
!= LDB_SUCCESS
) {
680 if (!list_union(ldb
, list
, list2
)) {
682 return LDB_ERR_OPERATIONS_ERROR
;
686 if (list
->count
== 0) {
687 return LDB_ERR_NO_SUCH_OBJECT
;
697 static int ltdb_index_dn_not(struct ldb_module
*module
,
698 const struct ldb_parse_tree
*tree
,
699 const struct ldb_message
*index_list
,
700 struct dn_list
*list
)
702 /* the only way to do an indexed not would be if we could
703 negate the not via another not or if we knew the total
704 number of database elements so we could know that the
705 existing expression covered the whole database.
707 instead, we just give up, and rely on a full index scan
708 (unless an outer & manages to reduce the list)
710 return LDB_ERR_OPERATIONS_ERROR
;
714 static bool ltdb_index_unique(struct ldb_context
*ldb
,
717 const struct ldb_schema_attribute
*a
;
718 a
= ldb_schema_attribute_by_name(ldb
, attr
);
719 if (a
->flags
& LDB_ATTR_FLAG_UNIQUE_INDEX
) {
726 process an AND expression (intersection)
728 static int ltdb_index_dn_and(struct ldb_module
*module
,
729 const struct ldb_parse_tree
*tree
,
730 const struct ldb_message
*index_list
,
731 struct dn_list
*list
)
733 struct ldb_context
*ldb
;
737 ldb
= ldb_module_get_ctx(module
);
742 /* in the first pass we only look for unique simple
743 equality tests, in the hope of avoiding having to look
745 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
746 const struct ldb_parse_tree
*subtree
= tree
->u
.list
.elements
[i
];
749 if (subtree
->operation
!= LDB_OP_EQUALITY
||
750 !ltdb_index_unique(ldb
, subtree
->u
.equality
.attr
)) {
754 ret
= ltdb_index_dn(module
, subtree
, index_list
, list
);
755 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
757 return LDB_ERR_NO_SUCH_OBJECT
;
759 if (ret
== LDB_SUCCESS
) {
760 /* a unique index match means we can
761 * stop. Note that we don't care if we return
762 * a few too many objects, due to later
768 /* now do a full intersection */
771 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
772 const struct ldb_parse_tree
*subtree
= tree
->u
.list
.elements
[i
];
773 struct dn_list
*list2
;
776 list2
= talloc_zero(list
, struct dn_list
);
778 return ldb_module_oom(module
);
781 ret
= ltdb_index_dn(module
, subtree
, index_list
, list2
);
783 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
788 return LDB_ERR_NO_SUCH_OBJECT
;
791 if (ret
!= LDB_SUCCESS
) {
792 /* this didn't adding anything */
798 talloc_reparent(list2
, list
, list
->dn
);
799 list
->dn
= list2
->dn
;
800 list
->count
= list2
->count
;
802 } else if (!list_intersect(ldb
, list
, list2
)) {
804 return LDB_ERR_OPERATIONS_ERROR
;
807 if (list
->count
== 0) {
809 return LDB_ERR_NO_SUCH_OBJECT
;
812 if (list
->count
< 2) {
813 /* it isn't worth loading the next part of the tree */
819 /* none of the attributes were indexed */
820 return LDB_ERR_OPERATIONS_ERROR
;
827 return a list of matching objects using a one-level index
829 static int ltdb_index_dn_one(struct ldb_module
*module
,
830 struct ldb_dn
*parent_dn
,
831 struct dn_list
*list
)
833 struct ldb_context
*ldb
;
838 ldb
= ldb_module_get_ctx(module
);
840 /* work out the index key from the parent DN */
841 val
.data
= (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn
));
842 val
.length
= strlen((char *)val
.data
);
843 key
= ltdb_index_key(ldb
, LTDB_IDXONE
, &val
, NULL
);
846 return LDB_ERR_OPERATIONS_ERROR
;
849 ret
= ltdb_dn_list_load(module
, key
, list
);
851 if (ret
!= LDB_SUCCESS
) {
855 if (list
->count
== 0) {
856 return LDB_ERR_NO_SUCH_OBJECT
;
863 return a list of dn's that might match a indexed search or
864 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
866 static int ltdb_index_dn(struct ldb_module
*module
,
867 const struct ldb_parse_tree
*tree
,
868 const struct ldb_message
*index_list
,
869 struct dn_list
*list
)
871 int ret
= LDB_ERR_OPERATIONS_ERROR
;
873 switch (tree
->operation
) {
875 ret
= ltdb_index_dn_and(module
, tree
, index_list
, list
);
879 ret
= ltdb_index_dn_or(module
, tree
, index_list
, list
);
883 ret
= ltdb_index_dn_not(module
, tree
, index_list
, list
);
886 case LDB_OP_EQUALITY
:
887 ret
= ltdb_index_dn_leaf(module
, tree
, index_list
, list
);
890 case LDB_OP_SUBSTRING
:
895 case LDB_OP_EXTENDED
:
896 /* we can't index with fancy bitops yet */
897 ret
= LDB_ERR_OPERATIONS_ERROR
;
905 filter a candidate dn_list from an indexed search into a set of results
906 extracting just the given attributes
908 static int ltdb_index_filter(const struct dn_list
*dn_list
,
909 struct ltdb_context
*ac
,
910 uint32_t *match_count
)
912 struct ldb_context
*ldb
;
913 struct ldb_message
*msg
;
916 ldb
= ldb_module_get_ctx(ac
->module
);
918 for (i
= 0; i
< dn_list
->count
; i
++) {
923 msg
= ldb_msg_new(ac
);
925 return LDB_ERR_OPERATIONS_ERROR
;
928 dn
= ldb_dn_from_ldb_val(msg
, ldb
, &dn_list
->dn
[i
]);
931 return LDB_ERR_OPERATIONS_ERROR
;
934 ret
= ltdb_search_dn1(ac
->module
, dn
, msg
);
936 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
937 /* the record has disappeared? yes, this can happen */
942 if (ret
!= LDB_SUCCESS
&& ret
!= LDB_ERR_NO_SUCH_OBJECT
) {
943 /* an internal error */
945 return LDB_ERR_OPERATIONS_ERROR
;
948 ret
= ldb_match_msg_error(ldb
, msg
,
949 ac
->tree
, ac
->base
, ac
->scope
, &matched
);
950 if (ret
!= LDB_SUCCESS
) {
959 /* filter the attributes that the user wants */
960 ret
= ltdb_filter_attrs(msg
, ac
->attrs
);
964 return LDB_ERR_OPERATIONS_ERROR
;
967 ret
= ldb_module_send_entry(ac
->req
, msg
, NULL
);
968 if (ret
!= LDB_SUCCESS
) {
969 /* Regardless of success or failure, the msg
970 * is the callbacks responsiblity, and should
971 * not be talloc_free()'ed */
972 ac
->request_terminated
= true;
983 remove any duplicated entries in a indexed result
985 static void ltdb_dn_list_remove_duplicates(struct dn_list
*list
)
987 unsigned int i
, new_count
;
989 if (list
->count
< 2) {
993 TYPESAFE_QSORT(list
->dn
, list
->count
, dn_list_cmp
);
996 for (i
=1; i
<list
->count
; i
++) {
997 if (dn_list_cmp(&list
->dn
[i
], &list
->dn
[new_count
-1]) != 0) {
998 if (new_count
!= i
) {
999 list
->dn
[new_count
] = list
->dn
[i
];
1005 list
->count
= new_count
;
1009 search the database with a LDAP-like expression using indexes
1010 returns -1 if an indexed search is not possible, in which
1011 case the caller should call ltdb_search_full()
1013 int ltdb_search_indexed(struct ltdb_context
*ac
, uint32_t *match_count
)
1015 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(ac
->module
), struct ltdb_private
);
1016 struct dn_list
*dn_list
;
1019 /* see if indexing is enabled */
1020 if (!ltdb
->cache
->attribute_indexes
&&
1021 !ltdb
->cache
->one_level_indexes
&&
1022 ac
->scope
!= LDB_SCOPE_BASE
) {
1023 /* fallback to a full search */
1024 return LDB_ERR_OPERATIONS_ERROR
;
1027 dn_list
= talloc_zero(ac
, struct dn_list
);
1028 if (dn_list
== NULL
) {
1029 return ldb_module_oom(ac
->module
);
1032 switch (ac
->scope
) {
1033 case LDB_SCOPE_BASE
:
1034 dn_list
->dn
= talloc_array(dn_list
, struct ldb_val
, 1);
1035 if (dn_list
->dn
== NULL
) {
1036 talloc_free(dn_list
);
1037 return ldb_module_oom(ac
->module
);
1039 dn_list
->dn
[0].data
= discard_const_p(unsigned char, ldb_dn_get_linearized(ac
->base
));
1040 if (dn_list
->dn
[0].data
== NULL
) {
1041 talloc_free(dn_list
);
1042 return ldb_module_oom(ac
->module
);
1044 dn_list
->dn
[0].length
= strlen((char *)dn_list
->dn
[0].data
);
1048 case LDB_SCOPE_ONELEVEL
:
1049 if (!ltdb
->cache
->one_level_indexes
) {
1050 talloc_free(dn_list
);
1051 return LDB_ERR_OPERATIONS_ERROR
;
1053 ret
= ltdb_index_dn_one(ac
->module
, ac
->base
, dn_list
);
1054 if (ret
!= LDB_SUCCESS
) {
1055 talloc_free(dn_list
);
1060 case LDB_SCOPE_SUBTREE
:
1061 case LDB_SCOPE_DEFAULT
:
1062 if (!ltdb
->cache
->attribute_indexes
) {
1063 talloc_free(dn_list
);
1064 return LDB_ERR_OPERATIONS_ERROR
;
1066 ret
= ltdb_index_dn(ac
->module
, ac
->tree
, ltdb
->cache
->indexlist
, dn_list
);
1067 if (ret
!= LDB_SUCCESS
) {
1068 talloc_free(dn_list
);
1071 ltdb_dn_list_remove_duplicates(dn_list
);
1075 ret
= ltdb_index_filter(dn_list
, ac
, match_count
);
1076 talloc_free(dn_list
);
1081 add an index entry for one message element
1083 static int ltdb_index_add1(struct ldb_module
*module
, const char *dn
,
1084 struct ldb_message_element
*el
, int v_idx
)
1086 struct ldb_context
*ldb
;
1087 struct ldb_dn
*dn_key
;
1089 const struct ldb_schema_attribute
*a
;
1090 struct dn_list
*list
;
1093 ldb
= ldb_module_get_ctx(module
);
1095 list
= talloc_zero(module
, struct dn_list
);
1097 return LDB_ERR_OPERATIONS_ERROR
;
1100 dn_key
= ltdb_index_key(ldb
, el
->name
, &el
->values
[v_idx
], &a
);
1103 return LDB_ERR_OPERATIONS_ERROR
;
1105 talloc_steal(list
, dn_key
);
1107 ret
= ltdb_dn_list_load(module
, dn_key
, list
);
1108 if (ret
!= LDB_SUCCESS
&& ret
!= LDB_ERR_NO_SUCH_OBJECT
) {
1113 if (ltdb_dn_list_find_str(list
, dn
) != -1) {
1118 if (list
->count
> 0 &&
1119 a
->flags
& LDB_ATTR_FLAG_UNIQUE_INDEX
) {
1121 ldb_asprintf_errstring(ldb
, __location__
": unique index violation on %s in %s",
1123 return LDB_ERR_ENTRY_ALREADY_EXISTS
;
1126 /* overallocate the list a bit, to reduce the number of
1127 * realloc trigered copies */
1128 alloc_len
= ((list
->count
+1)+7) & ~7;
1129 list
->dn
= talloc_realloc(list
, list
->dn
, struct ldb_val
, alloc_len
);
1130 if (list
->dn
== NULL
) {
1132 return LDB_ERR_OPERATIONS_ERROR
;
1134 list
->dn
[list
->count
].data
= (uint8_t *)talloc_strdup(list
->dn
, dn
);
1135 list
->dn
[list
->count
].length
= strlen(dn
);
1138 ret
= ltdb_dn_list_store(module
, dn_key
, list
);
1146 add index entries for one elements in a message
1148 static int ltdb_index_add_el(struct ldb_module
*module
, const char *dn
,
1149 struct ldb_message_element
*el
)
1152 for (i
= 0; i
< el
->num_values
; i
++) {
1153 int ret
= ltdb_index_add1(module
, dn
, el
, i
);
1154 if (ret
!= LDB_SUCCESS
) {
1163 add index entries for all elements in a message
1165 static int ltdb_index_add_all(struct ldb_module
*module
, const char *dn
,
1166 struct ldb_message_element
*elements
, int num_el
)
1168 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1175 if (ltdb
->cache
->indexlist
->num_elements
== 0) {
1176 /* no indexed fields */
1180 for (i
= 0; i
< num_el
; i
++) {
1182 if (!ltdb_is_indexed(ltdb
->cache
->indexlist
, elements
[i
].name
)) {
1185 ret
= ltdb_index_add_el(module
, dn
, &elements
[i
]);
1186 if (ret
!= LDB_SUCCESS
) {
1187 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1188 ldb_asprintf_errstring(ldb
,
1189 __location__
": Failed to re-index %s in %s - %s",
1190 elements
[i
].name
, dn
, ldb_errstring(ldb
));
1200 insert a one level index for a message
1202 static int ltdb_index_onelevel(struct ldb_module
*module
, const struct ldb_message
*msg
, int add
)
1204 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1205 struct ldb_message_element el
;
1211 /* We index for ONE Level only if requested */
1212 if (!ltdb
->cache
->one_level_indexes
) {
1216 pdn
= ldb_dn_get_parent(module
, msg
->dn
);
1218 return LDB_ERR_OPERATIONS_ERROR
;
1221 dn
= ldb_dn_get_linearized(msg
->dn
);
1224 return LDB_ERR_OPERATIONS_ERROR
;
1227 val
.data
= (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn
));
1228 if (val
.data
== NULL
) {
1230 return LDB_ERR_OPERATIONS_ERROR
;
1233 val
.length
= strlen((char *)val
.data
);
1234 el
.name
= LTDB_IDXONE
;
1239 ret
= ltdb_index_add1(module
, dn
, &el
, 0);
1240 } else { /* delete */
1241 ret
= ltdb_index_del_value(module
, msg
->dn
, &el
, 0);
1250 add the index entries for a new element in a record
1251 The caller guarantees that these element values are not yet indexed
1253 int ltdb_index_add_element(struct ldb_module
*module
, struct ldb_dn
*dn
,
1254 struct ldb_message_element
*el
)
1256 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1257 if (ldb_dn_is_special(dn
)) {
1260 if (!ltdb_is_indexed(ltdb
->cache
->indexlist
, el
->name
)) {
1263 return ltdb_index_add_el(module
, ldb_dn_get_linearized(dn
), el
);
1267 add the index entries for a new record
1269 int ltdb_index_add_new(struct ldb_module
*module
, const struct ldb_message
*msg
)
1274 if (ldb_dn_is_special(msg
->dn
)) {
1278 dn
= ldb_dn_get_linearized(msg
->dn
);
1280 return LDB_ERR_OPERATIONS_ERROR
;
1283 ret
= ltdb_index_add_all(module
, dn
, msg
->elements
, msg
->num_elements
);
1284 if (ret
!= LDB_SUCCESS
) {
1288 return ltdb_index_onelevel(module
, msg
, 1);
1293 delete an index entry for one message element
1295 int ltdb_index_del_value(struct ldb_module
*module
, struct ldb_dn
*dn
,
1296 struct ldb_message_element
*el
, unsigned int v_idx
)
1298 struct ldb_context
*ldb
;
1299 struct ldb_dn
*dn_key
;
1303 struct dn_list
*list
;
1305 ldb
= ldb_module_get_ctx(module
);
1307 dn_str
= ldb_dn_get_linearized(dn
);
1308 if (dn_str
== NULL
) {
1309 return LDB_ERR_OPERATIONS_ERROR
;
1312 if (dn_str
[0] == '@') {
1316 dn_key
= ltdb_index_key(ldb
, el
->name
, &el
->values
[v_idx
], NULL
);
1318 return LDB_ERR_OPERATIONS_ERROR
;
1321 list
= talloc_zero(dn_key
, struct dn_list
);
1323 talloc_free(dn_key
);
1324 return LDB_ERR_OPERATIONS_ERROR
;
1327 ret
= ltdb_dn_list_load(module
, dn_key
, list
);
1328 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
1329 /* it wasn't indexed. Did we have an earlier error? If we did then
1331 talloc_free(dn_key
);
1335 if (ret
!= LDB_SUCCESS
) {
1336 talloc_free(dn_key
);
1340 i
= ltdb_dn_list_find_str(list
, dn_str
);
1342 /* nothing to delete */
1343 talloc_free(dn_key
);
1347 j
= (unsigned int) i
;
1348 if (j
!= list
->count
- 1) {
1349 memmove(&list
->dn
[j
], &list
->dn
[j
+1], sizeof(list
->dn
[0])*(list
->count
- (j
+1)));
1352 list
->dn
= talloc_realloc(list
, list
->dn
, struct ldb_val
, list
->count
);
1354 ret
= ltdb_dn_list_store(module
, dn_key
, list
);
1356 talloc_free(dn_key
);
1362 delete the index entries for a element
1363 return -1 on failure
1365 int ltdb_index_del_element(struct ldb_module
*module
, struct ldb_dn
*dn
,
1366 struct ldb_message_element
*el
)
1368 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1373 if (!ltdb
->cache
->attribute_indexes
) {
1374 /* no indexed fields */
1378 dn_str
= ldb_dn_get_linearized(dn
);
1379 if (dn_str
== NULL
) {
1380 return LDB_ERR_OPERATIONS_ERROR
;
1383 if (dn_str
[0] == '@') {
1387 if (!ltdb_is_indexed(ltdb
->cache
->indexlist
, el
->name
)) {
1390 for (i
= 0; i
< el
->num_values
; i
++) {
1391 ret
= ltdb_index_del_value(module
, dn
, el
, i
);
1392 if (ret
!= LDB_SUCCESS
) {
1401 delete the index entries for a record
1402 return -1 on failure
1404 int ltdb_index_delete(struct ldb_module
*module
, const struct ldb_message
*msg
)
1406 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1410 if (ldb_dn_is_special(msg
->dn
)) {
1414 ret
= ltdb_index_onelevel(module
, msg
, 0);
1415 if (ret
!= LDB_SUCCESS
) {
1419 if (!ltdb
->cache
->attribute_indexes
) {
1420 /* no indexed fields */
1424 for (i
= 0; i
< msg
->num_elements
; i
++) {
1425 ret
= ltdb_index_del_element(module
, msg
->dn
, &msg
->elements
[i
]);
1426 if (ret
!= LDB_SUCCESS
) {
1436 traversal function that deletes all @INDEX records
1438 static int delete_index(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1440 struct ldb_module
*module
= state
;
1441 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1442 const char *dnstr
= "DN=" LTDB_INDEX
":";
1443 struct dn_list list
;
1448 if (strncmp((char *)key
.dptr
, dnstr
, strlen(dnstr
)) != 0) {
1451 /* we need to put a empty list in the internal tdb for this
1456 /* the offset of 3 is to remove the DN= prefix. */
1457 v
.data
= key
.dptr
+ 3;
1458 v
.length
= strnlen((char *)key
.dptr
, key
.dsize
) - 3;
1460 dn
= ldb_dn_from_ldb_val(ltdb
, ldb_module_get_ctx(module
), &v
);
1461 ret
= ltdb_dn_list_store(module
, dn
, &list
);
1462 if (ret
!= LDB_SUCCESS
) {
1463 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
1464 "Unable to store null index for %s\n",
1465 ldb_dn_get_linearized(dn
));
1473 struct ltdb_reindex_context
{
1474 struct ldb_module
*module
;
1479 traversal function that adds @INDEX records during a re index
1481 static int re_index(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1483 struct ldb_context
*ldb
;
1484 struct ltdb_reindex_context
*ctx
= (struct ltdb_reindex_context
*)state
;
1485 struct ldb_module
*module
= ctx
->module
;
1486 struct ldb_message
*msg
;
1487 const char *dn
= NULL
;
1491 ldb
= ldb_module_get_ctx(module
);
1493 if (strncmp((char *)key
.dptr
, "DN=@", 4) == 0 ||
1494 strncmp((char *)key
.dptr
, "DN=", 3) != 0) {
1498 msg
= ldb_msg_new(module
);
1503 ret
= ltdb_unpack_data(module
, &data
, msg
);
1505 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid data for index %s\n",
1506 ldb_dn_get_linearized(msg
->dn
));
1511 /* check if the DN key has changed, perhaps due to the
1512 case insensitivity of an element changing */
1513 key2
= ltdb_key(module
, msg
->dn
);
1514 if (key2
.dptr
== NULL
) {
1515 /* probably a corrupt record ... darn */
1516 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid DN in re_index: %s",
1517 ldb_dn_get_linearized(msg
->dn
));
1521 if (strcmp((char *)key2
.dptr
, (char *)key
.dptr
) != 0) {
1522 tdb_delete(tdb
, key
);
1523 tdb_store(tdb
, key2
, data
, 0);
1525 talloc_free(key2
.dptr
);
1527 if (msg
->dn
== NULL
) {
1528 dn
= (char *)key
.dptr
+ 3;
1530 dn
= ldb_dn_get_linearized(msg
->dn
);
1533 ret
= ltdb_index_onelevel(module
, msg
, 1);
1534 if (ret
!= LDB_SUCCESS
) {
1535 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1536 "Adding special ONE LEVEL index failed (%s)!",
1537 ldb_dn_get_linearized(msg
->dn
));
1542 ret
= ltdb_index_add_all(module
, dn
, msg
->elements
, msg
->num_elements
);
1544 if (ret
!= LDB_SUCCESS
) {
1556 force a complete reindex of the database
1558 int ltdb_reindex(struct ldb_module
*module
)
1560 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1562 struct ltdb_reindex_context ctx
;
1564 if (ltdb_cache_reload(module
) != 0) {
1565 return LDB_ERR_OPERATIONS_ERROR
;
1568 /* first traverse the database deleting any @INDEX records by
1569 * putting NULL entries in the in-memory tdb
1571 ret
= tdb_traverse(ltdb
->tdb
, delete_index
, module
);
1573 return LDB_ERR_OPERATIONS_ERROR
;
1576 /* if we don't have indexes we have nothing todo */
1577 if (ltdb
->cache
->indexlist
->num_elements
== 0) {
1581 ctx
.module
= module
;
1584 /* now traverse adding any indexes for normal LDB records */
1585 ret
= tdb_traverse(ltdb
->tdb
, re_index
, &ctx
);
1587 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1588 ldb_asprintf_errstring(ldb
, "reindexing traverse failed: %s", ldb_errstring(ldb
));
1589 return LDB_ERR_OPERATIONS_ERROR
;
1592 if (ctx
.error
!= LDB_SUCCESS
) {
1593 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
1594 ldb_asprintf_errstring(ldb
, "reindexing failed: %s", ldb_errstring(ldb
));