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);
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 if (v1->length > v2->length && v1->data[v2->length] != 0) {
67 if (v1->length < v2->length && v2->data[v1->length] != 0) {
70 return strncmp((char *)v1->data, (char *)v2->data, v1->length);
75 find a entry in a dn_list, using a ldb_val. Uses a case sensitive
76 comparison with the dn returns -1 if not found
78 static int ltdb_dn_list_find_val(const struct dn_list *list, const struct ldb_val *v)
81 for (i=0; i<list->count; i++) {
82 if (dn_list_cmp(&list->dn[i], v) == 0) return i;
88 find a entry in a dn_list. Uses a case sensitive comparison with the dn
89 returns -1 if not found
91 static int ltdb_dn_list_find_str(struct dn_list *list, const char *dn)
94 v.data = discard_const_p(unsigned char, dn);
95 v.length = strlen(dn);
96 return ltdb_dn_list_find_val(list, &v);
100 this is effectively a cast function, but with lots of paranoia
101 checks and also copes with CPUs that are fussy about pointer
104 static struct dn_list *ltdb_index_idxptr(struct ldb_module *module, TDB_DATA rec, bool check_parent)
106 struct dn_list *list;
107 if (rec.dsize != sizeof(void *)) {
108 ldb_asprintf_errstring(ldb_module_get_ctx(module),
109 "Bad data size for idxptr %u", (unsigned)rec.dsize);
112 /* note that we can't just use a cast here, as rec.dptr may
113 not be aligned sufficiently for a pointer. A cast would cause
114 platforms like some ARM CPUs to crash */
115 memcpy(&list, rec.dptr, sizeof(void *));
116 list = talloc_get_type(list, struct dn_list);
118 ldb_asprintf_errstring(ldb_module_get_ctx(module),
119 "Bad type '%s' for idxptr",
120 talloc_get_name(list));
123 if (check_parent && list->dn && talloc_parent(list->dn) != list) {
124 ldb_asprintf_errstring(ldb_module_get_ctx(module),
125 "Bad parent '%s' for idxptr",
126 talloc_get_name(talloc_parent(list->dn)));
133 return the @IDX list in an index entry for a dn as a
136 static int ltdb_dn_list_load(struct ldb_module *module,
137 struct ldb_dn *dn, struct dn_list *list)
139 struct ldb_message *msg;
141 struct ldb_message_element *el;
142 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
144 struct dn_list *list2;
150 /* see if we have any in-memory index entries */
151 if (ltdb->idxptr == NULL ||
152 ltdb->idxptr->itdb == NULL) {
156 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
157 key.dsize = strlen((char *)key.dptr);
159 rec = tdb_fetch(ltdb->idxptr->itdb, key);
160 if (rec.dptr == NULL) {
164 /* we've found an in-memory index entry */
165 list2 = ltdb_index_idxptr(module, rec, true);
168 return LDB_ERR_OPERATIONS_ERROR;
176 msg = ldb_msg_new(list);
178 return LDB_ERR_OPERATIONS_ERROR;
181 ret = ltdb_search_dn1(module, dn, msg);
182 if (ret != LDB_SUCCESS) {
187 /* TODO: check indexing version number */
189 el = ldb_msg_find_element(msg, LTDB_IDX);
196 * we avoid copying the strings by stealing the list. We have
197 * to steal msg onto el->values (which looks odd) because we
198 * asked for the memory to be allocated on msg, not on each
199 * value with LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC above
201 talloc_steal(el->values, msg);
202 list->dn = talloc_steal(list, el->values);
203 list->count = el->num_values;
205 /* We don't need msg->elements any more */
206 talloc_free(msg->elements);
212 save a dn_list into a full @IDX style record
214 static int ltdb_dn_list_store_full(struct ldb_module *module, struct ldb_dn *dn,
215 struct dn_list *list)
217 struct ldb_message *msg;
220 if (list->count == 0) {
221 ret = ltdb_delete_noindex(module, dn);
222 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
228 msg = ldb_msg_new(module);
230 return ldb_module_oom(module);
233 ret = ldb_msg_add_fmt(msg, LTDB_IDXVERSION, "%u", LTDB_INDEXING_VERSION);
234 if (ret != LDB_SUCCESS) {
236 return ldb_module_oom(module);
240 if (list->count > 0) {
241 struct ldb_message_element *el;
243 ret = ldb_msg_add_empty(msg, LTDB_IDX, LDB_FLAG_MOD_ADD, &el);
244 if (ret != LDB_SUCCESS) {
246 return ldb_module_oom(module);
248 el->values = list->dn;
249 el->num_values = list->count;
252 ret = ltdb_store(module, msg, TDB_REPLACE);
258 save a dn_list into the database, in either @IDX or internal format
260 static int ltdb_dn_list_store(struct ldb_module *module, struct ldb_dn *dn,
261 struct dn_list *list)
263 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
266 struct dn_list *list2;
268 if (ltdb->idxptr == NULL) {
269 return ltdb_dn_list_store_full(module, dn, list);
272 if (ltdb->idxptr->itdb == NULL) {
273 ltdb->idxptr->itdb = tdb_open(NULL, 1000, TDB_INTERNAL, O_RDWR, 0);
274 if (ltdb->idxptr->itdb == NULL) {
275 return LDB_ERR_OPERATIONS_ERROR;
279 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
280 key.dsize = strlen((char *)key.dptr);
282 rec = tdb_fetch(ltdb->idxptr->itdb, key);
283 if (rec.dptr != NULL) {
284 list2 = ltdb_index_idxptr(module, rec, false);
287 return LDB_ERR_OPERATIONS_ERROR;
290 list2->dn = talloc_steal(list2, list->dn);
291 list2->count = list->count;
295 list2 = talloc(ltdb->idxptr, struct dn_list);
297 return LDB_ERR_OPERATIONS_ERROR;
299 list2->dn = talloc_steal(list2, list->dn);
300 list2->count = list->count;
302 rec.dptr = (uint8_t *)&list2;
303 rec.dsize = sizeof(void *);
305 ret = tdb_store(ltdb->idxptr->itdb, key, rec, TDB_INSERT);
307 return ltdb_err_map(tdb_error(ltdb->idxptr->itdb));
313 traverse function for storing the in-memory index entries on disk
315 static int ltdb_index_traverse_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
317 struct ldb_module *module = state;
318 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
320 struct ldb_context *ldb = ldb_module_get_ctx(module);
322 struct dn_list *list;
324 list = ltdb_index_idxptr(module, data, true);
326 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
331 v.length = strnlen((char *)key.dptr, key.dsize);
333 dn = ldb_dn_from_ldb_val(module, ldb, &v);
335 ldb_asprintf_errstring(ldb, "Failed to parse index key %*.*s as an LDB DN", (int)v.length, (int)v.length, (const char *)v.data);
336 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
340 ltdb->idxptr->error = ltdb_dn_list_store_full(module, dn, list);
342 if (ltdb->idxptr->error != 0) {
348 /* cleanup the idxptr mode when transaction commits */
349 int ltdb_index_transaction_commit(struct ldb_module *module)
351 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
354 struct ldb_context *ldb = ldb_module_get_ctx(module);
356 ldb_reset_err_string(ldb);
358 if (ltdb->idxptr->itdb) {
359 tdb_traverse(ltdb->idxptr->itdb, ltdb_index_traverse_store, module);
360 tdb_close(ltdb->idxptr->itdb);
363 ret = ltdb->idxptr->error;
364 if (ret != LDB_SUCCESS) {
365 if (!ldb_errstring(ldb)) {
366 ldb_set_errstring(ldb, ldb_strerror(ret));
368 ldb_asprintf_errstring(ldb, "Failed to store index records in transaction commit: %s", ldb_errstring(ldb));
371 talloc_free(ltdb->idxptr);
376 /* cleanup the idxptr mode when transaction cancels */
377 int ltdb_index_transaction_cancel(struct ldb_module *module)
379 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
380 if (ltdb->idxptr && ltdb->idxptr->itdb) {
381 tdb_close(ltdb->idxptr->itdb);
383 talloc_free(ltdb->idxptr);
390 return the dn key to be used for an index
391 the caller is responsible for freeing
393 static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
394 const char *attr, const struct ldb_val *value,
395 const struct ldb_schema_attribute **ap)
399 const struct ldb_schema_attribute *a;
403 attr_folded = ldb_attr_casefold(ldb, attr);
408 a = ldb_schema_attribute_by_name(ldb, attr);
412 r = a->syntax->canonicalise_fn(ldb, ldb, value, &v);
413 if (r != LDB_SUCCESS) {
414 const char *errstr = ldb_errstring(ldb);
415 /* canonicalisation can be refused. For example,
416 a attribute that takes wildcards will refuse to canonicalise
417 if the value contains a wildcard */
418 ldb_asprintf_errstring(ldb, "Failed to create index key for attribute '%s':%s%s%s",
419 attr, ldb_strerror(r), (errstr?":":""), (errstr?errstr:""));
420 talloc_free(attr_folded);
423 if (ldb_should_b64_encode(ldb, &v)) {
424 char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length);
426 talloc_free(attr_folded);
429 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr);
432 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s:%.*s", LTDB_INDEX, attr_folded, (int)v.length, (char *)v.data);
435 if (v.data != value->data) {
438 talloc_free(attr_folded);
444 see if a attribute value is in the list of indexed attributes
446 static bool ltdb_is_indexed(const struct ldb_message *index_list, const char *attr)
449 struct ldb_message_element *el;
451 el = ldb_msg_find_element(index_list, LTDB_IDXATTR);
456 /* TODO: this is too expensive! At least use a binary search */
457 for (i=0; i<el->num_values; i++) {
458 if (ldb_attr_cmp((char *)el->values[i].data, attr) == 0) {
466 in the following logic functions, the return value is treated as
469 LDB_SUCCESS: we found some matching index values
471 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
473 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
474 we'll need a full search
478 return a list of dn's that might match a simple indexed search (an
479 equality search only)
481 static int ltdb_index_dn_simple(struct ldb_module *module,
482 const struct ldb_parse_tree *tree,
483 const struct ldb_message *index_list,
484 struct dn_list *list)
486 struct ldb_context *ldb;
490 ldb = ldb_module_get_ctx(module);
495 /* if the attribute isn't in the list of indexed attributes then
496 this node needs a full search */
497 if (!ltdb_is_indexed(index_list, tree->u.equality.attr)) {
498 return LDB_ERR_OPERATIONS_ERROR;
501 /* the attribute is indexed. Pull the list of DNs that match the
503 dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value, NULL);
504 if (!dn) return LDB_ERR_OPERATIONS_ERROR;
506 ret = ltdb_dn_list_load(module, dn, list);
512 static bool list_union(struct ldb_context *, struct dn_list *, const struct dn_list *);
515 return a list of dn's that might match a leaf indexed search
517 static int ltdb_index_dn_leaf(struct ldb_module *module,
518 const struct ldb_parse_tree *tree,
519 const struct ldb_message *index_list,
520 struct dn_list *list)
522 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module),
523 struct ltdb_private);
524 if (ltdb->disallow_dn_filter &&
525 (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0)) {
526 /* in AD mode we do not support "(dn=...)" search filters */
531 if (ldb_attr_dn(tree->u.equality.attr) == 0) {
532 list->dn = talloc_array(list, struct ldb_val, 1);
533 if (list->dn == NULL) {
534 ldb_module_oom(module);
535 return LDB_ERR_OPERATIONS_ERROR;
537 list->dn[0] = tree->u.equality.value;
541 return ltdb_index_dn_simple(module, tree, index_list, list);
549 static bool list_intersect(struct ldb_context *ldb,
550 struct dn_list *list, const struct dn_list *list2)
552 struct dn_list *list3;
555 if (list->count == 0) {
559 if (list2->count == 0) {
566 /* the indexing code is allowed to return a longer list than
567 what really matches, as all results are filtered by the
568 full expression at the end - this shortcut avoids a lot of
569 work in some cases */
570 if (list->count < 2 && list2->count > 10) {
573 if (list2->count < 2 && list->count > 10) {
574 list->count = list2->count;
575 list->dn = list2->dn;
576 /* note that list2 may not be the parent of list2->dn,
577 as list2->dn may be owned by ltdb->idxptr. In that
578 case we expect this reparent call to fail, which is
580 talloc_reparent(list2, list, list2->dn);
584 list3 = talloc_zero(list, struct dn_list);
589 list3->dn = talloc_array(list3, struct ldb_val, list->count);
596 for (i=0;i<list->count;i++) {
597 if (ltdb_dn_list_find_val(list2, &list->dn[i]) != -1) {
598 list3->dn[list3->count] = list->dn[i];
603 list->dn = talloc_steal(list, list3->dn);
604 list->count = list3->count;
615 static bool list_union(struct ldb_context *ldb,
616 struct dn_list *list, const struct dn_list *list2)
620 if (list2->count == 0) {
625 if (list->count == 0) {
627 list->count = list2->count;
628 list->dn = list2->dn;
629 /* note that list2 may not be the parent of list2->dn,
630 as list2->dn may be owned by ltdb->idxptr. In that
631 case we expect this reparent call to fail, which is
633 talloc_reparent(list2, list, list2->dn);
637 dn3 = talloc_array(list, struct ldb_val, list->count + list2->count);
643 /* we allow for duplicates here, and get rid of them later */
644 memcpy(dn3, list->dn, sizeof(list->dn[0])*list->count);
645 memcpy(dn3+list->count, list2->dn, sizeof(list2->dn[0])*list2->count);
648 list->count += list2->count;
653 static int ltdb_index_dn(struct ldb_module *module,
654 const struct ldb_parse_tree *tree,
655 const struct ldb_message *index_list,
656 struct dn_list *list);
660 process an OR list (a union)
662 static int ltdb_index_dn_or(struct ldb_module *module,
663 const struct ldb_parse_tree *tree,
664 const struct ldb_message *index_list,
665 struct dn_list *list)
667 struct ldb_context *ldb;
670 ldb = ldb_module_get_ctx(module);
675 for (i=0; i<tree->u.list.num_elements; i++) {
676 struct dn_list *list2;
679 list2 = talloc_zero(list, struct dn_list);
681 return LDB_ERR_OPERATIONS_ERROR;
684 ret = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2);
686 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
692 if (ret != LDB_SUCCESS) {
698 if (!list_union(ldb, list, list2)) {
700 return LDB_ERR_OPERATIONS_ERROR;
704 if (list->count == 0) {
705 return LDB_ERR_NO_SUCH_OBJECT;
715 static int ltdb_index_dn_not(struct ldb_module *module,
716 const struct ldb_parse_tree *tree,
717 const struct ldb_message *index_list,
718 struct dn_list *list)
720 /* the only way to do an indexed not would be if we could
721 negate the not via another not or if we knew the total
722 number of database elements so we could know that the
723 existing expression covered the whole database.
725 instead, we just give up, and rely on a full index scan
726 (unless an outer & manages to reduce the list)
728 return LDB_ERR_OPERATIONS_ERROR;
732 static bool ltdb_index_unique(struct ldb_context *ldb,
735 const struct ldb_schema_attribute *a;
736 a = ldb_schema_attribute_by_name(ldb, attr);
737 if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
744 process an AND expression (intersection)
746 static int ltdb_index_dn_and(struct ldb_module *module,
747 const struct ldb_parse_tree *tree,
748 const struct ldb_message *index_list,
749 struct dn_list *list)
751 struct ldb_context *ldb;
755 ldb = ldb_module_get_ctx(module);
760 /* in the first pass we only look for unique simple
761 equality tests, in the hope of avoiding having to look
763 for (i=0; i<tree->u.list.num_elements; i++) {
764 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
767 if (subtree->operation != LDB_OP_EQUALITY ||
768 !ltdb_index_unique(ldb, subtree->u.equality.attr)) {
772 ret = ltdb_index_dn(module, subtree, index_list, list);
773 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
775 return LDB_ERR_NO_SUCH_OBJECT;
777 if (ret == LDB_SUCCESS) {
778 /* a unique index match means we can
779 * stop. Note that we don't care if we return
780 * a few too many objects, due to later
786 /* now do a full intersection */
789 for (i=0; i<tree->u.list.num_elements; i++) {
790 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
791 struct dn_list *list2;
794 list2 = talloc_zero(list, struct dn_list);
796 return ldb_module_oom(module);
799 ret = ltdb_index_dn(module, subtree, index_list, list2);
801 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
806 return LDB_ERR_NO_SUCH_OBJECT;
809 if (ret != LDB_SUCCESS) {
810 /* this didn't adding anything */
816 talloc_reparent(list2, list, list->dn);
817 list->dn = list2->dn;
818 list->count = list2->count;
820 } else if (!list_intersect(ldb, list, list2)) {
822 return LDB_ERR_OPERATIONS_ERROR;
825 if (list->count == 0) {
827 return LDB_ERR_NO_SUCH_OBJECT;
830 if (list->count < 2) {
831 /* it isn't worth loading the next part of the tree */
837 /* none of the attributes were indexed */
838 return LDB_ERR_OPERATIONS_ERROR;
845 return a list of matching objects using a one-level index
847 static int ltdb_index_dn_one(struct ldb_module *module,
848 struct ldb_dn *parent_dn,
849 struct dn_list *list)
851 struct ldb_context *ldb;
856 ldb = ldb_module_get_ctx(module);
858 /* work out the index key from the parent DN */
859 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn));
860 val.length = strlen((char *)val.data);
861 key = ltdb_index_key(ldb, LTDB_IDXONE, &val, NULL);
864 return LDB_ERR_OPERATIONS_ERROR;
867 ret = ltdb_dn_list_load(module, key, list);
869 if (ret != LDB_SUCCESS) {
873 if (list->count == 0) {
874 return LDB_ERR_NO_SUCH_OBJECT;
881 return a list of dn's that might match a indexed search or
882 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
884 static int ltdb_index_dn(struct ldb_module *module,
885 const struct ldb_parse_tree *tree,
886 const struct ldb_message *index_list,
887 struct dn_list *list)
889 int ret = LDB_ERR_OPERATIONS_ERROR;
891 switch (tree->operation) {
893 ret = ltdb_index_dn_and(module, tree, index_list, list);
897 ret = ltdb_index_dn_or(module, tree, index_list, list);
901 ret = ltdb_index_dn_not(module, tree, index_list, list);
904 case LDB_OP_EQUALITY:
905 ret = ltdb_index_dn_leaf(module, tree, index_list, list);
908 case LDB_OP_SUBSTRING:
913 case LDB_OP_EXTENDED:
914 /* we can't index with fancy bitops yet */
915 ret = LDB_ERR_OPERATIONS_ERROR;
923 filter a candidate dn_list from an indexed search into a set of results
924 extracting just the given attributes
926 static int ltdb_index_filter(const struct dn_list *dn_list,
927 struct ltdb_context *ac,
928 uint32_t *match_count)
930 struct ldb_context *ldb;
931 struct ldb_message *msg;
934 ldb = ldb_module_get_ctx(ac->module);
936 for (i = 0; i < dn_list->count; i++) {
941 msg = ldb_msg_new(ac);
943 return LDB_ERR_OPERATIONS_ERROR;
946 dn = ldb_dn_from_ldb_val(msg, ldb, &dn_list->dn[i]);
949 return LDB_ERR_OPERATIONS_ERROR;
952 ret = ltdb_search_dn1(ac->module, dn, msg);
954 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
955 /* the record has disappeared? yes, this can happen */
960 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
961 /* an internal error */
963 return LDB_ERR_OPERATIONS_ERROR;
966 ret = ldb_match_msg_error(ldb, msg,
967 ac->tree, ac->base, ac->scope, &matched);
968 if (ret != LDB_SUCCESS) {
977 /* filter the attributes that the user wants */
978 ret = ltdb_filter_attrs(msg, ac->attrs);
982 return LDB_ERR_OPERATIONS_ERROR;
985 ret = ldb_module_send_entry(ac->req, msg, NULL);
986 if (ret != LDB_SUCCESS) {
987 /* Regardless of success or failure, the msg
988 * is the callbacks responsiblity, and should
989 * not be talloc_free()'ed */
990 ac->request_terminated = true;
1001 remove any duplicated entries in a indexed result
1003 static void ltdb_dn_list_remove_duplicates(struct dn_list *list)
1005 unsigned int i, new_count;
1007 if (list->count < 2) {
1011 TYPESAFE_QSORT(list->dn, list->count, dn_list_cmp);
1014 for (i=1; i<list->count; i++) {
1015 if (dn_list_cmp(&list->dn[i], &list->dn[new_count-1]) != 0) {
1016 if (new_count != i) {
1017 list->dn[new_count] = list->dn[i];
1023 list->count = new_count;
1027 search the database with a LDAP-like expression using indexes
1028 returns -1 if an indexed search is not possible, in which
1029 case the caller should call ltdb_search_full()
1031 int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
1033 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(ac->module), struct ltdb_private);
1034 struct dn_list *dn_list;
1037 /* see if indexing is enabled */
1038 if (!ltdb->cache->attribute_indexes &&
1039 !ltdb->cache->one_level_indexes &&
1040 ac->scope != LDB_SCOPE_BASE) {
1041 /* fallback to a full search */
1042 return LDB_ERR_OPERATIONS_ERROR;
1045 dn_list = talloc_zero(ac, struct dn_list);
1046 if (dn_list == NULL) {
1047 return ldb_module_oom(ac->module);
1050 switch (ac->scope) {
1051 case LDB_SCOPE_BASE:
1052 dn_list->dn = talloc_array(dn_list, struct ldb_val, 1);
1053 if (dn_list->dn == NULL) {
1054 talloc_free(dn_list);
1055 return ldb_module_oom(ac->module);
1057 dn_list->dn[0].data = discard_const_p(unsigned char, ldb_dn_get_linearized(ac->base));
1058 if (dn_list->dn[0].data == NULL) {
1059 talloc_free(dn_list);
1060 return ldb_module_oom(ac->module);
1062 dn_list->dn[0].length = strlen((char *)dn_list->dn[0].data);
1066 case LDB_SCOPE_ONELEVEL:
1067 if (!ltdb->cache->one_level_indexes) {
1068 talloc_free(dn_list);
1069 return LDB_ERR_OPERATIONS_ERROR;
1071 ret = ltdb_index_dn_one(ac->module, ac->base, dn_list);
1072 if (ret != LDB_SUCCESS) {
1073 talloc_free(dn_list);
1078 case LDB_SCOPE_SUBTREE:
1079 case LDB_SCOPE_DEFAULT:
1080 if (!ltdb->cache->attribute_indexes) {
1081 talloc_free(dn_list);
1082 return LDB_ERR_OPERATIONS_ERROR;
1084 ret = ltdb_index_dn(ac->module, ac->tree, ltdb->cache->indexlist, dn_list);
1085 if (ret != LDB_SUCCESS) {
1086 talloc_free(dn_list);
1089 ltdb_dn_list_remove_duplicates(dn_list);
1093 ret = ltdb_index_filter(dn_list, ac, match_count);
1094 talloc_free(dn_list);
1099 * @brief Add a DN in the index list of a given attribute name/value pair
1101 * This function will add the DN in the index list for the index for
1102 * the given attribute name and value.
1104 * @param[in] module A ldb_module structure
1106 * @param[in] dn The string representation of the DN as it
1107 * will be stored in the index entry
1109 * @param[in] el A ldb_message_element array, one of the entry
1110 * referred by the v_idx is the attribute name and
1111 * value pair which will be used to construct the
1114 * @param[in] v_idx The index of element in the el array to use
1116 * @return An ldb error code
1118 static int ltdb_index_add1(struct ldb_module *module, const char *dn,
1119 struct ldb_message_element *el, int v_idx,
1122 struct ldb_context *ldb;
1123 struct ldb_dn *dn_key;
1125 const struct ldb_schema_attribute *a;
1126 struct dn_list *list;
1129 ldb = ldb_module_get_ctx(module);
1131 list = talloc_zero(module, struct dn_list);
1133 return LDB_ERR_OPERATIONS_ERROR;
1136 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], &a);
1139 return LDB_ERR_OPERATIONS_ERROR;
1141 talloc_steal(list, dn_key);
1143 ret = ltdb_dn_list_load(module, dn_key, list);
1144 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1149 if (list->count > 0 &&
1150 a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
1152 ldb_asprintf_errstring(ldb, __location__ ": unique index violation on %s in %s",
1154 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1157 /* If we are doing an ADD, then this can not already be in the index,
1158 as it was not already in the database, and this has already been
1159 checked because the store succeeded */
1161 if (ltdb_dn_list_find_str(list, dn) != -1) {
1167 /* overallocate the list a bit, to reduce the number of
1168 * realloc trigered copies */
1169 alloc_len = ((list->count+1)+7) & ~7;
1170 list->dn = talloc_realloc(list, list->dn, struct ldb_val, alloc_len);
1171 if (list->dn == NULL) {
1173 return LDB_ERR_OPERATIONS_ERROR;
1175 list->dn[list->count].data = (uint8_t *)talloc_strdup(list->dn, dn);
1176 list->dn[list->count].length = strlen(dn);
1179 ret = ltdb_dn_list_store(module, dn_key, list);
1187 add index entries for one elements in a message
1189 static int ltdb_index_add_el(struct ldb_module *module, const char *dn,
1190 struct ldb_message_element *el, bool is_new)
1193 for (i = 0; i < el->num_values; i++) {
1194 int ret = ltdb_index_add1(module, dn, el, i, is_new);
1195 if (ret != LDB_SUCCESS) {
1204 add index entries for all elements in a message
1206 static int ltdb_index_add_all(struct ldb_module *module, const char *dn,
1207 struct ldb_message_element *elements, int num_el,
1210 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1217 if (ltdb->cache->indexlist->num_elements == 0) {
1218 /* no indexed fields */
1222 for (i = 0; i < num_el; i++) {
1224 if (!ltdb_is_indexed(ltdb->cache->indexlist, elements[i].name)) {
1227 ret = ltdb_index_add_el(module, dn, &elements[i], is_new);
1228 if (ret != LDB_SUCCESS) {
1229 struct ldb_context *ldb = ldb_module_get_ctx(module);
1230 ldb_asprintf_errstring(ldb,
1231 __location__ ": Failed to re-index %s in %s - %s",
1232 elements[i].name, dn, ldb_errstring(ldb));
1242 insert a one level index for a message
1244 static int ltdb_index_onelevel(struct ldb_module *module, const struct ldb_message *msg, int add)
1246 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1247 struct ldb_message_element el;
1253 /* We index for ONE Level only if requested */
1254 if (!ltdb->cache->one_level_indexes) {
1258 pdn = ldb_dn_get_parent(module, msg->dn);
1260 return LDB_ERR_OPERATIONS_ERROR;
1263 dn = ldb_dn_get_linearized(msg->dn);
1266 return LDB_ERR_OPERATIONS_ERROR;
1269 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn));
1270 if (val.data == NULL) {
1272 return LDB_ERR_OPERATIONS_ERROR;
1275 val.length = strlen((char *)val.data);
1276 el.name = LTDB_IDXONE;
1281 ret = ltdb_index_add1(module, dn, &el, 0, add);
1282 } else { /* delete */
1283 ret = ltdb_index_del_value(module, msg->dn, &el, 0);
1292 add the index entries for a new element in a record
1293 The caller guarantees that these element values are not yet indexed
1295 int ltdb_index_add_element(struct ldb_module *module, struct ldb_dn *dn,
1296 struct ldb_message_element *el)
1298 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1299 if (ldb_dn_is_special(dn)) {
1302 if (!ltdb_is_indexed(ltdb->cache->indexlist, el->name)) {
1305 return ltdb_index_add_el(module, ldb_dn_get_linearized(dn), el, true);
1309 add the index entries for a new record
1311 int ltdb_index_add_new(struct ldb_module *module, const struct ldb_message *msg)
1316 if (ldb_dn_is_special(msg->dn)) {
1320 dn = ldb_dn_get_linearized(msg->dn);
1322 return LDB_ERR_OPERATIONS_ERROR;
1325 ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements,
1327 if (ret != LDB_SUCCESS) {
1331 return ltdb_index_onelevel(module, msg, 1);
1336 delete an index entry for one message element
1338 int ltdb_index_del_value(struct ldb_module *module, struct ldb_dn *dn,
1339 struct ldb_message_element *el, unsigned int v_idx)
1341 struct ldb_context *ldb;
1342 struct ldb_dn *dn_key;
1346 struct dn_list *list;
1348 ldb = ldb_module_get_ctx(module);
1350 dn_str = ldb_dn_get_linearized(dn);
1351 if (dn_str == NULL) {
1352 return LDB_ERR_OPERATIONS_ERROR;
1355 if (dn_str[0] == '@') {
1359 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], NULL);
1361 return LDB_ERR_OPERATIONS_ERROR;
1364 list = talloc_zero(dn_key, struct dn_list);
1366 talloc_free(dn_key);
1367 return LDB_ERR_OPERATIONS_ERROR;
1370 ret = ltdb_dn_list_load(module, dn_key, list);
1371 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1372 /* it wasn't indexed. Did we have an earlier error? If we did then
1374 talloc_free(dn_key);
1378 if (ret != LDB_SUCCESS) {
1379 talloc_free(dn_key);
1383 i = ltdb_dn_list_find_str(list, dn_str);
1385 /* nothing to delete */
1386 talloc_free(dn_key);
1390 j = (unsigned int) i;
1391 if (j != list->count - 1) {
1392 memmove(&list->dn[j], &list->dn[j+1], sizeof(list->dn[0])*(list->count - (j+1)));
1395 if (list->count == 0) {
1396 talloc_free(list->dn);
1399 list->dn = talloc_realloc(list, list->dn, struct ldb_val, list->count);
1402 ret = ltdb_dn_list_store(module, dn_key, list);
1404 talloc_free(dn_key);
1410 delete the index entries for a element
1411 return -1 on failure
1413 int ltdb_index_del_element(struct ldb_module *module, struct ldb_dn *dn,
1414 struct ldb_message_element *el)
1416 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1421 if (!ltdb->cache->attribute_indexes) {
1422 /* no indexed fields */
1426 dn_str = ldb_dn_get_linearized(dn);
1427 if (dn_str == NULL) {
1428 return LDB_ERR_OPERATIONS_ERROR;
1431 if (dn_str[0] == '@') {
1435 if (!ltdb_is_indexed(ltdb->cache->indexlist, el->name)) {
1438 for (i = 0; i < el->num_values; i++) {
1439 ret = ltdb_index_del_value(module, dn, el, i);
1440 if (ret != LDB_SUCCESS) {
1449 delete the index entries for a record
1450 return -1 on failure
1452 int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg)
1454 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1458 if (ldb_dn_is_special(msg->dn)) {
1462 ret = ltdb_index_onelevel(module, msg, 0);
1463 if (ret != LDB_SUCCESS) {
1467 if (!ltdb->cache->attribute_indexes) {
1468 /* no indexed fields */
1472 for (i = 0; i < msg->num_elements; i++) {
1473 ret = ltdb_index_del_element(module, msg->dn, &msg->elements[i]);
1474 if (ret != LDB_SUCCESS) {
1484 traversal function that deletes all @INDEX records
1486 static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1488 struct ldb_module *module = state;
1489 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1490 const char *dnstr = "DN=" LTDB_INDEX ":";
1491 struct dn_list list;
1496 if (strncmp((char *)key.dptr, dnstr, strlen(dnstr)) != 0) {
1499 /* we need to put a empty list in the internal tdb for this
1504 /* the offset of 3 is to remove the DN= prefix. */
1505 v.data = key.dptr + 3;
1506 v.length = strnlen((char *)key.dptr, key.dsize) - 3;
1508 dn = ldb_dn_from_ldb_val(ltdb, ldb_module_get_ctx(module), &v);
1509 ret = ltdb_dn_list_store(module, dn, &list);
1510 if (ret != LDB_SUCCESS) {
1511 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1512 "Unable to store null index for %s\n",
1513 ldb_dn_get_linearized(dn));
1521 struct ltdb_reindex_context {
1522 struct ldb_module *module;
1527 traversal function that adds @INDEX records during a re index
1529 static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1531 struct ldb_context *ldb;
1532 struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
1533 struct ldb_module *module = ctx->module;
1534 struct ldb_message *msg;
1535 const char *dn = NULL;
1539 ldb = ldb_module_get_ctx(module);
1541 if (strncmp((char *)key.dptr, "DN=@", 4) == 0 ||
1542 strncmp((char *)key.dptr, "DN=", 3) != 0) {
1546 msg = ldb_msg_new(module);
1551 ret = ldb_unpack_data(ldb, (struct ldb_val *)&data, msg);
1553 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
1554 ldb_dn_get_linearized(msg->dn));
1559 /* check if the DN key has changed, perhaps due to the
1560 case insensitivity of an element changing */
1561 key2 = ltdb_key(module, msg->dn);
1562 if (key2.dptr == NULL) {
1563 /* probably a corrupt record ... darn */
1564 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s",
1565 ldb_dn_get_linearized(msg->dn));
1569 if (strcmp((char *)key2.dptr, (char *)key.dptr) != 0) {
1570 tdb_delete(tdb, key);
1571 tdb_store(tdb, key2, data, 0);
1573 talloc_free(key2.dptr);
1575 if (msg->dn == NULL) {
1576 dn = (char *)key.dptr + 3;
1578 dn = ldb_dn_get_linearized(msg->dn);
1581 ret = ltdb_index_onelevel(module, msg, 1);
1582 if (ret != LDB_SUCCESS) {
1583 ldb_debug(ldb, LDB_DEBUG_ERROR,
1584 "Adding special ONE LEVEL index failed (%s)!",
1585 ldb_dn_get_linearized(msg->dn));
1590 ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements,
1593 if (ret != LDB_SUCCESS) {
1605 force a complete reindex of the database
1607 int ltdb_reindex(struct ldb_module *module)
1609 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1611 struct ltdb_reindex_context ctx;
1613 if (ltdb_cache_reload(module) != 0) {
1614 return LDB_ERR_OPERATIONS_ERROR;
1617 /* first traverse the database deleting any @INDEX records by
1618 * putting NULL entries in the in-memory tdb
1620 ret = tdb_traverse(ltdb->tdb, delete_index, module);
1622 return LDB_ERR_OPERATIONS_ERROR;
1625 /* if we don't have indexes we have nothing todo */
1626 if (ltdb->cache->indexlist->num_elements == 0) {
1630 ctx.module = module;
1633 /* now traverse adding any indexes for normal LDB records */
1634 ret = tdb_traverse(ltdb->tdb, re_index, &ctx);
1636 struct ldb_context *ldb = ldb_module_get_ctx(module);
1637 ldb_asprintf_errstring(ldb, "reindexing traverse failed: %s", ldb_errstring(ldb));
1638 return LDB_ERR_OPERATIONS_ERROR;
1641 if (ctx.error != LDB_SUCCESS) {
1642 struct ldb_context *ldb = ldb_module_get_ctx(module);
1643 ldb_asprintf_errstring(ldb, "reindexing failed: %s", ldb_errstring(ldb));