4 Copyright (C) Andrew Tridgell 2004-2009
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 * Component: ldb tdb backend - indexing
29 * Description: indexing routines for ldb tdb backend
31 * Author: Andrew Tridgell
42 struct tdb_context *itdb;
47 /* we put a @IDXVERSION attribute on index entries. This
48 allows us to tell if it was written by an older version
50 #define LTDB_INDEXING_VERSION 2
52 /* enable the idxptr mode when transactions start */
53 int ltdb_index_transaction_start(struct ldb_module *module)
55 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
56 ltdb->idxptr = talloc_zero(ltdb, struct ltdb_idxptr);
60 /* compare two DN entries in a dn_list. Take account of possible
61 * differences in string termination */
62 static int dn_list_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
64 int ret = strncmp((char *)v1->data, (char *)v2->data, v1->length);
65 if (ret != 0) return ret;
66 if (v2->length > v1->length && v2->data[v1->length] != 0) {
74 find a entry in a dn_list, using a ldb_val. Uses a case sensitive
75 comparison with the dn returns -1 if not found
77 static int ltdb_dn_list_find_val(const struct dn_list *list, const struct ldb_val *v)
80 for (i=0; i<list->count; i++) {
81 if (dn_list_cmp(&list->dn[i], v) == 0) return i;
87 find a entry in a dn_list. Uses a case sensitive comparison with the dn
88 returns -1 if not found
90 static int ltdb_dn_list_find_str(struct dn_list *list, const char *dn)
93 v.data = discard_const_p(unsigned char, dn);
94 v.length = strlen(dn);
95 return ltdb_dn_list_find_val(list, &v);
98 static struct dn_list *ltdb_index_idxptr(struct ldb_module *module, TDB_DATA rec, bool check_parent)
100 struct dn_list *list;
101 if (rec.dsize != sizeof(void *)) {
102 ldb_asprintf_errstring(ldb_module_get_ctx(module),
103 "Bad data size for idxptr %u", (unsigned)rec.dsize);
107 list = talloc_get_type(*(struct dn_list **)rec.dptr, struct dn_list);
109 ldb_asprintf_errstring(ldb_module_get_ctx(module),
110 "Bad type '%s' for idxptr",
111 talloc_get_name(*(struct dn_list **)rec.dptr));
114 if (check_parent && list->dn && talloc_parent(list->dn) != list) {
115 ldb_asprintf_errstring(ldb_module_get_ctx(module),
116 "Bad parent '%s' for idxptr",
117 talloc_get_name(talloc_parent(list->dn)));
124 return the @IDX list in an index entry for a dn as a
127 static int ltdb_dn_list_load(struct ldb_module *module,
128 struct ldb_dn *dn, struct dn_list *list)
130 struct ldb_message *msg;
132 struct ldb_message_element *el;
133 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
135 struct dn_list *list2;
141 /* see if we have any in-memory index entries */
142 if (ltdb->idxptr == NULL ||
143 ltdb->idxptr->itdb == NULL) {
147 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
148 key.dsize = strlen((char *)key.dptr);
150 rec = tdb_fetch(ltdb->idxptr->itdb, key);
151 if (rec.dptr == NULL) {
155 /* we've found an in-memory index entry */
156 list2 = ltdb_index_idxptr(module, rec, true);
159 return LDB_ERR_OPERATIONS_ERROR;
167 msg = ldb_msg_new(list);
169 return LDB_ERR_OPERATIONS_ERROR;
172 ret = ltdb_search_dn1(module, dn, msg);
173 if (ret != LDB_SUCCESS) {
177 /* TODO: check indexing version number */
179 el = ldb_msg_find_element(msg, LTDB_IDX);
185 /* we avoid copying the strings by stealing the list */
186 list->dn = talloc_steal(list, el->values);
187 list->count = el->num_values;
194 save a dn_list into a full @IDX style record
196 static int ltdb_dn_list_store_full(struct ldb_module *module, struct ldb_dn *dn,
197 struct dn_list *list)
199 struct ldb_message *msg;
202 if (list->count == 0) {
203 ret = ltdb_delete_noindex(module, dn);
204 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
210 msg = ldb_msg_new(module);
212 ldb_module_oom(module);
213 return LDB_ERR_OPERATIONS_ERROR;
216 ret = ldb_msg_add_fmt(msg, LTDB_IDXVERSION, "%u", LTDB_INDEXING_VERSION);
217 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 = 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 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr);
407 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s:%.*s", LTDB_INDEX, attr_folded, (int)v.length, (char *)v.data);
410 if (v.data != value->data) {
413 talloc_free(attr_folded);
419 see if a attribute value is in the list of indexed attributes
421 static bool ltdb_is_indexed(const struct ldb_message *index_list, const char *attr)
424 struct ldb_message_element *el;
426 el = ldb_msg_find_element(index_list, LTDB_IDXATTR);
430 for (i=0; i<el->num_values; i++) {
431 if (ldb_attr_cmp((char *)el->values[i].data, attr) == 0) {
439 in the following logic functions, the return value is treated as
442 LDB_SUCCESS: we found some matching index values
444 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
446 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
447 we'll need a full search
451 return a list of dn's that might match a simple indexed search (an
452 equality search only)
454 static int ltdb_index_dn_simple(struct ldb_module *module,
455 const struct ldb_parse_tree *tree,
456 const struct ldb_message *index_list,
457 struct dn_list *list)
459 struct ldb_context *ldb;
463 ldb = ldb_module_get_ctx(module);
468 /* if the attribute isn't in the list of indexed attributes then
469 this node needs a full search */
470 if (!ltdb_is_indexed(index_list, tree->u.equality.attr)) {
471 return LDB_ERR_OPERATIONS_ERROR;
474 /* the attribute is indexed. Pull the list of DNs that match the
476 dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value, NULL);
477 if (!dn) return LDB_ERR_OPERATIONS_ERROR;
479 ret = ltdb_dn_list_load(module, dn, list);
485 static bool list_union(struct ldb_context *, struct dn_list *, const struct dn_list *);
488 return a list of dn's that might match a leaf indexed search
490 static int ltdb_index_dn_leaf(struct ldb_module *module,
491 const struct ldb_parse_tree *tree,
492 const struct ldb_message *index_list,
493 struct dn_list *list)
495 if (ldb_attr_dn(tree->u.equality.attr) == 0) {
496 list->dn = talloc_array(list, struct ldb_val, 1);
497 if (list->dn == NULL) {
498 ldb_module_oom(module);
499 return LDB_ERR_OPERATIONS_ERROR;
501 list->dn[0] = tree->u.equality.value;
505 return ltdb_index_dn_simple(module, tree, index_list, list);
513 static bool list_intersect(struct ldb_context *ldb,
514 struct dn_list *list, const struct dn_list *list2)
516 struct dn_list *list3;
519 if (list->count == 0) {
523 if (list2->count == 0) {
530 /* the indexing code is allowed to return a longer list than
531 what really matches, as all results are filtered by the
532 full expression at the end - this shortcut avoids a lot of
533 work in some cases */
534 if (list->count < 2 && list2->count > 10) {
537 if (list2->count < 2 && list->count > 10) {
538 list->count = list2->count;
539 list->dn = list2->dn;
540 /* note that list2 may not be the parent of list2->dn,
541 as list2->dn may be owned by ltdb->idxptr. In that
542 case we expect this reparent call to fail, which is
544 talloc_reparent(list2, list, list2->dn);
548 list3 = talloc_zero(list, struct dn_list);
553 list3->dn = talloc_array(list3, struct ldb_val, list->count);
560 for (i=0;i<list->count;i++) {
561 if (ltdb_dn_list_find_val(list2, &list->dn[i]) != -1) {
562 list3->dn[list3->count] = list->dn[i];
567 list->dn = talloc_steal(list, list3->dn);
568 list->count = list3->count;
579 static bool list_union(struct ldb_context *ldb,
580 struct dn_list *list, const struct dn_list *list2)
584 if (list2->count == 0) {
589 if (list->count == 0) {
591 list->count = list2->count;
592 list->dn = list2->dn;
593 /* note that list2 may not be the parent of list2->dn,
594 as list2->dn may be owned by ltdb->idxptr. In that
595 case we expect this reparent call to fail, which is
597 talloc_reparent(list2, list, list2->dn);
601 dn3 = talloc_array(list, struct ldb_val, list->count + list2->count);
607 /* we allow for duplicates here, and get rid of them later */
608 memcpy(dn3, list->dn, sizeof(list->dn[0])*list->count);
609 memcpy(dn3+list->count, list2->dn, sizeof(list2->dn[0])*list2->count);
612 list->count += list2->count;
617 static int ltdb_index_dn(struct ldb_module *module,
618 const struct ldb_parse_tree *tree,
619 const struct ldb_message *index_list,
620 struct dn_list *list);
624 process an OR list (a union)
626 static int ltdb_index_dn_or(struct ldb_module *module,
627 const struct ldb_parse_tree *tree,
628 const struct ldb_message *index_list,
629 struct dn_list *list)
631 struct ldb_context *ldb;
634 ldb = ldb_module_get_ctx(module);
639 for (i=0; i<tree->u.list.num_elements; i++) {
640 struct dn_list *list2;
643 list2 = talloc_zero(list, struct dn_list);
645 return LDB_ERR_OPERATIONS_ERROR;
648 ret = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2);
650 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
656 if (ret != LDB_SUCCESS) {
662 if (!list_union(ldb, list, list2)) {
664 return LDB_ERR_OPERATIONS_ERROR;
668 if (list->count == 0) {
669 return LDB_ERR_NO_SUCH_OBJECT;
679 static int ltdb_index_dn_not(struct ldb_module *module,
680 const struct ldb_parse_tree *tree,
681 const struct ldb_message *index_list,
682 struct dn_list *list)
684 /* the only way to do an indexed not would be if we could
685 negate the not via another not or if we knew the total
686 number of database elements so we could know that the
687 existing expression covered the whole database.
689 instead, we just give up, and rely on a full index scan
690 (unless an outer & manages to reduce the list)
692 return LDB_ERR_OPERATIONS_ERROR;
696 static bool ltdb_index_unique(struct ldb_context *ldb,
699 const struct ldb_schema_attribute *a;
700 a = ldb_schema_attribute_by_name(ldb, attr);
701 if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
708 process an AND expression (intersection)
710 static int ltdb_index_dn_and(struct ldb_module *module,
711 const struct ldb_parse_tree *tree,
712 const struct ldb_message *index_list,
713 struct dn_list *list)
715 struct ldb_context *ldb;
719 ldb = ldb_module_get_ctx(module);
724 /* in the first pass we only look for unique simple
725 equality tests, in the hope of avoiding having to look
727 for (i=0; i<tree->u.list.num_elements; i++) {
728 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
731 if (subtree->operation != LDB_OP_EQUALITY ||
732 !ltdb_index_unique(ldb, subtree->u.equality.attr)) {
736 ret = ltdb_index_dn(module, subtree, index_list, list);
737 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
739 return LDB_ERR_NO_SUCH_OBJECT;
741 if (ret == LDB_SUCCESS) {
742 /* a unique index match means we can
743 * stop. Note that we don't care if we return
744 * a few too many objects, due to later
750 /* now do a full intersection */
753 for (i=0; i<tree->u.list.num_elements; i++) {
754 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
755 struct dn_list *list2;
758 list2 = talloc_zero(list, struct dn_list);
760 ldb_module_oom(module);
761 return LDB_ERR_OPERATIONS_ERROR;
764 ret = ltdb_index_dn(module, subtree, index_list, list2);
766 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
771 return LDB_ERR_NO_SUCH_OBJECT;
774 if (ret != LDB_SUCCESS) {
775 /* this didn't adding anything */
781 talloc_reparent(list2, list, list->dn);
782 list->dn = list2->dn;
783 list->count = list2->count;
785 } else if (!list_intersect(ldb, list, list2)) {
787 return LDB_ERR_OPERATIONS_ERROR;
790 if (list->count == 0) {
792 return LDB_ERR_NO_SUCH_OBJECT;
795 if (list->count < 2) {
796 /* it isn't worth loading the next part of the tree */
802 /* none of the attributes were indexed */
803 return LDB_ERR_OPERATIONS_ERROR;
810 return a list of matching objects using a one-level index
812 static int ltdb_index_dn_one(struct ldb_module *module,
813 struct ldb_dn *parent_dn,
814 struct dn_list *list)
816 struct ldb_context *ldb;
821 ldb = ldb_module_get_ctx(module);
823 /* work out the index key from the parent DN */
824 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn));
825 val.length = strlen((char *)val.data);
826 key = ltdb_index_key(ldb, LTDB_IDXONE, &val, NULL);
829 return LDB_ERR_OPERATIONS_ERROR;
832 ret = ltdb_dn_list_load(module, key, list);
834 if (ret != LDB_SUCCESS) {
838 if (list->count == 0) {
839 return LDB_ERR_NO_SUCH_OBJECT;
846 return a list of dn's that might match a indexed search or
847 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
849 static int ltdb_index_dn(struct ldb_module *module,
850 const struct ldb_parse_tree *tree,
851 const struct ldb_message *index_list,
852 struct dn_list *list)
854 int ret = LDB_ERR_OPERATIONS_ERROR;
856 switch (tree->operation) {
858 ret = ltdb_index_dn_and(module, tree, index_list, list);
862 ret = ltdb_index_dn_or(module, tree, index_list, list);
866 ret = ltdb_index_dn_not(module, tree, index_list, list);
869 case LDB_OP_EQUALITY:
870 ret = ltdb_index_dn_leaf(module, tree, index_list, list);
873 case LDB_OP_SUBSTRING:
878 case LDB_OP_EXTENDED:
879 /* we can't index with fancy bitops yet */
880 ret = LDB_ERR_OPERATIONS_ERROR;
888 filter a candidate dn_list from an indexed search into a set of results
889 extracting just the given attributes
891 static int ltdb_index_filter(const struct dn_list *dn_list,
892 struct ltdb_context *ac,
893 uint32_t *match_count)
895 struct ldb_context *ldb;
896 struct ldb_message *msg;
899 ldb = ldb_module_get_ctx(ac->module);
901 for (i = 0; i < dn_list->count; i++) {
905 msg = ldb_msg_new(ac);
907 return LDB_ERR_OPERATIONS_ERROR;
910 dn = ldb_dn_from_ldb_val(msg, ldb, &dn_list->dn[i]);
913 return LDB_ERR_OPERATIONS_ERROR;
916 ret = ltdb_search_dn1(ac->module, dn, msg);
918 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
919 /* the record has disappeared? yes, this can happen */
924 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
925 /* an internal error */
927 return LDB_ERR_OPERATIONS_ERROR;
930 if (!ldb_match_msg(ldb, msg,
931 ac->tree, ac->base, ac->scope)) {
936 /* filter the attributes that the user wants */
937 ret = ltdb_filter_attrs(msg, ac->attrs);
941 return LDB_ERR_OPERATIONS_ERROR;
944 ret = ldb_module_send_entry(ac->req, msg, NULL);
945 if (ret != LDB_SUCCESS) {
946 ac->request_terminated = true;
957 remove any duplicated entries in a indexed result
959 static void ltdb_dn_list_remove_duplicates(struct dn_list *list)
963 if (list->count < 2) {
967 qsort(list->dn, list->count, sizeof(struct ldb_val), (comparison_fn_t) dn_list_cmp);
970 for (i=1; i<list->count; i++) {
971 if (dn_list_cmp(&list->dn[i], &list->dn[new_count-1]) != 0) {
972 if (new_count != i) {
973 list->dn[new_count] = list->dn[i];
979 list->count = new_count;
983 search the database with a LDAP-like expression using indexes
984 returns -1 if an indexed search is not possible, in which
985 case the caller should call ltdb_search_full()
987 int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
989 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(ac->module), struct ltdb_private);
990 struct dn_list *dn_list;
993 /* see if indexing is enabled */
994 if (!ltdb->cache->attribute_indexes &&
995 !ltdb->cache->one_level_indexes &&
996 ac->scope != LDB_SCOPE_BASE) {
997 /* fallback to a full search */
998 return LDB_ERR_OPERATIONS_ERROR;
1001 dn_list = talloc_zero(ac, struct dn_list);
1002 if (dn_list == NULL) {
1003 ldb_module_oom(ac->module);
1004 return LDB_ERR_OPERATIONS_ERROR;
1007 switch (ac->scope) {
1008 case LDB_SCOPE_BASE:
1009 dn_list->dn = talloc_array(dn_list, struct ldb_val, 1);
1010 if (dn_list->dn == NULL) {
1011 ldb_module_oom(ac->module);
1012 talloc_free(dn_list);
1013 return LDB_ERR_OPERATIONS_ERROR;
1015 dn_list->dn[0].data = discard_const_p(unsigned char, ldb_dn_get_linearized(ac->base));
1016 if (dn_list->dn[0].data == NULL) {
1017 ldb_module_oom(ac->module);
1018 talloc_free(dn_list);
1019 return LDB_ERR_OPERATIONS_ERROR;
1021 dn_list->dn[0].length = strlen((char *)dn_list->dn[0].data);
1025 case LDB_SCOPE_ONELEVEL:
1026 if (!ltdb->cache->one_level_indexes) {
1027 talloc_free(dn_list);
1028 return LDB_ERR_OPERATIONS_ERROR;
1030 ret = ltdb_index_dn_one(ac->module, ac->base, dn_list);
1031 if (ret != LDB_SUCCESS) {
1032 talloc_free(dn_list);
1037 case LDB_SCOPE_SUBTREE:
1038 case LDB_SCOPE_DEFAULT:
1039 if (!ltdb->cache->attribute_indexes) {
1040 talloc_free(dn_list);
1041 return LDB_ERR_OPERATIONS_ERROR;
1043 ret = ltdb_index_dn(ac->module, ac->tree, ltdb->cache->indexlist, dn_list);
1044 if (ret != LDB_SUCCESS) {
1045 talloc_free(dn_list);
1048 ltdb_dn_list_remove_duplicates(dn_list);
1052 ret = ltdb_index_filter(dn_list, ac, match_count);
1053 talloc_free(dn_list);
1058 add an index entry for one message element
1060 static int ltdb_index_add1(struct ldb_module *module, const char *dn,
1061 struct ldb_message_element *el, int v_idx)
1063 struct ldb_context *ldb;
1064 struct ldb_dn *dn_key;
1066 const struct ldb_schema_attribute *a;
1067 struct dn_list *list;
1070 ldb = ldb_module_get_ctx(module);
1072 list = talloc_zero(module, struct dn_list);
1074 return LDB_ERR_OPERATIONS_ERROR;
1077 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], &a);
1080 return LDB_ERR_OPERATIONS_ERROR;
1082 talloc_steal(list, dn_key);
1084 ret = ltdb_dn_list_load(module, dn_key, list);
1085 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1090 if (ltdb_dn_list_find_str(list, dn) != -1) {
1095 if (list->count > 0 &&
1096 a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
1097 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1100 /* overallocate the list a bit, to reduce the number of
1101 * realloc trigered copies */
1102 alloc_len = ((list->count+1)+7) & ~7;
1103 list->dn = talloc_realloc(list, list->dn, struct ldb_val, alloc_len);
1104 if (list->dn == NULL) {
1106 return LDB_ERR_OPERATIONS_ERROR;
1108 list->dn[list->count].data = (uint8_t *)talloc_strdup(list->dn, dn);
1109 list->dn[list->count].length = strlen(dn);
1112 ret = ltdb_dn_list_store(module, dn_key, list);
1120 add index entries for one elements in a message
1122 static int ltdb_index_add_el(struct ldb_module *module, const char *dn,
1123 struct ldb_message_element *el)
1126 for (i = 0; i < el->num_values; i++) {
1127 int ret = ltdb_index_add1(module, dn, el, i);
1128 if (ret != LDB_SUCCESS) {
1137 add index entries for all elements in a message
1139 static int ltdb_index_add_all(struct ldb_module *module, const char *dn,
1140 struct ldb_message_element *elements, int num_el)
1142 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1149 if (ltdb->cache->indexlist->num_elements == 0) {
1150 /* no indexed fields */
1154 for (i = 0; i < num_el; i++) {
1156 if (!ltdb_is_indexed(ltdb->cache->indexlist, elements[i].name)) {
1159 ret = ltdb_index_add_el(module, dn, &elements[i]);
1160 if (ret != LDB_SUCCESS) {
1170 insert a one level index for a message
1172 static int ltdb_index_onelevel(struct ldb_module *module, const struct ldb_message *msg, int add)
1174 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1175 struct ldb_message_element el;
1181 /* We index for ONE Level only if requested */
1182 if (!ltdb->cache->one_level_indexes) {
1186 pdn = ldb_dn_get_parent(module, msg->dn);
1188 return LDB_ERR_OPERATIONS_ERROR;
1191 dn = ldb_dn_get_linearized(msg->dn);
1194 return LDB_ERR_OPERATIONS_ERROR;
1197 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn));
1198 if (val.data == NULL) {
1200 return LDB_ERR_OPERATIONS_ERROR;
1203 val.length = strlen((char *)val.data);
1204 el.name = LTDB_IDXONE;
1209 ret = ltdb_index_add1(module, dn, &el, 0);
1210 } else { /* delete */
1211 ret = ltdb_index_del_value(module, dn, &el, 0);
1220 add the index entries for a new element in a record
1221 The caller guarantees that these element values are not yet indexed
1223 int ltdb_index_add_element(struct ldb_module *module, struct ldb_dn *dn,
1224 struct ldb_message_element *el)
1226 if (ldb_dn_is_special(dn)) {
1229 return ltdb_index_add_el(module, ldb_dn_get_linearized(dn), el);
1233 add the index entries for a new record
1235 int ltdb_index_add_new(struct ldb_module *module, const struct ldb_message *msg)
1240 if (ldb_dn_is_special(msg->dn)) {
1244 dn = ldb_dn_get_linearized(msg->dn);
1246 return LDB_ERR_OPERATIONS_ERROR;
1249 ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements);
1250 if (ret != LDB_SUCCESS) {
1254 return ltdb_index_onelevel(module, msg, 1);
1259 delete an index entry for one message element
1261 int ltdb_index_del_value(struct ldb_module *module, const char *dn,
1262 struct ldb_message_element *el, int v_idx)
1264 struct ldb_context *ldb;
1265 struct ldb_dn *dn_key;
1267 struct dn_list *list;
1269 ldb = ldb_module_get_ctx(module);
1275 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], NULL);
1277 return LDB_ERR_OPERATIONS_ERROR;
1280 list = talloc_zero(dn_key, struct dn_list);
1282 talloc_free(dn_key);
1283 return LDB_ERR_OPERATIONS_ERROR;
1286 ret = ltdb_dn_list_load(module, dn_key, list);
1287 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1288 /* it wasn't indexed. Did we have an earlier error? If we did then
1290 talloc_free(dn_key);
1294 if (ret != LDB_SUCCESS) {
1295 talloc_free(dn_key);
1299 i = ltdb_dn_list_find_str(list, dn);
1301 /* nothing to delete */
1302 talloc_free(dn_key);
1306 if (i != list->count-1) {
1307 memmove(&list->dn[i], &list->dn[i+1], sizeof(list->dn[0])*(list->count - (i+1)));
1310 list->dn = talloc_realloc(list, list->dn, struct ldb_val, list->count);
1312 ret = ltdb_dn_list_store(module, dn_key, list);
1314 talloc_free(dn_key);
1320 delete the index entries for a element
1321 return -1 on failure
1323 int ltdb_index_del_element(struct ldb_module *module, const char *dn, struct ldb_message_element *el)
1325 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1329 if (!ltdb->cache->attribute_indexes) {
1330 /* no indexed fields */
1338 if (!ltdb_is_indexed(ltdb->cache->indexlist, el->name)) {
1341 for (i = 0; i < el->num_values; i++) {
1342 ret = ltdb_index_del_value(module, dn, el, i);
1343 if (ret != LDB_SUCCESS) {
1352 delete the index entries for a record
1353 return -1 on failure
1355 int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg)
1357 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1362 if (ldb_dn_is_special(msg->dn)) {
1366 ret = ltdb_index_onelevel(module, msg, 0);
1367 if (ret != LDB_SUCCESS) {
1371 if (!ltdb->cache->attribute_indexes) {
1372 /* no indexed fields */
1376 dn = ldb_dn_get_linearized(msg->dn);
1378 return LDB_ERR_OPERATIONS_ERROR;
1381 for (i = 0; i < msg->num_elements; i++) {
1382 ret = ltdb_index_del_element(module, dn, &msg->elements[i]);
1383 if (ret != LDB_SUCCESS) {
1393 traversal function that deletes all @INDEX records
1395 static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1397 const char *dn = "DN=" LTDB_INDEX ":";
1398 if (strncmp((char *)key.dptr, dn, strlen(dn)) == 0) {
1399 return tdb_delete(tdb, key);
1405 traversal function that adds @INDEX records during a re index
1407 static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1409 struct ldb_context *ldb;
1410 struct ldb_module *module = (struct ldb_module *)state;
1411 struct ldb_message *msg;
1412 const char *dn = NULL;
1416 ldb = ldb_module_get_ctx(module);
1418 if (strncmp((char *)key.dptr, "DN=@", 4) == 0 ||
1419 strncmp((char *)key.dptr, "DN=", 3) != 0) {
1423 msg = talloc(module, struct ldb_message);
1428 ret = ltdb_unpack_data(module, &data, msg);
1430 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
1431 ldb_dn_get_linearized(msg->dn));
1436 /* check if the DN key has changed, perhaps due to the
1437 case insensitivity of an element changing */
1438 key2 = ltdb_key(module, msg->dn);
1439 if (key2.dptr == NULL) {
1440 /* probably a corrupt record ... darn */
1441 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s",
1442 ldb_dn_get_linearized(msg->dn));
1446 if (strcmp((char *)key2.dptr, (char *)key.dptr) != 0) {
1447 tdb_delete(tdb, key);
1448 tdb_store(tdb, key2, data, 0);
1450 talloc_free(key2.dptr);
1452 if (msg->dn == NULL) {
1453 dn = (char *)key.dptr + 3;
1455 dn = ldb_dn_get_linearized(msg->dn);
1458 ret = ltdb_index_onelevel(module, msg, 1);
1459 if (ret != LDB_SUCCESS) {
1460 ldb_debug(ldb, LDB_DEBUG_ERROR,
1461 "Adding special ONE LEVEL index failed (%s)!",
1462 ldb_dn_get_linearized(msg->dn));
1467 ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements);
1471 if (ret != LDB_SUCCESS) return -1;
1477 force a complete reindex of the database
1479 int ltdb_reindex(struct ldb_module *module)
1481 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1484 if (ltdb_cache_reload(module) != 0) {
1485 return LDB_ERR_OPERATIONS_ERROR;
1488 /* first traverse the database deleting any @INDEX records */
1489 ret = tdb_traverse(ltdb->tdb, delete_index, NULL);
1491 return LDB_ERR_OPERATIONS_ERROR;
1494 /* if we don't have indexes we have nothing todo */
1495 if (ltdb->cache->indexlist->num_elements == 0) {
1499 /* now traverse adding any indexes for normal LDB records */
1500 ret = tdb_traverse(ltdb->tdb, re_index, module);
1502 return LDB_ERR_OPERATIONS_ERROR;
1506 ltdb->idxptr->repack = true;