ldb_tdb: Provide struct ltdb_private to index routines
[Samba.git] / lib / ldb / ldb_tdb / ldb_index.c
blob6a61c2ea2255efc1be5e33881c57be7290b6bebb
1 /*
2 ldb database library
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
8 ** under the LGPL
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/>.
25 * Name: ldb
27 * Component: ldb tdb backend - indexing
29 * Description: indexing routines for ldb tdb backend
31 * Author: Andrew Tridgell
34 #include "ldb_tdb.h"
35 #include "ldb_private.h"
37 struct dn_list {
38 unsigned int count;
39 struct ldb_val *dn;
42 struct ltdb_idxptr {
43 struct tdb_context *itdb;
44 int error;
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);
57 if (ltdb->idxptr == NULL) {
58 return ldb_oom(ldb_module_get_ctx(module));
61 return LDB_SUCCESS;
64 /* compare two DN entries in a dn_list. Take account of possible
65 * differences in string termination */
66 static int dn_list_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
68 if (v1->length > v2->length && v1->data[v2->length] != 0) {
69 return -1;
71 if (v1->length < v2->length && v2->data[v1->length] != 0) {
72 return 1;
74 return strncmp((char *)v1->data, (char *)v2->data, v1->length);
79 find a entry in a dn_list, using a ldb_val. Uses a case sensitive
80 comparison with the dn returns -1 if not found
82 static int ltdb_dn_list_find_val(struct ltdb_private *ltdb,
83 const struct dn_list *list,
84 const struct ldb_val *v)
86 unsigned int i;
87 for (i=0; i<list->count; i++) {
88 if (dn_list_cmp(&list->dn[i], v) == 0) {
89 return i;
92 return -1;
96 find a entry in a dn_list. Uses a case sensitive comparison with the dn
97 returns -1 if not found
99 static int ltdb_dn_list_find_str(struct ltdb_private *ltdb,
100 struct dn_list *list,
101 const char *dn)
103 struct ldb_val v;
104 v.data = discard_const_p(unsigned char, dn);
105 v.length = strlen(dn);
106 return ltdb_dn_list_find_val(ltdb, list, &v);
110 this is effectively a cast function, but with lots of paranoia
111 checks and also copes with CPUs that are fussy about pointer
112 alignment
114 static struct dn_list *ltdb_index_idxptr(struct ldb_module *module, TDB_DATA rec, bool check_parent)
116 struct dn_list *list;
117 if (rec.dsize != sizeof(void *)) {
118 ldb_asprintf_errstring(ldb_module_get_ctx(module),
119 "Bad data size for idxptr %u", (unsigned)rec.dsize);
120 return NULL;
122 /* note that we can't just use a cast here, as rec.dptr may
123 not be aligned sufficiently for a pointer. A cast would cause
124 platforms like some ARM CPUs to crash */
125 memcpy(&list, rec.dptr, sizeof(void *));
126 list = talloc_get_type(list, struct dn_list);
127 if (list == NULL) {
128 ldb_asprintf_errstring(ldb_module_get_ctx(module),
129 "Bad type '%s' for idxptr",
130 talloc_get_name(list));
131 return NULL;
133 if (check_parent && list->dn && talloc_parent(list->dn) != list) {
134 ldb_asprintf_errstring(ldb_module_get_ctx(module),
135 "Bad parent '%s' for idxptr",
136 talloc_get_name(talloc_parent(list->dn)));
137 return NULL;
139 return list;
143 return the @IDX list in an index entry for a dn as a
144 struct dn_list
146 static int ltdb_dn_list_load(struct ldb_module *module,
147 struct ldb_dn *dn, struct dn_list *list)
149 struct ldb_message *msg;
150 int ret;
151 struct ldb_message_element *el;
152 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
153 TDB_DATA rec;
154 struct dn_list *list2;
155 TDB_DATA key;
157 list->dn = NULL;
158 list->count = 0;
160 /* see if we have any in-memory index entries */
161 if (ltdb->idxptr == NULL ||
162 ltdb->idxptr->itdb == NULL) {
163 goto normal_index;
166 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
167 key.dsize = strlen((char *)key.dptr);
169 rec = tdb_fetch(ltdb->idxptr->itdb, key);
170 if (rec.dptr == NULL) {
171 goto normal_index;
174 /* we've found an in-memory index entry */
175 list2 = ltdb_index_idxptr(module, rec, true);
176 if (list2 == NULL) {
177 free(rec.dptr);
178 return LDB_ERR_OPERATIONS_ERROR;
180 free(rec.dptr);
182 *list = *list2;
183 return LDB_SUCCESS;
185 normal_index:
186 msg = ldb_msg_new(list);
187 if (msg == NULL) {
188 return LDB_ERR_OPERATIONS_ERROR;
191 ret = ltdb_search_dn1(module, dn, msg,
192 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
193 |LDB_UNPACK_DATA_FLAG_NO_DN);
194 if (ret != LDB_SUCCESS) {
195 talloc_free(msg);
196 return ret;
199 /* TODO: check indexing version number */
201 el = ldb_msg_find_element(msg, LTDB_IDX);
202 if (!el) {
203 talloc_free(msg);
204 return LDB_SUCCESS;
208 * we avoid copying the strings by stealing the list. We have
209 * to steal msg onto el->values (which looks odd) because we
210 * asked for the memory to be allocated on msg, not on each
211 * value with LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC above
213 talloc_steal(el->values, msg);
214 list->dn = talloc_steal(list, el->values);
215 list->count = el->num_values;
217 /* We don't need msg->elements any more */
218 talloc_free(msg->elements);
219 return LDB_SUCCESS;
224 save a dn_list into a full @IDX style record
226 static int ltdb_dn_list_store_full(struct ldb_module *module,
227 struct ltdb_private *ltdb,
228 struct ldb_dn *dn,
229 struct dn_list *list)
231 struct ldb_message *msg;
232 int ret;
234 if (list->count == 0) {
235 ret = ltdb_delete_noindex(module, dn);
236 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
237 return LDB_SUCCESS;
239 return ret;
242 msg = ldb_msg_new(module);
243 if (!msg) {
244 return ldb_module_oom(module);
247 ret = ldb_msg_add_fmt(msg, LTDB_IDXVERSION, "%u", LTDB_INDEXING_VERSION);
248 if (ret != LDB_SUCCESS) {
249 talloc_free(msg);
250 return ldb_module_oom(module);
253 msg->dn = dn;
254 if (list->count > 0) {
255 struct ldb_message_element *el;
257 ret = ldb_msg_add_empty(msg, LTDB_IDX, LDB_FLAG_MOD_ADD, &el);
258 if (ret != LDB_SUCCESS) {
259 talloc_free(msg);
260 return ldb_module_oom(module);
262 el->values = list->dn;
263 el->num_values = list->count;
266 ret = ltdb_store(module, msg, TDB_REPLACE);
267 talloc_free(msg);
268 return ret;
272 save a dn_list into the database, in either @IDX or internal format
274 static int ltdb_dn_list_store(struct ldb_module *module, struct ldb_dn *dn,
275 struct dn_list *list)
277 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
278 TDB_DATA rec, key;
279 int ret;
280 struct dn_list *list2;
282 if (ltdb->idxptr == NULL) {
283 return ltdb_dn_list_store_full(module, ltdb,
284 dn, list);
287 if (ltdb->idxptr->itdb == NULL) {
288 ltdb->idxptr->itdb = tdb_open(NULL, 1000, TDB_INTERNAL, O_RDWR, 0);
289 if (ltdb->idxptr->itdb == NULL) {
290 return LDB_ERR_OPERATIONS_ERROR;
294 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
295 key.dsize = strlen((char *)key.dptr);
297 rec = tdb_fetch(ltdb->idxptr->itdb, key);
298 if (rec.dptr != NULL) {
299 list2 = ltdb_index_idxptr(module, rec, false);
300 if (list2 == NULL) {
301 free(rec.dptr);
302 return LDB_ERR_OPERATIONS_ERROR;
304 free(rec.dptr);
305 list2->dn = talloc_steal(list2, list->dn);
306 list2->count = list->count;
307 return LDB_SUCCESS;
310 list2 = talloc(ltdb->idxptr, struct dn_list);
311 if (list2 == NULL) {
312 return LDB_ERR_OPERATIONS_ERROR;
314 list2->dn = talloc_steal(list2, list->dn);
315 list2->count = list->count;
317 rec.dptr = (uint8_t *)&list2;
318 rec.dsize = sizeof(void *);
322 * This is not a store into the main DB, but into an in-memory
323 * TDB, so we don't need a guard on ltdb->read_only
325 ret = tdb_store(ltdb->idxptr->itdb, key, rec, TDB_INSERT);
326 if (ret != 0) {
327 return ltdb_err_map(tdb_error(ltdb->idxptr->itdb));
329 return LDB_SUCCESS;
333 traverse function for storing the in-memory index entries on disk
335 static int ltdb_index_traverse_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
337 struct ldb_module *module = state;
338 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
339 struct ldb_dn *dn;
340 struct ldb_context *ldb = ldb_module_get_ctx(module);
341 struct ldb_val v;
342 struct dn_list *list;
344 list = ltdb_index_idxptr(module, data, true);
345 if (list == NULL) {
346 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
347 return -1;
350 v.data = key.dptr;
351 v.length = strnlen((char *)key.dptr, key.dsize);
353 dn = ldb_dn_from_ldb_val(module, ldb, &v);
354 if (dn == NULL) {
355 ldb_asprintf_errstring(ldb, "Failed to parse index key %*.*s as an LDB DN", (int)v.length, (int)v.length, (const char *)v.data);
356 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
357 return -1;
360 ltdb->idxptr->error = ltdb_dn_list_store_full(module, ltdb,
361 dn, list);
362 talloc_free(dn);
363 if (ltdb->idxptr->error != 0) {
364 return -1;
366 return 0;
369 /* cleanup the idxptr mode when transaction commits */
370 int ltdb_index_transaction_commit(struct ldb_module *module)
372 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
373 int ret;
375 struct ldb_context *ldb = ldb_module_get_ctx(module);
377 ldb_reset_err_string(ldb);
379 if (ltdb->idxptr->itdb) {
380 tdb_traverse(ltdb->idxptr->itdb, ltdb_index_traverse_store, module);
381 tdb_close(ltdb->idxptr->itdb);
384 ret = ltdb->idxptr->error;
385 if (ret != LDB_SUCCESS) {
386 if (!ldb_errstring(ldb)) {
387 ldb_set_errstring(ldb, ldb_strerror(ret));
389 ldb_asprintf_errstring(ldb, "Failed to store index records in transaction commit: %s", ldb_errstring(ldb));
392 talloc_free(ltdb->idxptr);
393 ltdb->idxptr = NULL;
394 return ret;
397 /* cleanup the idxptr mode when transaction cancels */
398 int ltdb_index_transaction_cancel(struct ldb_module *module)
400 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
401 if (ltdb->idxptr && ltdb->idxptr->itdb) {
402 tdb_close(ltdb->idxptr->itdb);
404 talloc_free(ltdb->idxptr);
405 ltdb->idxptr = NULL;
406 return LDB_SUCCESS;
411 return the dn key to be used for an index
412 the caller is responsible for freeing
414 static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
415 const char *attr, const struct ldb_val *value,
416 const struct ldb_schema_attribute **ap)
418 struct ldb_dn *ret;
419 struct ldb_val v;
420 const struct ldb_schema_attribute *a;
421 char *attr_folded;
422 int r;
424 attr_folded = ldb_attr_casefold(ldb, attr);
425 if (!attr_folded) {
426 return NULL;
429 a = ldb_schema_attribute_by_name(ldb, attr);
430 if (ap) {
431 *ap = a;
433 r = a->syntax->canonicalise_fn(ldb, ldb, value, &v);
434 if (r != LDB_SUCCESS) {
435 const char *errstr = ldb_errstring(ldb);
436 /* canonicalisation can be refused. For example,
437 a attribute that takes wildcards will refuse to canonicalise
438 if the value contains a wildcard */
439 ldb_asprintf_errstring(ldb, "Failed to create index key for attribute '%s':%s%s%s",
440 attr, ldb_strerror(r), (errstr?":":""), (errstr?errstr:""));
441 talloc_free(attr_folded);
442 return NULL;
444 if (ldb_should_b64_encode(ldb, &v)) {
445 char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length);
446 if (!vstr) {
447 talloc_free(attr_folded);
448 return NULL;
450 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr);
451 talloc_free(vstr);
452 } else {
453 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s:%.*s", LTDB_INDEX, attr_folded, (int)v.length, (char *)v.data);
456 if (v.data != value->data) {
457 talloc_free(v.data);
459 talloc_free(attr_folded);
461 return ret;
465 see if a attribute value is in the list of indexed attributes
467 static bool ltdb_is_indexed(struct ldb_module *module,
468 struct ltdb_private *ltdb,
469 const char *attr)
471 struct ldb_context *ldb = ldb_module_get_ctx(module);
472 unsigned int i;
473 struct ldb_message_element *el;
475 if (ldb->schema.index_handler_override) {
476 const struct ldb_schema_attribute *a
477 = ldb_schema_attribute_by_name(ldb, attr);
479 if (a == NULL) {
480 return false;
483 if (a->flags & LDB_ATTR_FLAG_INDEXED) {
484 return true;
485 } else {
486 return false;
490 if (!ltdb->cache->attribute_indexes) {
491 return false;
494 el = ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXATTR);
495 if (el == NULL) {
496 return false;
499 /* TODO: this is too expensive! At least use a binary search */
500 for (i=0; i<el->num_values; i++) {
501 if (ldb_attr_cmp((char *)el->values[i].data, attr) == 0) {
502 return true;
505 return false;
509 in the following logic functions, the return value is treated as
510 follows:
512 LDB_SUCCESS: we found some matching index values
514 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
516 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
517 we'll need a full search
521 return a list of dn's that might match a simple indexed search (an
522 equality search only)
524 static int ltdb_index_dn_simple(struct ldb_module *module,
525 struct ltdb_private *ltdb,
526 const struct ldb_parse_tree *tree,
527 struct dn_list *list)
529 struct ldb_context *ldb;
530 struct ldb_dn *dn;
531 int ret;
533 ldb = ldb_module_get_ctx(module);
535 list->count = 0;
536 list->dn = NULL;
538 /* if the attribute isn't in the list of indexed attributes then
539 this node needs a full search */
540 if (!ltdb_is_indexed(module, ltdb, tree->u.equality.attr)) {
541 return LDB_ERR_OPERATIONS_ERROR;
544 /* the attribute is indexed. Pull the list of DNs that match the
545 search criterion */
546 dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value, NULL);
547 if (!dn) return LDB_ERR_OPERATIONS_ERROR;
549 ret = ltdb_dn_list_load(module, dn, list);
550 talloc_free(dn);
551 return ret;
555 static bool list_union(struct ldb_context *, struct dn_list *, const struct dn_list *);
558 return a list of dn's that might match a leaf indexed search
560 static int ltdb_index_dn_leaf(struct ldb_module *module,
561 struct ltdb_private *ltdb,
562 const struct ldb_parse_tree *tree,
563 struct dn_list *list)
565 if (ltdb->disallow_dn_filter &&
566 (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0)) {
567 /* in AD mode we do not support "(dn=...)" search filters */
568 list->dn = NULL;
569 list->count = 0;
570 return LDB_SUCCESS;
572 if (ldb_attr_dn(tree->u.equality.attr) == 0) {
573 list->dn = talloc_array(list, struct ldb_val, 1);
574 if (list->dn == NULL) {
575 ldb_module_oom(module);
576 return LDB_ERR_OPERATIONS_ERROR;
578 list->dn[0] = tree->u.equality.value;
579 list->count = 1;
580 return LDB_SUCCESS;
582 return ltdb_index_dn_simple(module, ltdb, tree, list);
587 list intersection
588 list = list & list2
590 static bool list_intersect(struct ldb_context *ldb,
591 struct ltdb_private *ltdb,
592 struct dn_list *list, const struct dn_list *list2)
594 struct dn_list *list3;
595 unsigned int i;
597 if (list->count == 0) {
598 /* 0 & X == 0 */
599 return true;
601 if (list2->count == 0) {
602 /* X & 0 == 0 */
603 list->count = 0;
604 list->dn = NULL;
605 return true;
608 /* the indexing code is allowed to return a longer list than
609 what really matches, as all results are filtered by the
610 full expression at the end - this shortcut avoids a lot of
611 work in some cases */
612 if (list->count < 2 && list2->count > 10) {
613 return true;
615 if (list2->count < 2 && list->count > 10) {
616 list->count = list2->count;
617 list->dn = list2->dn;
618 /* note that list2 may not be the parent of list2->dn,
619 as list2->dn may be owned by ltdb->idxptr. In that
620 case we expect this reparent call to fail, which is
621 OK */
622 talloc_reparent(list2, list, list2->dn);
623 return true;
626 list3 = talloc_zero(list, struct dn_list);
627 if (list3 == NULL) {
628 return false;
631 list3->dn = talloc_array(list3, struct ldb_val, list->count);
632 if (!list3->dn) {
633 talloc_free(list3);
634 return false;
636 list3->count = 0;
638 for (i=0;i<list->count;i++) {
639 if (ltdb_dn_list_find_val(ltdb, list2,
640 &list->dn[i]) != -1) {
641 list3->dn[list3->count] = list->dn[i];
642 list3->count++;
646 list->dn = talloc_steal(list, list3->dn);
647 list->count = list3->count;
648 talloc_free(list3);
650 return true;
655 list union
656 list = list | list2
658 static bool list_union(struct ldb_context *ldb,
659 struct dn_list *list, const struct dn_list *list2)
661 struct ldb_val *dn3;
663 if (list2->count == 0) {
664 /* X | 0 == X */
665 return true;
668 if (list->count == 0) {
669 /* 0 | X == X */
670 list->count = list2->count;
671 list->dn = list2->dn;
672 /* note that list2 may not be the parent of list2->dn,
673 as list2->dn may be owned by ltdb->idxptr. In that
674 case we expect this reparent call to fail, which is
675 OK */
676 talloc_reparent(list2, list, list2->dn);
677 return true;
680 dn3 = talloc_array(list, struct ldb_val, list->count + list2->count);
681 if (!dn3) {
682 ldb_oom(ldb);
683 return false;
686 /* we allow for duplicates here, and get rid of them later */
687 memcpy(dn3, list->dn, sizeof(list->dn[0])*list->count);
688 memcpy(dn3+list->count, list2->dn, sizeof(list2->dn[0])*list2->count);
690 list->dn = dn3;
691 list->count += list2->count;
693 return true;
696 static int ltdb_index_dn(struct ldb_module *module,
697 struct ltdb_private *ltdb,
698 const struct ldb_parse_tree *tree,
699 struct dn_list *list);
703 process an OR list (a union)
705 static int ltdb_index_dn_or(struct ldb_module *module,
706 struct ltdb_private *ltdb,
707 const struct ldb_parse_tree *tree,
708 struct dn_list *list)
710 struct ldb_context *ldb;
711 unsigned int i;
713 ldb = ldb_module_get_ctx(module);
715 list->dn = NULL;
716 list->count = 0;
718 for (i=0; i<tree->u.list.num_elements; i++) {
719 struct dn_list *list2;
720 int ret;
722 list2 = talloc_zero(list, struct dn_list);
723 if (list2 == NULL) {
724 return LDB_ERR_OPERATIONS_ERROR;
727 ret = ltdb_index_dn(module, ltdb,
728 tree->u.list.elements[i], list2);
730 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
731 /* X || 0 == X */
732 talloc_free(list2);
733 continue;
736 if (ret != LDB_SUCCESS) {
737 /* X || * == * */
738 talloc_free(list2);
739 return ret;
742 if (!list_union(ldb, list, list2)) {
743 talloc_free(list2);
744 return LDB_ERR_OPERATIONS_ERROR;
748 if (list->count == 0) {
749 return LDB_ERR_NO_SUCH_OBJECT;
752 return LDB_SUCCESS;
757 NOT an index results
759 static int ltdb_index_dn_not(struct ldb_module *module,
760 struct ltdb_private *ltdb,
761 const struct ldb_parse_tree *tree,
762 struct dn_list *list)
764 /* the only way to do an indexed not would be if we could
765 negate the not via another not or if we knew the total
766 number of database elements so we could know that the
767 existing expression covered the whole database.
769 instead, we just give up, and rely on a full index scan
770 (unless an outer & manages to reduce the list)
772 return LDB_ERR_OPERATIONS_ERROR;
776 static bool ltdb_index_unique(struct ldb_context *ldb,
777 const char *attr)
779 const struct ldb_schema_attribute *a;
780 a = ldb_schema_attribute_by_name(ldb, attr);
781 if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
782 return true;
784 return false;
788 process an AND expression (intersection)
790 static int ltdb_index_dn_and(struct ldb_module *module,
791 struct ltdb_private *ltdb,
792 const struct ldb_parse_tree *tree,
793 struct dn_list *list)
795 struct ldb_context *ldb;
796 unsigned int i;
797 bool found;
799 ldb = ldb_module_get_ctx(module);
801 list->dn = NULL;
802 list->count = 0;
804 /* in the first pass we only look for unique simple
805 equality tests, in the hope of avoiding having to look
806 at any others */
807 for (i=0; i<tree->u.list.num_elements; i++) {
808 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
809 int ret;
811 if (subtree->operation != LDB_OP_EQUALITY ||
812 !ltdb_index_unique(ldb, subtree->u.equality.attr)) {
813 continue;
816 ret = ltdb_index_dn(module, ltdb, subtree, list);
817 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
818 /* 0 && X == 0 */
819 return LDB_ERR_NO_SUCH_OBJECT;
821 if (ret == LDB_SUCCESS) {
822 /* a unique index match means we can
823 * stop. Note that we don't care if we return
824 * a few too many objects, due to later
825 * filtering */
826 return LDB_SUCCESS;
830 /* now do a full intersection */
831 found = false;
833 for (i=0; i<tree->u.list.num_elements; i++) {
834 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
835 struct dn_list *list2;
836 int ret;
838 list2 = talloc_zero(list, struct dn_list);
839 if (list2 == NULL) {
840 return ldb_module_oom(module);
843 ret = ltdb_index_dn(module, ltdb, subtree, list2);
845 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
846 /* X && 0 == 0 */
847 list->dn = NULL;
848 list->count = 0;
849 talloc_free(list2);
850 return LDB_ERR_NO_SUCH_OBJECT;
853 if (ret != LDB_SUCCESS) {
854 /* this didn't adding anything */
855 talloc_free(list2);
856 continue;
859 if (!found) {
860 talloc_reparent(list2, list, list->dn);
861 list->dn = list2->dn;
862 list->count = list2->count;
863 found = true;
864 } else if (!list_intersect(ldb, ltdb,
865 list, list2)) {
866 talloc_free(list2);
867 return LDB_ERR_OPERATIONS_ERROR;
870 if (list->count == 0) {
871 list->dn = NULL;
872 return LDB_ERR_NO_SUCH_OBJECT;
875 if (list->count < 2) {
876 /* it isn't worth loading the next part of the tree */
877 return LDB_SUCCESS;
881 if (!found) {
882 /* none of the attributes were indexed */
883 return LDB_ERR_OPERATIONS_ERROR;
886 return LDB_SUCCESS;
890 return a list of matching objects using a one-level index
892 static int ltdb_index_dn_one(struct ldb_module *module,
893 struct ldb_dn *parent_dn,
894 struct dn_list *list)
896 struct ldb_context *ldb;
897 struct ldb_dn *key;
898 struct ldb_val val;
899 int ret;
901 ldb = ldb_module_get_ctx(module);
903 /* work out the index key from the parent DN */
904 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn));
905 val.length = strlen((char *)val.data);
906 key = ltdb_index_key(ldb, LTDB_IDXONE, &val, NULL);
907 if (!key) {
908 ldb_oom(ldb);
909 return LDB_ERR_OPERATIONS_ERROR;
912 ret = ltdb_dn_list_load(module, key, list);
913 talloc_free(key);
914 if (ret != LDB_SUCCESS) {
915 return ret;
918 if (list->count == 0) {
919 return LDB_ERR_NO_SUCH_OBJECT;
922 return LDB_SUCCESS;
926 return a list of dn's that might match a indexed search or
927 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
929 static int ltdb_index_dn(struct ldb_module *module,
930 struct ltdb_private *ltdb,
931 const struct ldb_parse_tree *tree,
932 struct dn_list *list)
934 int ret = LDB_ERR_OPERATIONS_ERROR;
936 switch (tree->operation) {
937 case LDB_OP_AND:
938 ret = ltdb_index_dn_and(module, ltdb, tree, list);
939 break;
941 case LDB_OP_OR:
942 ret = ltdb_index_dn_or(module, ltdb, tree, list);
943 break;
945 case LDB_OP_NOT:
946 ret = ltdb_index_dn_not(module, ltdb, tree, list);
947 break;
949 case LDB_OP_EQUALITY:
950 ret = ltdb_index_dn_leaf(module, ltdb, tree, list);
951 break;
953 case LDB_OP_SUBSTRING:
954 case LDB_OP_GREATER:
955 case LDB_OP_LESS:
956 case LDB_OP_PRESENT:
957 case LDB_OP_APPROX:
958 case LDB_OP_EXTENDED:
959 /* we can't index with fancy bitops yet */
960 ret = LDB_ERR_OPERATIONS_ERROR;
961 break;
964 return ret;
968 filter a candidate dn_list from an indexed search into a set of results
969 extracting just the given attributes
971 static int ltdb_index_filter(struct ltdb_private *ltdb,
972 const struct dn_list *dn_list,
973 struct ltdb_context *ac,
974 uint32_t *match_count)
976 struct ldb_context *ldb;
977 struct ldb_message *msg;
978 struct ldb_message *filtered_msg;
979 unsigned int i;
981 ldb = ldb_module_get_ctx(ac->module);
983 for (i = 0; i < dn_list->count; i++) {
984 struct ldb_dn *dn;
985 int ret;
986 bool matched;
988 msg = ldb_msg_new(ac);
989 if (!msg) {
990 return LDB_ERR_OPERATIONS_ERROR;
993 dn = ldb_dn_from_ldb_val(msg, ldb, &dn_list->dn[i]);
994 if (dn == NULL) {
995 talloc_free(msg);
996 return LDB_ERR_OPERATIONS_ERROR;
999 ret = ltdb_search_dn1(ac->module, dn, msg,
1000 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC|
1001 LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC);
1002 talloc_free(dn);
1003 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1004 /* the record has disappeared? yes, this can happen */
1005 talloc_free(msg);
1006 continue;
1009 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1010 /* an internal error */
1011 talloc_free(msg);
1012 return LDB_ERR_OPERATIONS_ERROR;
1015 ret = ldb_match_msg_error(ldb, msg,
1016 ac->tree, ac->base, ac->scope, &matched);
1017 if (ret != LDB_SUCCESS) {
1018 talloc_free(msg);
1019 return ret;
1021 if (!matched) {
1022 talloc_free(msg);
1023 continue;
1026 /* filter the attributes that the user wants */
1027 ret = ltdb_filter_attrs(ac, msg, ac->attrs, &filtered_msg);
1029 talloc_free(msg);
1031 if (ret == -1) {
1032 return LDB_ERR_OPERATIONS_ERROR;
1035 ret = ldb_module_send_entry(ac->req, filtered_msg, NULL);
1036 if (ret != LDB_SUCCESS) {
1037 /* Regardless of success or failure, the msg
1038 * is the callbacks responsiblity, and should
1039 * not be talloc_free()'ed */
1040 ac->request_terminated = true;
1041 return ret;
1044 (*match_count)++;
1047 return LDB_SUCCESS;
1051 remove any duplicated entries in a indexed result
1053 static void ltdb_dn_list_remove_duplicates(struct dn_list *list)
1055 unsigned int i, new_count;
1057 if (list->count < 2) {
1058 return;
1061 TYPESAFE_QSORT(list->dn, list->count, dn_list_cmp);
1063 new_count = 1;
1064 for (i=1; i<list->count; i++) {
1065 if (dn_list_cmp(&list->dn[i], &list->dn[new_count-1]) != 0) {
1066 if (new_count != i) {
1067 list->dn[new_count] = list->dn[i];
1069 new_count++;
1073 list->count = new_count;
1077 search the database with a LDAP-like expression using indexes
1078 returns -1 if an indexed search is not possible, in which
1079 case the caller should call ltdb_search_full()
1081 int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
1083 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(ac->module), struct ltdb_private);
1084 struct dn_list *dn_list;
1085 int ret;
1087 /* see if indexing is enabled */
1088 if (!ltdb->cache->attribute_indexes &&
1089 !ltdb->cache->one_level_indexes &&
1090 ac->scope != LDB_SCOPE_BASE) {
1091 /* fallback to a full search */
1092 return LDB_ERR_OPERATIONS_ERROR;
1095 dn_list = talloc_zero(ac, struct dn_list);
1096 if (dn_list == NULL) {
1097 return ldb_module_oom(ac->module);
1100 switch (ac->scope) {
1101 case LDB_SCOPE_BASE:
1102 dn_list->dn = talloc_array(dn_list, struct ldb_val, 1);
1103 if (dn_list->dn == NULL) {
1104 talloc_free(dn_list);
1105 return ldb_module_oom(ac->module);
1107 dn_list->dn[0].data = discard_const_p(unsigned char, ldb_dn_get_linearized(ac->base));
1108 if (dn_list->dn[0].data == NULL) {
1109 talloc_free(dn_list);
1110 return ldb_module_oom(ac->module);
1112 dn_list->dn[0].length = strlen((char *)dn_list->dn[0].data);
1113 dn_list->count = 1;
1114 break;
1116 case LDB_SCOPE_ONELEVEL:
1117 if (!ltdb->cache->one_level_indexes) {
1118 talloc_free(dn_list);
1119 return LDB_ERR_OPERATIONS_ERROR;
1121 ret = ltdb_index_dn_one(ac->module, ac->base, dn_list);
1122 if (ret != LDB_SUCCESS) {
1123 talloc_free(dn_list);
1124 return ret;
1126 break;
1128 case LDB_SCOPE_SUBTREE:
1129 case LDB_SCOPE_DEFAULT:
1130 if (!ltdb->cache->attribute_indexes) {
1131 talloc_free(dn_list);
1132 return LDB_ERR_OPERATIONS_ERROR;
1134 ret = ltdb_index_dn(ac->module, ltdb, ac->tree, dn_list);
1135 if (ret != LDB_SUCCESS) {
1136 talloc_free(dn_list);
1137 return ret;
1139 ltdb_dn_list_remove_duplicates(dn_list);
1140 break;
1143 ret = ltdb_index_filter(ltdb, dn_list, ac, match_count);
1144 talloc_free(dn_list);
1145 return ret;
1149 * @brief Add a DN in the index list of a given attribute name/value pair
1151 * This function will add the DN in the index list for the index for
1152 * the given attribute name and value.
1154 * @param[in] module A ldb_module structure
1156 * @param[in] dn The string representation of the DN as it
1157 * will be stored in the index entry
1159 * @param[in] el A ldb_message_element array, one of the entry
1160 * referred by the v_idx is the attribute name and
1161 * value pair which will be used to construct the
1162 * index name
1164 * @param[in] v_idx The index of element in the el array to use
1166 * @return An ldb error code
1168 static int ltdb_index_add1(struct ldb_module *module,
1169 struct ltdb_private *ltdb,
1170 const char *dn,
1171 struct ldb_message_element *el, int v_idx)
1173 struct ldb_context *ldb;
1174 struct ldb_dn *dn_key;
1175 int ret;
1176 const struct ldb_schema_attribute *a;
1177 struct dn_list *list;
1178 unsigned alloc_len;
1180 ldb = ldb_module_get_ctx(module);
1182 list = talloc_zero(module, struct dn_list);
1183 if (list == NULL) {
1184 return LDB_ERR_OPERATIONS_ERROR;
1187 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], &a);
1188 if (!dn_key) {
1189 talloc_free(list);
1190 return LDB_ERR_OPERATIONS_ERROR;
1192 talloc_steal(list, dn_key);
1194 ret = ltdb_dn_list_load(module, dn_key, list);
1195 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1196 talloc_free(list);
1197 return ret;
1200 if (list->count > 0 &&
1201 a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
1203 * We do not want to print info about a possibly
1204 * confidential DN that the conflict was with in the
1205 * user-visible error string
1207 ldb_debug(ldb, LDB_DEBUG_WARNING,
1208 __location__ ": unique index violation on %s in %s, "
1209 "conficts with %*.*s in %s",
1210 el->name, dn,
1211 (int)list->dn[0].length,
1212 (int)list->dn[0].length,
1213 list->dn[0].data,
1214 ldb_dn_get_linearized(dn_key));
1215 ldb_asprintf_errstring(ldb, __location__ ": unique index violation on %s in %s",
1216 el->name, dn);
1217 talloc_free(list);
1218 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1221 /* overallocate the list a bit, to reduce the number of
1222 * realloc trigered copies */
1223 alloc_len = ((list->count+1)+7) & ~7;
1224 list->dn = talloc_realloc(list, list->dn, struct ldb_val, alloc_len);
1225 if (list->dn == NULL) {
1226 talloc_free(list);
1227 return LDB_ERR_OPERATIONS_ERROR;
1230 list->dn[list->count].data
1231 = (uint8_t *)talloc_strdup(list->dn, dn);
1232 if (list->dn[list->count].data == NULL) {
1233 talloc_free(list);
1234 return LDB_ERR_OPERATIONS_ERROR;
1236 list->dn[list->count].length = strlen(dn);
1237 list->count++;
1239 ret = ltdb_dn_list_store(module, dn_key, list);
1241 talloc_free(list);
1243 return ret;
1247 add index entries for one elements in a message
1249 static int ltdb_index_add_el(struct ldb_module *module,
1250 struct ltdb_private *ltdb,
1251 const char *dn,
1252 struct ldb_message_element *el)
1254 unsigned int i;
1255 for (i = 0; i < el->num_values; i++) {
1256 int ret = ltdb_index_add1(module, ltdb,
1257 dn, el, i);
1258 if (ret != LDB_SUCCESS) {
1259 return ret;
1263 return LDB_SUCCESS;
1267 add index entries for all elements in a message
1269 static int ltdb_index_add_all(struct ldb_module *module,
1270 struct ltdb_private *ltdb,
1271 const char *dn,
1272 struct ldb_message_element *elements,
1273 unsigned int num_el)
1275 unsigned int i;
1277 if (dn[0] == '@') {
1278 return LDB_SUCCESS;
1281 if (!ltdb->cache->attribute_indexes) {
1282 /* no indexed fields */
1283 return LDB_SUCCESS;
1286 for (i = 0; i < num_el; i++) {
1287 int ret;
1288 if (!ltdb_is_indexed(module, ltdb, elements[i].name)) {
1289 continue;
1291 ret = ltdb_index_add_el(module, ltdb, dn, &elements[i]);
1292 if (ret != LDB_SUCCESS) {
1293 struct ldb_context *ldb = ldb_module_get_ctx(module);
1294 ldb_asprintf_errstring(ldb,
1295 __location__ ": Failed to re-index %s in %s - %s",
1296 elements[i].name, dn, ldb_errstring(ldb));
1297 return ret;
1301 return LDB_SUCCESS;
1306 insert a one level index for a message
1308 static int ltdb_index_onelevel(struct ldb_module *module,
1309 const struct ldb_message *msg, int add)
1311 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module),
1312 struct ltdb_private);
1313 struct ldb_message_element el;
1314 struct ldb_val val;
1315 struct ldb_dn *pdn;
1316 const char *dn;
1317 int ret;
1319 /* We index for ONE Level only if requested */
1320 if (!ltdb->cache->one_level_indexes) {
1321 return LDB_SUCCESS;
1324 pdn = ldb_dn_get_parent(module, msg->dn);
1325 if (pdn == NULL) {
1326 return LDB_ERR_OPERATIONS_ERROR;
1329 dn = ldb_dn_get_linearized(msg->dn);
1330 if (dn == NULL) {
1331 talloc_free(pdn);
1332 return LDB_ERR_OPERATIONS_ERROR;
1335 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(pdn));
1336 if (val.data == NULL) {
1337 talloc_free(pdn);
1338 return LDB_ERR_OPERATIONS_ERROR;
1341 val.length = strlen((char *)val.data);
1342 el.name = LTDB_IDXONE;
1343 el.values = &val;
1344 el.num_values = 1;
1346 if (add) {
1347 ret = ltdb_index_add1(module, ltdb, dn, &el, 0);
1348 } else { /* delete */
1349 ret = ltdb_index_del_value(module, ltdb, msg->dn, &el, 0);
1352 talloc_free(pdn);
1354 return ret;
1358 add the index entries for a new element in a record
1359 The caller guarantees that these element values are not yet indexed
1361 int ltdb_index_add_element(struct ldb_module *module,
1362 struct ltdb_private *ltdb,
1363 struct ldb_dn *dn,
1364 struct ldb_message_element *el)
1366 if (ldb_dn_is_special(dn)) {
1367 return LDB_SUCCESS;
1369 if (!ltdb_is_indexed(module, ltdb, el->name)) {
1370 return LDB_SUCCESS;
1372 return ltdb_index_add_el(module, ltdb,
1373 ldb_dn_get_linearized(dn), el);
1377 add the index entries for a new record
1379 int ltdb_index_add_new(struct ldb_module *module,
1380 struct ltdb_private *ltdb,
1381 const struct ldb_message *msg)
1383 const char *dn;
1384 int ret;
1386 if (ldb_dn_is_special(msg->dn)) {
1387 return LDB_SUCCESS;
1390 dn = ldb_dn_get_linearized(msg->dn);
1391 if (dn == NULL) {
1392 return LDB_ERR_OPERATIONS_ERROR;
1395 ret = ltdb_index_add_all(module, ltdb, dn, msg->elements,
1396 msg->num_elements);
1397 if (ret != LDB_SUCCESS) {
1398 return ret;
1401 return ltdb_index_onelevel(module, msg, 1);
1406 delete an index entry for one message element
1408 int ltdb_index_del_value(struct ldb_module *module,
1409 struct ltdb_private *ltdb,
1410 struct ldb_dn *dn,
1411 struct ldb_message_element *el, unsigned int v_idx)
1413 struct ldb_context *ldb;
1414 struct ldb_dn *dn_key;
1415 const char *dn_str;
1416 int ret, i;
1417 unsigned int j;
1418 struct dn_list *list;
1420 ldb = ldb_module_get_ctx(module);
1422 dn_str = ldb_dn_get_linearized(dn);
1423 if (dn_str == NULL) {
1424 return LDB_ERR_OPERATIONS_ERROR;
1427 if (dn_str[0] == '@') {
1428 return LDB_SUCCESS;
1431 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], NULL);
1432 if (!dn_key) {
1433 return LDB_ERR_OPERATIONS_ERROR;
1436 list = talloc_zero(dn_key, struct dn_list);
1437 if (list == NULL) {
1438 talloc_free(dn_key);
1439 return LDB_ERR_OPERATIONS_ERROR;
1442 ret = ltdb_dn_list_load(module, dn_key, list);
1443 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1444 /* it wasn't indexed. Did we have an earlier error? If we did then
1445 its gone now */
1446 talloc_free(dn_key);
1447 return LDB_SUCCESS;
1450 if (ret != LDB_SUCCESS) {
1451 talloc_free(dn_key);
1452 return ret;
1455 i = ltdb_dn_list_find_str(ltdb, list, dn_str);
1456 if (i == -1) {
1457 /* nothing to delete */
1458 talloc_free(dn_key);
1459 return LDB_SUCCESS;
1462 j = (unsigned int) i;
1463 if (j != list->count - 1) {
1464 memmove(&list->dn[j], &list->dn[j+1], sizeof(list->dn[0])*(list->count - (j+1)));
1466 list->count--;
1467 if (list->count == 0) {
1468 talloc_free(list->dn);
1469 list->dn = NULL;
1470 } else {
1471 list->dn = talloc_realloc(list, list->dn, struct ldb_val, list->count);
1474 ret = ltdb_dn_list_store(module, dn_key, list);
1476 talloc_free(dn_key);
1478 return ret;
1482 delete the index entries for a element
1483 return -1 on failure
1485 int ltdb_index_del_element(struct ldb_module *module,
1486 struct ltdb_private *ltdb,
1487 struct ldb_dn *dn,
1488 struct ldb_message_element *el)
1490 const char *dn_str;
1491 int ret;
1492 unsigned int i;
1494 if (!ltdb->cache->attribute_indexes) {
1495 /* no indexed fields */
1496 return LDB_SUCCESS;
1499 dn_str = ldb_dn_get_linearized(dn);
1500 if (dn_str == NULL) {
1501 return LDB_ERR_OPERATIONS_ERROR;
1504 if (dn_str[0] == '@') {
1505 return LDB_SUCCESS;
1508 if (!ltdb_is_indexed(module, ltdb, el->name)) {
1509 return LDB_SUCCESS;
1511 for (i = 0; i < el->num_values; i++) {
1512 ret = ltdb_index_del_value(module, ltdb, dn, el, i);
1513 if (ret != LDB_SUCCESS) {
1514 return ret;
1518 return LDB_SUCCESS;
1522 delete the index entries for a record
1523 return -1 on failure
1525 int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg)
1527 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1528 int ret;
1529 unsigned int i;
1531 if (ldb_dn_is_special(msg->dn)) {
1532 return LDB_SUCCESS;
1535 ret = ltdb_index_onelevel(module, msg, 0);
1536 if (ret != LDB_SUCCESS) {
1537 return ret;
1540 if (!ltdb->cache->attribute_indexes) {
1541 /* no indexed fields */
1542 return LDB_SUCCESS;
1545 for (i = 0; i < msg->num_elements; i++) {
1546 ret = ltdb_index_del_element(module, ltdb,
1547 msg->dn, &msg->elements[i]);
1548 if (ret != LDB_SUCCESS) {
1549 return ret;
1553 return LDB_SUCCESS;
1558 traversal function that deletes all @INDEX records
1560 static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1562 struct ldb_module *module = state;
1563 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1564 const char *dnstr = "DN=" LTDB_INDEX ":";
1565 struct dn_list list;
1566 struct ldb_dn *dn;
1567 struct ldb_val v;
1568 int ret;
1570 if (strncmp((char *)key.dptr, dnstr, strlen(dnstr)) != 0) {
1571 return 0;
1573 /* we need to put a empty list in the internal tdb for this
1574 * index entry */
1575 list.dn = NULL;
1576 list.count = 0;
1578 /* the offset of 3 is to remove the DN= prefix. */
1579 v.data = key.dptr + 3;
1580 v.length = strnlen((char *)key.dptr, key.dsize) - 3;
1582 dn = ldb_dn_from_ldb_val(ltdb, ldb_module_get_ctx(module), &v);
1583 ret = ltdb_dn_list_store(module, dn, &list);
1584 if (ret != LDB_SUCCESS) {
1585 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1586 "Unable to store null index for %s\n",
1587 ldb_dn_get_linearized(dn));
1588 talloc_free(dn);
1589 return -1;
1591 talloc_free(dn);
1592 return 0;
1595 struct ltdb_reindex_context {
1596 struct ldb_module *module;
1597 int error;
1601 traversal function that adds @INDEX records during a re index
1603 static int re_key(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1605 struct ldb_context *ldb;
1606 struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
1607 struct ldb_module *module = ctx->module;
1608 struct ldb_message *msg;
1609 unsigned int nb_elements_in_db;
1610 const struct ldb_val val = {
1611 .data = data.dptr,
1612 .length = data.dsize,
1614 int ret;
1615 TDB_DATA key2;
1616 bool is_record;
1618 ldb = ldb_module_get_ctx(module);
1620 if (key.dsize > 4 &&
1621 memcmp(key.dptr, "DN=@", 4) == 0) {
1622 return 0;
1625 is_record = ltdb_key_is_record(key);
1626 if (is_record == false) {
1627 return 0;
1630 msg = ldb_msg_new(module);
1631 if (msg == NULL) {
1632 return -1;
1635 ret = ldb_unpack_data_only_attr_list_flags(ldb, &val,
1636 msg,
1637 NULL, 0,
1638 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC,
1639 &nb_elements_in_db);
1640 if (ret != 0) {
1641 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
1642 ldb_dn_get_linearized(msg->dn));
1643 ctx->error = ret;
1644 talloc_free(msg);
1645 return -1;
1648 if (msg->dn == NULL) {
1649 ldb_debug(ldb, LDB_DEBUG_ERROR,
1650 "Refusing to re-index as GUID "
1651 "key %*.*s with no DN\n",
1652 (int)key.dsize, (int)key.dsize,
1653 (char *)key.dptr);
1654 talloc_free(msg);
1655 return -1;
1658 /* check if the DN key has changed, perhaps due to the case
1659 insensitivity of an element changing, or a change from DN
1660 to GUID keys */
1661 key2 = ltdb_key_msg(module, msg);
1662 if (key2.dptr == NULL) {
1663 /* probably a corrupt record ... darn */
1664 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s",
1665 ldb_dn_get_linearized(msg->dn));
1666 talloc_free(msg);
1667 return 0;
1669 if (key.dsize != key2.dsize ||
1670 (memcmp(key.dptr, key2.dptr, key.dsize) != 0)) {
1671 int tdb_ret;
1672 tdb_ret = tdb_delete(tdb, key);
1673 if (tdb_ret != 0) {
1674 ldb_debug(ldb, LDB_DEBUG_ERROR,
1675 "Failed to delete %*.*s "
1676 "for rekey as %*.*s: %s",
1677 (int)key.dsize, (int)key.dsize,
1678 (const char *)key.dptr,
1679 (int)key2.dsize, (int)key2.dsize,
1680 (const char *)key.dptr,
1681 tdb_errorstr(tdb));
1682 ctx->error = ltdb_err_map(tdb_error(tdb));
1683 return -1;
1685 tdb_ret = tdb_store(tdb, key2, data, 0);
1686 if (tdb_ret != 0) {
1687 ldb_debug(ldb, LDB_DEBUG_ERROR,
1688 "Failed to rekey %*.*s as %*.*s: %s",
1689 (int)key.dsize, (int)key.dsize,
1690 (const char *)key.dptr,
1691 (int)key2.dsize, (int)key2.dsize,
1692 (const char *)key.dptr,
1693 tdb_errorstr(tdb));
1694 ctx->error = ltdb_err_map(tdb_error(tdb));
1695 return -1;
1698 talloc_free(key2.dptr);
1700 talloc_free(msg);
1702 return 0;
1706 traversal function that adds @INDEX records during a re index
1708 static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
1710 struct ldb_context *ldb;
1711 struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
1712 struct ldb_module *module = ctx->module;
1713 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module),
1714 struct ltdb_private);
1715 struct ldb_message *msg;
1716 const char *dn = NULL;
1717 unsigned int nb_elements_in_db;
1718 const struct ldb_val val = {
1719 .data = data.dptr,
1720 .length = data.dsize,
1722 int ret;
1723 bool is_record;
1725 ldb = ldb_module_get_ctx(module);
1727 if (key.dsize > 4 &&
1728 memcmp(key.dptr, "DN=@", 4) == 0) {
1729 return 0;
1732 is_record = ltdb_key_is_record(key);
1733 if (is_record == false) {
1734 return 0;
1737 msg = ldb_msg_new(module);
1738 if (msg == NULL) {
1739 return -1;
1742 ret = ldb_unpack_data_only_attr_list_flags(ldb, &val,
1743 msg,
1744 NULL, 0,
1745 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC,
1746 &nb_elements_in_db);
1747 if (ret != 0) {
1748 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
1749 ldb_dn_get_linearized(msg->dn));
1750 ctx->error = ret;
1751 talloc_free(msg);
1752 return -1;
1755 if (msg->dn == NULL) {
1756 ldb_debug(ldb, LDB_DEBUG_ERROR,
1757 "Refusing to re-index as GUID "
1758 "key %*.*s with no DN\n",
1759 (int)key.dsize, (int)key.dsize,
1760 (char *)key.dptr);
1761 talloc_free(msg);
1762 return -1;
1763 } else {
1764 dn = ldb_dn_get_linearized(msg->dn);
1767 ret = ltdb_index_onelevel(module, msg, 1);
1768 if (ret != LDB_SUCCESS) {
1769 ldb_debug(ldb, LDB_DEBUG_ERROR,
1770 "Adding special ONE LEVEL index failed (%s)!",
1771 ldb_dn_get_linearized(msg->dn));
1772 talloc_free(msg);
1773 return -1;
1776 ret = ltdb_index_add_all(module, ltdb, dn,
1777 msg->elements, msg->num_elements);
1779 if (ret != LDB_SUCCESS) {
1780 ctx->error = ret;
1781 talloc_free(msg);
1782 return -1;
1785 talloc_free(msg);
1787 return 0;
1791 force a complete reindex of the database
1793 int ltdb_reindex(struct ldb_module *module)
1795 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
1796 int ret;
1797 struct ltdb_reindex_context ctx;
1800 * Only triggered after a modification, but make clear we do
1801 * not re-index a read-only DB
1803 if (ltdb->read_only) {
1804 return LDB_ERR_UNWILLING_TO_PERFORM;
1807 if (ltdb_cache_reload(module) != 0) {
1808 return LDB_ERR_OPERATIONS_ERROR;
1812 * Ensure we read (and so remove) the entries from the real
1813 * DB, no values stored so far are any use as we want to do a
1814 * re-index
1816 ltdb_index_transaction_cancel(module);
1818 ret = ltdb_index_transaction_start(module);
1819 if (ret != LDB_SUCCESS) {
1820 return ret;
1823 /* first traverse the database deleting any @INDEX records by
1824 * putting NULL entries in the in-memory tdb
1826 ret = tdb_traverse(ltdb->tdb, delete_index, module);
1827 if (ret < 0) {
1828 struct ldb_context *ldb = ldb_module_get_ctx(module);
1829 ldb_asprintf_errstring(ldb, "index deletion traverse failed: %s",
1830 ldb_errstring(ldb));
1831 return LDB_ERR_OPERATIONS_ERROR;
1834 /* if we don't have indexes we have nothing todo */
1835 if (!ltdb->cache->attribute_indexes) {
1836 return LDB_SUCCESS;
1839 ctx.module = module;
1840 ctx.error = 0;
1842 /* now traverse adding any indexes for normal LDB records */
1843 ret = tdb_traverse(ltdb->tdb, re_key, &ctx);
1844 if (ret < 0) {
1845 struct ldb_context *ldb = ldb_module_get_ctx(module);
1846 ldb_asprintf_errstring(ldb, "key correction traverse failed: %s",
1847 ldb_errstring(ldb));
1848 return LDB_ERR_OPERATIONS_ERROR;
1851 if (ctx.error != LDB_SUCCESS) {
1852 struct ldb_context *ldb = ldb_module_get_ctx(module);
1853 ldb_asprintf_errstring(ldb, "reindexing failed: %s", ldb_errstring(ldb));
1854 return ctx.error;
1857 ctx.error = 0;
1859 /* now traverse adding any indexes for normal LDB records */
1860 ret = tdb_traverse(ltdb->tdb, re_index, &ctx);
1861 if (ret < 0) {
1862 struct ldb_context *ldb = ldb_module_get_ctx(module);
1863 ldb_asprintf_errstring(ldb, "reindexing traverse failed: %s",
1864 ldb_errstring(ldb));
1865 return LDB_ERR_OPERATIONS_ERROR;
1868 if (ctx.error != LDB_SUCCESS) {
1869 struct ldb_context *ldb = ldb_module_get_ctx(module);
1870 ldb_asprintf_errstring(ldb, "reindexing failed: %s", ldb_errstring(ldb));
1871 return ctx.error;
1874 return LDB_SUCCESS;