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 char *base_p = (const char *)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 /* the following cast looks strange, but is
387 correct. The key to understanding it is that base_p
388 is a pointer to an array of pointers, so we have to
389 dereference it after casting to void **. The strange
390 const in the middle gives us the right type of pointer
391 after the dereference (tridge) */
392 r = comp_fn(needle, *(void * const *)(base_p + (size * test_i)));
394 /* scan back for first element */
396 comp_fn(needle, *(void * const *)(base_p + (size * (test_i-1)))) == 0) {
412 if (comp_fn(needle, *(void * const *)(base_p + (size * min_i))) == 0) {
425 return the dn key to be used for an index
428 static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
429 const char *attr, const struct ldb_val *value)
433 const struct ldb_schema_attribute *a;
437 attr_folded = ldb_attr_casefold(ldb, attr);
442 a = ldb_schema_attribute_by_name(ldb, attr);
443 r = a->syntax->canonicalise_fn(ldb, ldb, value, &v);
444 if (r != LDB_SUCCESS) {
445 const char *errstr = ldb_errstring(ldb);
446 /* canonicalisation can be refused. For example,
447 a attribute that takes wildcards will refuse to canonicalise
448 if the value contains a wildcard */
449 ldb_asprintf_errstring(ldb, "Failed to create index key for attribute '%s':%s%s%s",
450 attr, ldb_strerror(r), (errstr?":":""), (errstr?errstr:""));
451 talloc_free(attr_folded);
454 if (ldb_should_b64_encode(&v)) {
455 char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length);
456 if (!vstr) return NULL;
457 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr);
460 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s:%.*s", LTDB_INDEX, attr_folded, (int)v.length, (char *)v.data);
463 if (v.data != value->data) {
466 talloc_free(attr_folded);
472 see if a attribute value is in the list of indexed attributes
474 static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr,
475 unsigned int *v_idx, const char *key)
478 for (i=0;i<msg->num_elements;i++) {
479 if (ldb_attr_cmp(msg->elements[i].name, key) == 0) {
480 const struct ldb_message_element *el = &msg->elements[i];
483 /* in this case we are just looking to see if key is present,
484 we are not spearching for a specific index */
488 for (j=0;j<el->num_values;j++) {
489 if (ldb_attr_cmp((char *)el->values[j].data, attr) == 0) {
501 /* used in sorting dn lists */
502 static int list_cmp(const char **s1, const char **s2)
504 return strcmp(*s1, *s2);
508 return a list of dn's that might match a simple indexed search or
510 static int ltdb_index_dn_simple(struct ldb_module *module,
511 const struct ldb_parse_tree *tree,
512 const struct ldb_message *index_list,
513 struct dn_list *list)
515 struct ldb_context *ldb;
519 struct ldb_message *msg;
521 ldb = ldb_module_get_ctx(module);
526 /* if the attribute isn't in the list of indexed attributes then
527 this node needs a full search */
528 if (ldb_msg_find_idx(index_list, tree->u.equality.attr, NULL, LTDB_IDXATTR) == -1) {
529 return LDB_ERR_OPERATIONS_ERROR;
532 /* the attribute is indexed. Pull the list of DNs that match the
534 dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value);
535 if (!dn) return LDB_ERR_OPERATIONS_ERROR;
537 msg = talloc(list, struct ldb_message);
539 return LDB_ERR_OPERATIONS_ERROR;
542 ret = ltdb_search_dn1_index(module, dn, msg);
544 if (ret != LDB_SUCCESS) {
548 for (i=0;i<msg->num_elements;i++) {
549 struct ldb_message_element *el;
551 if (strcmp(msg->elements[i].name, LTDB_IDX) != 0) {
555 el = &msg->elements[i];
557 list->dn = talloc_array(list, char *, el->num_values);
560 return LDB_ERR_OPERATIONS_ERROR;
563 for (j=0;j<el->num_values;j++) {
564 list->dn[list->count] =
565 talloc_strdup(list->dn, (char *)el->values[j].data);
566 if (!list->dn[list->count]) {
568 return LDB_ERR_OPERATIONS_ERROR;
576 if (list->count > 1) {
577 qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t) list_cmp);
584 static int list_union(struct ldb_context *, struct dn_list *, const struct dn_list *);
587 return a list of dn's that might match a leaf indexed search
589 static int ltdb_index_dn_leaf(struct ldb_module *module,
590 const struct ldb_parse_tree *tree,
591 const struct ldb_message *index_list,
592 struct dn_list *list)
594 struct ldb_context *ldb;
595 ldb = ldb_module_get_ctx(module);
597 if (ldb_attr_dn(tree->u.equality.attr) == 0) {
598 list->dn = talloc_array(list, char *, 1);
599 if (list->dn == NULL) {
601 return LDB_ERR_OPERATIONS_ERROR;
603 list->dn[0] = talloc_strdup(list->dn, (char *)tree->u.equality.value.data);
604 if (list->dn[0] == NULL) {
606 return LDB_ERR_OPERATIONS_ERROR;
611 return ltdb_index_dn_simple(module, tree, index_list, list);
618 relies on the lists being sorted
620 static int list_intersect(struct ldb_context *ldb,
621 struct dn_list *list, const struct dn_list *list2)
623 struct dn_list *list3;
626 if (list->count == 0 || list2->count == 0) {
628 return LDB_ERR_NO_SUCH_OBJECT;
631 list3 = talloc(ldb, struct dn_list);
633 return LDB_ERR_OPERATIONS_ERROR;
636 list3->dn = talloc_array(list3, char *, list->count);
639 return LDB_ERR_OPERATIONS_ERROR;
643 for (i=0;i<list->count;i++) {
644 if (ldb_list_find(list->dn[i], list2->dn, list2->count,
645 sizeof(char *), (comparison_fn_t)strcmp) != -1) {
646 list3->dn[list3->count] = talloc_move(list3->dn, &list->dn[i]);
649 talloc_free(list->dn[i]);
653 talloc_free(list->dn);
654 list->dn = talloc_move(list, &list3->dn);
655 list->count = list3->count;
658 return LDB_ERR_NO_SUCH_OBJECT;
665 relies on the lists being sorted
667 static int list_union(struct ldb_context *ldb,
668 struct dn_list *list, const struct dn_list *list2)
672 unsigned int count = list->count;
674 if (list->count == 0 && list2->count == 0) {
676 return LDB_ERR_NO_SUCH_OBJECT;
679 d = talloc_realloc(list, list->dn, char *, list->count + list2->count);
681 return LDB_ERR_OPERATIONS_ERROR;
685 for (i=0;i<list2->count;i++) {
686 if (ldb_list_find(list2->dn[i], list->dn, count,
687 sizeof(char *), (comparison_fn_t)strcmp) == -1) {
688 list->dn[list->count] = talloc_strdup(list->dn, list2->dn[i]);
689 if (!list->dn[list->count]) {
690 return LDB_ERR_OPERATIONS_ERROR;
696 if (list->count != count) {
697 qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t)list_cmp);
700 return LDB_ERR_NO_SUCH_OBJECT;
703 static int ltdb_index_dn(struct ldb_module *module,
704 const struct ldb_parse_tree *tree,
705 const struct ldb_message *index_list,
706 struct dn_list *list);
712 static int ltdb_index_dn_or(struct ldb_module *module,
713 const struct ldb_parse_tree *tree,
714 const struct ldb_message *index_list,
715 struct dn_list *list)
717 struct ldb_context *ldb;
721 ldb = ldb_module_get_ctx(module);
723 ret = LDB_ERR_OPERATIONS_ERROR;
727 for (i=0;i<tree->u.list.num_elements;i++) {
728 struct dn_list *list2;
731 list2 = talloc(module, struct dn_list);
733 return LDB_ERR_OPERATIONS_ERROR;
736 v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2);
738 if (v == LDB_ERR_NO_SUCH_OBJECT) {
740 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
747 if (v != LDB_SUCCESS && v != LDB_ERR_NO_SUCH_OBJECT) {
749 talloc_free(list->dn);
754 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
756 list->dn = talloc_move(list, &list2->dn);
757 list->count = list2->count;
759 if (list_union(ldb, list, list2) == -1) {
761 return LDB_ERR_OPERATIONS_ERROR;
768 if (list->count == 0) {
769 return LDB_ERR_NO_SUCH_OBJECT;
779 static int ltdb_index_dn_not(struct ldb_module *module,
780 const struct ldb_parse_tree *tree,
781 const struct ldb_message *index_list,
782 struct dn_list *list)
784 /* the only way to do an indexed not would be if we could
785 negate the not via another not or if we knew the total
786 number of database elements so we could know that the
787 existing expression covered the whole database.
789 instead, we just give up, and rely on a full index scan
790 (unless an outer & manages to reduce the list)
792 return LDB_ERR_OPERATIONS_ERROR;
796 AND two index results
798 static int ltdb_index_dn_and(struct ldb_module *module,
799 const struct ldb_parse_tree *tree,
800 const struct ldb_message *index_list,
801 struct dn_list *list)
803 struct ldb_context *ldb;
807 ldb = ldb_module_get_ctx(module);
809 ret = LDB_ERR_OPERATIONS_ERROR;
813 for (i=0;i<tree->u.list.num_elements;i++) {
814 struct dn_list *list2;
817 list2 = talloc(module, struct dn_list);
819 return LDB_ERR_OPERATIONS_ERROR;
822 v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2);
824 if (v == LDB_ERR_NO_SUCH_OBJECT) {
826 talloc_free(list->dn);
828 return LDB_ERR_NO_SUCH_OBJECT;
831 if (v != LDB_SUCCESS && v != LDB_ERR_NO_SUCH_OBJECT) {
836 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
838 talloc_free(list->dn);
839 list->dn = talloc_move(list, &list2->dn);
840 list->count = list2->count;
842 if (list_intersect(ldb, list, list2) == -1) {
844 return LDB_ERR_OPERATIONS_ERROR;
850 if (list->count == 0) {
851 talloc_free(list->dn);
852 return LDB_ERR_NO_SUCH_OBJECT;
860 AND index results and ONE level special index
862 static int ltdb_index_dn_one(struct ldb_module *module,
863 struct ldb_dn *parent_dn,
864 struct dn_list *list)
866 struct ldb_context *ldb;
867 struct dn_list *list2;
868 struct ldb_message *msg;
874 ldb = ldb_module_get_ctx(module);
876 list2 = talloc_zero(module, struct dn_list);
878 return LDB_ERR_OPERATIONS_ERROR;
881 /* the attribute is indexed. Pull the list of DNs that match the
883 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn));
884 val.length = strlen((char *)val.data);
885 key = ltdb_index_key(ldb, LTDB_IDXONE, &val);
888 return LDB_ERR_OPERATIONS_ERROR;
891 msg = talloc(list2, struct ldb_message);
894 return LDB_ERR_OPERATIONS_ERROR;
897 ret = ltdb_search_dn1_index(module, key, msg);
899 if (ret != LDB_SUCCESS) {
903 for (i = 0; i < msg->num_elements; i++) {
904 struct ldb_message_element *el;
906 if (strcmp(msg->elements[i].name, LTDB_IDX) != 0) {
910 el = &msg->elements[i];
912 list2->dn = talloc_array(list2, char *, el->num_values);
915 return LDB_ERR_OPERATIONS_ERROR;
918 for (j = 0; j < el->num_values; j++) {
919 list2->dn[list2->count] = talloc_strdup(list2->dn, (char *)el->values[j].data);
920 if (!list2->dn[list2->count]) {
922 return LDB_ERR_OPERATIONS_ERROR;
928 if (list2->count == 0) {
930 return LDB_ERR_NO_SUCH_OBJECT;
933 if (list2->count > 1) {
934 qsort(list2->dn, list2->count, sizeof(char *), (comparison_fn_t) list_cmp);
937 if (list->count > 0) {
938 if (list_intersect(ldb, list, list2) == -1) {
940 return LDB_ERR_OPERATIONS_ERROR;
943 if (list->count == 0) {
944 talloc_free(list->dn);
946 return LDB_ERR_NO_SUCH_OBJECT;
949 list->dn = talloc_move(list, &list2->dn);
950 list->count = list2->count;
959 return a list of dn's that might match a indexed search or
960 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
962 static int ltdb_index_dn(struct ldb_module *module,
963 const struct ldb_parse_tree *tree,
964 const struct ldb_message *index_list,
965 struct dn_list *list)
967 int ret = LDB_ERR_OPERATIONS_ERROR;
969 switch (tree->operation) {
971 ret = ltdb_index_dn_and(module, tree, index_list, list);
975 ret = ltdb_index_dn_or(module, tree, index_list, list);
979 ret = ltdb_index_dn_not(module, tree, index_list, list);
982 case LDB_OP_EQUALITY:
983 ret = ltdb_index_dn_leaf(module, tree, index_list, list);
986 case LDB_OP_SUBSTRING:
991 case LDB_OP_EXTENDED:
992 /* we can't index with fancy bitops yet */
993 ret = LDB_ERR_OPERATIONS_ERROR;
1001 filter a candidate dn_list from an indexed search into a set of results
1002 extracting just the given attributes
1004 static int ltdb_index_filter(const struct dn_list *dn_list,
1005 struct ltdb_context *ac)
1007 struct ldb_context *ldb;
1008 struct ldb_message *msg;
1011 ldb = ldb_module_get_ctx(ac->module);
1013 for (i = 0; i < dn_list->count; i++) {
1017 msg = ldb_msg_new(ac);
1019 return LDB_ERR_OPERATIONS_ERROR;
1022 dn = ldb_dn_new(msg, ldb, dn_list->dn[i]);
1025 return LDB_ERR_OPERATIONS_ERROR;
1028 ret = ltdb_search_dn1(ac->module, dn, msg);
1030 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1031 /* the record has disappeared? yes, this can happen */
1036 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1037 /* an internal error */
1039 return LDB_ERR_OPERATIONS_ERROR;
1042 if (!ldb_match_msg(ldb, msg,
1043 ac->tree, ac->base, ac->scope)) {
1048 /* filter the attributes that the user wants */
1049 ret = ltdb_filter_attrs(msg, ac->attrs);
1053 return LDB_ERR_OPERATIONS_ERROR;
1056 ret = ldb_module_send_entry(ac->req, msg, NULL);
1057 if (ret != LDB_SUCCESS) {
1058 ac->request_terminated = true;
1067 search the database with a LDAP-like expression using indexes
1068 returns -1 if an indexed search is not possible, in which
1069 case the caller should call ltdb_search_full()
1071 int ltdb_search_indexed(struct ltdb_context *ac)
1073 struct ldb_context *ldb;
1074 void *data = ldb_module_get_private(ac->module);
1075 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1076 struct dn_list *dn_list;
1077 int ret, idxattr, idxone;
1079 ldb = ldb_module_get_ctx(ac->module);
1081 idxattr = idxone = 0;
1082 ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXATTR);
1087 /* We do one level indexing only if requested */
1088 ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXONE);
1093 if ((ac->scope == LDB_SCOPE_ONELEVEL && (idxattr+idxone == 0)) ||
1094 (ac->scope == LDB_SCOPE_SUBTREE && idxattr == 0)) {
1095 /* no indexes? must do full search */
1096 return LDB_ERR_OPERATIONS_ERROR;
1099 ret = LDB_ERR_OPERATIONS_ERROR;
1101 dn_list = talloc_zero(ac, struct dn_list);
1102 if (dn_list == NULL) {
1103 return LDB_ERR_OPERATIONS_ERROR;
1106 if (ac->scope == LDB_SCOPE_BASE) {
1107 /* with BASE searches only one DN can match */
1108 dn_list->dn = talloc_array(dn_list, char *, 1);
1109 if (dn_list->dn == NULL) {
1111 return LDB_ERR_OPERATIONS_ERROR;
1113 dn_list->dn[0] = ldb_dn_alloc_linearized(dn_list, ac->base);
1114 if (dn_list->dn[0] == NULL) {
1116 return LDB_ERR_OPERATIONS_ERROR;
1122 if (ac->scope != LDB_SCOPE_BASE && idxattr == 1) {
1123 ret = ltdb_index_dn(ac->module, ac->tree, ltdb->cache->indexlist, dn_list);
1125 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1126 talloc_free(dn_list);
1131 if (ac->scope == LDB_SCOPE_ONELEVEL && idxone == 1) {
1132 ret = ltdb_index_dn_one(ac->module, ac->base, dn_list);
1135 if (ret == LDB_SUCCESS) {
1136 /* we've got a candidate list - now filter by the full tree
1137 and extract the needed attributes */
1138 ret = ltdb_index_filter(dn_list, ac);
1141 talloc_free(dn_list);
1147 add a index element where this is the first indexed DN for this value
1149 static int ltdb_index_add1_new(struct ldb_context *ldb,
1150 struct ldb_message *msg,
1153 struct ldb_message_element *el;
1155 /* add another entry */
1156 el = talloc_realloc(msg, msg->elements,
1157 struct ldb_message_element, msg->num_elements+1);
1159 return LDB_ERR_OPERATIONS_ERROR;
1163 msg->elements[msg->num_elements].name = talloc_strdup(msg->elements, LTDB_IDX);
1164 if (!msg->elements[msg->num_elements].name) {
1165 return LDB_ERR_OPERATIONS_ERROR;
1167 msg->elements[msg->num_elements].num_values = 0;
1168 msg->elements[msg->num_elements].values = talloc(msg->elements, struct ldb_val);
1169 if (!msg->elements[msg->num_elements].values) {
1170 return LDB_ERR_OPERATIONS_ERROR;
1172 msg->elements[msg->num_elements].values[0].length = strlen(dn);
1173 msg->elements[msg->num_elements].values[0].data = discard_const_p(uint8_t, dn);
1174 msg->elements[msg->num_elements].num_values = 1;
1175 msg->num_elements++;
1182 add a index element where this is not the first indexed DN for this
1185 static int ltdb_index_add1_add(struct ldb_context *ldb,
1186 struct ldb_message *msg,
1193 /* for multi-valued attributes we can end up with repeats */
1194 for (i=0;i<msg->elements[idx].num_values;i++) {
1195 if (strcmp(dn, (char *)msg->elements[idx].values[i].data) == 0) {
1200 v2 = talloc_realloc(msg->elements, msg->elements[idx].values,
1202 msg->elements[idx].num_values+1);
1204 return LDB_ERR_OPERATIONS_ERROR;
1206 msg->elements[idx].values = v2;
1208 msg->elements[idx].values[msg->elements[idx].num_values].length = strlen(dn);
1209 msg->elements[idx].values[msg->elements[idx].num_values].data = discard_const_p(uint8_t, dn);
1210 msg->elements[idx].num_values++;
1216 add an index entry for one message element
1218 static int ltdb_index_add1(struct ldb_module *module, const char *dn,
1219 struct ldb_message_element *el, int v_idx)
1221 struct ldb_context *ldb;
1222 struct ldb_message *msg;
1223 struct ldb_dn *dn_key;
1227 ldb = ldb_module_get_ctx(module);
1229 msg = talloc(module, struct ldb_message);
1232 return LDB_ERR_OPERATIONS_ERROR;
1235 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx]);
1238 return LDB_ERR_OPERATIONS_ERROR;
1240 talloc_steal(msg, dn_key);
1242 ret = ltdb_search_dn1_index(module, dn_key, msg);
1243 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1248 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1250 msg->num_elements = 0;
1251 msg->elements = NULL;
1254 for (i=0;i<msg->num_elements;i++) {
1255 if (strcmp(LTDB_IDX, msg->elements[i].name) == 0) {
1260 if (i == msg->num_elements) {
1261 ret = ltdb_index_add1_new(ldb, msg, dn);
1263 ret = ltdb_index_add1_add(ldb, msg, i, dn);
1266 if (ret == LDB_SUCCESS) {
1267 ret = ltdb_store_idxptr(module, msg, TDB_REPLACE);
1275 static int ltdb_index_add0(struct ldb_module *module, const char *dn,
1276 struct ldb_message_element *elements, int num_el)
1278 void *data = ldb_module_get_private(module);
1279 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1287 if (ltdb->cache->indexlist->num_elements == 0) {
1288 /* no indexed fields */
1292 for (i = 0; i < num_el; i++) {
1293 ret = ldb_msg_find_idx(ltdb->cache->indexlist, elements[i].name,
1294 NULL, LTDB_IDXATTR);
1298 for (j = 0; j < elements[i].num_values; j++) {
1299 ret = ltdb_index_add1(module, dn, &elements[i], j);
1300 if (ret != LDB_SUCCESS) {
1310 add the index entries for a new record
1312 int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg)
1317 dn = ldb_dn_get_linearized(msg->dn);
1319 return LDB_ERR_OPERATIONS_ERROR;
1322 ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements);
1329 delete an index entry for one message element
1331 int ltdb_index_del_value(struct ldb_module *module, const char *dn,
1332 struct ldb_message_element *el, int v_idx)
1334 struct ldb_context *ldb;
1335 struct ldb_message *msg;
1336 struct ldb_dn *dn_key;
1340 ldb = ldb_module_get_ctx(module);
1346 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx]);
1348 return LDB_ERR_OPERATIONS_ERROR;
1351 msg = talloc(dn_key, struct ldb_message);
1353 talloc_free(dn_key);
1354 return LDB_ERR_OPERATIONS_ERROR;
1357 ret = ltdb_search_dn1_index(module, dn_key, msg);
1358 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1359 talloc_free(dn_key);
1363 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1364 /* it wasn't indexed. Did we have an earlier error? If we did then
1366 talloc_free(dn_key);
1370 i = ldb_msg_find_idx(msg, dn, &j, LTDB_IDX);
1372 struct ldb_ldif ldif;
1374 ldb_debug(ldb, LDB_DEBUG_ERROR,
1375 "ERROR: dn %s not found in %s\n", dn,
1376 ldb_dn_get_linearized(dn_key));
1377 ldif.changetype = LDB_CHANGETYPE_NONE;
1379 ldb_ldif_write_file(ldb, stdout, &ldif);
1381 /* it ain't there. hmmm */
1382 talloc_free(dn_key);
1386 if (j != msg->elements[i].num_values - 1) {
1387 memmove(&msg->elements[i].values[j],
1388 &msg->elements[i].values[j+1],
1389 (msg->elements[i].num_values-(j+1)) *
1390 sizeof(msg->elements[i].values[0]));
1392 msg->elements[i].num_values--;
1394 if (msg->elements[i].num_values == 0) {
1395 ret = ltdb_delete_noindex(module, dn_key);
1397 ret = ltdb_store_idxptr(module, msg, TDB_REPLACE);
1400 talloc_free(dn_key);
1406 delete the index entries for a record
1407 return -1 on failure
1409 int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg)
1411 void *data = ldb_module_get_private(module);
1412 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1417 /* find the list of indexed fields */
1418 if (ltdb->cache->indexlist->num_elements == 0) {
1419 /* no indexed fields */
1423 if (ldb_dn_is_special(msg->dn)) {
1427 dn = ldb_dn_get_linearized(msg->dn);
1429 return LDB_ERR_OPERATIONS_ERROR;
1432 for (i = 0; i < msg->num_elements; i++) {
1433 ret = ldb_msg_find_idx(ltdb->cache->indexlist, msg->elements[i].name,
1434 NULL, LTDB_IDXATTR);
1438 for (j = 0; j < msg->elements[i].num_values; j++) {
1439 ret = ltdb_index_del_value(module, dn, &msg->elements[i], j);
1440 if (ret != LDB_SUCCESS) {
1450 handle special index for one level searches
1452 int ltdb_index_one(struct ldb_module *module, const struct ldb_message *msg, int add)
1454 void *data = ldb_module_get_private(module);
1455 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1456 struct ldb_message_element el;
1462 /* We index for ONE Level only if requested */
1463 ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXONE);
1468 pdn = ldb_dn_get_parent(module, msg->dn);
1470 return LDB_ERR_OPERATIONS_ERROR;
1473 dn = ldb_dn_get_linearized(msg->dn);
1476 return LDB_ERR_OPERATIONS_ERROR;
1479 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn));
1480 if (val.data == NULL) {
1482 return LDB_ERR_OPERATIONS_ERROR;
1485 val.length = strlen((char *)val.data);
1486 el.name = LTDB_IDXONE;
1491 ret = ltdb_index_add1(module, dn, &el, 0);
1492 } else { /* delete */
1493 ret = ltdb_index_del_value(module, dn, &el, 0);
1503 traversal function that deletes all @INDEX records
1505 static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1507 const char *dn = "DN=" LTDB_INDEX ":";
1508 if (strncmp((char *)key.dptr, dn, strlen(dn)) == 0) {
1509 return tdb_delete(tdb, key);
1515 traversal function that adds @INDEX records during a re index
1517 static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1519 struct ldb_context *ldb;
1520 struct ldb_module *module = (struct ldb_module *)state;
1521 struct ldb_message *msg;
1522 const char *dn = NULL;
1526 ldb = ldb_module_get_ctx(module);
1528 if (strncmp((char *)key.dptr, "DN=@", 4) == 0 ||
1529 strncmp((char *)key.dptr, "DN=", 3) != 0) {
1533 msg = talloc(module, struct ldb_message);
1538 ret = ltdb_unpack_data(module, &data, msg);
1544 /* check if the DN key has changed, perhaps due to the
1545 case insensitivity of an element changing */
1546 key2 = ltdb_key(module, msg->dn);
1547 if (key2.dptr == NULL) {
1548 /* probably a corrupt record ... darn */
1549 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s\n",
1550 ldb_dn_get_linearized(msg->dn));
1554 if (strcmp((char *)key2.dptr, (char *)key.dptr) != 0) {
1555 tdb_delete(tdb, key);
1556 tdb_store(tdb, key2, data, 0);
1558 talloc_free(key2.dptr);
1560 if (msg->dn == NULL) {
1561 dn = (char *)key.dptr + 3;
1563 dn = ldb_dn_get_linearized(msg->dn);
1566 ret = ltdb_index_one(module, msg, 1);
1567 if (ret == LDB_SUCCESS) {
1568 ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements);
1570 ldb_debug(ldb, LDB_DEBUG_ERROR,
1571 "Adding special ONE LEVEL index failed (%s)!\n",
1572 ldb_dn_get_linearized(msg->dn));
1577 if (ret != LDB_SUCCESS) return -1;
1583 force a complete reindex of the database
1585 int ltdb_reindex(struct ldb_module *module)
1587 void *data = ldb_module_get_private(module);
1588 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
1591 if (ltdb_cache_reload(module) != 0) {
1592 return LDB_ERR_OPERATIONS_ERROR;
1595 /* first traverse the database deleting any @INDEX records */
1596 ret = tdb_traverse(ltdb->tdb, delete_index, NULL);
1598 return LDB_ERR_OPERATIONS_ERROR;
1601 /* if we don't have indexes we have nothing todo */
1602 if (ltdb->cache->indexlist->num_elements == 0) {
1606 /* now traverse adding any indexes for normal LDB records */
1607 ret = tdb_traverse(ltdb->tdb, re_index, module);
1609 return LDB_ERR_OPERATIONS_ERROR;
1613 ltdb->idxptr->repack = true;