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 msg = ldb_msg_new(module);
204 ldb_module_oom(module);
205 return LDB_ERR_OPERATIONS_ERROR;
208 ret = ldb_msg_add_fmt(msg, LTDB_IDXVERSION, "%u", LTDB_INDEXING_VERSION);
209 if (ret != LDB_SUCCESS) {
210 ldb_module_oom(module);
211 return LDB_ERR_OPERATIONS_ERROR;
215 if (list->count > 0) {
216 struct ldb_message_element *el;
218 ret = ldb_msg_add_empty(msg, LTDB_IDX, LDB_FLAG_MOD_ADD, &el);
219 if (ret != LDB_SUCCESS) {
220 ldb_module_oom(module);
222 return LDB_ERR_OPERATIONS_ERROR;
224 el->values = list->dn;
225 el->num_values = list->count;
228 ret = ltdb_store(module, msg, TDB_REPLACE);
234 save a dn_list into the database, in either @IDX or internal format
236 static int ltdb_dn_list_store(struct ldb_module *module, struct ldb_dn *dn,
237 struct dn_list *list)
239 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
242 struct dn_list *list2;
244 if (ltdb->idxptr == NULL) {
245 return ltdb_dn_list_store_full(module, dn, list);
248 if (ltdb->idxptr->itdb == NULL) {
249 ltdb->idxptr->itdb = tdb_open(NULL, 1000, TDB_INTERNAL, O_RDWR, 0);
250 if (ltdb->idxptr->itdb == NULL) {
251 return LDB_ERR_OPERATIONS_ERROR;
255 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
256 key.dsize = strlen((char *)key.dptr);
258 rec = tdb_fetch(ltdb->idxptr->itdb, key);
259 if (rec.dptr != NULL) {
260 list2 = ltdb_index_idxptr(module, rec, false);
263 return LDB_ERR_OPERATIONS_ERROR;
266 list2->dn = talloc_steal(list2, list->dn);
267 list2->count = list->count;
271 list2 = talloc(ltdb->idxptr, struct dn_list);
273 return LDB_ERR_OPERATIONS_ERROR;
275 list2->dn = talloc_steal(list2, list->dn);
276 list2->count = list->count;
278 rec.dptr = (uint8_t *)&list2;
279 rec.dsize = sizeof(void *);
281 ret = tdb_store(ltdb->idxptr->itdb, key, rec, TDB_INSERT);
287 traverse function for storing the in-memory index entries on disk
289 static int ltdb_index_traverse_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
291 struct ldb_module *module = state;
292 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
294 struct ldb_context *ldb = ldb_module_get_ctx(module);
296 struct dn_list *list;
298 list = ltdb_index_idxptr(module, data, true);
300 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
305 v.length = key.dsize;
307 dn = ldb_dn_from_ldb_val(module, ldb, &v);
309 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
313 ltdb->idxptr->error = ltdb_dn_list_store_full(module, dn, list);
315 return ltdb->idxptr->error;
318 /* cleanup the idxptr mode when transaction commits */
319 int ltdb_index_transaction_commit(struct ldb_module *module)
321 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
324 if (ltdb->idxptr->itdb) {
325 tdb_traverse(ltdb->idxptr->itdb, ltdb_index_traverse_store, module);
326 tdb_close(ltdb->idxptr->itdb);
329 ret = ltdb->idxptr->error;
331 if (ret != LDB_SUCCESS) {
332 struct ldb_context *ldb = ldb_module_get_ctx(module);
333 ldb_asprintf_errstring(ldb, "Failed to store index records in transaction commit");
336 talloc_free(ltdb->idxptr);
341 /* cleanup the idxptr mode when transaction cancels */
342 int ltdb_index_transaction_cancel(struct ldb_module *module)
344 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
345 if (ltdb->idxptr && ltdb->idxptr->itdb) {
346 tdb_close(ltdb->idxptr->itdb);
348 talloc_free(ltdb->idxptr);
355 return the dn key to be used for an index
356 the caller is responsible for freeing
358 static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
359 const char *attr, const struct ldb_val *value,
360 const struct ldb_schema_attribute **ap)
364 const struct ldb_schema_attribute *a;
368 attr_folded = ldb_attr_casefold(ldb, attr);
373 a = ldb_schema_attribute_by_name(ldb, attr);
377 r = a->syntax->canonicalise_fn(ldb, ldb, value, &v);
378 if (r != LDB_SUCCESS) {
379 const char *errstr = ldb_errstring(ldb);
380 /* canonicalisation can be refused. For example,
381 a attribute that takes wildcards will refuse to canonicalise
382 if the value contains a wildcard */
383 ldb_asprintf_errstring(ldb, "Failed to create index key for attribute '%s':%s%s%s",
384 attr, ldb_strerror(r), (errstr?":":""), (errstr?errstr:""));
385 talloc_free(attr_folded);
388 if (ldb_should_b64_encode(ldb, &v)) {
389 char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length);
390 if (!vstr) return NULL;
391 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr);
394 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s:%.*s", LTDB_INDEX, attr_folded, (int)v.length, (char *)v.data);
397 if (v.data != value->data) {
400 talloc_free(attr_folded);
406 see if a attribute value is in the list of indexed attributes
408 static bool ltdb_is_indexed(const struct ldb_message *index_list, const char *attr)
411 struct ldb_message_element *el;
413 el = ldb_msg_find_element(index_list, LTDB_IDXATTR);
417 for (i=0; i<el->num_values; i++) {
418 if (ldb_attr_cmp((char *)el->values[i].data, attr) == 0) {
426 in the following logic functions, the return value is treated as
429 LDB_SUCCESS: we found some matching index values
431 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
433 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
434 we'll need a full search
438 return a list of dn's that might match a simple indexed search (an
439 equality search only)
441 static int ltdb_index_dn_simple(struct ldb_module *module,
442 const struct ldb_parse_tree *tree,
443 const struct ldb_message *index_list,
444 struct dn_list *list)
446 struct ldb_context *ldb;
450 ldb = ldb_module_get_ctx(module);
455 /* if the attribute isn't in the list of indexed attributes then
456 this node needs a full search */
457 if (!ltdb_is_indexed(index_list, tree->u.equality.attr)) {
458 return LDB_ERR_OPERATIONS_ERROR;
461 /* the attribute is indexed. Pull the list of DNs that match the
463 dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value, NULL);
464 if (!dn) return LDB_ERR_OPERATIONS_ERROR;
466 ret = ltdb_dn_list_load(module, dn, list);
472 static bool list_union(struct ldb_context *, struct dn_list *, const struct dn_list *);
475 return a list of dn's that might match a leaf indexed search
477 static int ltdb_index_dn_leaf(struct ldb_module *module,
478 const struct ldb_parse_tree *tree,
479 const struct ldb_message *index_list,
480 struct dn_list *list)
482 if (ldb_attr_dn(tree->u.equality.attr) == 0) {
483 list->dn = talloc_array(list, struct ldb_val, 1);
484 if (list->dn == NULL) {
485 ldb_module_oom(module);
486 return LDB_ERR_OPERATIONS_ERROR;
488 list->dn[0] = tree->u.equality.value;
492 return ltdb_index_dn_simple(module, tree, index_list, list);
500 static bool list_intersect(struct ldb_context *ldb,
501 struct dn_list *list, const struct dn_list *list2)
503 struct dn_list *list3;
506 if (list->count == 0) {
510 if (list2->count == 0) {
517 /* the indexing code is allowed to return a longer list than
518 what really matches, as all results are filtered by the
519 full expression at the end - this shortcut avoids a lot of
520 work in some cases */
521 if (list->count < 2 && list2->count > 10) {
524 if (list2->count < 2 && list->count > 10) {
525 list->count = list2->count;
526 list->dn = list2->dn;
527 /* note that list2 may not be the parent of list2->dn,
528 as list2->dn may be owned by ltdb->idxptr. In that
529 case we expect this reparent call to fail, which is
531 talloc_reparent(list2, list, list2->dn);
535 list3 = talloc_zero(list, struct dn_list);
540 list3->dn = talloc_array(list3, struct ldb_val, list->count);
547 for (i=0;i<list->count;i++) {
548 if (ltdb_dn_list_find_val(list2, &list->dn[i]) != -1) {
549 list3->dn[list3->count] = list->dn[i];
554 list->dn = talloc_steal(list, list3->dn);
555 list->count = list3->count;
566 static bool list_union(struct ldb_context *ldb,
567 struct dn_list *list, const struct dn_list *list2)
571 if (list2->count == 0) {
576 if (list->count == 0) {
578 list->count = list2->count;
579 list->dn = list2->dn;
580 /* note that list2 may not be the parent of list2->dn,
581 as list2->dn may be owned by ltdb->idxptr. In that
582 case we expect this reparent call to fail, which is
584 talloc_reparent(list2, list, list2->dn);
588 dn3 = talloc_array(list, struct ldb_val, list->count + list2->count);
594 /* we allow for duplicates here, and get rid of them later */
595 memcpy(dn3, list->dn, sizeof(list->dn[0])*list->count);
596 memcpy(dn3+list->count, list2->dn, sizeof(list2->dn[0])*list2->count);
599 list->count += list2->count;
604 static int ltdb_index_dn(struct ldb_module *module,
605 const struct ldb_parse_tree *tree,
606 const struct ldb_message *index_list,
607 struct dn_list *list);
611 process an OR list (a union)
613 static int ltdb_index_dn_or(struct ldb_module *module,
614 const struct ldb_parse_tree *tree,
615 const struct ldb_message *index_list,
616 struct dn_list *list)
618 struct ldb_context *ldb;
621 ldb = ldb_module_get_ctx(module);
626 for (i=0; i<tree->u.list.num_elements; i++) {
627 struct dn_list *list2;
630 list2 = talloc_zero(list, struct dn_list);
632 return LDB_ERR_OPERATIONS_ERROR;
635 ret = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2);
637 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
643 if (ret != LDB_SUCCESS) {
649 if (!list_union(ldb, list, list2)) {
651 return LDB_ERR_OPERATIONS_ERROR;
655 if (list->count == 0) {
656 return LDB_ERR_NO_SUCH_OBJECT;
666 static int ltdb_index_dn_not(struct ldb_module *module,
667 const struct ldb_parse_tree *tree,
668 const struct ldb_message *index_list,
669 struct dn_list *list)
671 /* the only way to do an indexed not would be if we could
672 negate the not via another not or if we knew the total
673 number of database elements so we could know that the
674 existing expression covered the whole database.
676 instead, we just give up, and rely on a full index scan
677 (unless an outer & manages to reduce the list)
679 return LDB_ERR_OPERATIONS_ERROR;
683 static bool ltdb_index_unique(struct ldb_context *ldb,
686 const struct ldb_schema_attribute *a;
687 a = ldb_schema_attribute_by_name(ldb, attr);
688 if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
695 process an AND expression (intersection)
697 static int ltdb_index_dn_and(struct ldb_module *module,
698 const struct ldb_parse_tree *tree,
699 const struct ldb_message *index_list,
700 struct dn_list *list)
702 struct ldb_context *ldb;
706 ldb = ldb_module_get_ctx(module);
711 /* in the first pass we only look for unique simple
712 equality tests, in the hope of avoiding having to look
714 for (i=0; i<tree->u.list.num_elements; i++) {
715 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
718 if (subtree->operation != LDB_OP_EQUALITY ||
719 !ltdb_index_unique(ldb, subtree->u.equality.attr)) {
723 ret = ltdb_index_dn(module, subtree, index_list, list);
724 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
726 return LDB_ERR_NO_SUCH_OBJECT;
728 if (ret == LDB_SUCCESS) {
729 /* a unique index match means we can
730 * stop. Note that we don't care if we return
731 * a few too many objects, due to later
737 /* now do a full intersection */
740 for (i=0; i<tree->u.list.num_elements; i++) {
741 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
742 struct dn_list *list2;
745 list2 = talloc_zero(list, struct dn_list);
747 ldb_module_oom(module);
748 return LDB_ERR_OPERATIONS_ERROR;
751 ret = ltdb_index_dn(module, subtree, index_list, list2);
753 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
758 return LDB_ERR_NO_SUCH_OBJECT;
761 if (ret != LDB_SUCCESS) {
762 /* this didn't adding anything */
768 talloc_reparent(list2, list, list->dn);
769 list->dn = list2->dn;
770 list->count = list2->count;
772 } else if (!list_intersect(ldb, list, list2)) {
774 return LDB_ERR_OPERATIONS_ERROR;
777 if (list->count == 0) {
779 return LDB_ERR_NO_SUCH_OBJECT;
782 if (list->count < 2) {
783 /* it isn't worth loading the next part of the tree */
789 /* none of the attributes were indexed */
790 return LDB_ERR_OPERATIONS_ERROR;
797 return a list of matching objects using a one-level index
799 static int ltdb_index_dn_one(struct ldb_module *module,
800 struct ldb_dn *parent_dn,
801 struct dn_list *list)
803 struct ldb_context *ldb;
808 ldb = ldb_module_get_ctx(module);
810 /* work out the index key from the parent DN */
811 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn));
812 val.length = strlen((char *)val.data);
813 key = ltdb_index_key(ldb, LTDB_IDXONE, &val, NULL);
816 return LDB_ERR_OPERATIONS_ERROR;
819 ret = ltdb_dn_list_load(module, key, list);
821 if (ret != LDB_SUCCESS) {
825 if (list->count == 0) {
826 return LDB_ERR_NO_SUCH_OBJECT;
833 return a list of dn's that might match a indexed search or
834 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
836 static int ltdb_index_dn(struct ldb_module *module,
837 const struct ldb_parse_tree *tree,
838 const struct ldb_message *index_list,
839 struct dn_list *list)
841 int ret = LDB_ERR_OPERATIONS_ERROR;
843 switch (tree->operation) {
845 ret = ltdb_index_dn_and(module, tree, index_list, list);
849 ret = ltdb_index_dn_or(module, tree, index_list, list);
853 ret = ltdb_index_dn_not(module, tree, index_list, list);
856 case LDB_OP_EQUALITY:
857 ret = ltdb_index_dn_leaf(module, tree, index_list, list);
860 case LDB_OP_SUBSTRING:
865 case LDB_OP_EXTENDED:
866 /* we can't index with fancy bitops yet */
867 ret = LDB_ERR_OPERATIONS_ERROR;
875 filter a candidate dn_list from an indexed search into a set of results
876 extracting just the given attributes
878 static int ltdb_index_filter(const struct dn_list *dn_list,
879 struct ltdb_context *ac,
880 uint32_t *match_count)
882 struct ldb_context *ldb;
883 struct ldb_message *msg;
886 ldb = ldb_module_get_ctx(ac->module);
888 for (i = 0; i < dn_list->count; i++) {
892 msg = ldb_msg_new(ac);
894 return LDB_ERR_OPERATIONS_ERROR;
897 dn = ldb_dn_from_ldb_val(msg, ldb, &dn_list->dn[i]);
900 return LDB_ERR_OPERATIONS_ERROR;
903 ret = ltdb_search_dn1(ac->module, dn, msg);
905 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
906 /* the record has disappeared? yes, this can happen */
911 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
912 /* an internal error */
914 return LDB_ERR_OPERATIONS_ERROR;
917 if (!ldb_match_msg(ldb, msg,
918 ac->tree, ac->base, ac->scope)) {
923 /* filter the attributes that the user wants */
924 ret = ltdb_filter_attrs(msg, ac->attrs);
928 return LDB_ERR_OPERATIONS_ERROR;
931 ret = ldb_module_send_entry(ac->req, msg, NULL);
932 if (ret != LDB_SUCCESS) {
933 ac->request_terminated = true;
944 remove any duplicated entries in a indexed result
946 static void ltdb_dn_list_remove_duplicates(struct dn_list *list)
950 if (list->count < 2) {
954 qsort(list->dn, list->count, sizeof(struct ldb_val), (comparison_fn_t) dn_list_cmp);
957 for (i=1; i<list->count; i++) {
958 if (dn_list_cmp(&list->dn[i], &list->dn[new_count-1]) != 0) {
959 if (new_count != i) {
960 list->dn[new_count] = list->dn[i];
966 list->count = new_count;
970 search the database with a LDAP-like expression using indexes
971 returns -1 if an indexed search is not possible, in which
972 case the caller should call ltdb_search_full()
974 int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
976 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(ac->module), struct ltdb_private);
977 struct dn_list *dn_list;
980 /* see if indexing is enabled */
981 if (!ltdb->cache->attribute_indexes &&
982 !ltdb->cache->one_level_indexes &&
983 ac->scope != LDB_SCOPE_BASE) {
984 /* fallback to a full search */
985 return LDB_ERR_OPERATIONS_ERROR;
988 dn_list = talloc_zero(ac, struct dn_list);
989 if (dn_list == NULL) {
990 ldb_module_oom(ac->module);
991 return LDB_ERR_OPERATIONS_ERROR;
996 dn_list->dn = talloc_array(dn_list, struct ldb_val, 1);
997 if (dn_list->dn == NULL) {
998 ldb_module_oom(ac->module);
999 talloc_free(dn_list);
1000 return LDB_ERR_OPERATIONS_ERROR;
1002 dn_list->dn[0].data = discard_const_p(unsigned char, ldb_dn_get_linearized(ac->base));
1003 if (dn_list->dn[0].data == NULL) {
1004 ldb_module_oom(ac->module);
1005 talloc_free(dn_list);
1006 return LDB_ERR_OPERATIONS_ERROR;
1008 dn_list->dn[0].length = strlen((char *)dn_list->dn[0].data);
1012 case LDB_SCOPE_ONELEVEL:
1013 if (!ltdb->cache->one_level_indexes) {
1014 talloc_free(dn_list);
1015 return LDB_ERR_OPERATIONS_ERROR;
1017 ret = ltdb_index_dn_one(ac->module, ac->base, dn_list);
1018 if (ret != LDB_SUCCESS) {
1019 talloc_free(dn_list);
1024 case LDB_SCOPE_SUBTREE:
1025 case LDB_SCOPE_DEFAULT:
1026 if (!ltdb->cache->attribute_indexes) {
1027 talloc_free(dn_list);
1028 return LDB_ERR_OPERATIONS_ERROR;
1030 ret = ltdb_index_dn(ac->module, ac->tree, ltdb->cache->indexlist, dn_list);
1031 if (ret != LDB_SUCCESS) {
1032 talloc_free(dn_list);
1035 ltdb_dn_list_remove_duplicates(dn_list);
1039 ret = ltdb_index_filter(dn_list, ac, match_count);
1040 talloc_free(dn_list);
1045 add an index entry for one message element
1047 static int ltdb_index_add1(struct ldb_module *module, const char *dn,
1048 struct ldb_message_element *el, int v_idx)
1050 struct ldb_context *ldb;
1051 struct ldb_dn *dn_key;
1053 const struct ldb_schema_attribute *a;
1054 struct dn_list *list;
1056 ldb = ldb_module_get_ctx(module);
1058 list = talloc_zero(module, struct dn_list);
1060 return LDB_ERR_OPERATIONS_ERROR;
1063 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], &a);
1066 return LDB_ERR_OPERATIONS_ERROR;
1068 talloc_steal(list, dn_key);
1070 ret = ltdb_dn_list_load(module, dn_key, list);
1071 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1076 if (ltdb_dn_list_find_str(list, dn) != -1) {
1081 if (list->count > 0 &&
1082 a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
1083 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1086 list->dn = talloc_realloc(list, list->dn, struct ldb_val, list->count+1);
1087 if (list->dn == NULL) {
1089 return LDB_ERR_OPERATIONS_ERROR;
1091 list->dn[list->count].data = discard_const_p(unsigned char, dn);
1092 list->dn[list->count].length = strlen(dn);
1095 ret = ltdb_dn_list_store(module, dn_key, list);
1103 add index entries for one elements in a message
1105 static int ltdb_index_add_el(struct ldb_module *module, const char *dn,
1106 struct ldb_message_element *el)
1109 for (i = 0; i < el->num_values; i++) {
1110 int ret = ltdb_index_add1(module, dn, el, i);
1111 if (ret != LDB_SUCCESS) {
1120 add index entries for all elements in a message
1122 static int ltdb_index_add_all(struct ldb_module *module, const char *dn,
1123 struct ldb_message_element *elements, int num_el)
1125 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1132 if (ltdb->cache->indexlist->num_elements == 0) {
1133 /* no indexed fields */
1137 for (i = 0; i < num_el; i++) {
1139 if (!ltdb_is_indexed(ltdb->cache->indexlist, elements[i].name)) {
1142 ret = ltdb_index_add_el(module, dn, &elements[i]);
1143 if (ret != LDB_SUCCESS) {
1153 insert a one level index for a message
1155 static int ltdb_index_onelevel(struct ldb_module *module, const struct ldb_message *msg, int add)
1157 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1158 struct ldb_message_element el;
1164 /* We index for ONE Level only if requested */
1165 if (!ltdb->cache->one_level_indexes) {
1169 pdn = ldb_dn_get_parent(module, msg->dn);
1171 return LDB_ERR_OPERATIONS_ERROR;
1174 dn = ldb_dn_get_linearized(msg->dn);
1177 return LDB_ERR_OPERATIONS_ERROR;
1180 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn));
1181 if (val.data == NULL) {
1183 return LDB_ERR_OPERATIONS_ERROR;
1186 val.length = strlen((char *)val.data);
1187 el.name = LTDB_IDXONE;
1192 ret = ltdb_index_add1(module, dn, &el, 0);
1193 } else { /* delete */
1194 ret = ltdb_index_del_value(module, dn, &el, 0);
1203 add the index entries for a new element in a record
1204 The caller guarantees that these element values are not yet indexed
1206 int ltdb_index_add_element(struct ldb_module *module, struct ldb_dn *dn,
1207 struct ldb_message_element *el)
1209 if (ldb_dn_is_special(dn)) {
1212 return ltdb_index_add_el(module, ldb_dn_get_linearized(dn), el);
1216 add the index entries for a new record
1218 int ltdb_index_add_new(struct ldb_module *module, const struct ldb_message *msg)
1223 if (ldb_dn_is_special(msg->dn)) {
1227 dn = ldb_dn_get_linearized(msg->dn);
1229 return LDB_ERR_OPERATIONS_ERROR;
1232 ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements);
1233 if (ret != LDB_SUCCESS) {
1237 return ltdb_index_onelevel(module, msg, 1);
1242 delete an index entry for one message element
1244 int ltdb_index_del_value(struct ldb_module *module, const char *dn,
1245 struct ldb_message_element *el, int v_idx)
1247 struct ldb_context *ldb;
1248 struct ldb_dn *dn_key;
1250 struct dn_list *list;
1252 ldb = ldb_module_get_ctx(module);
1258 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], NULL);
1260 return LDB_ERR_OPERATIONS_ERROR;
1263 list = talloc_zero(dn_key, struct dn_list);
1265 talloc_free(dn_key);
1266 return LDB_ERR_OPERATIONS_ERROR;
1269 ret = ltdb_dn_list_load(module, dn_key, list);
1270 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1271 /* it wasn't indexed. Did we have an earlier error? If we did then
1273 talloc_free(dn_key);
1277 if (ret != LDB_SUCCESS) {
1278 talloc_free(dn_key);
1282 i = ltdb_dn_list_find_str(list, dn);
1284 /* nothing to delete */
1285 talloc_free(dn_key);
1289 if (i != list->count-1) {
1290 memmove(&list->dn[i], &list->dn[i+1], sizeof(list->dn[0])*(list->count - (i+1)));
1293 list->dn = talloc_realloc(list, list->dn, struct ldb_val, list->count);
1295 ret = ltdb_dn_list_store(module, dn_key, list);
1297 talloc_free(dn_key);
1303 delete the index entries for a element
1304 return -1 on failure
1306 int ltdb_index_del_element(struct ldb_module *module, const char *dn, struct ldb_message_element *el)
1308 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1312 if (!ltdb->cache->attribute_indexes) {
1313 /* no indexed fields */
1321 if (!ltdb_is_indexed(ltdb->cache->indexlist, el->name)) {
1324 for (i = 0; i < el->num_values; i++) {
1325 ret = ltdb_index_del_value(module, dn, el, i);
1326 if (ret != LDB_SUCCESS) {
1335 delete the index entries for a record
1336 return -1 on failure
1338 int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg)
1340 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1345 if (ldb_dn_is_special(msg->dn)) {
1349 ret = ltdb_index_onelevel(module, msg, 0);
1350 if (ret != LDB_SUCCESS) {
1354 if (!ltdb->cache->attribute_indexes) {
1355 /* no indexed fields */
1359 dn = ldb_dn_get_linearized(msg->dn);
1361 return LDB_ERR_OPERATIONS_ERROR;
1364 for (i = 0; i < msg->num_elements; i++) {
1365 ret = ltdb_index_del_element(module, dn, &msg->elements[i]);
1366 if (ret != LDB_SUCCESS) {
1376 traversal function that deletes all @INDEX records
1378 static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1380 const char *dn = "DN=" LTDB_INDEX ":";
1381 if (strncmp((char *)key.dptr, dn, strlen(dn)) == 0) {
1382 return tdb_delete(tdb, key);
1388 traversal function that adds @INDEX records during a re index
1390 static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1392 struct ldb_context *ldb;
1393 struct ldb_module *module = (struct ldb_module *)state;
1394 struct ldb_message *msg;
1395 const char *dn = NULL;
1399 ldb = ldb_module_get_ctx(module);
1401 if (strncmp((char *)key.dptr, "DN=@", 4) == 0 ||
1402 strncmp((char *)key.dptr, "DN=", 3) != 0) {
1406 msg = talloc(module, struct ldb_message);
1411 ret = ltdb_unpack_data(module, &data, msg);
1413 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
1414 ldb_dn_get_linearized(msg->dn));
1419 /* check if the DN key has changed, perhaps due to the
1420 case insensitivity of an element changing */
1421 key2 = ltdb_key(module, msg->dn);
1422 if (key2.dptr == NULL) {
1423 /* probably a corrupt record ... darn */
1424 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s",
1425 ldb_dn_get_linearized(msg->dn));
1429 if (strcmp((char *)key2.dptr, (char *)key.dptr) != 0) {
1430 tdb_delete(tdb, key);
1431 tdb_store(tdb, key2, data, 0);
1433 talloc_free(key2.dptr);
1435 if (msg->dn == NULL) {
1436 dn = (char *)key.dptr + 3;
1438 dn = ldb_dn_get_linearized(msg->dn);
1441 ret = ltdb_index_onelevel(module, msg, 1);
1442 if (ret != LDB_SUCCESS) {
1443 ldb_debug(ldb, LDB_DEBUG_ERROR,
1444 "Adding special ONE LEVEL index failed (%s)!",
1445 ldb_dn_get_linearized(msg->dn));
1450 ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements);
1454 if (ret != LDB_SUCCESS) return -1;
1460 force a complete reindex of the database
1462 int ltdb_reindex(struct ldb_module *module)
1464 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1467 if (ltdb_cache_reload(module) != 0) {
1468 return LDB_ERR_OPERATIONS_ERROR;
1471 /* first traverse the database deleting any @INDEX records */
1472 ret = tdb_traverse(ltdb->tdb, delete_index, NULL);
1474 return LDB_ERR_OPERATIONS_ERROR;
1477 /* if we don't have indexes we have nothing todo */
1478 if (ltdb->cache->indexlist->num_elements == 0) {
1482 /* now traverse adding any indexes for normal LDB records */
1483 ret = tdb_traverse(ltdb->tdb, re_index, module);
1485 return LDB_ERR_OPERATIONS_ERROR;
1489 ltdb->idxptr->repack = true;