4 Copyright (C) Andrew Tridgell 2004
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 "dlinklist.h"
38 the idxptr code is a bit unusual. The way it works is to replace
39 @IDX elements in records during a transaction with @IDXPTR
40 elements. The @IDXPTR elements don't contain the actual index entry
41 values, but contain a pointer to a linked list of values.
43 This means we are storing pointers in a database, which is normally
44 not allowed, but in this case we are storing them only for the
45 duration of a transaction, and re-writing them into the normal @IDX
46 format at the end of the transaction. That means no other processes
47 are ever exposed to the @IDXPTR values.
49 The advantage is that the linked list doesn't cause huge
50 fragmentation during a transaction. Without the @IDXPTR method we
51 often ended up with a ldb that was between 10x and 100x larger then
52 it needs to be due to massive fragmentation caused by re-writing
53 @INDEX records many times during indexing.
55 struct ldb_index_pointer {
56 struct ldb_index_pointer *next, *prev;
67 add to the list of DNs that need to be fixed on transaction end
69 static int ltdb_idxptr_add(struct ldb_module *module, const struct ldb_message *msg)
71 void *data = ldb_module_get_private(module);
72 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
73 ltdb->idxptr->dn_list = talloc_realloc(ltdb->idxptr, ltdb->idxptr->dn_list,
74 const char *, ltdb->idxptr->num_dns+1);
75 if (ltdb->idxptr->dn_list == NULL) {
76 ltdb->idxptr->num_dns = 0;
77 return LDB_ERR_OPERATIONS_ERROR;
79 ltdb->idxptr->dn_list[ltdb->idxptr->num_dns] =
80 talloc_strdup(ltdb->idxptr->dn_list, ldb_dn_get_linearized(msg->dn));
81 if (ltdb->idxptr->dn_list[ltdb->idxptr->num_dns] == NULL) {
82 return LDB_ERR_OPERATIONS_ERROR;
84 ltdb->idxptr->num_dns++;
88 /* free an idxptr record */
89 static int ltdb_free_idxptr(struct ldb_module *module, struct ldb_message_element *el)
92 struct ldb_index_pointer *ptr;
94 if (el->num_values != 1) {
95 return LDB_ERR_OPERATIONS_ERROR;
99 if (val.length != sizeof(void *)) {
100 return LDB_ERR_OPERATIONS_ERROR;
103 ptr = *(struct ldb_index_pointer **)val.data;
104 if (talloc_get_type(ptr, struct ldb_index_pointer) != ptr) {
105 return LDB_ERR_OPERATIONS_ERROR;
109 struct ldb_index_pointer *tmp = ptr;
110 DLIST_REMOVE(ptr, ptr);
118 /* convert from the IDXPTR format to a ldb_message_element format */
119 static int ltdb_convert_from_idxptr(struct ldb_module *module, struct ldb_message_element *el)
122 struct ldb_index_pointer *ptr, *tmp;
124 struct ldb_val *val2;
126 if (el->num_values != 1) {
127 return LDB_ERR_OPERATIONS_ERROR;
131 if (val.length != sizeof(void *)) {
132 return LDB_ERR_OPERATIONS_ERROR;
135 ptr = *(struct ldb_index_pointer **)val.data;
136 if (talloc_get_type(ptr, struct ldb_index_pointer) != ptr) {
137 return LDB_ERR_OPERATIONS_ERROR;
140 /* count the length of the list */
141 for (i=0, tmp = ptr; tmp; tmp=tmp->next) {
145 /* allocate the new values array */
146 val2 = talloc_realloc(NULL, el->values, struct ldb_val, i);
148 return LDB_ERR_OPERATIONS_ERROR;
153 /* populate the values array */
154 for (i=0, tmp = ptr; tmp; tmp=tmp->next, i++) {
155 el->values[i].length = tmp->value.length;
156 /* we need to over-allocate here as there are still some places
157 in ldb that rely on null termination. */
158 el->values[i].data = talloc_size(el->values, tmp->value.length+1);
159 if (el->values[i].data == NULL) {
160 return LDB_ERR_OPERATIONS_ERROR;
162 memcpy(el->values[i].data, tmp->value.data, tmp->value.length);
163 el->values[i].data[tmp->value.length] = 0;
166 /* update the name */
173 /* convert to the IDXPTR format from a ldb_message_element format */
174 static int ltdb_convert_to_idxptr(struct ldb_module *module, struct ldb_message_element *el)
176 struct ldb_index_pointer *ptr, *tmp;
178 struct ldb_val *val2;
179 void *data = ldb_module_get_private(module);
180 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
184 for (i=0;i<el->num_values;i++) {
185 tmp = talloc(ltdb->idxptr, struct ldb_index_pointer);
187 return LDB_ERR_OPERATIONS_ERROR;
189 tmp->value = el->values[i];
190 tmp->value.data = talloc_memdup(tmp, tmp->value.data, tmp->value.length);
191 if (tmp->value.data == NULL) {
192 return LDB_ERR_OPERATIONS_ERROR;
197 /* allocate the new values array */
198 val2 = talloc_realloc(NULL, el->values, struct ldb_val, 1);
200 return LDB_ERR_OPERATIONS_ERROR;
205 el->values[0].data = talloc_memdup(el->values, &ptr, sizeof(ptr));
206 el->values[0].length = sizeof(ptr);
208 /* update the name */
209 el->name = LTDB_IDXPTR;
215 /* enable the idxptr mode when transactions start */
216 int ltdb_index_transaction_start(struct ldb_module *module)
218 void *data = ldb_module_get_private(module);
219 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
220 ltdb->idxptr = talloc_zero(module, struct ltdb_idxptr);
225 a wrapper around ltdb_search_dn1() which translates pointer based index records
226 and maps them into normal ldb message structures
228 static int ltdb_search_dn1_index(struct ldb_module *module,
229 struct ldb_dn *dn, struct ldb_message *msg)
232 ret = ltdb_search_dn1(module, dn, msg);
233 if (ret != LDB_SUCCESS) {
237 /* if this isn't a @INDEX record then don't munge it */
238 if (strncmp(ldb_dn_get_linearized(msg->dn), LTDB_INDEX ":", strlen(LTDB_INDEX) + 1) != 0) {
239 return LDB_ERR_OPERATIONS_ERROR;
242 for (i=0;i<msg->num_elements;i++) {
243 struct ldb_message_element *el = &msg->elements[i];
244 if (strcmp(el->name, LTDB_IDXPTR) == 0) {
245 ret = ltdb_convert_from_idxptr(module, el);
246 if (ret != LDB_SUCCESS) {
258 fixup the idxptr for one DN
260 static int ltdb_idxptr_fix_dn(struct ldb_module *module, const char *strdn)
262 struct ldb_context *ldb;
264 struct ldb_message *msg = ldb_msg_new(module);
267 ldb = ldb_module_get_ctx(module);
269 dn = ldb_dn_new(msg, ldb, strdn);
270 if (ltdb_search_dn1_index(module, dn, msg) == LDB_SUCCESS) {
271 ret = ltdb_store(module, msg, TDB_REPLACE);
277 /* cleanup the idxptr mode when transaction commits */
278 int ltdb_index_transaction_commit(struct ldb_module *module)
281 void *data = ldb_module_get_private(module);
282 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
284 /* fix all the DNs that we have modified */
286 for (i=0;i<ltdb->idxptr->num_dns;i++) {
287 ltdb_idxptr_fix_dn(module, ltdb->idxptr->dn_list[i]);
290 if (ltdb->idxptr->repack) {
291 tdb_repack(ltdb->tdb);
295 talloc_free(ltdb->idxptr);
300 /* cleanup the idxptr mode when transaction cancels */
301 int ltdb_index_transaction_cancel(struct ldb_module *module)
303 void *data = ldb_module_get_private(module);
304 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
305 talloc_free(ltdb->idxptr);
312 /* a wrapper around ltdb_store() for the index code which
313 stores in IDXPTR format when idxptr mode is enabled
315 WARNING: This modifies the msg which is passed in
317 int ltdb_store_idxptr(struct ldb_module *module, const struct ldb_message *msg, int flgs)
319 void *data = ldb_module_get_private(module);
320 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
325 struct ldb_message *msg2 = ldb_msg_new(module);
327 /* free any old pointer */
328 ret = ltdb_search_dn1(module, msg->dn, msg2);
330 for (i=0;i<msg2->num_elements;i++) {
331 struct ldb_message_element *el = &msg2->elements[i];
332 if (strcmp(el->name, LTDB_IDXPTR) == 0) {
333 ret = ltdb_free_idxptr(module, el);
334 if (ret != LDB_SUCCESS) {
342 for (i=0;i<msg->num_elements;i++) {
343 struct ldb_message_element *el = &msg->elements[i];
344 if (strcmp(el->name, LTDB_IDX) == 0) {
345 ret = ltdb_convert_to_idxptr(module, el);
346 if (ret != LDB_SUCCESS) {
352 if (ltdb_idxptr_add(module, msg) != 0) {
353 return LDB_ERR_OPERATIONS_ERROR;
357 ret = ltdb_store(module, msg, flgs);
363 find an element in a list, using the given comparison function and
364 assuming that the list is already sorted using comp_fn
366 return -1 if not found, or the index of the first occurance of needle if found
368 static int ldb_list_find(const void *needle,
369 const void *base, size_t nmemb, size_t size,
370 comparison_fn_t comp_fn)
372 const uint8_t *base_p = (const uint8_t *)base;
373 size_t min_i, max_i, test_i;
382 while (min_i < max_i) {
385 test_i = (min_i + max_i) / 2;
386 r = comp_fn(needle, (void const *)(base_p + (size * test_i)));
388 /* scan back for first element */
390 comp_fn(needle, (void const *)(base_p + (size * (test_i-1)))) == 0) {
406 if (comp_fn(needle, (void const *)(base_p + (size * min_i))) == 0) {
419 return the dn key to be used for an index
422 static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
423 const char *attr, const struct ldb_val *value,
424 const struct ldb_schema_attribute **ap)
428 const struct ldb_schema_attribute *a;
432 attr_folded = ldb_attr_casefold(ldb, attr);
437 a = ldb_schema_attribute_by_name(ldb, attr);
441 r = a->syntax->canonicalise_fn(ldb, ldb, value, &v);
442 if (r != LDB_SUCCESS) {
443 const char *errstr = ldb_errstring(ldb);
444 /* canonicalisation can be refused. For example,
445 a attribute that takes wildcards will refuse to canonicalise
446 if the value contains a wildcard */
447 ldb_asprintf_errstring(ldb, "Failed to create index key for attribute '%s':%s%s%s",
448 attr, ldb_strerror(r), (errstr?":":""), (errstr?errstr:""));
449 talloc_free(attr_folded);
452 if (ldb_should_b64_encode(ldb, &v)) {
453 char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length);
454 if (!vstr) return NULL;
455 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr);
458 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s:%.*s", LTDB_INDEX, attr_folded, (int)v.length, (char *)v.data);
461 if (v.data != value->data) {
464 talloc_free(attr_folded);
470 see if a attribute value is in the list of indexed attributes
472 static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr,
473 unsigned int *v_idx, const char *key)
476 for (i=0;i<msg->num_elements;i++) {
477 if (ldb_attr_cmp(msg->elements[i].name, key) == 0) {
478 const struct ldb_message_element *el = &msg->elements[i];
481 /* in this case we are just looking to see if key is present,
482 we are not spearching for a specific index */
486 for (j=0;j<el->num_values;j++) {
487 if (ldb_attr_cmp((char *)el->values[j].data, attr) == 0) {
499 /* used in sorting dn lists */
500 static int list_cmp(const char **s1, const char **s2)
502 return strcmp(*s1, *s2);
506 return a list of dn's that might match a simple indexed search or
508 static int ltdb_index_dn_simple(struct ldb_module *module,
509 const struct ldb_parse_tree *tree,
510 const struct ldb_message *index_list,
511 struct dn_list *list)
513 struct ldb_context *ldb;
517 struct ldb_message *msg;
519 ldb = ldb_module_get_ctx(module);
524 /* if the attribute isn't in the list of indexed attributes then
525 this node needs a full search */
526 if (ldb_msg_find_idx(index_list, tree->u.equality.attr, NULL, LTDB_IDXATTR) == -1) {
527 return LDB_ERR_OPERATIONS_ERROR;
530 /* the attribute is indexed. Pull the list of DNs that match the
532 dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value, NULL);
533 if (!dn) return LDB_ERR_OPERATIONS_ERROR;
535 msg = talloc(list, struct ldb_message);
537 return LDB_ERR_OPERATIONS_ERROR;
540 ret = ltdb_search_dn1_index(module, dn, msg);
542 if (ret != LDB_SUCCESS) {
546 for (i=0;i<msg->num_elements;i++) {
547 struct ldb_message_element *el;
549 if (strcmp(msg->elements[i].name, LTDB_IDX) != 0) {
553 el = &msg->elements[i];
555 list->dn = talloc_array(list, char *, el->num_values);
558 return LDB_ERR_OPERATIONS_ERROR;
561 for (j=0;j<el->num_values;j++) {
562 list->dn[list->count] =
563 talloc_strdup(list->dn, (char *)el->values[j].data);
564 if (!list->dn[list->count]) {
566 return LDB_ERR_OPERATIONS_ERROR;
574 if (list->count > 1) {
575 qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t) list_cmp);
582 static int list_union(struct ldb_context *, struct dn_list *, const struct dn_list *);
585 return a list of dn's that might match a leaf indexed search
587 static int ltdb_index_dn_leaf(struct ldb_module *module,
588 const struct ldb_parse_tree *tree,
589 const struct ldb_message *index_list,
590 struct dn_list *list)
592 struct ldb_context *ldb;
593 ldb = ldb_module_get_ctx(module);
595 if (ldb_attr_dn(tree->u.equality.attr) == 0) {
596 list->dn = talloc_array(list, char *, 1);
597 if (list->dn == NULL) {
599 return LDB_ERR_OPERATIONS_ERROR;
601 list->dn[0] = talloc_strdup(list->dn, (char *)tree->u.equality.value.data);
602 if (list->dn[0] == NULL) {
604 return LDB_ERR_OPERATIONS_ERROR;
609 return ltdb_index_dn_simple(module, tree, index_list, list);
616 relies on the lists being sorted
618 static int list_intersect(struct ldb_context *ldb,
619 struct dn_list *list, const struct dn_list *list2)
621 struct dn_list *list3;
624 if (list->count == 0 || list2->count == 0) {
626 return LDB_ERR_NO_SUCH_OBJECT;
629 list3 = talloc(ldb, struct dn_list);
631 return LDB_ERR_OPERATIONS_ERROR;
634 list3->dn = talloc_array(list3, char *, list->count);
637 return LDB_ERR_OPERATIONS_ERROR;
641 for (i=0;i<list->count;i++) {
642 if (ldb_list_find(list->dn[i], list2->dn, list2->count,
643 sizeof(char *), (comparison_fn_t)strcmp) != -1) {
644 list3->dn[list3->count] = talloc_move(list3->dn, &list->dn[i]);
647 talloc_free(list->dn[i]);
651 talloc_free(list->dn);
652 list->dn = talloc_move(list, &list3->dn);
653 list->count = list3->count;
656 return LDB_ERR_NO_SUCH_OBJECT;
663 relies on the lists being sorted
665 static int list_union(struct ldb_context *ldb,
666 struct dn_list *list, const struct dn_list *list2)
670 unsigned int count = list->count;
672 if (list->count == 0 && list2->count == 0) {
674 return LDB_ERR_NO_SUCH_OBJECT;
677 d = talloc_realloc(list, list->dn, char *, list->count + list2->count);
679 return LDB_ERR_OPERATIONS_ERROR;
683 for (i=0;i<list2->count;i++) {
684 if (ldb_list_find(list2->dn[i], list->dn, count,
685 sizeof(char *), (comparison_fn_t)strcmp) == -1) {
686 list->dn[list->count] = talloc_strdup(list->dn, list2->dn[i]);
687 if (!list->dn[list->count]) {
688 return LDB_ERR_OPERATIONS_ERROR;
694 if (list->count != count) {
695 qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t)list_cmp);
698 return LDB_ERR_NO_SUCH_OBJECT;
701 static int ltdb_index_dn(struct ldb_module *module,
702 const struct ldb_parse_tree *tree,
703 const struct ldb_message *index_list,
704 struct dn_list *list);
710 static int ltdb_index_dn_or(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);
721 ret = LDB_ERR_OPERATIONS_ERROR;
725 for (i=0;i<tree->u.list.num_elements;i++) {
726 struct dn_list *list2;
729 list2 = talloc(module, struct dn_list);
731 return LDB_ERR_OPERATIONS_ERROR;
734 v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2);
736 if (v == LDB_ERR_NO_SUCH_OBJECT) {
738 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
745 if (v != LDB_SUCCESS && v != LDB_ERR_NO_SUCH_OBJECT) {
747 talloc_free(list->dn);
752 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
754 list->dn = talloc_move(list, &list2->dn);
755 list->count = list2->count;
757 if (list_union(ldb, list, list2) == -1) {
759 return LDB_ERR_OPERATIONS_ERROR;
766 if (list->count == 0) {
767 return LDB_ERR_NO_SUCH_OBJECT;
777 static int ltdb_index_dn_not(struct ldb_module *module,
778 const struct ldb_parse_tree *tree,
779 const struct ldb_message *index_list,
780 struct dn_list *list)
782 /* the only way to do an indexed not would be if we could
783 negate the not via another not or if we knew the total
784 number of database elements so we could know that the
785 existing expression covered the whole database.
787 instead, we just give up, and rely on a full index scan
788 (unless an outer & manages to reduce the list)
790 return LDB_ERR_OPERATIONS_ERROR;
794 static bool ltdb_index_unique(struct ldb_context *ldb,
797 const struct ldb_schema_attribute *a;
798 a = ldb_schema_attribute_by_name(ldb, attr);
799 if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
806 AND two index results
808 static int ltdb_index_dn_and(struct ldb_module *module,
809 const struct ldb_parse_tree *tree,
810 const struct ldb_message *index_list,
811 struct dn_list *list)
813 struct ldb_context *ldb;
817 ldb = ldb_module_get_ctx(module);
819 ret = LDB_ERR_OPERATIONS_ERROR;
823 for (pass=0;pass<=1;pass++) {
824 /* in the first pass we only look for unique simple
825 equality tests, in the hope of avoiding having to look
827 bool only_unique = pass==0?true:false;
829 for (i=0;i<tree->u.list.num_elements;i++) {
830 struct dn_list *list2;
832 bool is_unique = false;
833 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
835 if (subtree->operation == LDB_OP_EQUALITY &&
836 ltdb_index_unique(ldb, subtree->u.equality.attr)) {
839 if (is_unique != only_unique) continue;
841 list2 = talloc(module, struct dn_list);
843 return LDB_ERR_OPERATIONS_ERROR;
846 v = ltdb_index_dn(module, subtree, index_list, list2);
848 if (v == LDB_ERR_NO_SUCH_OBJECT) {
850 talloc_free(list->dn);
852 return LDB_ERR_NO_SUCH_OBJECT;
855 if (v != LDB_SUCCESS && v != LDB_ERR_NO_SUCH_OBJECT) {
860 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
862 talloc_free(list->dn);
863 list->dn = talloc_move(list, &list2->dn);
864 list->count = list2->count;
866 if (list_intersect(ldb, list, list2) == -1) {
868 return LDB_ERR_OPERATIONS_ERROR;
874 if (list->count == 0) {
875 talloc_free(list->dn);
876 return LDB_ERR_NO_SUCH_OBJECT;
879 if (list->count == 1) {
880 /* it isn't worth loading the next part of the tree */
889 AND index results and ONE level special index
891 static int ltdb_index_dn_one(struct ldb_module *module,
892 struct ldb_dn *parent_dn,
893 struct dn_list *list)
895 struct ldb_context *ldb;
896 struct dn_list *list2;
897 struct ldb_message *msg;
903 ldb = ldb_module_get_ctx(module);
905 list2 = talloc_zero(module, struct dn_list);
907 return LDB_ERR_OPERATIONS_ERROR;
910 /* the attribute is indexed. Pull the list of DNs that match the
912 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn));
913 val.length = strlen((char *)val.data);
914 key = ltdb_index_key(ldb, LTDB_IDXONE, &val, NULL);
917 return LDB_ERR_OPERATIONS_ERROR;
920 msg = talloc(list2, struct ldb_message);
923 return LDB_ERR_OPERATIONS_ERROR;
926 ret = ltdb_search_dn1_index(module, key, msg);
928 if (ret != LDB_SUCCESS) {
932 for (i = 0; i < msg->num_elements; i++) {
933 struct ldb_message_element *el;
935 if (strcmp(msg->elements[i].name, LTDB_IDX) != 0) {
939 el = &msg->elements[i];
941 list2->dn = talloc_array(list2, char *, el->num_values);
944 return LDB_ERR_OPERATIONS_ERROR;
947 for (j = 0; j < el->num_values; j++) {
948 list2->dn[list2->count] = talloc_strdup(list2->dn, (char *)el->values[j].data);
949 if (!list2->dn[list2->count]) {
951 return LDB_ERR_OPERATIONS_ERROR;
957 if (list2->count == 0) {
959 return LDB_ERR_NO_SUCH_OBJECT;
962 if (list2->count > 1) {
963 qsort(list2->dn, list2->count, sizeof(char *), (comparison_fn_t) list_cmp);
966 if (list->count > 0) {
967 if (list_intersect(ldb, list, list2) == -1) {
969 return LDB_ERR_OPERATIONS_ERROR;
972 if (list->count == 0) {
973 talloc_free(list->dn);
975 return LDB_ERR_NO_SUCH_OBJECT;
978 list->dn = talloc_move(list, &list2->dn);
979 list->count = list2->count;
988 return a list of dn's that might match a indexed search or
989 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
991 static int ltdb_index_dn(struct ldb_module *module,
992 const struct ldb_parse_tree *tree,
993 const struct ldb_message *index_list,
994 struct dn_list *list)
996 int ret = LDB_ERR_OPERATIONS_ERROR;
998 switch (tree->operation) {
1000 ret = ltdb_index_dn_and(module, tree, index_list, list);
1004 ret = ltdb_index_dn_or(module, tree, index_list, list);
1008 ret = ltdb_index_dn_not(module, tree, index_list, list);
1011 case LDB_OP_EQUALITY:
1012 ret = ltdb_index_dn_leaf(module, tree, index_list, list);
1015 case LDB_OP_SUBSTRING:
1016 case LDB_OP_GREATER:
1018 case LDB_OP_PRESENT:
1020 case LDB_OP_EXTENDED:
1021 /* we can't index with fancy bitops yet */
1022 ret = LDB_ERR_OPERATIONS_ERROR;
1030 filter a candidate dn_list from an indexed search into a set of results
1031 extracting just the given attributes
1033 static int ltdb_index_filter(const struct dn_list *dn_list,
1034 struct ltdb_context *ac,
1035 uint32_t *match_count)
1037 struct ldb_context *ldb;
1038 struct ldb_message *msg;
1041 ldb = ldb_module_get_ctx(ac->module);
1043 for (i = 0; i < dn_list->count; i++) {
1047 msg = ldb_msg_new(ac);
1049 return LDB_ERR_OPERATIONS_ERROR;
1052 dn = ldb_dn_new(msg, ldb, dn_list->dn[i]);
1055 return LDB_ERR_OPERATIONS_ERROR;
1058 ret = ltdb_search_dn1(ac->module, dn, msg);
1060 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1061 /* the record has disappeared? yes, this can happen */
1066 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1067 /* an internal error */
1069 return LDB_ERR_OPERATIONS_ERROR;
1072 if (!ldb_match_msg(ldb, msg,
1073 ac->tree, ac->base, ac->scope)) {
1078 /* filter the attributes that the user wants */
1079 ret = ltdb_filter_attrs(msg, ac->attrs);
1083 return LDB_ERR_OPERATIONS_ERROR;
1086 ret = ldb_module_send_entry(ac->req, msg, NULL);
1087 if (ret != LDB_SUCCESS) {
1088 ac->request_terminated = true;
1099 search the database with a LDAP-like expression using indexes
1100 returns -1 if an indexed search is not possible, in which
1101 case the caller should call ltdb_search_full()
1103 int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
1105 struct ldb_context *ldb;
1106 void *data = ldb_module_get_private(ac->module);
1107 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1108 struct dn_list *dn_list;
1109 int ret, idxattr, idxone;
1111 ldb = ldb_module_get_ctx(ac->module);
1113 idxattr = idxone = 0;
1114 ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXATTR);
1119 /* We do one level indexing only if requested */
1120 ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXONE);
1125 if ((ac->scope == LDB_SCOPE_ONELEVEL && (idxattr+idxone == 0)) ||
1126 (ac->scope == LDB_SCOPE_SUBTREE && idxattr == 0)) {
1127 /* no indexes? must do full search */
1128 return LDB_ERR_OPERATIONS_ERROR;
1131 ret = LDB_ERR_OPERATIONS_ERROR;
1133 dn_list = talloc_zero(ac, struct dn_list);
1134 if (dn_list == NULL) {
1135 return LDB_ERR_OPERATIONS_ERROR;
1138 if (ac->scope == LDB_SCOPE_BASE) {
1139 /* with BASE searches only one DN can match */
1140 dn_list->dn = talloc_array(dn_list, char *, 1);
1141 if (dn_list->dn == NULL) {
1143 return LDB_ERR_OPERATIONS_ERROR;
1145 dn_list->dn[0] = ldb_dn_alloc_linearized(dn_list, ac->base);
1146 if (dn_list->dn[0] == NULL) {
1148 return LDB_ERR_OPERATIONS_ERROR;
1154 if (ac->scope != LDB_SCOPE_BASE && idxattr == 1) {
1155 ret = ltdb_index_dn(ac->module, ac->tree, ltdb->cache->indexlist, dn_list);
1158 if (ret == LDB_ERR_OPERATIONS_ERROR &&
1159 ac->scope == LDB_SCOPE_ONELEVEL && idxone == 1) {
1160 ret = ltdb_index_dn_one(ac->module, ac->base, dn_list);
1163 if (ret == LDB_SUCCESS) {
1164 /* we've got a candidate list - now filter by the full tree
1165 and extract the needed attributes */
1166 ret = ltdb_index_filter(dn_list, ac, match_count);
1169 talloc_free(dn_list);
1175 add a index element where this is the first indexed DN for this value
1177 static int ltdb_index_add1_new(struct ldb_context *ldb,
1178 struct ldb_message *msg,
1181 struct ldb_message_element *el;
1183 /* add another entry */
1184 el = talloc_realloc(msg, msg->elements,
1185 struct ldb_message_element, msg->num_elements+1);
1187 return LDB_ERR_OPERATIONS_ERROR;
1191 msg->elements[msg->num_elements].name = talloc_strdup(msg->elements, LTDB_IDX);
1192 if (!msg->elements[msg->num_elements].name) {
1193 return LDB_ERR_OPERATIONS_ERROR;
1195 msg->elements[msg->num_elements].num_values = 0;
1196 msg->elements[msg->num_elements].values = talloc(msg->elements, struct ldb_val);
1197 if (!msg->elements[msg->num_elements].values) {
1198 return LDB_ERR_OPERATIONS_ERROR;
1200 msg->elements[msg->num_elements].values[0].length = strlen(dn);
1201 msg->elements[msg->num_elements].values[0].data = discard_const_p(uint8_t, dn);
1202 msg->elements[msg->num_elements].num_values = 1;
1203 msg->num_elements++;
1210 add a index element where this is not the first indexed DN for this
1213 static int ltdb_index_add1_add(struct ldb_context *ldb,
1214 struct ldb_message *msg,
1217 const struct ldb_schema_attribute *a)
1222 /* for multi-valued attributes we can end up with repeats */
1223 for (i=0;i<msg->elements[idx].num_values;i++) {
1224 if (strcmp(dn, (char *)msg->elements[idx].values[i].data) == 0) {
1229 if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
1230 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1233 v2 = talloc_realloc(msg->elements, msg->elements[idx].values,
1235 msg->elements[idx].num_values+1);
1237 return LDB_ERR_OPERATIONS_ERROR;
1239 msg->elements[idx].values = v2;
1241 msg->elements[idx].values[msg->elements[idx].num_values].length = strlen(dn);
1242 msg->elements[idx].values[msg->elements[idx].num_values].data = discard_const_p(uint8_t, dn);
1243 msg->elements[idx].num_values++;
1249 add an index entry for one message element
1251 static int ltdb_index_add1(struct ldb_module *module, const char *dn,
1252 struct ldb_message_element *el, int v_idx)
1254 struct ldb_context *ldb;
1255 struct ldb_message *msg;
1256 struct ldb_dn *dn_key;
1259 const struct ldb_schema_attribute *a;
1261 ldb = ldb_module_get_ctx(module);
1263 msg = talloc(module, struct ldb_message);
1266 return LDB_ERR_OPERATIONS_ERROR;
1269 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], &a);
1272 return LDB_ERR_OPERATIONS_ERROR;
1274 talloc_steal(msg, dn_key);
1276 ret = ltdb_search_dn1_index(module, dn_key, msg);
1277 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1282 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1284 msg->num_elements = 0;
1285 msg->elements = NULL;
1288 for (i=0;i<msg->num_elements;i++) {
1289 if (strcmp(LTDB_IDX, msg->elements[i].name) == 0) {
1294 if (i == msg->num_elements) {
1295 ret = ltdb_index_add1_new(ldb, msg, dn);
1297 ret = ltdb_index_add1_add(ldb, msg, i, dn, a);
1300 if (ret == LDB_SUCCESS) {
1301 ret = ltdb_store_idxptr(module, msg, TDB_REPLACE);
1309 static int ltdb_index_add0(struct ldb_module *module, const char *dn,
1310 struct ldb_message_element *elements, int num_el)
1312 void *data = ldb_module_get_private(module);
1313 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1321 if (ltdb->cache->indexlist->num_elements == 0) {
1322 /* no indexed fields */
1326 for (i = 0; i < num_el; i++) {
1327 ret = ldb_msg_find_idx(ltdb->cache->indexlist, elements[i].name,
1328 NULL, LTDB_IDXATTR);
1332 for (j = 0; j < elements[i].num_values; j++) {
1333 ret = ltdb_index_add1(module, dn, &elements[i], j);
1334 if (ret != LDB_SUCCESS) {
1344 add the index entries for a new record
1346 int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg)
1351 dn = ldb_dn_get_linearized(msg->dn);
1353 return LDB_ERR_OPERATIONS_ERROR;
1356 ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements);
1363 delete an index entry for one message element
1365 int ltdb_index_del_value(struct ldb_module *module, const char *dn,
1366 struct ldb_message_element *el, int v_idx)
1368 struct ldb_context *ldb;
1369 struct ldb_message *msg;
1370 struct ldb_dn *dn_key;
1374 ldb = ldb_module_get_ctx(module);
1380 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], NULL);
1382 return LDB_ERR_OPERATIONS_ERROR;
1385 msg = talloc(dn_key, struct ldb_message);
1387 talloc_free(dn_key);
1388 return LDB_ERR_OPERATIONS_ERROR;
1391 ret = ltdb_search_dn1_index(module, dn_key, msg);
1392 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1393 talloc_free(dn_key);
1397 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1398 /* it wasn't indexed. Did we have an earlier error? If we did then
1400 talloc_free(dn_key);
1404 i = ldb_msg_find_idx(msg, dn, &j, LTDB_IDX);
1406 struct ldb_ldif ldif;
1408 ldif.changetype = LDB_CHANGETYPE_NONE;
1410 ldif_string = ldb_ldif_write_string(ldb, NULL, &ldif);
1411 ldb_debug(ldb, LDB_DEBUG_ERROR,
1412 "ERROR: dn %s not found in %s", dn,
1414 talloc_free(ldif_string);
1415 /* it ain't there. hmmm */
1416 talloc_free(dn_key);
1420 if (j != msg->elements[i].num_values - 1) {
1421 memmove(&msg->elements[i].values[j],
1422 &msg->elements[i].values[j+1],
1423 (msg->elements[i].num_values-(j+1)) *
1424 sizeof(msg->elements[i].values[0]));
1426 msg->elements[i].num_values--;
1428 if (msg->elements[i].num_values == 0) {
1429 ret = ltdb_delete_noindex(module, dn_key);
1431 ret = ltdb_store_idxptr(module, msg, TDB_REPLACE);
1434 talloc_free(dn_key);
1440 delete the index entries for a record
1441 return -1 on failure
1443 int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg)
1445 void *data = ldb_module_get_private(module);
1446 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1451 /* find the list of indexed fields */
1452 if (ltdb->cache->indexlist->num_elements == 0) {
1453 /* no indexed fields */
1457 if (ldb_dn_is_special(msg->dn)) {
1461 dn = ldb_dn_get_linearized(msg->dn);
1463 return LDB_ERR_OPERATIONS_ERROR;
1466 for (i = 0; i < msg->num_elements; i++) {
1467 ret = ldb_msg_find_idx(ltdb->cache->indexlist, msg->elements[i].name,
1468 NULL, LTDB_IDXATTR);
1472 for (j = 0; j < msg->elements[i].num_values; j++) {
1473 ret = ltdb_index_del_value(module, dn, &msg->elements[i], j);
1474 if (ret != LDB_SUCCESS) {
1484 handle special index for one level searches
1486 int ltdb_index_one(struct ldb_module *module, const struct ldb_message *msg, int add)
1488 void *data = ldb_module_get_private(module);
1489 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1490 struct ldb_message_element el;
1496 if (ldb_dn_is_special(msg->dn)) {
1500 /* We index for ONE Level only if requested */
1501 ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXONE);
1506 pdn = ldb_dn_get_parent(module, msg->dn);
1508 return LDB_ERR_OPERATIONS_ERROR;
1511 dn = ldb_dn_get_linearized(msg->dn);
1514 return LDB_ERR_OPERATIONS_ERROR;
1517 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn));
1518 if (val.data == NULL) {
1520 return LDB_ERR_OPERATIONS_ERROR;
1523 val.length = strlen((char *)val.data);
1524 el.name = LTDB_IDXONE;
1529 ret = ltdb_index_add1(module, dn, &el, 0);
1530 } else { /* delete */
1531 ret = ltdb_index_del_value(module, dn, &el, 0);
1541 traversal function that deletes all @INDEX records
1543 static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1545 const char *dn = "DN=" LTDB_INDEX ":";
1546 if (strncmp((char *)key.dptr, dn, strlen(dn)) == 0) {
1547 return tdb_delete(tdb, key);
1553 traversal function that adds @INDEX records during a re index
1555 static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1557 struct ldb_context *ldb;
1558 struct ldb_module *module = (struct ldb_module *)state;
1559 struct ldb_message *msg;
1560 const char *dn = NULL;
1564 ldb = ldb_module_get_ctx(module);
1566 if (strncmp((char *)key.dptr, "DN=@", 4) == 0 ||
1567 strncmp((char *)key.dptr, "DN=", 3) != 0) {
1571 msg = talloc(module, struct ldb_message);
1576 ret = ltdb_unpack_data(module, &data, msg);
1578 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
1579 ldb_dn_get_linearized(msg->dn));
1584 /* check if the DN key has changed, perhaps due to the
1585 case insensitivity of an element changing */
1586 key2 = ltdb_key(module, msg->dn);
1587 if (key2.dptr == NULL) {
1588 /* probably a corrupt record ... darn */
1589 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s",
1590 ldb_dn_get_linearized(msg->dn));
1594 if (strcmp((char *)key2.dptr, (char *)key.dptr) != 0) {
1595 tdb_delete(tdb, key);
1596 tdb_store(tdb, key2, data, 0);
1598 talloc_free(key2.dptr);
1600 if (msg->dn == NULL) {
1601 dn = (char *)key.dptr + 3;
1603 dn = ldb_dn_get_linearized(msg->dn);
1606 ret = ltdb_index_one(module, msg, 1);
1607 if (ret == LDB_SUCCESS) {
1608 ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements);
1610 ldb_debug(ldb, LDB_DEBUG_ERROR,
1611 "Adding special ONE LEVEL index failed (%s)!",
1612 ldb_dn_get_linearized(msg->dn));
1617 if (ret != LDB_SUCCESS) return -1;
1623 force a complete reindex of the database
1625 int ltdb_reindex(struct ldb_module *module)
1627 void *data = ldb_module_get_private(module);
1628 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1631 if (ltdb_cache_reload(module) != 0) {
1632 return LDB_ERR_OPERATIONS_ERROR;
1635 /* first traverse the database deleting any @INDEX records */
1636 ret = tdb_traverse(ltdb->tdb, delete_index, NULL);
1638 return LDB_ERR_OPERATIONS_ERROR;
1641 /* if we don't have indexes we have nothing todo */
1642 if (ltdb->cache->indexlist->num_elements == 0) {
1646 /* now traverse adding any indexes for normal LDB records */
1647 ret = tdb_traverse(ltdb->tdb, re_index, module);
1649 return LDB_ERR_OPERATIONS_ERROR;
1653 ltdb->idxptr->repack = true;