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 int ret
= strncmp((char *)v1
->data
, (char *)v2
->data
, v1
->length
);
64 if (ret
!= 0) return ret
;
65 if (v2
->length
> v1
->length
&& v2
->data
[v1
->length
] != 0) {
73 find a entry in a dn_list, using a ldb_val. Uses a case sensitive
74 comparison with the dn returns -1 if not found
76 static int ltdb_dn_list_find_val(const struct dn_list
*list
, const struct ldb_val
*v
)
79 for (i
=0; i
<list
->count
; i
++) {
80 if (dn_list_cmp(&list
->dn
[i
], v
) == 0) return i
;
86 find a entry in a dn_list. Uses a case sensitive comparison with the dn
87 returns -1 if not found
89 static int ltdb_dn_list_find_str(struct dn_list
*list
, const char *dn
)
92 v
.data
= discard_const_p(unsigned char, dn
);
93 v
.length
= strlen(dn
);
94 return ltdb_dn_list_find_val(list
, &v
);
97 static struct dn_list
*ltdb_index_idxptr(struct ldb_module
*module
, TDB_DATA rec
, bool check_parent
)
100 if (rec
.dsize
!= sizeof(void *)) {
101 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
102 "Bad data size for idxptr %u", (unsigned)rec
.dsize
);
106 list
= talloc_get_type(*(struct dn_list
**)rec
.dptr
, struct dn_list
);
108 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
109 "Bad type '%s' for idxptr",
110 talloc_get_name(*(struct dn_list
**)rec
.dptr
));
113 if (check_parent
&& list
->dn
&& talloc_parent(list
->dn
) != list
) {
114 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
115 "Bad parent '%s' for idxptr",
116 talloc_get_name(talloc_parent(list
->dn
)));
123 return the @IDX list in an index entry for a dn as a
126 static int ltdb_dn_list_load(struct ldb_module
*module
,
127 struct ldb_dn
*dn
, struct dn_list
*list
)
129 struct ldb_message
*msg
;
131 struct ldb_message_element
*el
;
132 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
134 struct dn_list
*list2
;
140 /* see if we have any in-memory index entries */
141 if (ltdb
->idxptr
== NULL
||
142 ltdb
->idxptr
->itdb
== NULL
) {
146 key
.dptr
= discard_const_p(unsigned char, ldb_dn_get_linearized(dn
));
147 key
.dsize
= strlen((char *)key
.dptr
);
149 rec
= tdb_fetch(ltdb
->idxptr
->itdb
, key
);
150 if (rec
.dptr
== NULL
) {
154 /* we've found an in-memory index entry */
155 list2
= ltdb_index_idxptr(module
, rec
, true);
158 return LDB_ERR_OPERATIONS_ERROR
;
166 msg
= ldb_msg_new(list
);
168 return LDB_ERR_OPERATIONS_ERROR
;
171 ret
= ltdb_search_dn1(module
, dn
, msg
);
172 if (ret
!= LDB_SUCCESS
) {
176 /* TODO: check indexing version number */
178 el
= ldb_msg_find_element(msg
, LTDB_IDX
);
184 /* we avoid copying the strings by stealing the list */
185 list
->dn
= talloc_steal(list
, el
->values
);
186 list
->count
= el
->num_values
;
193 save a dn_list into a full @IDX style record
195 static int ltdb_dn_list_store_full(struct ldb_module
*module
, struct ldb_dn
*dn
,
196 struct dn_list
*list
)
198 struct ldb_message
*msg
;
201 if (list
->count
== 0) {
202 ret
= ltdb_delete_noindex(module
, dn
);
203 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
209 msg
= ldb_msg_new(module
);
211 ldb_module_oom(module
);
212 return LDB_ERR_OPERATIONS_ERROR
;
215 ret
= ldb_msg_add_fmt(msg
, LTDB_IDXVERSION
, "%u", LTDB_INDEXING_VERSION
);
216 if (ret
!= LDB_SUCCESS
) {
218 ldb_module_oom(module
);
219 return LDB_ERR_OPERATIONS_ERROR
;
223 if (list
->count
> 0) {
224 struct ldb_message_element
*el
;
226 ret
= ldb_msg_add_empty(msg
, LTDB_IDX
, LDB_FLAG_MOD_ADD
, &el
);
227 if (ret
!= LDB_SUCCESS
) {
228 ldb_module_oom(module
);
230 return LDB_ERR_OPERATIONS_ERROR
;
232 el
->values
= list
->dn
;
233 el
->num_values
= list
->count
;
236 ret
= ltdb_store(module
, msg
, TDB_REPLACE
);
242 save a dn_list into the database, in either @IDX or internal format
244 static int ltdb_dn_list_store(struct ldb_module
*module
, struct ldb_dn
*dn
,
245 struct dn_list
*list
)
247 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
250 struct dn_list
*list2
;
252 if (ltdb
->idxptr
== NULL
) {
253 return ltdb_dn_list_store_full(module
, dn
, list
);
256 if (ltdb
->idxptr
->itdb
== NULL
) {
257 ltdb
->idxptr
->itdb
= tdb_open(NULL
, 1000, TDB_INTERNAL
, O_RDWR
, 0);
258 if (ltdb
->idxptr
->itdb
== NULL
) {
259 return LDB_ERR_OPERATIONS_ERROR
;
263 key
.dptr
= discard_const_p(unsigned char, ldb_dn_get_linearized(dn
));
264 key
.dsize
= strlen((char *)key
.dptr
);
266 rec
= tdb_fetch(ltdb
->idxptr
->itdb
, key
);
267 if (rec
.dptr
!= NULL
) {
268 list2
= ltdb_index_idxptr(module
, rec
, false);
271 return LDB_ERR_OPERATIONS_ERROR
;
274 list2
->dn
= talloc_steal(list2
, list
->dn
);
275 list2
->count
= list
->count
;
279 list2
= talloc(ltdb
->idxptr
, struct dn_list
);
281 return LDB_ERR_OPERATIONS_ERROR
;
283 list2
->dn
= talloc_steal(list2
, list
->dn
);
284 list2
->count
= list
->count
;
286 rec
.dptr
= (uint8_t *)&list2
;
287 rec
.dsize
= sizeof(void *);
289 ret
= tdb_store(ltdb
->idxptr
->itdb
, key
, rec
, TDB_INSERT
);
291 return ltdb_err_map(tdb_error(ltdb
->idxptr
->itdb
));
297 traverse function for storing the in-memory index entries on disk
299 static int ltdb_index_traverse_store(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
301 struct ldb_module
*module
= state
;
302 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
304 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
306 struct dn_list
*list
;
308 list
= ltdb_index_idxptr(module
, data
, true);
310 ltdb
->idxptr
->error
= LDB_ERR_OPERATIONS_ERROR
;
315 v
.length
= strnlen((char *)key
.dptr
, key
.dsize
);
317 dn
= ldb_dn_from_ldb_val(module
, ldb
, &v
);
319 ltdb
->idxptr
->error
= LDB_ERR_OPERATIONS_ERROR
;
323 ltdb
->idxptr
->error
= ltdb_dn_list_store_full(module
, dn
, list
);
325 if (ltdb
->idxptr
->error
!= 0) {
331 /* cleanup the idxptr mode when transaction commits */
332 int ltdb_index_transaction_commit(struct ldb_module
*module
)
334 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
337 if (ltdb
->idxptr
->itdb
) {
338 tdb_traverse(ltdb
->idxptr
->itdb
, ltdb_index_traverse_store
, module
);
339 tdb_close(ltdb
->idxptr
->itdb
);
342 ret
= ltdb
->idxptr
->error
;
344 if (ret
!= LDB_SUCCESS
) {
345 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
346 ldb_asprintf_errstring(ldb
, "Failed to store index records in transaction commit");
349 talloc_free(ltdb
->idxptr
);
354 /* cleanup the idxptr mode when transaction cancels */
355 int ltdb_index_transaction_cancel(struct ldb_module
*module
)
357 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
358 if (ltdb
->idxptr
&& ltdb
->idxptr
->itdb
) {
359 tdb_close(ltdb
->idxptr
->itdb
);
361 talloc_free(ltdb
->idxptr
);
368 return the dn key to be used for an index
369 the caller is responsible for freeing
371 static struct ldb_dn
*ltdb_index_key(struct ldb_context
*ldb
,
372 const char *attr
, const struct ldb_val
*value
,
373 const struct ldb_schema_attribute
**ap
)
377 const struct ldb_schema_attribute
*a
;
381 attr_folded
= ldb_attr_casefold(ldb
, attr
);
386 a
= ldb_schema_attribute_by_name(ldb
, attr
);
390 r
= a
->syntax
->canonicalise_fn(ldb
, ldb
, value
, &v
);
391 if (r
!= LDB_SUCCESS
) {
392 const char *errstr
= ldb_errstring(ldb
);
393 /* canonicalisation can be refused. For example,
394 a attribute that takes wildcards will refuse to canonicalise
395 if the value contains a wildcard */
396 ldb_asprintf_errstring(ldb
, "Failed to create index key for attribute '%s':%s%s%s",
397 attr
, ldb_strerror(r
), (errstr
?":":""), (errstr
?errstr
:""));
398 talloc_free(attr_folded
);
401 if (ldb_should_b64_encode(ldb
, &v
)) {
402 char *vstr
= ldb_base64_encode(ldb
, (char *)v
.data
, v
.length
);
403 if (!vstr
) return NULL
;
404 /* remove trailing '=' to make it a valid DN */
405 if (vstr
[strlen(vstr
)-1] == '=') {
406 vstr
[strlen(vstr
)-1] = 0;
408 ret
= ldb_dn_new_fmt(ldb
, ldb
, "%s:%s::%s", LTDB_INDEX
, attr_folded
, vstr
);
411 ret
= ldb_dn_new_fmt(ldb
, ldb
, "%s:%s:%.*s", LTDB_INDEX
, attr_folded
, (int)v
.length
, (char *)v
.data
);
414 if (v
.data
!= value
->data
) {
417 talloc_free(attr_folded
);
423 see if a attribute value is in the list of indexed attributes
425 static bool ltdb_is_indexed(const struct ldb_message
*index_list
, const char *attr
)
428 struct ldb_message_element
*el
;
430 el
= ldb_msg_find_element(index_list
, LTDB_IDXATTR
);
435 /* TODO: this is too expensive! At least use a binary search */
436 for (i
=0; i
<el
->num_values
; i
++) {
437 if (ldb_attr_cmp((char *)el
->values
[i
].data
, attr
) == 0) {
445 in the following logic functions, the return value is treated as
448 LDB_SUCCESS: we found some matching index values
450 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
452 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
453 we'll need a full search
457 return a list of dn's that might match a simple indexed search (an
458 equality search only)
460 static int ltdb_index_dn_simple(struct ldb_module
*module
,
461 const struct ldb_parse_tree
*tree
,
462 const struct ldb_message
*index_list
,
463 struct dn_list
*list
)
465 struct ldb_context
*ldb
;
469 ldb
= ldb_module_get_ctx(module
);
474 /* if the attribute isn't in the list of indexed attributes then
475 this node needs a full search */
476 if (!ltdb_is_indexed(index_list
, tree
->u
.equality
.attr
)) {
477 return LDB_ERR_OPERATIONS_ERROR
;
480 /* the attribute is indexed. Pull the list of DNs that match the
482 dn
= ltdb_index_key(ldb
, tree
->u
.equality
.attr
, &tree
->u
.equality
.value
, NULL
);
483 if (!dn
) return LDB_ERR_OPERATIONS_ERROR
;
485 ret
= ltdb_dn_list_load(module
, dn
, list
);
491 static bool list_union(struct ldb_context
*, struct dn_list
*, const struct dn_list
*);
494 return a list of dn's that might match a leaf indexed search
496 static int ltdb_index_dn_leaf(struct ldb_module
*module
,
497 const struct ldb_parse_tree
*tree
,
498 const struct ldb_message
*index_list
,
499 struct dn_list
*list
)
501 if (ldb_attr_dn(tree
->u
.equality
.attr
) == 0) {
502 list
->dn
= talloc_array(list
, struct ldb_val
, 1);
503 if (list
->dn
== NULL
) {
504 ldb_module_oom(module
);
505 return LDB_ERR_OPERATIONS_ERROR
;
507 list
->dn
[0] = tree
->u
.equality
.value
;
511 return ltdb_index_dn_simple(module
, tree
, index_list
, list
);
519 static bool list_intersect(struct ldb_context
*ldb
,
520 struct dn_list
*list
, const struct dn_list
*list2
)
522 struct dn_list
*list3
;
525 if (list
->count
== 0) {
529 if (list2
->count
== 0) {
536 /* the indexing code is allowed to return a longer list than
537 what really matches, as all results are filtered by the
538 full expression at the end - this shortcut avoids a lot of
539 work in some cases */
540 if (list
->count
< 2 && list2
->count
> 10) {
543 if (list2
->count
< 2 && list
->count
> 10) {
544 list
->count
= list2
->count
;
545 list
->dn
= list2
->dn
;
546 /* note that list2 may not be the parent of list2->dn,
547 as list2->dn may be owned by ltdb->idxptr. In that
548 case we expect this reparent call to fail, which is
550 talloc_reparent(list2
, list
, list2
->dn
);
554 list3
= talloc_zero(list
, struct dn_list
);
559 list3
->dn
= talloc_array(list3
, struct ldb_val
, list
->count
);
566 for (i
=0;i
<list
->count
;i
++) {
567 if (ltdb_dn_list_find_val(list2
, &list
->dn
[i
]) != -1) {
568 list3
->dn
[list3
->count
] = list
->dn
[i
];
573 list
->dn
= talloc_steal(list
, list3
->dn
);
574 list
->count
= list3
->count
;
585 static bool list_union(struct ldb_context
*ldb
,
586 struct dn_list
*list
, const struct dn_list
*list2
)
590 if (list2
->count
== 0) {
595 if (list
->count
== 0) {
597 list
->count
= list2
->count
;
598 list
->dn
= list2
->dn
;
599 /* note that list2 may not be the parent of list2->dn,
600 as list2->dn may be owned by ltdb->idxptr. In that
601 case we expect this reparent call to fail, which is
603 talloc_reparent(list2
, list
, list2
->dn
);
607 dn3
= talloc_array(list
, struct ldb_val
, list
->count
+ list2
->count
);
613 /* we allow for duplicates here, and get rid of them later */
614 memcpy(dn3
, list
->dn
, sizeof(list
->dn
[0])*list
->count
);
615 memcpy(dn3
+list
->count
, list2
->dn
, sizeof(list2
->dn
[0])*list2
->count
);
618 list
->count
+= list2
->count
;
623 static int ltdb_index_dn(struct ldb_module
*module
,
624 const struct ldb_parse_tree
*tree
,
625 const struct ldb_message
*index_list
,
626 struct dn_list
*list
);
630 process an OR list (a union)
632 static int ltdb_index_dn_or(struct ldb_module
*module
,
633 const struct ldb_parse_tree
*tree
,
634 const struct ldb_message
*index_list
,
635 struct dn_list
*list
)
637 struct ldb_context
*ldb
;
640 ldb
= ldb_module_get_ctx(module
);
645 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
646 struct dn_list
*list2
;
649 list2
= talloc_zero(list
, struct dn_list
);
651 return LDB_ERR_OPERATIONS_ERROR
;
654 ret
= ltdb_index_dn(module
, tree
->u
.list
.elements
[i
], index_list
, list2
);
656 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
662 if (ret
!= LDB_SUCCESS
) {
668 if (!list_union(ldb
, list
, list2
)) {
670 return LDB_ERR_OPERATIONS_ERROR
;
674 if (list
->count
== 0) {
675 return LDB_ERR_NO_SUCH_OBJECT
;
685 static int ltdb_index_dn_not(struct ldb_module
*module
,
686 const struct ldb_parse_tree
*tree
,
687 const struct ldb_message
*index_list
,
688 struct dn_list
*list
)
690 /* the only way to do an indexed not would be if we could
691 negate the not via another not or if we knew the total
692 number of database elements so we could know that the
693 existing expression covered the whole database.
695 instead, we just give up, and rely on a full index scan
696 (unless an outer & manages to reduce the list)
698 return LDB_ERR_OPERATIONS_ERROR
;
702 static bool ltdb_index_unique(struct ldb_context
*ldb
,
705 const struct ldb_schema_attribute
*a
;
706 a
= ldb_schema_attribute_by_name(ldb
, attr
);
707 if (a
->flags
& LDB_ATTR_FLAG_UNIQUE_INDEX
) {
714 process an AND expression (intersection)
716 static int ltdb_index_dn_and(struct ldb_module
*module
,
717 const struct ldb_parse_tree
*tree
,
718 const struct ldb_message
*index_list
,
719 struct dn_list
*list
)
721 struct ldb_context
*ldb
;
725 ldb
= ldb_module_get_ctx(module
);
730 /* in the first pass we only look for unique simple
731 equality tests, in the hope of avoiding having to look
733 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
734 const struct ldb_parse_tree
*subtree
= tree
->u
.list
.elements
[i
];
737 if (subtree
->operation
!= LDB_OP_EQUALITY
||
738 !ltdb_index_unique(ldb
, subtree
->u
.equality
.attr
)) {
742 ret
= ltdb_index_dn(module
, subtree
, index_list
, list
);
743 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
745 return LDB_ERR_NO_SUCH_OBJECT
;
747 if (ret
== LDB_SUCCESS
) {
748 /* a unique index match means we can
749 * stop. Note that we don't care if we return
750 * a few too many objects, due to later
756 /* now do a full intersection */
759 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
760 const struct ldb_parse_tree
*subtree
= tree
->u
.list
.elements
[i
];
761 struct dn_list
*list2
;
764 list2
= talloc_zero(list
, struct dn_list
);
766 ldb_module_oom(module
);
767 return LDB_ERR_OPERATIONS_ERROR
;
770 ret
= ltdb_index_dn(module
, subtree
, index_list
, list2
);
772 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
777 return LDB_ERR_NO_SUCH_OBJECT
;
780 if (ret
!= LDB_SUCCESS
) {
781 /* this didn't adding anything */
787 talloc_reparent(list2
, list
, list
->dn
);
788 list
->dn
= list2
->dn
;
789 list
->count
= list2
->count
;
791 } else if (!list_intersect(ldb
, list
, list2
)) {
793 return LDB_ERR_OPERATIONS_ERROR
;
796 if (list
->count
== 0) {
798 return LDB_ERR_NO_SUCH_OBJECT
;
801 if (list
->count
< 2) {
802 /* it isn't worth loading the next part of the tree */
808 /* none of the attributes were indexed */
809 return LDB_ERR_OPERATIONS_ERROR
;
816 return a list of matching objects using a one-level index
818 static int ltdb_index_dn_one(struct ldb_module
*module
,
819 struct ldb_dn
*parent_dn
,
820 struct dn_list
*list
)
822 struct ldb_context
*ldb
;
827 ldb
= ldb_module_get_ctx(module
);
829 /* work out the index key from the parent DN */
830 val
.data
= (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn
));
831 val
.length
= strlen((char *)val
.data
);
832 key
= ltdb_index_key(ldb
, LTDB_IDXONE
, &val
, NULL
);
835 return LDB_ERR_OPERATIONS_ERROR
;
838 ret
= ltdb_dn_list_load(module
, key
, list
);
840 if (ret
!= LDB_SUCCESS
) {
844 if (list
->count
== 0) {
845 return LDB_ERR_NO_SUCH_OBJECT
;
852 return a list of dn's that might match a indexed search or
853 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
855 static int ltdb_index_dn(struct ldb_module
*module
,
856 const struct ldb_parse_tree
*tree
,
857 const struct ldb_message
*index_list
,
858 struct dn_list
*list
)
860 int ret
= LDB_ERR_OPERATIONS_ERROR
;
862 switch (tree
->operation
) {
864 ret
= ltdb_index_dn_and(module
, tree
, index_list
, list
);
868 ret
= ltdb_index_dn_or(module
, tree
, index_list
, list
);
872 ret
= ltdb_index_dn_not(module
, tree
, index_list
, list
);
875 case LDB_OP_EQUALITY
:
876 ret
= ltdb_index_dn_leaf(module
, tree
, index_list
, list
);
879 case LDB_OP_SUBSTRING
:
884 case LDB_OP_EXTENDED
:
885 /* we can't index with fancy bitops yet */
886 ret
= LDB_ERR_OPERATIONS_ERROR
;
894 filter a candidate dn_list from an indexed search into a set of results
895 extracting just the given attributes
897 static int ltdb_index_filter(const struct dn_list
*dn_list
,
898 struct ltdb_context
*ac
,
899 uint32_t *match_count
)
901 struct ldb_context
*ldb
;
902 struct ldb_message
*msg
;
905 ldb
= ldb_module_get_ctx(ac
->module
);
907 for (i
= 0; i
< dn_list
->count
; i
++) {
911 msg
= ldb_msg_new(ac
);
913 return LDB_ERR_OPERATIONS_ERROR
;
916 dn
= ldb_dn_from_ldb_val(msg
, ldb
, &dn_list
->dn
[i
]);
919 return LDB_ERR_OPERATIONS_ERROR
;
922 ret
= ltdb_search_dn1(ac
->module
, dn
, msg
);
924 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
925 /* the record has disappeared? yes, this can happen */
930 if (ret
!= LDB_SUCCESS
&& ret
!= LDB_ERR_NO_SUCH_OBJECT
) {
931 /* an internal error */
933 return LDB_ERR_OPERATIONS_ERROR
;
936 if (!ldb_match_msg(ldb
, msg
,
937 ac
->tree
, ac
->base
, ac
->scope
)) {
942 /* filter the attributes that the user wants */
943 ret
= ltdb_filter_attrs(msg
, ac
->attrs
);
947 return LDB_ERR_OPERATIONS_ERROR
;
950 ret
= ldb_module_send_entry(ac
->req
, msg
, NULL
);
951 if (ret
!= LDB_SUCCESS
) {
952 ac
->request_terminated
= true;
963 remove any duplicated entries in a indexed result
965 static void ltdb_dn_list_remove_duplicates(struct dn_list
*list
)
969 if (list
->count
< 2) {
973 qsort(list
->dn
, list
->count
, sizeof(struct ldb_val
), (comparison_fn_t
) dn_list_cmp
);
976 for (i
=1; i
<list
->count
; i
++) {
977 if (dn_list_cmp(&list
->dn
[i
], &list
->dn
[new_count
-1]) != 0) {
978 if (new_count
!= i
) {
979 list
->dn
[new_count
] = list
->dn
[i
];
985 list
->count
= new_count
;
989 search the database with a LDAP-like expression using indexes
990 returns -1 if an indexed search is not possible, in which
991 case the caller should call ltdb_search_full()
993 int ltdb_search_indexed(struct ltdb_context
*ac
, uint32_t *match_count
)
995 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(ac
->module
), struct ltdb_private
);
996 struct dn_list
*dn_list
;
999 /* see if indexing is enabled */
1000 if (!ltdb
->cache
->attribute_indexes
&&
1001 !ltdb
->cache
->one_level_indexes
&&
1002 ac
->scope
!= LDB_SCOPE_BASE
) {
1003 /* fallback to a full search */
1004 return LDB_ERR_OPERATIONS_ERROR
;
1007 dn_list
= talloc_zero(ac
, struct dn_list
);
1008 if (dn_list
== NULL
) {
1009 ldb_module_oom(ac
->module
);
1010 return LDB_ERR_OPERATIONS_ERROR
;
1013 switch (ac
->scope
) {
1014 case LDB_SCOPE_BASE
:
1015 dn_list
->dn
= talloc_array(dn_list
, struct ldb_val
, 1);
1016 if (dn_list
->dn
== NULL
) {
1017 ldb_module_oom(ac
->module
);
1018 talloc_free(dn_list
);
1019 return LDB_ERR_OPERATIONS_ERROR
;
1021 dn_list
->dn
[0].data
= discard_const_p(unsigned char, ldb_dn_get_linearized(ac
->base
));
1022 if (dn_list
->dn
[0].data
== NULL
) {
1023 ldb_module_oom(ac
->module
);
1024 talloc_free(dn_list
);
1025 return LDB_ERR_OPERATIONS_ERROR
;
1027 dn_list
->dn
[0].length
= strlen((char *)dn_list
->dn
[0].data
);
1031 case LDB_SCOPE_ONELEVEL
:
1032 if (!ltdb
->cache
->one_level_indexes
) {
1033 talloc_free(dn_list
);
1034 return LDB_ERR_OPERATIONS_ERROR
;
1036 ret
= ltdb_index_dn_one(ac
->module
, ac
->base
, dn_list
);
1037 if (ret
!= LDB_SUCCESS
) {
1038 talloc_free(dn_list
);
1043 case LDB_SCOPE_SUBTREE
:
1044 case LDB_SCOPE_DEFAULT
:
1045 if (!ltdb
->cache
->attribute_indexes
) {
1046 talloc_free(dn_list
);
1047 return LDB_ERR_OPERATIONS_ERROR
;
1049 ret
= ltdb_index_dn(ac
->module
, ac
->tree
, ltdb
->cache
->indexlist
, dn_list
);
1050 if (ret
!= LDB_SUCCESS
) {
1051 talloc_free(dn_list
);
1054 ltdb_dn_list_remove_duplicates(dn_list
);
1058 ret
= ltdb_index_filter(dn_list
, ac
, match_count
);
1059 talloc_free(dn_list
);
1064 add an index entry for one message element
1066 static int ltdb_index_add1(struct ldb_module
*module
, const char *dn
,
1067 struct ldb_message_element
*el
, int v_idx
)
1069 struct ldb_context
*ldb
;
1070 struct ldb_dn
*dn_key
;
1072 const struct ldb_schema_attribute
*a
;
1073 struct dn_list
*list
;
1076 ldb
= ldb_module_get_ctx(module
);
1078 list
= talloc_zero(module
, struct dn_list
);
1080 return LDB_ERR_OPERATIONS_ERROR
;
1083 dn_key
= ltdb_index_key(ldb
, el
->name
, &el
->values
[v_idx
], &a
);
1086 return LDB_ERR_OPERATIONS_ERROR
;
1088 talloc_steal(list
, dn_key
);
1090 ret
= ltdb_dn_list_load(module
, dn_key
, list
);
1091 if (ret
!= LDB_SUCCESS
&& ret
!= LDB_ERR_NO_SUCH_OBJECT
) {
1096 if (ltdb_dn_list_find_str(list
, dn
) != -1) {
1101 if (list
->count
> 0 &&
1102 a
->flags
& LDB_ATTR_FLAG_UNIQUE_INDEX
) {
1104 return LDB_ERR_ENTRY_ALREADY_EXISTS
;
1107 /* overallocate the list a bit, to reduce the number of
1108 * realloc trigered copies */
1109 alloc_len
= ((list
->count
+1)+7) & ~7;
1110 list
->dn
= talloc_realloc(list
, list
->dn
, struct ldb_val
, alloc_len
);
1111 if (list
->dn
== NULL
) {
1113 return LDB_ERR_OPERATIONS_ERROR
;
1115 list
->dn
[list
->count
].data
= (uint8_t *)talloc_strdup(list
->dn
, dn
);
1116 list
->dn
[list
->count
].length
= strlen(dn
);
1119 ret
= ltdb_dn_list_store(module
, dn_key
, list
);
1127 add index entries for one elements in a message
1129 static int ltdb_index_add_el(struct ldb_module
*module
, const char *dn
,
1130 struct ldb_message_element
*el
)
1133 for (i
= 0; i
< el
->num_values
; i
++) {
1134 int ret
= ltdb_index_add1(module
, dn
, el
, i
);
1135 if (ret
!= LDB_SUCCESS
) {
1144 add index entries for all elements in a message
1146 static int ltdb_index_add_all(struct ldb_module
*module
, const char *dn
,
1147 struct ldb_message_element
*elements
, int num_el
)
1149 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1156 if (ltdb
->cache
->indexlist
->num_elements
== 0) {
1157 /* no indexed fields */
1161 for (i
= 0; i
< num_el
; i
++) {
1163 if (!ltdb_is_indexed(ltdb
->cache
->indexlist
, elements
[i
].name
)) {
1166 ret
= ltdb_index_add_el(module
, dn
, &elements
[i
]);
1167 if (ret
!= LDB_SUCCESS
) {
1177 insert a one level index for a message
1179 static int ltdb_index_onelevel(struct ldb_module
*module
, const struct ldb_message
*msg
, int add
)
1181 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1182 struct ldb_message_element el
;
1188 /* We index for ONE Level only if requested */
1189 if (!ltdb
->cache
->one_level_indexes
) {
1193 pdn
= ldb_dn_get_parent(module
, msg
->dn
);
1195 return LDB_ERR_OPERATIONS_ERROR
;
1198 dn
= ldb_dn_get_linearized(msg
->dn
);
1201 return LDB_ERR_OPERATIONS_ERROR
;
1204 val
.data
= (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn
));
1205 if (val
.data
== NULL
) {
1207 return LDB_ERR_OPERATIONS_ERROR
;
1210 val
.length
= strlen((char *)val
.data
);
1211 el
.name
= LTDB_IDXONE
;
1216 ret
= ltdb_index_add1(module
, dn
, &el
, 0);
1217 } else { /* delete */
1218 ret
= ltdb_index_del_value(module
, dn
, &el
, 0);
1227 add the index entries for a new element in a record
1228 The caller guarantees that these element values are not yet indexed
1230 int ltdb_index_add_element(struct ldb_module
*module
, struct ldb_dn
*dn
,
1231 struct ldb_message_element
*el
)
1233 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1234 if (ldb_dn_is_special(dn
)) {
1237 if (!ltdb_is_indexed(ltdb
->cache
->indexlist
, el
->name
)) {
1240 return ltdb_index_add_el(module
, ldb_dn_get_linearized(dn
), el
);
1244 add the index entries for a new record
1246 int ltdb_index_add_new(struct ldb_module
*module
, const struct ldb_message
*msg
)
1251 if (ldb_dn_is_special(msg
->dn
)) {
1255 dn
= ldb_dn_get_linearized(msg
->dn
);
1257 return LDB_ERR_OPERATIONS_ERROR
;
1260 ret
= ltdb_index_add_all(module
, dn
, msg
->elements
, msg
->num_elements
);
1261 if (ret
!= LDB_SUCCESS
) {
1265 return ltdb_index_onelevel(module
, msg
, 1);
1270 delete an index entry for one message element
1272 int ltdb_index_del_value(struct ldb_module
*module
, const char *dn
,
1273 struct ldb_message_element
*el
, int v_idx
)
1275 struct ldb_context
*ldb
;
1276 struct ldb_dn
*dn_key
;
1278 struct dn_list
*list
;
1280 ldb
= ldb_module_get_ctx(module
);
1286 dn_key
= ltdb_index_key(ldb
, el
->name
, &el
->values
[v_idx
], NULL
);
1288 return LDB_ERR_OPERATIONS_ERROR
;
1291 list
= talloc_zero(dn_key
, struct dn_list
);
1293 talloc_free(dn_key
);
1294 return LDB_ERR_OPERATIONS_ERROR
;
1297 ret
= ltdb_dn_list_load(module
, dn_key
, list
);
1298 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
1299 /* it wasn't indexed. Did we have an earlier error? If we did then
1301 talloc_free(dn_key
);
1305 if (ret
!= LDB_SUCCESS
) {
1306 talloc_free(dn_key
);
1310 i
= ltdb_dn_list_find_str(list
, dn
);
1312 /* nothing to delete */
1313 talloc_free(dn_key
);
1317 if (i
!= list
->count
-1) {
1318 memmove(&list
->dn
[i
], &list
->dn
[i
+1], sizeof(list
->dn
[0])*(list
->count
- (i
+1)));
1321 list
->dn
= talloc_realloc(list
, list
->dn
, struct ldb_val
, list
->count
);
1323 ret
= ltdb_dn_list_store(module
, dn_key
, list
);
1325 talloc_free(dn_key
);
1331 delete the index entries for a element
1332 return -1 on failure
1334 int ltdb_index_del_element(struct ldb_module
*module
, const char *dn
, struct ldb_message_element
*el
)
1336 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1340 if (!ltdb
->cache
->attribute_indexes
) {
1341 /* no indexed fields */
1349 if (!ltdb_is_indexed(ltdb
->cache
->indexlist
, el
->name
)) {
1352 for (i
= 0; i
< el
->num_values
; i
++) {
1353 ret
= ltdb_index_del_value(module
, dn
, el
, i
);
1354 if (ret
!= LDB_SUCCESS
) {
1363 delete the index entries for a record
1364 return -1 on failure
1366 int ltdb_index_delete(struct ldb_module
*module
, const struct ldb_message
*msg
)
1368 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1373 if (ldb_dn_is_special(msg
->dn
)) {
1377 ret
= ltdb_index_onelevel(module
, msg
, 0);
1378 if (ret
!= LDB_SUCCESS
) {
1382 if (!ltdb
->cache
->attribute_indexes
) {
1383 /* no indexed fields */
1387 dn
= ldb_dn_get_linearized(msg
->dn
);
1389 return LDB_ERR_OPERATIONS_ERROR
;
1392 for (i
= 0; i
< msg
->num_elements
; i
++) {
1393 ret
= ltdb_index_del_element(module
, dn
, &msg
->elements
[i
]);
1394 if (ret
!= LDB_SUCCESS
) {
1404 traversal function that deletes all @INDEX records
1406 static int delete_index(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1408 struct ldb_module
*module
= state
;
1409 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1410 const char *dnstr
= "DN=" LTDB_INDEX
":";
1411 struct dn_list list
;
1416 if (strncmp((char *)key
.dptr
, dnstr
, strlen(dnstr
)) != 0) {
1419 /* we need to put a empty list in the internal tdb for this
1424 v
.length
= strnlen((char *)key
.dptr
, key
.dsize
);
1426 dn
= ldb_dn_from_ldb_val(ltdb
, ldb_module_get_ctx(module
), &v
);
1427 ret
= ltdb_dn_list_store(module
, dn
, &list
);
1428 if (ret
!= LDB_SUCCESS
) {
1429 ldb_asprintf_errstring(ldb_module_get_ctx(module
),
1430 "Unable to store null index for %s\n",
1431 ldb_dn_get_linearized(dn
));
1440 traversal function that adds @INDEX records during a re index
1442 static int re_index(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1444 struct ldb_context
*ldb
;
1445 struct ldb_module
*module
= (struct ldb_module
*)state
;
1446 struct ldb_message
*msg
;
1447 const char *dn
= NULL
;
1451 ldb
= ldb_module_get_ctx(module
);
1453 if (strncmp((char *)key
.dptr
, "DN=@", 4) == 0 ||
1454 strncmp((char *)key
.dptr
, "DN=", 3) != 0) {
1458 msg
= ldb_msg_new(module
);
1463 ret
= ltdb_unpack_data(module
, &data
, msg
);
1465 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid data for index %s\n",
1466 ldb_dn_get_linearized(msg
->dn
));
1471 /* check if the DN key has changed, perhaps due to the
1472 case insensitivity of an element changing */
1473 key2
= ltdb_key(module
, msg
->dn
);
1474 if (key2
.dptr
== NULL
) {
1475 /* probably a corrupt record ... darn */
1476 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Invalid DN in re_index: %s",
1477 ldb_dn_get_linearized(msg
->dn
));
1481 if (strcmp((char *)key2
.dptr
, (char *)key
.dptr
) != 0) {
1482 tdb_delete(tdb
, key
);
1483 tdb_store(tdb
, key2
, data
, 0);
1485 talloc_free(key2
.dptr
);
1487 if (msg
->dn
== NULL
) {
1488 dn
= (char *)key
.dptr
+ 3;
1490 dn
= ldb_dn_get_linearized(msg
->dn
);
1493 ret
= ltdb_index_onelevel(module
, msg
, 1);
1494 if (ret
!= LDB_SUCCESS
) {
1495 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
1496 "Adding special ONE LEVEL index failed (%s)!",
1497 ldb_dn_get_linearized(msg
->dn
));
1502 ret
= ltdb_index_add_all(module
, dn
, msg
->elements
, msg
->num_elements
);
1506 if (ret
!= LDB_SUCCESS
) return -1;
1512 force a complete reindex of the database
1514 int ltdb_reindex(struct ldb_module
*module
)
1516 struct ltdb_private
*ltdb
= talloc_get_type(ldb_module_get_private(module
), struct ltdb_private
);
1519 if (ltdb_cache_reload(module
) != 0) {
1520 return LDB_ERR_OPERATIONS_ERROR
;
1523 /* first traverse the database deleting any @INDEX records by
1524 * putting NULL entries in the in-memory tdb
1526 ret
= tdb_traverse(ltdb
->tdb
, delete_index
, module
);
1528 return LDB_ERR_OPERATIONS_ERROR
;
1531 /* if we don't have indexes we have nothing todo */
1532 if (ltdb
->cache
->indexlist
->num_elements
== 0) {
1536 /* now traverse adding any indexes for normal LDB records */
1537 ret
= tdb_traverse(ltdb
->tdb
, re_index
, module
);
1539 return LDB_ERR_OPERATIONS_ERROR
;