4 Copyright (C) Andrew Tridgell 2004-2009
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 * Component: ldb tdb backend - indexing
29 * Description: indexing routines for ldb tdb backend
31 * Author: Andrew Tridgell
35 #include "ldb_private.h"
43 struct tdb_context *itdb;
47 /* we put a @IDXVERSION attribute on index entries. This
48 allows us to tell if it was written by an older version
50 #define LTDB_INDEXING_VERSION 2
52 /* enable the idxptr mode when transactions start */
53 int ltdb_index_transaction_start(struct ldb_module *module)
55 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
56 ltdb->idxptr = talloc_zero(ltdb, struct ltdb_idxptr);
57 if (ltdb->idxptr == NULL) {
58 return ldb_oom(ldb_module_get_ctx(module));
64 /* compare two DN entries in a dn_list. Take account of possible
65 * differences in string termination */
66 static int dn_list_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
68 if (v1->length > v2->length && v1->data[v2->length] != 0) {
71 if (v1->length < v2->length && v2->data[v1->length] != 0) {
74 return strncmp((char *)v1->data, (char *)v2->data, v1->length);
79 find a entry in a dn_list, using a ldb_val. Uses a case sensitive
80 comparison with the dn returns -1 if not found
82 static int ltdb_dn_list_find_val(const struct dn_list *list, const struct ldb_val *v)
85 for (i=0; i<list->count; i++) {
86 if (dn_list_cmp(&list->dn[i], v) == 0) return i;
92 find a entry in a dn_list. Uses a case sensitive comparison with the dn
93 returns -1 if not found
95 static int ltdb_dn_list_find_str(struct dn_list *list, const char *dn)
98 v.data = discard_const_p(unsigned char, dn);
99 v.length = strlen(dn);
100 return ltdb_dn_list_find_val(list, &v);
104 this is effectively a cast function, but with lots of paranoia
105 checks and also copes with CPUs that are fussy about pointer
108 static struct dn_list *ltdb_index_idxptr(struct ldb_module *module, TDB_DATA rec, bool check_parent)
110 struct dn_list *list;
111 if (rec.dsize != sizeof(void *)) {
112 ldb_asprintf_errstring(ldb_module_get_ctx(module),
113 "Bad data size for idxptr %u", (unsigned)rec.dsize);
116 /* note that we can't just use a cast here, as rec.dptr may
117 not be aligned sufficiently for a pointer. A cast would cause
118 platforms like some ARM CPUs to crash */
119 memcpy(&list, rec.dptr, sizeof(void *));
120 list = talloc_get_type(list, struct dn_list);
122 ldb_asprintf_errstring(ldb_module_get_ctx(module),
123 "Bad type '%s' for idxptr",
124 talloc_get_name(list));
127 if (check_parent && list->dn && talloc_parent(list->dn) != list) {
128 ldb_asprintf_errstring(ldb_module_get_ctx(module),
129 "Bad parent '%s' for idxptr",
130 talloc_get_name(talloc_parent(list->dn)));
137 return the @IDX list in an index entry for a dn as a
140 static int ltdb_dn_list_load(struct ldb_module *module,
141 struct ldb_dn *dn, struct dn_list *list)
143 struct ldb_message *msg;
145 struct ldb_message_element *el;
146 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
148 struct dn_list *list2;
154 /* see if we have any in-memory index entries */
155 if (ltdb->idxptr == NULL ||
156 ltdb->idxptr->itdb == NULL) {
160 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
161 key.dsize = strlen((char *)key.dptr);
163 rec = tdb_fetch(ltdb->idxptr->itdb, key);
164 if (rec.dptr == NULL) {
168 /* we've found an in-memory index entry */
169 list2 = ltdb_index_idxptr(module, rec, true);
172 return LDB_ERR_OPERATIONS_ERROR;
180 msg = ldb_msg_new(list);
182 return LDB_ERR_OPERATIONS_ERROR;
185 ret = ltdb_search_dn1(module, dn, msg,
186 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
187 |LDB_UNPACK_DATA_FLAG_NO_DN);
188 if (ret != LDB_SUCCESS) {
193 /* TODO: check indexing version number */
195 el = ldb_msg_find_element(msg, LTDB_IDX);
202 * we avoid copying the strings by stealing the list. We have
203 * to steal msg onto el->values (which looks odd) because we
204 * asked for the memory to be allocated on msg, not on each
205 * value with LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC above
207 talloc_steal(el->values, msg);
208 list->dn = talloc_steal(list, el->values);
209 list->count = el->num_values;
211 /* We don't need msg->elements any more */
212 talloc_free(msg->elements);
218 save a dn_list into a full @IDX style record
220 static int ltdb_dn_list_store_full(struct ldb_module *module, struct ldb_dn *dn,
221 struct dn_list *list)
223 struct ldb_message *msg;
226 if (list->count == 0) {
227 ret = ltdb_delete_noindex(module, dn);
228 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
234 msg = ldb_msg_new(module);
236 return ldb_module_oom(module);
239 ret = ldb_msg_add_fmt(msg, LTDB_IDXVERSION, "%u", LTDB_INDEXING_VERSION);
240 if (ret != LDB_SUCCESS) {
242 return ldb_module_oom(module);
246 if (list->count > 0) {
247 struct ldb_message_element *el;
249 ret = ldb_msg_add_empty(msg, LTDB_IDX, LDB_FLAG_MOD_ADD, &el);
250 if (ret != LDB_SUCCESS) {
252 return ldb_module_oom(module);
254 el->values = list->dn;
255 el->num_values = list->count;
258 ret = ltdb_store(module, msg, TDB_REPLACE);
264 save a dn_list into the database, in either @IDX or internal format
266 static int ltdb_dn_list_store(struct ldb_module *module, struct ldb_dn *dn,
267 struct dn_list *list)
269 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
272 struct dn_list *list2;
274 if (ltdb->idxptr == NULL) {
275 return ltdb_dn_list_store_full(module, dn, list);
278 if (ltdb->idxptr->itdb == NULL) {
279 ltdb->idxptr->itdb = tdb_open(NULL, 1000, TDB_INTERNAL, O_RDWR, 0);
280 if (ltdb->idxptr->itdb == NULL) {
281 return LDB_ERR_OPERATIONS_ERROR;
285 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
286 key.dsize = strlen((char *)key.dptr);
288 rec = tdb_fetch(ltdb->idxptr->itdb, key);
289 if (rec.dptr != NULL) {
290 list2 = ltdb_index_idxptr(module, rec, false);
293 return LDB_ERR_OPERATIONS_ERROR;
296 list2->dn = talloc_steal(list2, list->dn);
297 list2->count = list->count;
301 list2 = talloc(ltdb->idxptr, struct dn_list);
303 return LDB_ERR_OPERATIONS_ERROR;
305 list2->dn = talloc_steal(list2, list->dn);
306 list2->count = list->count;
308 rec.dptr = (uint8_t *)&list2;
309 rec.dsize = sizeof(void *);
311 ret = tdb_store(ltdb->idxptr->itdb, key, rec, TDB_INSERT);
313 return ltdb_err_map(tdb_error(ltdb->idxptr->itdb));
319 traverse function for storing the in-memory index entries on disk
321 static int ltdb_index_traverse_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
323 struct ldb_module *module = state;
324 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
326 struct ldb_context *ldb = ldb_module_get_ctx(module);
328 struct dn_list *list;
330 list = ltdb_index_idxptr(module, data, true);
332 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
337 v.length = strnlen((char *)key.dptr, key.dsize);
339 dn = ldb_dn_from_ldb_val(module, ldb, &v);
341 ldb_asprintf_errstring(ldb, "Failed to parse index key %*.*s as an LDB DN", (int)v.length, (int)v.length, (const char *)v.data);
342 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
346 ltdb->idxptr->error = ltdb_dn_list_store_full(module, dn, list);
348 if (ltdb->idxptr->error != 0) {
354 /* cleanup the idxptr mode when transaction commits */
355 int ltdb_index_transaction_commit(struct ldb_module *module)
357 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
360 struct ldb_context *ldb = ldb_module_get_ctx(module);
362 ldb_reset_err_string(ldb);
364 if (ltdb->idxptr->itdb) {
365 tdb_traverse(ltdb->idxptr->itdb, ltdb_index_traverse_store, module);
366 tdb_close(ltdb->idxptr->itdb);
369 ret = ltdb->idxptr->error;
370 if (ret != LDB_SUCCESS) {
371 if (!ldb_errstring(ldb)) {
372 ldb_set_errstring(ldb, ldb_strerror(ret));
374 ldb_asprintf_errstring(ldb, "Failed to store index records in transaction commit: %s", ldb_errstring(ldb));
377 talloc_free(ltdb->idxptr);
382 /* cleanup the idxptr mode when transaction cancels */
383 int ltdb_index_transaction_cancel(struct ldb_module *module)
385 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
386 if (ltdb->idxptr && ltdb->idxptr->itdb) {
387 tdb_close(ltdb->idxptr->itdb);
389 talloc_free(ltdb->idxptr);
396 return the dn key to be used for an index
397 the caller is responsible for freeing
399 static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
400 const char *attr, const struct ldb_val *value,
401 const struct ldb_schema_attribute **ap)
405 const struct ldb_schema_attribute *a;
409 attr_folded = ldb_attr_casefold(ldb, attr);
414 a = ldb_schema_attribute_by_name(ldb, attr);
418 r = a->syntax->canonicalise_fn(ldb, ldb, value, &v);
419 if (r != LDB_SUCCESS) {
420 const char *errstr = ldb_errstring(ldb);
421 /* canonicalisation can be refused. For example,
422 a attribute that takes wildcards will refuse to canonicalise
423 if the value contains a wildcard */
424 ldb_asprintf_errstring(ldb, "Failed to create index key for attribute '%s':%s%s%s",
425 attr, ldb_strerror(r), (errstr?":":""), (errstr?errstr:""));
426 talloc_free(attr_folded);
429 if (ldb_should_b64_encode(ldb, &v)) {
430 char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length);
432 talloc_free(attr_folded);
435 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr);
438 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s:%.*s", LTDB_INDEX, attr_folded, (int)v.length, (char *)v.data);
441 if (v.data != value->data) {
444 talloc_free(attr_folded);
450 see if a attribute value is in the list of indexed attributes
452 static bool ltdb_is_indexed(struct ldb_module *module,
453 struct ltdb_private *ltdb,
456 struct ldb_context *ldb = ldb_module_get_ctx(module);
458 struct ldb_message_element *el;
460 if (ldb->schema.index_handler_override) {
461 const struct ldb_schema_attribute *a
462 = ldb_schema_attribute_by_name(ldb, attr);
468 if (a->flags & LDB_ATTR_FLAG_INDEXED) {
475 if (!ltdb->cache->attribute_indexes) {
479 el = ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXATTR);
484 /* TODO: this is too expensive! At least use a binary search */
485 for (i=0; i<el->num_values; i++) {
486 if (ldb_attr_cmp((char *)el->values[i].data, attr) == 0) {
494 in the following logic functions, the return value is treated as
497 LDB_SUCCESS: we found some matching index values
499 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
501 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
502 we'll need a full search
506 return a list of dn's that might match a simple indexed search (an
507 equality search only)
509 static int ltdb_index_dn_simple(struct ldb_module *module,
510 struct ltdb_private *ltdb,
511 const struct ldb_parse_tree *tree,
512 struct dn_list *list)
514 struct ldb_context *ldb;
518 ldb = ldb_module_get_ctx(module);
523 /* if the attribute isn't in the list of indexed attributes then
524 this node needs a full search */
525 if (!ltdb_is_indexed(module, ltdb, tree->u.equality.attr)) {
526 return LDB_ERR_OPERATIONS_ERROR;
529 /* the attribute is indexed. Pull the list of DNs that match the
531 dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value, NULL);
532 if (!dn) return LDB_ERR_OPERATIONS_ERROR;
534 ret = ltdb_dn_list_load(module, dn, list);
540 static bool list_union(struct ldb_context *, struct dn_list *, const struct dn_list *);
543 return a list of dn's that might match a leaf indexed search
545 static int ltdb_index_dn_leaf(struct ldb_module *module,
546 struct ltdb_private *ltdb,
547 const struct ldb_parse_tree *tree,
548 struct dn_list *list)
550 if (ltdb->disallow_dn_filter &&
551 (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0)) {
552 /* in AD mode we do not support "(dn=...)" search filters */
557 if (ldb_attr_dn(tree->u.equality.attr) == 0) {
558 list->dn = talloc_array(list, struct ldb_val, 1);
559 if (list->dn == NULL) {
560 ldb_module_oom(module);
561 return LDB_ERR_OPERATIONS_ERROR;
563 list->dn[0] = tree->u.equality.value;
567 return ltdb_index_dn_simple(module, ltdb, tree, list);
575 static bool list_intersect(struct ldb_context *ldb,
576 struct dn_list *list, const struct dn_list *list2)
578 struct dn_list *list3;
581 if (list->count == 0) {
585 if (list2->count == 0) {
592 /* the indexing code is allowed to return a longer list than
593 what really matches, as all results are filtered by the
594 full expression at the end - this shortcut avoids a lot of
595 work in some cases */
596 if (list->count < 2 && list2->count > 10) {
599 if (list2->count < 2 && list->count > 10) {
600 list->count = list2->count;
601 list->dn = list2->dn;
602 /* note that list2 may not be the parent of list2->dn,
603 as list2->dn may be owned by ltdb->idxptr. In that
604 case we expect this reparent call to fail, which is
606 talloc_reparent(list2, list, list2->dn);
610 list3 = talloc_zero(list, struct dn_list);
615 list3->dn = talloc_array(list3, struct ldb_val, list->count);
622 for (i=0;i<list->count;i++) {
623 if (ltdb_dn_list_find_val(list2, &list->dn[i]) != -1) {
624 list3->dn[list3->count] = list->dn[i];
629 list->dn = talloc_steal(list, list3->dn);
630 list->count = list3->count;
641 static bool list_union(struct ldb_context *ldb,
642 struct dn_list *list, const struct dn_list *list2)
646 if (list2->count == 0) {
651 if (list->count == 0) {
653 list->count = list2->count;
654 list->dn = list2->dn;
655 /* note that list2 may not be the parent of list2->dn,
656 as list2->dn may be owned by ltdb->idxptr. In that
657 case we expect this reparent call to fail, which is
659 talloc_reparent(list2, list, list2->dn);
663 dn3 = talloc_array(list, struct ldb_val, list->count + list2->count);
669 /* we allow for duplicates here, and get rid of them later */
670 memcpy(dn3, list->dn, sizeof(list->dn[0])*list->count);
671 memcpy(dn3+list->count, list2->dn, sizeof(list2->dn[0])*list2->count);
674 list->count += list2->count;
679 static int ltdb_index_dn(struct ldb_module *module,
680 struct ltdb_private *ltdb,
681 const struct ldb_parse_tree *tree,
682 struct dn_list *list);
686 process an OR list (a union)
688 static int ltdb_index_dn_or(struct ldb_module *module,
689 struct ltdb_private *ltdb,
690 const struct ldb_parse_tree *tree,
691 struct dn_list *list)
693 struct ldb_context *ldb;
696 ldb = ldb_module_get_ctx(module);
701 for (i=0; i<tree->u.list.num_elements; i++) {
702 struct dn_list *list2;
705 list2 = talloc_zero(list, struct dn_list);
707 return LDB_ERR_OPERATIONS_ERROR;
710 ret = ltdb_index_dn(module, ltdb,
711 tree->u.list.elements[i], list2);
713 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
719 if (ret != LDB_SUCCESS) {
725 if (!list_union(ldb, list, list2)) {
727 return LDB_ERR_OPERATIONS_ERROR;
731 if (list->count == 0) {
732 return LDB_ERR_NO_SUCH_OBJECT;
742 static int ltdb_index_dn_not(struct ldb_module *module,
743 struct ltdb_private *ltdb,
744 const struct ldb_parse_tree *tree,
745 struct dn_list *list)
747 /* the only way to do an indexed not would be if we could
748 negate the not via another not or if we knew the total
749 number of database elements so we could know that the
750 existing expression covered the whole database.
752 instead, we just give up, and rely on a full index scan
753 (unless an outer & manages to reduce the list)
755 return LDB_ERR_OPERATIONS_ERROR;
759 static bool ltdb_index_unique(struct ldb_context *ldb,
762 const struct ldb_schema_attribute *a;
763 a = ldb_schema_attribute_by_name(ldb, attr);
764 if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
771 process an AND expression (intersection)
773 static int ltdb_index_dn_and(struct ldb_module *module,
774 struct ltdb_private *ltdb,
775 const struct ldb_parse_tree *tree,
776 struct dn_list *list)
778 struct ldb_context *ldb;
782 ldb = ldb_module_get_ctx(module);
787 /* in the first pass we only look for unique simple
788 equality tests, in the hope of avoiding having to look
790 for (i=0; i<tree->u.list.num_elements; i++) {
791 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
794 if (subtree->operation != LDB_OP_EQUALITY ||
795 !ltdb_index_unique(ldb, subtree->u.equality.attr)) {
799 ret = ltdb_index_dn(module, ltdb, subtree, list);
800 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
802 return LDB_ERR_NO_SUCH_OBJECT;
804 if (ret == LDB_SUCCESS) {
805 /* a unique index match means we can
806 * stop. Note that we don't care if we return
807 * a few too many objects, due to later
813 /* now do a full intersection */
816 for (i=0; i<tree->u.list.num_elements; i++) {
817 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
818 struct dn_list *list2;
821 list2 = talloc_zero(list, struct dn_list);
823 return ldb_module_oom(module);
826 ret = ltdb_index_dn(module, ltdb, subtree, list2);
828 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
833 return LDB_ERR_NO_SUCH_OBJECT;
836 if (ret != LDB_SUCCESS) {
837 /* this didn't adding anything */
843 talloc_reparent(list2, list, list->dn);
844 list->dn = list2->dn;
845 list->count = list2->count;
847 } else if (!list_intersect(ldb, list, list2)) {
849 return LDB_ERR_OPERATIONS_ERROR;
852 if (list->count == 0) {
854 return LDB_ERR_NO_SUCH_OBJECT;
857 if (list->count < 2) {
858 /* it isn't worth loading the next part of the tree */
864 /* none of the attributes were indexed */
865 return LDB_ERR_OPERATIONS_ERROR;
872 return a list of matching objects using a one-level index
874 static int ltdb_index_dn_one(struct ldb_module *module,
875 struct ldb_dn *parent_dn,
876 struct dn_list *list)
878 struct ldb_context *ldb;
883 ldb = ldb_module_get_ctx(module);
885 /* work out the index key from the parent DN */
886 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn));
887 val.length = strlen((char *)val.data);
888 key = ltdb_index_key(ldb, LTDB_IDXONE, &val, NULL);
891 return LDB_ERR_OPERATIONS_ERROR;
894 ret = ltdb_dn_list_load(module, key, list);
896 if (ret != LDB_SUCCESS) {
900 if (list->count == 0) {
901 return LDB_ERR_NO_SUCH_OBJECT;
908 return a list of dn's that might match a indexed search or
909 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
911 static int ltdb_index_dn(struct ldb_module *module,
912 struct ltdb_private *ltdb,
913 const struct ldb_parse_tree *tree,
914 struct dn_list *list)
916 int ret = LDB_ERR_OPERATIONS_ERROR;
918 switch (tree->operation) {
920 ret = ltdb_index_dn_and(module, ltdb, tree, list);
924 ret = ltdb_index_dn_or(module, ltdb, tree, list);
928 ret = ltdb_index_dn_not(module, ltdb, tree, list);
931 case LDB_OP_EQUALITY:
932 ret = ltdb_index_dn_leaf(module, ltdb, tree, list);
935 case LDB_OP_SUBSTRING:
940 case LDB_OP_EXTENDED:
941 /* we can't index with fancy bitops yet */
942 ret = LDB_ERR_OPERATIONS_ERROR;
950 filter a candidate dn_list from an indexed search into a set of results
951 extracting just the given attributes
953 static int ltdb_index_filter(const struct dn_list *dn_list,
954 struct ltdb_context *ac,
955 uint32_t *match_count)
957 struct ldb_context *ldb;
958 struct ldb_message *msg;
959 struct ldb_message *filtered_msg;
962 ldb = ldb_module_get_ctx(ac->module);
964 for (i = 0; i < dn_list->count; i++) {
969 msg = ldb_msg_new(ac);
971 return LDB_ERR_OPERATIONS_ERROR;
974 dn = ldb_dn_from_ldb_val(msg, ldb, &dn_list->dn[i]);
977 return LDB_ERR_OPERATIONS_ERROR;
980 ret = ltdb_search_dn1(ac->module, dn, msg,
981 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC|
982 LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC);
984 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
985 /* the record has disappeared? yes, this can happen */
990 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
991 /* an internal error */
993 return LDB_ERR_OPERATIONS_ERROR;
996 ret = ldb_match_msg_error(ldb, msg,
997 ac->tree, ac->base, ac->scope, &matched);
998 if (ret != LDB_SUCCESS) {
1007 /* filter the attributes that the user wants */
1008 ret = ltdb_filter_attrs(ac, msg, ac->attrs, &filtered_msg);
1013 return LDB_ERR_OPERATIONS_ERROR;
1016 ret = ldb_module_send_entry(ac->req, filtered_msg, NULL);
1017 if (ret != LDB_SUCCESS) {
1018 /* Regardless of success or failure, the msg
1019 * is the callbacks responsiblity, and should
1020 * not be talloc_free()'ed */
1021 ac->request_terminated = true;
1032 remove any duplicated entries in a indexed result
1034 static void ltdb_dn_list_remove_duplicates(struct dn_list *list)
1036 unsigned int i, new_count;
1038 if (list->count < 2) {
1042 TYPESAFE_QSORT(list->dn, list->count, dn_list_cmp);
1045 for (i=1; i<list->count; i++) {
1046 if (dn_list_cmp(&list->dn[i], &list->dn[new_count-1]) != 0) {
1047 if (new_count != i) {
1048 list->dn[new_count] = list->dn[i];
1054 list->count = new_count;
1058 search the database with a LDAP-like expression using indexes
1059 returns -1 if an indexed search is not possible, in which
1060 case the caller should call ltdb_search_full()
1062 int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
1064 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(ac->module), struct ltdb_private);
1065 struct dn_list *dn_list;
1068 /* see if indexing is enabled */
1069 if (!ltdb->cache->attribute_indexes &&
1070 !ltdb->cache->one_level_indexes &&
1071 ac->scope != LDB_SCOPE_BASE) {
1072 /* fallback to a full search */
1073 return LDB_ERR_OPERATIONS_ERROR;
1076 dn_list = talloc_zero(ac, struct dn_list);
1077 if (dn_list == NULL) {
1078 return ldb_module_oom(ac->module);
1081 switch (ac->scope) {
1082 case LDB_SCOPE_BASE:
1083 dn_list->dn = talloc_array(dn_list, struct ldb_val, 1);
1084 if (dn_list->dn == NULL) {
1085 talloc_free(dn_list);
1086 return ldb_module_oom(ac->module);
1088 dn_list->dn[0].data = discard_const_p(unsigned char, ldb_dn_get_linearized(ac->base));
1089 if (dn_list->dn[0].data == NULL) {
1090 talloc_free(dn_list);
1091 return ldb_module_oom(ac->module);
1093 dn_list->dn[0].length = strlen((char *)dn_list->dn[0].data);
1097 case LDB_SCOPE_ONELEVEL:
1098 if (!ltdb->cache->one_level_indexes) {
1099 talloc_free(dn_list);
1100 return LDB_ERR_OPERATIONS_ERROR;
1102 ret = ltdb_index_dn_one(ac->module, ac->base, dn_list);
1103 if (ret != LDB_SUCCESS) {
1104 talloc_free(dn_list);
1109 case LDB_SCOPE_SUBTREE:
1110 case LDB_SCOPE_DEFAULT:
1111 if (!ltdb->cache->attribute_indexes) {
1112 talloc_free(dn_list);
1113 return LDB_ERR_OPERATIONS_ERROR;
1115 ret = ltdb_index_dn(ac->module, ltdb, ac->tree, dn_list);
1116 if (ret != LDB_SUCCESS) {
1117 talloc_free(dn_list);
1120 ltdb_dn_list_remove_duplicates(dn_list);
1124 ret = ltdb_index_filter(dn_list, ac, match_count);
1125 talloc_free(dn_list);
1130 * @brief Add a DN in the index list of a given attribute name/value pair
1132 * This function will add the DN in the index list for the index for
1133 * the given attribute name and value.
1135 * @param[in] module A ldb_module structure
1137 * @param[in] dn The string representation of the DN as it
1138 * will be stored in the index entry
1140 * @param[in] el A ldb_message_element array, one of the entry
1141 * referred by the v_idx is the attribute name and
1142 * value pair which will be used to construct the
1145 * @param[in] v_idx The index of element in the el array to use
1147 * @return An ldb error code
1149 static int ltdb_index_add1(struct ldb_module *module, const char *dn,
1150 struct ldb_message_element *el, int v_idx,
1153 struct ldb_context *ldb;
1154 struct ldb_dn *dn_key;
1156 const struct ldb_schema_attribute *a;
1157 struct dn_list *list;
1160 ldb = ldb_module_get_ctx(module);
1162 list = talloc_zero(module, struct dn_list);
1164 return LDB_ERR_OPERATIONS_ERROR;
1167 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], &a);
1170 return LDB_ERR_OPERATIONS_ERROR;
1172 talloc_steal(list, dn_key);
1174 ret = ltdb_dn_list_load(module, dn_key, list);
1175 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1180 if (list->count > 0 &&
1181 a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
1183 ldb_asprintf_errstring(ldb, __location__ ": unique index violation on %s in %s",
1185 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1188 /* If we are doing an ADD, then this can not already be in the index,
1189 as it was not already in the database, and this has already been
1190 checked because the store succeeded */
1192 if (ltdb_dn_list_find_str(list, dn) != -1) {
1198 /* overallocate the list a bit, to reduce the number of
1199 * realloc trigered copies */
1200 alloc_len = ((list->count+1)+7) & ~7;
1201 list->dn = talloc_realloc(list, list->dn, struct ldb_val, alloc_len);
1202 if (list->dn == NULL) {
1204 return LDB_ERR_OPERATIONS_ERROR;
1206 list->dn[list->count].data = (uint8_t *)talloc_strdup(list->dn, dn);
1207 list->dn[list->count].length = strlen(dn);
1210 ret = ltdb_dn_list_store(module, dn_key, list);
1218 add index entries for one elements in a message
1220 static int ltdb_index_add_el(struct ldb_module *module, const char *dn,
1221 struct ldb_message_element *el, bool is_new)
1224 for (i = 0; i < el->num_values; i++) {
1225 int ret = ltdb_index_add1(module, dn, el, i, is_new);
1226 if (ret != LDB_SUCCESS) {
1235 add index entries for all elements in a message
1237 static int ltdb_index_add_all(struct ldb_module *module, const char *dn,
1238 struct ldb_message_element *elements,
1239 unsigned int num_el,
1242 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1249 if (!ltdb->cache->attribute_indexes) {
1250 /* no indexed fields */
1254 for (i = 0; i < num_el; i++) {
1256 if (!ltdb_is_indexed(module, ltdb, elements[i].name)) {
1259 ret = ltdb_index_add_el(module, dn, &elements[i], is_new);
1260 if (ret != LDB_SUCCESS) {
1261 struct ldb_context *ldb = ldb_module_get_ctx(module);
1262 ldb_asprintf_errstring(ldb,
1263 __location__ ": Failed to re-index %s in %s - %s",
1264 elements[i].name, dn, ldb_errstring(ldb));
1274 insert a one level index for a message
1276 static int ltdb_index_onelevel(struct ldb_module *module, const struct ldb_message *msg, int add)
1278 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1279 struct ldb_message_element el;
1285 /* We index for ONE Level only if requested */
1286 if (!ltdb->cache->one_level_indexes) {
1290 pdn = ldb_dn_get_parent(module, msg->dn);
1292 return LDB_ERR_OPERATIONS_ERROR;
1295 dn = ldb_dn_get_linearized(msg->dn);
1298 return LDB_ERR_OPERATIONS_ERROR;
1301 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn));
1302 if (val.data == NULL) {
1304 return LDB_ERR_OPERATIONS_ERROR;
1307 val.length = strlen((char *)val.data);
1308 el.name = LTDB_IDXONE;
1313 ret = ltdb_index_add1(module, dn, &el, 0, add);
1314 } else { /* delete */
1315 ret = ltdb_index_del_value(module, msg->dn, &el, 0);
1324 add the index entries for a new element in a record
1325 The caller guarantees that these element values are not yet indexed
1327 int ltdb_index_add_element(struct ldb_module *module, struct ldb_dn *dn,
1328 struct ldb_message_element *el)
1330 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1331 if (ldb_dn_is_special(dn)) {
1334 if (!ltdb_is_indexed(module, ltdb, el->name)) {
1337 return ltdb_index_add_el(module, ldb_dn_get_linearized(dn), el, true);
1341 add the index entries for a new record
1343 int ltdb_index_add_new(struct ldb_module *module, const struct ldb_message *msg)
1348 if (ldb_dn_is_special(msg->dn)) {
1352 dn = ldb_dn_get_linearized(msg->dn);
1354 return LDB_ERR_OPERATIONS_ERROR;
1357 ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements,
1359 if (ret != LDB_SUCCESS) {
1363 return ltdb_index_onelevel(module, msg, 1);
1368 delete an index entry for one message element
1370 int ltdb_index_del_value(struct ldb_module *module, struct ldb_dn *dn,
1371 struct ldb_message_element *el, unsigned int v_idx)
1373 struct ldb_context *ldb;
1374 struct ldb_dn *dn_key;
1378 struct dn_list *list;
1380 ldb = ldb_module_get_ctx(module);
1382 dn_str = ldb_dn_get_linearized(dn);
1383 if (dn_str == NULL) {
1384 return LDB_ERR_OPERATIONS_ERROR;
1387 if (dn_str[0] == '@') {
1391 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], NULL);
1393 return LDB_ERR_OPERATIONS_ERROR;
1396 list = talloc_zero(dn_key, struct dn_list);
1398 talloc_free(dn_key);
1399 return LDB_ERR_OPERATIONS_ERROR;
1402 ret = ltdb_dn_list_load(module, dn_key, list);
1403 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1404 /* it wasn't indexed. Did we have an earlier error? If we did then
1406 talloc_free(dn_key);
1410 if (ret != LDB_SUCCESS) {
1411 talloc_free(dn_key);
1415 i = ltdb_dn_list_find_str(list, dn_str);
1417 /* nothing to delete */
1418 talloc_free(dn_key);
1422 j = (unsigned int) i;
1423 if (j != list->count - 1) {
1424 memmove(&list->dn[j], &list->dn[j+1], sizeof(list->dn[0])*(list->count - (j+1)));
1427 if (list->count == 0) {
1428 talloc_free(list->dn);
1431 list->dn = talloc_realloc(list, list->dn, struct ldb_val, list->count);
1434 ret = ltdb_dn_list_store(module, dn_key, list);
1436 talloc_free(dn_key);
1442 delete the index entries for a element
1443 return -1 on failure
1445 int ltdb_index_del_element(struct ldb_module *module, struct ldb_dn *dn,
1446 struct ldb_message_element *el)
1448 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1453 if (!ltdb->cache->attribute_indexes) {
1454 /* no indexed fields */
1458 dn_str = ldb_dn_get_linearized(dn);
1459 if (dn_str == NULL) {
1460 return LDB_ERR_OPERATIONS_ERROR;
1463 if (dn_str[0] == '@') {
1467 if (!ltdb_is_indexed(module, ltdb, el->name)) {
1470 for (i = 0; i < el->num_values; i++) {
1471 ret = ltdb_index_del_value(module, dn, el, i);
1472 if (ret != LDB_SUCCESS) {
1481 delete the index entries for a record
1482 return -1 on failure
1484 int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg)
1486 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1490 if (ldb_dn_is_special(msg->dn)) {
1494 ret = ltdb_index_onelevel(module, msg, 0);
1495 if (ret != LDB_SUCCESS) {
1499 if (!ltdb->cache->attribute_indexes) {
1500 /* no indexed fields */
1504 for (i = 0; i < msg->num_elements; i++) {
1505 ret = ltdb_index_del_element(module, msg->dn, &msg->elements[i]);
1506 if (ret != LDB_SUCCESS) {
1516 traversal function that deletes all @INDEX records
1518 static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1520 struct ldb_module *module = state;
1521 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1522 const char *dnstr = "DN=" LTDB_INDEX ":";
1523 struct dn_list list;
1528 if (strncmp((char *)key.dptr, dnstr, strlen(dnstr)) != 0) {
1531 /* we need to put a empty list in the internal tdb for this
1536 /* the offset of 3 is to remove the DN= prefix. */
1537 v.data = key.dptr + 3;
1538 v.length = strnlen((char *)key.dptr, key.dsize) - 3;
1540 dn = ldb_dn_from_ldb_val(ltdb, ldb_module_get_ctx(module), &v);
1541 ret = ltdb_dn_list_store(module, dn, &list);
1542 if (ret != LDB_SUCCESS) {
1543 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1544 "Unable to store null index for %s\n",
1545 ldb_dn_get_linearized(dn));
1553 struct ltdb_reindex_context {
1554 struct ldb_module *module;
1559 traversal function that adds @INDEX records during a re index
1561 static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1563 struct ldb_context *ldb;
1564 struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
1565 struct ldb_module *module = ctx->module;
1566 struct ldb_message *msg;
1567 unsigned int nb_elements_in_db;
1568 const struct ldb_val val = {
1570 .length = data.dsize,
1572 const char *dn = NULL;
1576 ldb = ldb_module_get_ctx(module);
1578 if (strncmp((char *)key.dptr, "DN=@", 4) == 0 ||
1579 strncmp((char *)key.dptr, "DN=", 3) != 0) {
1583 msg = ldb_msg_new(module);
1588 ret = ldb_unpack_data_only_attr_list_flags(ldb, &val,
1591 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC,
1592 &nb_elements_in_db);
1594 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
1595 ldb_dn_get_linearized(msg->dn));
1600 /* check if the DN key has changed, perhaps due to the
1601 case insensitivity of an element changing */
1602 key2 = ltdb_key(module, msg->dn);
1603 if (key2.dptr == NULL) {
1604 /* probably a corrupt record ... darn */
1605 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s",
1606 ldb_dn_get_linearized(msg->dn));
1610 if (strcmp((char *)key2.dptr, (char *)key.dptr) != 0) {
1611 tdb_delete(tdb, key);
1612 tdb_store(tdb, key2, data, 0);
1614 talloc_free(key2.dptr);
1616 if (msg->dn == NULL) {
1617 dn = (char *)key.dptr + 3;
1619 dn = ldb_dn_get_linearized(msg->dn);
1622 ret = ltdb_index_onelevel(module, msg, 1);
1623 if (ret != LDB_SUCCESS) {
1624 ldb_debug(ldb, LDB_DEBUG_ERROR,
1625 "Adding special ONE LEVEL index failed (%s)!",
1626 ldb_dn_get_linearized(msg->dn));
1631 ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements,
1634 if (ret != LDB_SUCCESS) {
1646 force a complete reindex of the database
1648 int ltdb_reindex(struct ldb_module *module)
1650 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1652 struct ltdb_reindex_context ctx;
1654 if (ltdb_cache_reload(module) != 0) {
1655 return LDB_ERR_OPERATIONS_ERROR;
1658 /* first traverse the database deleting any @INDEX records by
1659 * putting NULL entries in the in-memory tdb
1661 ret = tdb_traverse(ltdb->tdb, delete_index, module);
1663 return LDB_ERR_OPERATIONS_ERROR;
1666 /* if we don't have indexes we have nothing todo */
1667 if (!ltdb->cache->attribute_indexes) {
1671 ctx.module = module;
1674 /* now traverse adding any indexes for normal LDB records */
1675 ret = tdb_traverse(ltdb->tdb, re_index, &ctx);
1677 struct ldb_context *ldb = ldb_module_get_ctx(module);
1678 ldb_asprintf_errstring(ldb, "reindexing traverse failed: %s", ldb_errstring(ldb));
1679 return LDB_ERR_OPERATIONS_ERROR;
1682 if (ctx.error != LDB_SUCCESS) {
1683 struct ldb_context *ldb = ldb_module_get_ctx(module);
1684 ldb_asprintf_errstring(ldb, "reindexing failed: %s", ldb_errstring(ldb));