4 Copyright (C) Andrew Tridgell 2004-2009
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 * Component: ldb tdb backend - indexing
29 * Description: indexing routines for ldb tdb backend
31 * Author: Andrew Tridgell
36 LDB Index design and choice of TDB key:
37 =======================================
39 LDB has index records held as LDB objects with a special record like:
43 value may be base64 encoded, if it is deemed not printable:
45 dn: @INDEX:attr::base64-value
47 In each record, there is two possible formats:
49 The original format is:
50 -----------------------
52 dn: @INDEX:NAME:DNSUPDATEPROXY
54 @IDX: CN=DnsUpdateProxy,CN=Users,DC=addom,DC=samba,DC=example,DC=com
56 In this format, @IDX is multi-valued, one entry for each match
58 The corrosponding entry is stored in a TDB record with key:
60 DN=CN=DNSUPDATEPROXY,CN=USERS,DC=ADDOM,DC=SAMBA,DC=EXAMPLE,DC=COM
62 (This allows a scope BASE search to directly find the record via
63 a simple casefold of the DN).
65 The original mixed-case DN is stored in the entry iself.
68 The new 'GUID index' format is:
69 -------------------------------
71 dn: @INDEX:NAME:DNSUPDATEPROXY
73 @IDX: <binary GUID>[<binary GUID>[...]]
75 The binary guid is 16 bytes, as bytes and not expanded as hexidecimal
76 or pretty-printed. The GUID is chosen from the message to be stored
77 by the @IDXGUID attribute on @INDEXLIST.
79 If there are multiple values the @IDX value simply becomes longer,
82 The corrosponding entry is stored in a TDB record with key:
86 This allows a very quick translation between the fixed-length index
87 values and the TDB key, while seperating entries from other data
88 in the TDB, should they be unlucky enough to start with the bytes of
91 Additionally, this allows a scope BASE search to directly find the
92 record via a simple match on a GUID= extended DN, controlled via
93 @IDX_DN_GUID on @INDEXLIST
95 Exception for special @ DNs:
97 @BASEINFO, @INDEXLIST and all other special DNs are stored as per the
98 original format, as they are never referenced in an index and are used
99 to bootstrap the database.
102 Control points for choice of index mode
103 ---------------------------------------
105 The choice of index and TDB key mode is made based (for example, from
106 Samba) on entries in the @INDEXLIST DN:
112 By default, the original DN format is used.
115 Control points for choosing indexed attributes
116 ----------------------------------------------
118 @IDXATTR controls if an attribute is indexed
121 @IDXATTR: samAccountName
122 @IDXATTR: nETBIOSName
128 void ldb_schema_set_override_GUID_index(struct ldb_context *ldb,
129 const char *GUID_index_attribute,
130 const char *GUID_index_dn_component)
132 This is used, particularly in combination with the below, instead of
133 the @IDXGUID and @IDX_DN_GUID values in @INDEXLIST.
135 void ldb_schema_set_override_indexlist(struct ldb_context *ldb,
136 bool one_level_indexes);
137 void ldb_schema_attribute_set_override_handler(struct ldb_context *ldb,
138 ldb_attribute_handler_override_fn_t override,
141 When the above two functions are called in combination, the @INDEXLIST
142 values are not read from the DB, so
143 ldb_schema_set_override_GUID_index() must be called.
148 #include "ldb_private.h"
149 #include "lib/util/binsearch.h"
155 * Do not optimise the intersection of this list,
156 * we must never return an entry not in this
157 * list. This allows the index for
158 * SCOPE_ONELEVEL to be trusted.
164 struct tdb_context *itdb;
168 enum key_truncation {
173 static int ltdb_write_index_dn_guid(struct ldb_module *module,
174 const struct ldb_message *msg,
176 static int ltdb_index_dn_base_dn(struct ldb_module *module,
177 struct ltdb_private *ltdb,
178 struct ldb_dn *base_dn,
179 struct dn_list *dn_list,
180 enum key_truncation *truncation);
182 static void ltdb_dn_list_sort(struct ltdb_private *ltdb,
183 struct dn_list *list);
185 /* we put a @IDXVERSION attribute on index entries. This
186 allows us to tell if it was written by an older version
188 #define LTDB_INDEXING_VERSION 2
190 #define LTDB_GUID_INDEXING_VERSION 3
192 static unsigned ltdb_max_key_length(struct ltdb_private *ltdb) {
193 if (ltdb->max_key_length == 0){
196 return ltdb->max_key_length;
199 /* enable the idxptr mode when transactions start */
200 int ltdb_index_transaction_start(struct ldb_module *module)
202 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
203 ltdb->idxptr = talloc_zero(ltdb, struct ltdb_idxptr);
204 if (ltdb->idxptr == NULL) {
205 return ldb_oom(ldb_module_get_ctx(module));
212 see if two ldb_val structures contain exactly the same data
213 return -1 or 1 for a mismatch, 0 for match
215 static int ldb_val_equal_exact_for_qsort(const struct ldb_val *v1,
216 const struct ldb_val *v2)
218 if (v1->length > v2->length) {
221 if (v1->length < v2->length) {
224 return memcmp(v1->data, v2->data, v1->length);
228 see if two ldb_val structures contain exactly the same data
229 return -1 or 1 for a mismatch, 0 for match
231 static int ldb_val_equal_exact_ordered(const struct ldb_val v1,
232 const struct ldb_val *v2)
234 if (v1.length > v2->length) {
237 if (v1.length < v2->length) {
240 return memcmp(v1.data, v2->data, v1.length);
245 find a entry in a dn_list, using a ldb_val. Uses a case sensitive
246 binary-safe comparison for the 'dn' returns -1 if not found
248 This is therefore safe when the value is a GUID in the future
250 static int ltdb_dn_list_find_val(struct ltdb_private *ltdb,
251 const struct dn_list *list,
252 const struct ldb_val *v)
255 struct ldb_val *exact = NULL, *next = NULL;
257 if (ltdb->cache->GUID_index_attribute == NULL) {
258 for (i=0; i<list->count; i++) {
259 if (ldb_val_equal_exact(&list->dn[i], v) == 1) {
266 BINARY_ARRAY_SEARCH_GTE(list->dn, list->count,
267 *v, ldb_val_equal_exact_ordered,
272 /* Not required, but keeps the compiler quiet */
277 i = exact - list->dn;
282 find a entry in a dn_list. Uses a case sensitive comparison with the dn
283 returns -1 if not found
285 static int ltdb_dn_list_find_msg(struct ltdb_private *ltdb,
286 struct dn_list *list,
287 const struct ldb_message *msg)
290 const struct ldb_val *key_val;
291 if (ltdb->cache->GUID_index_attribute == NULL) {
292 const char *dn_str = ldb_dn_get_linearized(msg->dn);
293 v.data = discard_const_p(unsigned char, dn_str);
294 v.length = strlen(dn_str);
296 key_val = ldb_msg_find_ldb_val(msg,
297 ltdb->cache->GUID_index_attribute);
298 if (key_val == NULL) {
303 return ltdb_dn_list_find_val(ltdb, list, &v);
307 this is effectively a cast function, but with lots of paranoia
308 checks and also copes with CPUs that are fussy about pointer
311 static struct dn_list *ltdb_index_idxptr(struct ldb_module *module, TDB_DATA rec, bool check_parent)
313 struct dn_list *list;
314 if (rec.dsize != sizeof(void *)) {
315 ldb_asprintf_errstring(ldb_module_get_ctx(module),
316 "Bad data size for idxptr %u", (unsigned)rec.dsize);
319 /* note that we can't just use a cast here, as rec.dptr may
320 not be aligned sufficiently for a pointer. A cast would cause
321 platforms like some ARM CPUs to crash */
322 memcpy(&list, rec.dptr, sizeof(void *));
323 list = talloc_get_type(list, struct dn_list);
325 ldb_asprintf_errstring(ldb_module_get_ctx(module),
326 "Bad type '%s' for idxptr",
327 talloc_get_name(list));
330 if (check_parent && list->dn && talloc_parent(list->dn) != list) {
331 ldb_asprintf_errstring(ldb_module_get_ctx(module),
332 "Bad parent '%s' for idxptr",
333 talloc_get_name(talloc_parent(list->dn)));
340 return the @IDX list in an index entry for a dn as a
343 static int ltdb_dn_list_load(struct ldb_module *module,
344 struct ltdb_private *ltdb,
345 struct ldb_dn *dn, struct dn_list *list)
347 struct ldb_message *msg;
349 struct ldb_message_element *el;
351 struct dn_list *list2;
357 /* see if we have any in-memory index entries */
358 if (ltdb->idxptr == NULL ||
359 ltdb->idxptr->itdb == NULL) {
363 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
364 key.dsize = strlen((char *)key.dptr);
366 rec = tdb_fetch(ltdb->idxptr->itdb, key);
367 if (rec.dptr == NULL) {
371 /* we've found an in-memory index entry */
372 list2 = ltdb_index_idxptr(module, rec, true);
375 return LDB_ERR_OPERATIONS_ERROR;
383 msg = ldb_msg_new(list);
385 return LDB_ERR_OPERATIONS_ERROR;
388 ret = ltdb_search_dn1(module, dn, msg,
389 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
390 |LDB_UNPACK_DATA_FLAG_NO_DN);
391 if (ret != LDB_SUCCESS) {
396 el = ldb_msg_find_element(msg, LTDB_IDX);
402 version = ldb_msg_find_attr_as_int(msg, LTDB_IDXVERSION, 0);
405 * we avoid copying the strings by stealing the list. We have
406 * to steal msg onto el->values (which looks odd) because we
407 * asked for the memory to be allocated on msg, not on each
408 * value with LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC above
410 if (ltdb->cache->GUID_index_attribute == NULL) {
411 /* check indexing version number */
412 if (version != LTDB_INDEXING_VERSION) {
413 ldb_debug_set(ldb_module_get_ctx(module),
415 "Wrong DN index version %d "
416 "expected %d for %s",
417 version, LTDB_INDEXING_VERSION,
418 ldb_dn_get_linearized(dn));
420 return LDB_ERR_OPERATIONS_ERROR;
423 talloc_steal(el->values, msg);
424 list->dn = talloc_steal(list, el->values);
425 list->count = el->num_values;
428 if (version != LTDB_GUID_INDEXING_VERSION) {
429 /* This is quite likely during the DB startup
430 on first upgrade to using a GUID index */
431 ldb_debug_set(ldb_module_get_ctx(module),
433 "Wrong GUID index version %d "
434 "expected %d for %s",
435 version, LTDB_GUID_INDEXING_VERSION,
436 ldb_dn_get_linearized(dn));
438 return LDB_ERR_OPERATIONS_ERROR;
441 if (el->num_values == 0) {
443 return LDB_ERR_OPERATIONS_ERROR;
446 if ((el->values[0].length % LTDB_GUID_SIZE) != 0) {
448 return LDB_ERR_OPERATIONS_ERROR;
451 list->count = el->values[0].length / LTDB_GUID_SIZE;
452 list->dn = talloc_array(list, struct ldb_val, list->count);
453 if (list->dn == NULL) {
455 return LDB_ERR_OPERATIONS_ERROR;
459 * The actual data is on msg, due to
460 * LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
462 talloc_steal(list->dn, msg);
463 for (i = 0; i < list->count; i++) {
465 = &el->values[0].data[i * LTDB_GUID_SIZE];
466 list->dn[i].length = LTDB_GUID_SIZE;
470 /* We don't need msg->elements any more */
471 talloc_free(msg->elements);
475 int ltdb_key_dn_from_idx(struct ldb_module *module,
476 struct ltdb_private *ltdb,
481 struct ldb_context *ldb = ldb_module_get_ctx(module);
484 enum key_truncation truncation = KEY_NOT_TRUNCATED;
485 struct dn_list *list = talloc(mem_ctx, struct dn_list);
488 return LDB_ERR_OPERATIONS_ERROR;
492 ret = ltdb_index_dn_base_dn(module, ltdb, dn, list, &truncation);
493 if (ret != LDB_SUCCESS) {
498 if (list->count == 0) {
500 return LDB_ERR_NO_SUCH_OBJECT;
503 if (list->count > 1 && truncation == KEY_NOT_TRUNCATED) {
504 const char *dn_str = ldb_dn_get_linearized(dn);
505 ldb_asprintf_errstring(ldb_module_get_ctx(module),
507 ": Failed to read DN index "
508 "against %s for %s: too many "
510 ltdb->cache->GUID_index_attribute,
511 dn_str, list->count);
513 return LDB_ERR_CONSTRAINT_VIOLATION;
516 if (list->count > 0 && truncation == KEY_TRUNCATED) {
518 * DN key has been truncated, need to inspect the actual
519 * records to locate the actual DN
523 for (i=0; i < list->count; i++) {
524 uint8_t guid_key[LTDB_GUID_KEY_SIZE];
527 .dsize = sizeof(guid_key)
529 const int flags = LDB_UNPACK_DATA_FLAG_NO_ATTRS;
530 struct ldb_message *rec = ldb_msg_new(ldb);
533 return LDB_ERR_OPERATIONS_ERROR;
536 ret = ltdb_idx_to_key(module, ltdb,
539 if (ret != LDB_SUCCESS) {
545 ret = ltdb_search_key(module, ltdb, key,
547 if (key.dptr != guid_key) {
548 TALLOC_FREE(key.dptr);
550 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
552 * the record has disappeared?
553 * yes, this can happen
559 if (ret != LDB_SUCCESS) {
560 /* an internal error */
563 return LDB_ERR_OPERATIONS_ERROR;
567 * We found the actual DN that we wanted from in the
568 * multiple values that matched the index
569 * (due to truncation), so return that.
572 if (ldb_dn_compare(dn, rec->dn) == 0) {
580 * We matched the index but the actual DN we wanted
585 return LDB_ERR_NO_SUCH_OBJECT;
589 /* The tdb_key memory is allocated by the caller */
590 ret = ltdb_guid_to_key(module, ltdb,
591 &list->dn[index], tdb_key);
594 if (ret != LDB_SUCCESS) {
595 return LDB_ERR_OPERATIONS_ERROR;
604 save a dn_list into a full @IDX style record
606 static int ltdb_dn_list_store_full(struct ldb_module *module,
607 struct ltdb_private *ltdb,
609 struct dn_list *list)
611 struct ldb_message *msg;
614 msg = ldb_msg_new(module);
616 return ldb_module_oom(module);
621 if (list->count == 0) {
622 ret = ltdb_delete_noindex(module, msg);
623 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
630 if (ltdb->cache->GUID_index_attribute == NULL) {
631 ret = ldb_msg_add_fmt(msg, LTDB_IDXVERSION, "%u",
632 LTDB_INDEXING_VERSION);
633 if (ret != LDB_SUCCESS) {
635 return ldb_module_oom(module);
638 ret = ldb_msg_add_fmt(msg, LTDB_IDXVERSION, "%u",
639 LTDB_GUID_INDEXING_VERSION);
640 if (ret != LDB_SUCCESS) {
642 return ldb_module_oom(module);
646 if (list->count > 0) {
647 struct ldb_message_element *el;
649 ret = ldb_msg_add_empty(msg, LTDB_IDX, LDB_FLAG_MOD_ADD, &el);
650 if (ret != LDB_SUCCESS) {
652 return ldb_module_oom(module);
655 if (ltdb->cache->GUID_index_attribute == NULL) {
656 el->values = list->dn;
657 el->num_values = list->count;
661 el->values = talloc_array(msg,
663 if (el->values == NULL) {
665 return ldb_module_oom(module);
668 v.data = talloc_array_size(el->values,
671 if (v.data == NULL) {
673 return ldb_module_oom(module);
676 v.length = talloc_get_size(v.data);
678 for (i = 0; i < list->count; i++) {
679 if (list->dn[i].length !=
682 return ldb_module_operr(module);
684 memcpy(&v.data[LTDB_GUID_SIZE*i],
693 ret = ltdb_store(module, msg, TDB_REPLACE);
699 save a dn_list into the database, in either @IDX or internal format
701 static int ltdb_dn_list_store(struct ldb_module *module, struct ldb_dn *dn,
702 struct dn_list *list)
704 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
707 struct dn_list *list2;
709 if (ltdb->idxptr == NULL) {
710 return ltdb_dn_list_store_full(module, ltdb,
714 if (ltdb->idxptr->itdb == NULL) {
715 ltdb->idxptr->itdb = tdb_open(NULL, 1000, TDB_INTERNAL, O_RDWR, 0);
716 if (ltdb->idxptr->itdb == NULL) {
717 return LDB_ERR_OPERATIONS_ERROR;
721 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn));
722 if (key.dptr == NULL) {
723 return LDB_ERR_OPERATIONS_ERROR;
725 key.dsize = strlen((char *)key.dptr);
727 rec = tdb_fetch(ltdb->idxptr->itdb, key);
728 if (rec.dptr != NULL) {
729 list2 = ltdb_index_idxptr(module, rec, false);
732 return LDB_ERR_OPERATIONS_ERROR;
735 list2->dn = talloc_steal(list2, list->dn);
736 list2->count = list->count;
740 list2 = talloc(ltdb->idxptr, struct dn_list);
742 return LDB_ERR_OPERATIONS_ERROR;
744 list2->dn = talloc_steal(list2, list->dn);
745 list2->count = list->count;
747 rec.dptr = (uint8_t *)&list2;
748 rec.dsize = sizeof(void *);
752 * This is not a store into the main DB, but into an in-memory
753 * TDB, so we don't need a guard on ltdb->read_only
755 ret = tdb_store(ltdb->idxptr->itdb, key, rec, TDB_INSERT);
757 return ltdb_err_map(tdb_error(ltdb->idxptr->itdb));
763 traverse function for storing the in-memory index entries on disk
765 static int ltdb_index_traverse_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
767 struct ldb_module *module = state;
768 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
770 struct ldb_context *ldb = ldb_module_get_ctx(module);
772 struct dn_list *list;
774 list = ltdb_index_idxptr(module, data, true);
776 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
781 v.length = strnlen((char *)key.dptr, key.dsize);
783 dn = ldb_dn_from_ldb_val(module, ldb, &v);
785 ldb_asprintf_errstring(ldb, "Failed to parse index key %*.*s as an LDB DN", (int)v.length, (int)v.length, (const char *)v.data);
786 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR;
790 ltdb->idxptr->error = ltdb_dn_list_store_full(module, ltdb,
793 if (ltdb->idxptr->error != 0) {
799 /* cleanup the idxptr mode when transaction commits */
800 int ltdb_index_transaction_commit(struct ldb_module *module)
802 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
805 struct ldb_context *ldb = ldb_module_get_ctx(module);
807 ldb_reset_err_string(ldb);
809 if (ltdb->idxptr->itdb) {
810 tdb_traverse(ltdb->idxptr->itdb, ltdb_index_traverse_store, module);
811 tdb_close(ltdb->idxptr->itdb);
814 ret = ltdb->idxptr->error;
815 if (ret != LDB_SUCCESS) {
816 if (!ldb_errstring(ldb)) {
817 ldb_set_errstring(ldb, ldb_strerror(ret));
819 ldb_asprintf_errstring(ldb, "Failed to store index records in transaction commit: %s", ldb_errstring(ldb));
822 talloc_free(ltdb->idxptr);
827 /* cleanup the idxptr mode when transaction cancels */
828 int ltdb_index_transaction_cancel(struct ldb_module *module)
830 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
831 if (ltdb->idxptr && ltdb->idxptr->itdb) {
832 tdb_close(ltdb->idxptr->itdb);
834 talloc_free(ltdb->idxptr);
841 return the dn key to be used for an index
842 the caller is responsible for freeing
844 static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
845 struct ltdb_private *ltdb,
846 const char *attr, const struct ldb_val *value,
847 const struct ldb_schema_attribute **ap,
848 enum key_truncation *truncation)
852 const struct ldb_schema_attribute *a = NULL;
853 char *attr_folded = NULL;
854 const char *attr_for_dn = NULL;
856 bool should_b64_encode;
858 unsigned int max_key_length = ltdb_max_key_length(ltdb);
861 const size_t indx_len = sizeof(LTDB_INDEX) - 1;
862 unsigned frmt_len = 0;
863 const size_t additional_key_length = 4;
864 unsigned int num_separators = 3; /* Estimate for overflow check */
865 const size_t min_data = 1;
866 const size_t min_key_length = additional_key_length
867 + indx_len + num_separators + min_data;
869 if (attr[0] == '@') {
876 attr_folded = ldb_attr_casefold(ldb, attr);
881 attr_for_dn = attr_folded;
883 a = ldb_schema_attribute_by_name(ldb, attr);
887 r = a->syntax->canonicalise_fn(ldb, ldb, value, &v);
888 if (r != LDB_SUCCESS) {
889 const char *errstr = ldb_errstring(ldb);
890 /* canonicalisation can be refused. For
891 example, a attribute that takes wildcards
892 will refuse to canonicalise if the value
893 contains a wildcard */
894 ldb_asprintf_errstring(ldb,
895 "Failed to create index "
896 "key for attribute '%s':%s%s%s",
897 attr, ldb_strerror(r),
900 talloc_free(attr_folded);
904 attr_len = strlen(attr_for_dn);
907 * Check if there is any hope this will fit into the DB.
908 * Overflow here is not actually critical the code below
909 * checks again to make the printf and the DB does another
910 * check for too long keys
912 if (max_key_length - attr_len < min_key_length) {
913 ldb_asprintf_errstring(
915 __location__ ": max_key_length "
916 "is too small (%u) < (%u)",
918 (unsigned)(min_key_length + attr_len));
919 talloc_free(attr_folded);
924 * ltdb_key_dn() makes something 4 bytes longer, it adds a leading
925 * "DN=" and a trailing string terminator
927 max_key_length -= additional_key_length;
930 * We do not base 64 encode a DN in a key, it has already been
931 * casefold and lineraized, that is good enough. That already
932 * avoids embedded NUL etc.
934 if (ltdb->cache->GUID_index_attribute != NULL) {
935 if (strcmp(attr, LTDB_IDXDN) == 0) {
936 should_b64_encode = false;
937 } else if (strcmp(attr, LTDB_IDXONE) == 0) {
939 * We can only change the behaviour for IDXONE
940 * when the GUID index is enabled
942 should_b64_encode = false;
945 = ldb_should_b64_encode(ldb, &v);
948 should_b64_encode = ldb_should_b64_encode(ldb, &v);
951 if (should_b64_encode) {
953 char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length);
955 talloc_free(attr_folded);
958 vstr_len = strlen(vstr);
960 * Overflow here is not critical as we only use this
961 * to choose the printf truncation
963 key_len = num_separators + indx_len + attr_len + vstr_len;
964 if (key_len > max_key_length) {
965 size_t excess = key_len - max_key_length;
966 frmt_len = vstr_len - excess;
967 *truncation = KEY_TRUNCATED;
969 * Truncated keys are placed in a separate key space
970 * from the non truncated keys
971 * Note: the double hash "##" is not a typo and
972 * indicates that the following value is base64 encoded
974 ret = ldb_dn_new_fmt(ldb, ldb, "%s#%s##%.*s",
975 LTDB_INDEX, attr_for_dn,
979 *truncation = KEY_NOT_TRUNCATED;
981 * Note: the double colon "::" is not a typo and
982 * indicates that the following value is base64 encoded
984 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%.*s",
985 LTDB_INDEX, attr_for_dn,
990 /* Only need two seperators */
994 * Overflow here is not critical as we only use this
995 * to choose the printf truncation
997 key_len = num_separators + indx_len + attr_len + (int)v.length;
998 if (key_len > max_key_length) {
999 size_t excess = key_len - max_key_length;
1000 frmt_len = v.length - excess;
1001 *truncation = KEY_TRUNCATED;
1003 * Truncated keys are placed in a separate key space
1004 * from the non truncated keys
1006 ret = ldb_dn_new_fmt(ldb, ldb, "%s#%s#%.*s",
1007 LTDB_INDEX, attr_for_dn,
1008 frmt_len, (char *)v.data);
1010 frmt_len = v.length;
1011 *truncation = KEY_NOT_TRUNCATED;
1012 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s:%.*s",
1013 LTDB_INDEX, attr_for_dn,
1014 frmt_len, (char *)v.data);
1018 if (v.data != value->data) {
1019 talloc_free(v.data);
1021 talloc_free(attr_folded);
1027 see if a attribute value is in the list of indexed attributes
1029 static bool ltdb_is_indexed(struct ldb_module *module,
1030 struct ltdb_private *ltdb,
1033 struct ldb_context *ldb = ldb_module_get_ctx(module);
1035 struct ldb_message_element *el;
1037 if ((ltdb->cache->GUID_index_attribute != NULL) &&
1039 ltdb->cache->GUID_index_attribute) == 0)) {
1040 /* Implicity covered, this is the index key */
1043 if (ldb->schema.index_handler_override) {
1044 const struct ldb_schema_attribute *a
1045 = ldb_schema_attribute_by_name(ldb, attr);
1051 if (a->flags & LDB_ATTR_FLAG_INDEXED) {
1058 if (!ltdb->cache->attribute_indexes) {
1062 el = ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXATTR);
1067 /* TODO: this is too expensive! At least use a binary search */
1068 for (i=0; i<el->num_values; i++) {
1069 if (ldb_attr_cmp((char *)el->values[i].data, attr) == 0) {
1077 in the following logic functions, the return value is treated as
1080 LDB_SUCCESS: we found some matching index values
1082 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches
1084 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call,
1085 we'll need a full search
1089 return a list of dn's that might match a simple indexed search (an
1090 equality search only)
1092 static int ltdb_index_dn_simple(struct ldb_module *module,
1093 struct ltdb_private *ltdb,
1094 const struct ldb_parse_tree *tree,
1095 struct dn_list *list)
1097 struct ldb_context *ldb;
1100 enum key_truncation truncation = KEY_NOT_TRUNCATED;
1102 ldb = ldb_module_get_ctx(module);
1107 /* if the attribute isn't in the list of indexed attributes then
1108 this node needs a full search */
1109 if (!ltdb_is_indexed(module, ltdb, tree->u.equality.attr)) {
1110 return LDB_ERR_OPERATIONS_ERROR;
1113 /* the attribute is indexed. Pull the list of DNs that match the
1115 dn = ltdb_index_key(ldb, ltdb,
1116 tree->u.equality.attr,
1117 &tree->u.equality.value, NULL, &truncation);
1119 * We ignore truncation here and allow multi-valued matches
1120 * as ltdb_search_indexed will filter out the wrong one in
1121 * ltdb_index_filter() which calls ldb_match_message().
1123 if (!dn) return LDB_ERR_OPERATIONS_ERROR;
1125 ret = ltdb_dn_list_load(module, ltdb, dn, list);
1131 static bool list_union(struct ldb_context *ldb,
1132 struct ltdb_private *ltdb,
1133 struct dn_list *list, struct dn_list *list2);
1136 return a list of dn's that might match a leaf indexed search
1138 static int ltdb_index_dn_leaf(struct ldb_module *module,
1139 struct ltdb_private *ltdb,
1140 const struct ldb_parse_tree *tree,
1141 struct dn_list *list)
1143 if (ltdb->disallow_dn_filter &&
1144 (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0)) {
1145 /* in AD mode we do not support "(dn=...)" search filters */
1150 if (tree->u.equality.attr[0] == '@') {
1151 /* Do not allow a indexed search against an @ */
1156 if (ldb_attr_dn(tree->u.equality.attr) == 0) {
1157 enum key_truncation truncation = KEY_NOT_TRUNCATED;
1159 = ldb_dn_from_ldb_val(list,
1160 ldb_module_get_ctx(module),
1161 &tree->u.equality.value);
1163 /* If we can't parse it, no match */
1170 * Re-use the same code we use for a SCOPE_BASE
1173 * We can't call TALLOC_FREE(dn) as this must belong
1174 * to list for the memory to remain valid.
1176 return ltdb_index_dn_base_dn(module, ltdb, dn, list,
1179 * We ignore truncation here and allow multi-valued matches
1180 * as ltdb_search_indexed will filter out the wrong one in
1181 * ltdb_index_filter() which calls ldb_match_message().
1184 } else if ((ltdb->cache->GUID_index_attribute != NULL) &&
1185 (ldb_attr_cmp(tree->u.equality.attr,
1186 ltdb->cache->GUID_index_attribute) == 0)) {
1188 struct ldb_context *ldb = ldb_module_get_ctx(module);
1189 list->dn = talloc_array(list, struct ldb_val, 1);
1190 if (list->dn == NULL) {
1191 ldb_module_oom(module);
1192 return LDB_ERR_OPERATIONS_ERROR;
1195 * We need to go via the canonicalise_fn() to
1196 * ensure we get the index in binary, rather
1199 ret = ltdb->GUID_index_syntax->canonicalise_fn(ldb,
1201 &tree->u.equality.value,
1203 if (ret != LDB_SUCCESS) {
1204 return LDB_ERR_OPERATIONS_ERROR;
1210 return ltdb_index_dn_simple(module, ltdb, tree, list);
1218 static bool list_intersect(struct ldb_context *ldb,
1219 struct ltdb_private *ltdb,
1220 struct dn_list *list, const struct dn_list *list2)
1222 const struct dn_list *short_list, *long_list;
1223 struct dn_list *list3;
1226 if (list->count == 0) {
1230 if (list2->count == 0) {
1237 /* the indexing code is allowed to return a longer list than
1238 what really matches, as all results are filtered by the
1239 full expression at the end - this shortcut avoids a lot of
1240 work in some cases */
1241 if (list->count < 2 && list2->count > 10 && list2->strict == false) {
1244 if (list2->count < 2 && list->count > 10 && list->strict == false) {
1245 list->count = list2->count;
1246 list->dn = list2->dn;
1247 /* note that list2 may not be the parent of list2->dn,
1248 as list2->dn may be owned by ltdb->idxptr. In that
1249 case we expect this reparent call to fail, which is
1251 talloc_reparent(list2, list, list2->dn);
1255 if (list->count > list2->count) {
1263 list3 = talloc_zero(list, struct dn_list);
1264 if (list3 == NULL) {
1268 list3->dn = talloc_array(list3, struct ldb_val,
1269 MIN(list->count, list2->count));
1276 for (i=0;i<short_list->count;i++) {
1277 /* For the GUID index case, this is a binary search */
1278 if (ltdb_dn_list_find_val(ltdb, long_list,
1279 &short_list->dn[i]) != -1) {
1280 list3->dn[list3->count] = short_list->dn[i];
1285 list->strict |= list2->strict;
1286 list->dn = talloc_steal(list, list3->dn);
1287 list->count = list3->count;
1298 static bool list_union(struct ldb_context *ldb,
1299 struct ltdb_private *ltdb,
1300 struct dn_list *list, struct dn_list *list2)
1302 struct ldb_val *dn3;
1303 unsigned int i = 0, j = 0, k = 0;
1305 if (list2->count == 0) {
1310 if (list->count == 0) {
1312 list->count = list2->count;
1313 list->dn = list2->dn;
1314 /* note that list2 may not be the parent of list2->dn,
1315 as list2->dn may be owned by ltdb->idxptr. In that
1316 case we expect this reparent call to fail, which is
1318 talloc_reparent(list2, list, list2->dn);
1323 * Sort the lists (if not in GUID DN mode) so we can do
1324 * the de-duplication during the merge
1326 * NOTE: This can sort the in-memory index values, as list or
1327 * list2 might not be a copy!
1329 ltdb_dn_list_sort(ltdb, list);
1330 ltdb_dn_list_sort(ltdb, list2);
1332 dn3 = talloc_array(list, struct ldb_val, list->count + list2->count);
1338 while (i < list->count || j < list2->count) {
1340 if (i >= list->count) {
1342 } else if (j >= list2->count) {
1345 cmp = ldb_val_equal_exact_ordered(list->dn[i],
1351 dn3[k] = list->dn[i];
1354 } else if (cmp > 0) {
1356 dn3[k] = list2->dn[j];
1360 /* Equal, take list */
1361 dn3[k] = list->dn[i];
1374 static int ltdb_index_dn(struct ldb_module *module,
1375 struct ltdb_private *ltdb,
1376 const struct ldb_parse_tree *tree,
1377 struct dn_list *list);
1381 process an OR list (a union)
1383 static int ltdb_index_dn_or(struct ldb_module *module,
1384 struct ltdb_private *ltdb,
1385 const struct ldb_parse_tree *tree,
1386 struct dn_list *list)
1388 struct ldb_context *ldb;
1391 ldb = ldb_module_get_ctx(module);
1396 for (i=0; i<tree->u.list.num_elements; i++) {
1397 struct dn_list *list2;
1400 list2 = talloc_zero(list, struct dn_list);
1401 if (list2 == NULL) {
1402 return LDB_ERR_OPERATIONS_ERROR;
1405 ret = ltdb_index_dn(module, ltdb,
1406 tree->u.list.elements[i], list2);
1408 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1414 if (ret != LDB_SUCCESS) {
1420 if (!list_union(ldb, ltdb, list, list2)) {
1422 return LDB_ERR_OPERATIONS_ERROR;
1426 if (list->count == 0) {
1427 return LDB_ERR_NO_SUCH_OBJECT;
1435 NOT an index results
1437 static int ltdb_index_dn_not(struct ldb_module *module,
1438 struct ltdb_private *ltdb,
1439 const struct ldb_parse_tree *tree,
1440 struct dn_list *list)
1442 /* the only way to do an indexed not would be if we could
1443 negate the not via another not or if we knew the total
1444 number of database elements so we could know that the
1445 existing expression covered the whole database.
1447 instead, we just give up, and rely on a full index scan
1448 (unless an outer & manages to reduce the list)
1450 return LDB_ERR_OPERATIONS_ERROR;
1454 * These things are unique, so avoid a full scan if this is a search
1455 * by GUID, DN or a unique attribute
1457 static bool ltdb_index_unique(struct ldb_context *ldb,
1458 struct ltdb_private *ltdb,
1461 const struct ldb_schema_attribute *a;
1462 if (ltdb->cache->GUID_index_attribute != NULL) {
1463 if (ldb_attr_cmp(attr, ltdb->cache->GUID_index_attribute) == 0) {
1467 if (ldb_attr_dn(attr) == 0) {
1471 a = ldb_schema_attribute_by_name(ldb, attr);
1472 if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
1479 process an AND expression (intersection)
1481 static int ltdb_index_dn_and(struct ldb_module *module,
1482 struct ltdb_private *ltdb,
1483 const struct ldb_parse_tree *tree,
1484 struct dn_list *list)
1486 struct ldb_context *ldb;
1490 ldb = ldb_module_get_ctx(module);
1495 /* in the first pass we only look for unique simple
1496 equality tests, in the hope of avoiding having to look
1498 for (i=0; i<tree->u.list.num_elements; i++) {
1499 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
1502 if (subtree->operation != LDB_OP_EQUALITY ||
1503 !ltdb_index_unique(ldb, ltdb,
1504 subtree->u.equality.attr)) {
1508 ret = ltdb_index_dn(module, ltdb, subtree, list);
1509 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1511 return LDB_ERR_NO_SUCH_OBJECT;
1513 if (ret == LDB_SUCCESS) {
1514 /* a unique index match means we can
1515 * stop. Note that we don't care if we return
1516 * a few too many objects, due to later
1522 /* now do a full intersection */
1525 for (i=0; i<tree->u.list.num_elements; i++) {
1526 const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
1527 struct dn_list *list2;
1530 list2 = talloc_zero(list, struct dn_list);
1531 if (list2 == NULL) {
1532 return ldb_module_oom(module);
1535 ret = ltdb_index_dn(module, ltdb, subtree, list2);
1537 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1542 return LDB_ERR_NO_SUCH_OBJECT;
1545 if (ret != LDB_SUCCESS) {
1546 /* this didn't adding anything */
1552 talloc_reparent(list2, list, list->dn);
1553 list->dn = list2->dn;
1554 list->count = list2->count;
1556 } else if (!list_intersect(ldb, ltdb,
1559 return LDB_ERR_OPERATIONS_ERROR;
1562 if (list->count == 0) {
1564 return LDB_ERR_NO_SUCH_OBJECT;
1567 if (list->count < 2) {
1568 /* it isn't worth loading the next part of the tree */
1574 /* none of the attributes were indexed */
1575 return LDB_ERR_OPERATIONS_ERROR;
1582 return a list of matching objects using a one-level index
1584 static int ltdb_index_dn_attr(struct ldb_module *module,
1585 struct ltdb_private *ltdb,
1588 struct dn_list *list,
1589 enum key_truncation *truncation)
1591 struct ldb_context *ldb;
1596 ldb = ldb_module_get_ctx(module);
1598 /* work out the index key from the parent DN */
1599 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(dn));
1600 val.length = strlen((char *)val.data);
1601 key = ltdb_index_key(ldb, ltdb, attr, &val, NULL, truncation);
1604 return LDB_ERR_OPERATIONS_ERROR;
1607 ret = ltdb_dn_list_load(module, ltdb, key, list);
1609 if (ret != LDB_SUCCESS) {
1613 if (list->count == 0) {
1614 return LDB_ERR_NO_SUCH_OBJECT;
1621 return a list of matching objects using a one-level index
1623 static int ltdb_index_dn_one(struct ldb_module *module,
1624 struct ltdb_private *ltdb,
1625 struct ldb_dn *parent_dn,
1626 struct dn_list *list,
1627 enum key_truncation *truncation)
1629 /* Ensure we do not shortcut on intersection for this list */
1630 list->strict = true;
1631 return ltdb_index_dn_attr(module, ltdb,
1632 LTDB_IDXONE, parent_dn, list, truncation);
1637 return a list of matching objects using the DN index
1639 static int ltdb_index_dn_base_dn(struct ldb_module *module,
1640 struct ltdb_private *ltdb,
1641 struct ldb_dn *base_dn,
1642 struct dn_list *dn_list,
1643 enum key_truncation *truncation)
1645 const struct ldb_val *guid_val = NULL;
1646 if (ltdb->cache->GUID_index_attribute == NULL) {
1647 dn_list->dn = talloc_array(dn_list, struct ldb_val, 1);
1648 if (dn_list->dn == NULL) {
1649 return ldb_module_oom(module);
1651 dn_list->dn[0].data = discard_const_p(unsigned char,
1652 ldb_dn_get_linearized(base_dn));
1653 if (dn_list->dn[0].data == NULL) {
1654 return ldb_module_oom(module);
1656 dn_list->dn[0].length = strlen((char *)dn_list->dn[0].data);
1662 if (ltdb->cache->GUID_index_dn_component != NULL) {
1663 guid_val = ldb_dn_get_extended_component(base_dn,
1664 ltdb->cache->GUID_index_dn_component);
1667 if (guid_val != NULL) {
1668 dn_list->dn = talloc_array(dn_list, struct ldb_val, 1);
1669 if (dn_list->dn == NULL) {
1670 return ldb_module_oom(module);
1672 dn_list->dn[0].data = guid_val->data;
1673 dn_list->dn[0].length = guid_val->length;
1679 return ltdb_index_dn_attr(module, ltdb,
1680 LTDB_IDXDN, base_dn, dn_list, truncation);
1684 return a list of dn's that might match a indexed search or
1685 an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
1687 static int ltdb_index_dn(struct ldb_module *module,
1688 struct ltdb_private *ltdb,
1689 const struct ldb_parse_tree *tree,
1690 struct dn_list *list)
1692 int ret = LDB_ERR_OPERATIONS_ERROR;
1694 switch (tree->operation) {
1696 ret = ltdb_index_dn_and(module, ltdb, tree, list);
1700 ret = ltdb_index_dn_or(module, ltdb, tree, list);
1704 ret = ltdb_index_dn_not(module, ltdb, tree, list);
1707 case LDB_OP_EQUALITY:
1708 ret = ltdb_index_dn_leaf(module, ltdb, tree, list);
1711 case LDB_OP_SUBSTRING:
1712 case LDB_OP_GREATER:
1714 case LDB_OP_PRESENT:
1716 case LDB_OP_EXTENDED:
1717 /* we can't index with fancy bitops yet */
1718 ret = LDB_ERR_OPERATIONS_ERROR;
1726 filter a candidate dn_list from an indexed search into a set of results
1727 extracting just the given attributes
1729 static int ltdb_index_filter(struct ltdb_private *ltdb,
1730 const struct dn_list *dn_list,
1731 struct ltdb_context *ac,
1732 uint32_t *match_count,
1733 enum key_truncation scope_one_truncation)
1735 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1736 struct ldb_message *msg;
1737 struct ldb_message *filtered_msg;
1739 unsigned int num_keys = 0;
1740 uint8_t previous_guid_key[LTDB_GUID_KEY_SIZE] = {};
1741 TDB_DATA *keys = NULL;
1744 * We have to allocate the key list (rather than just walk the
1745 * caller supplied list) as the callback could change the list
1746 * (by modifying an indexed attribute hosted in the in-memory
1749 keys = talloc_array(ac, TDB_DATA, dn_list->count);
1751 return ldb_module_oom(ac->module);
1754 if (ltdb->cache->GUID_index_attribute != NULL) {
1756 * We speculate that the keys will be GUID based and so
1757 * pre-fill in enough space for a GUID (avoiding a pile of
1758 * small allocations)
1760 struct guid_tdb_key {
1761 uint8_t guid_key[LTDB_GUID_KEY_SIZE];
1762 } *key_values = NULL;
1764 key_values = talloc_array(keys,
1765 struct guid_tdb_key,
1768 for (i = 0; i < dn_list->count; i++) {
1769 keys[i].dptr = key_values[i].guid_key;
1770 keys[i].dsize = sizeof(key_values[i].guid_key);
1772 if (key_values == NULL) {
1773 return ldb_module_oom(ac->module);
1776 for (i = 0; i < dn_list->count; i++) {
1777 keys[i].dptr = NULL;
1782 for (i = 0; i < dn_list->count; i++) {
1785 ret = ltdb_idx_to_key(ac->module,
1790 if (ret != LDB_SUCCESS) {
1794 if (ltdb->cache->GUID_index_attribute != NULL) {
1796 * If we are in GUID index mode, then the dn_list is
1797 * sorted. If we got a duplicate, forget about it, as
1798 * otherwise we would send the same entry back more
1801 * This is needed in the truncated DN case, or if a
1802 * duplicate was forced in via
1803 * LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK
1806 if (memcmp(previous_guid_key,
1807 keys[num_keys].dptr,
1808 sizeof(previous_guid_key)) == 0) {
1812 memcpy(previous_guid_key,
1813 keys[num_keys].dptr,
1814 sizeof(previous_guid_key));
1821 * Now that the list is a safe copy, send the callbacks
1823 for (i = 0; i < num_keys; i++) {
1826 msg = ldb_msg_new(ac);
1828 return LDB_ERR_OPERATIONS_ERROR;
1831 ret = ltdb_search_key(ac->module, ltdb,
1833 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC|
1834 LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC);
1835 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1837 * the record has disappeared? yes, this can
1838 * happen if the entry is deleted by something
1839 * operating in the callback (not another
1840 * process, as we have a read lock)
1846 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
1847 /* an internal error */
1849 return LDB_ERR_OPERATIONS_ERROR;
1853 * We trust the index for LDB_SCOPE_ONELEVEL
1854 * unless the index key has been truncated.
1856 * LDB_SCOPE_BASE is not passed in by our only caller.
1858 if (ac->scope == LDB_SCOPE_ONELEVEL
1859 && ltdb->cache->one_level_indexes
1860 && scope_one_truncation == KEY_NOT_TRUNCATED) {
1861 ret = ldb_match_message(ldb, msg, ac->tree,
1862 ac->scope, &matched);
1864 ret = ldb_match_msg_error(ldb, msg,
1866 ac->scope, &matched);
1869 if (ret != LDB_SUCCESS) {
1878 /* filter the attributes that the user wants */
1879 ret = ltdb_filter_attrs(ac, msg, ac->attrs, &filtered_msg);
1884 return LDB_ERR_OPERATIONS_ERROR;
1887 ret = ldb_module_send_entry(ac->req, filtered_msg, NULL);
1888 if (ret != LDB_SUCCESS) {
1889 /* Regardless of success or failure, the msg
1890 * is the callbacks responsiblity, and should
1891 * not be talloc_free()'ed */
1892 ac->request_terminated = true;
1906 static void ltdb_dn_list_sort(struct ltdb_private *ltdb,
1907 struct dn_list *list)
1909 if (list->count < 2) {
1913 /* We know the list is sorted when using the GUID index */
1914 if (ltdb->cache->GUID_index_attribute != NULL) {
1918 TYPESAFE_QSORT(list->dn, list->count,
1919 ldb_val_equal_exact_for_qsort);
1923 search the database with a LDAP-like expression using indexes
1924 returns -1 if an indexed search is not possible, in which
1925 case the caller should call ltdb_search_full()
1927 int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
1929 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1930 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(ac->module), struct ltdb_private);
1931 struct dn_list *dn_list;
1933 enum ldb_scope index_scope;
1934 enum key_truncation scope_one_truncation = KEY_NOT_TRUNCATED;
1936 /* see if indexing is enabled */
1937 if (!ltdb->cache->attribute_indexes &&
1938 !ltdb->cache->one_level_indexes &&
1939 ac->scope != LDB_SCOPE_BASE) {
1940 /* fallback to a full search */
1941 return LDB_ERR_OPERATIONS_ERROR;
1944 dn_list = talloc_zero(ac, struct dn_list);
1945 if (dn_list == NULL) {
1946 return ldb_module_oom(ac->module);
1950 * For the purposes of selecting the switch arm below, if we
1951 * don't have a one-level index then treat it like a subtree
1954 if (ac->scope == LDB_SCOPE_ONELEVEL &&
1955 !ltdb->cache->one_level_indexes) {
1956 index_scope = LDB_SCOPE_SUBTREE;
1958 index_scope = ac->scope;
1961 switch (index_scope) {
1962 case LDB_SCOPE_BASE:
1964 * The only caller will have filtered the operation out
1965 * so we should never get here
1967 return ldb_operr(ldb);
1969 case LDB_SCOPE_ONELEVEL:
1971 * If we ever start to also load the index values for
1972 * the tree, we must ensure we strictly intersect with
1973 * this list, as we trust the ONELEVEL index
1975 ret = ltdb_index_dn_one(ac->module, ltdb, ac->base, dn_list,
1976 &scope_one_truncation);
1977 if (ret != LDB_SUCCESS) {
1978 talloc_free(dn_list);
1983 * If we have too many matches, running the filter
1984 * tree over the SCOPE_ONELEVEL can be quite expensive
1985 * so we now check the filter tree index as well.
1987 * We only do this in the GUID index mode, which is
1988 * O(n*log(m)) otherwise the intersection below will
1989 * be too costly at O(n*m).
1991 * We don't set a heuristic for 'too many' but instead
1992 * do it always and rely on the index lookup being
1993 * fast enough in the small case.
1995 if (ltdb->cache->GUID_index_attribute != NULL) {
1996 struct dn_list *idx_one_tree_list
1997 = talloc_zero(ac, struct dn_list);
1998 if (idx_one_tree_list == NULL) {
1999 return ldb_module_oom(ac->module);
2002 if (!ltdb->cache->attribute_indexes) {
2003 talloc_free(idx_one_tree_list);
2004 talloc_free(dn_list);
2005 return LDB_ERR_OPERATIONS_ERROR;
2008 * Here we load the index for the tree.
2010 * We only care if this is successful, if the
2011 * index can't trim the result list down then
2012 * the ONELEVEL index is still good enough.
2014 ret = ltdb_index_dn(ac->module, ltdb, ac->tree,
2016 if (ret == LDB_SUCCESS) {
2017 if (!list_intersect(ldb, ltdb,
2019 idx_one_tree_list)) {
2020 talloc_free(idx_one_tree_list);
2021 talloc_free(dn_list);
2022 return LDB_ERR_OPERATIONS_ERROR;
2028 case LDB_SCOPE_SUBTREE:
2029 case LDB_SCOPE_DEFAULT:
2030 if (!ltdb->cache->attribute_indexes) {
2031 talloc_free(dn_list);
2032 return LDB_ERR_OPERATIONS_ERROR;
2035 * Here we load the index for the tree. We have no
2036 * index for the subtree.
2038 ret = ltdb_index_dn(ac->module, ltdb, ac->tree, dn_list);
2039 if (ret != LDB_SUCCESS) {
2040 talloc_free(dn_list);
2047 * It is critical that this function do the re-filter even
2048 * on things found by the index as the index can over-match
2049 * in cases of truncation (as well as when it decides it is
2050 * not worth further filtering)
2052 * If this changes, then the index code above would need to
2053 * pass up a flag to say if any index was truncated during
2054 * processing as the truncation here refers only to the
2055 * SCOPE_ONELEVEL index.
2057 ret = ltdb_index_filter(ltdb, dn_list, ac, match_count,
2058 scope_one_truncation);
2059 talloc_free(dn_list);
2064 * @brief Add a DN in the index list of a given attribute name/value pair
2066 * This function will add the DN in the index list for the index for
2067 * the given attribute name and value.
2069 * @param[in] module A ldb_module structure
2071 * @param[in] dn The string representation of the DN as it
2072 * will be stored in the index entry
2074 * @param[in] el A ldb_message_element array, one of the entry
2075 * referred by the v_idx is the attribute name and
2076 * value pair which will be used to construct the
2079 * @param[in] v_idx The index of element in the el array to use
2081 * @return An ldb error code
2083 static int ltdb_index_add1(struct ldb_module *module,
2084 struct ltdb_private *ltdb,
2085 const struct ldb_message *msg,
2086 struct ldb_message_element *el, int v_idx)
2088 struct ldb_context *ldb;
2089 struct ldb_dn *dn_key;
2091 const struct ldb_schema_attribute *a;
2092 struct dn_list *list;
2094 enum key_truncation truncation = KEY_TRUNCATED;
2097 ldb = ldb_module_get_ctx(module);
2099 list = talloc_zero(module, struct dn_list);
2101 return LDB_ERR_OPERATIONS_ERROR;
2104 dn_key = ltdb_index_key(ldb, ltdb,
2105 el->name, &el->values[v_idx], &a, &truncation);
2108 return LDB_ERR_OPERATIONS_ERROR;
2111 * Samba only maintains unique indexes on the objectSID and objectGUID
2112 * so if a unique index key exceeds the maximum length there is a
2115 if ((truncation == KEY_TRUNCATED) && (a != NULL &&
2116 (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX ||
2117 (el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX)))) {
2119 ldb_asprintf_errstring(
2121 __location__ ": unique index key on %s in %s, "
2122 "exceeds maximum key length of %u (encoded).",
2124 ldb_dn_get_linearized(msg->dn),
2125 ltdb->max_key_length);
2127 return LDB_ERR_CONSTRAINT_VIOLATION;
2129 talloc_steal(list, dn_key);
2131 ret = ltdb_dn_list_load(module, ltdb, dn_key, list);
2132 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
2138 * Check for duplicates in the @IDXDN DN -> GUID record
2140 * This is very normal, it just means a duplicate DN creation
2141 * was attempted, so don't set the error string or print scary
2144 if (list->count > 0 &&
2145 ldb_attr_cmp(el->name, LTDB_IDXDN) == 0 &&
2146 truncation == KEY_NOT_TRUNCATED) {
2149 return LDB_ERR_CONSTRAINT_VIOLATION;
2151 } else if (list->count > 0
2152 && ldb_attr_cmp(el->name, LTDB_IDXDN) == 0) {
2155 * At least one existing entry in the DN->GUID index, which
2156 * arises when the DN indexes have been truncated
2158 * So need to pull the DN's to check if it's really a duplicate
2161 for (i=0; i < list->count; i++) {
2162 uint8_t guid_key[LTDB_GUID_KEY_SIZE];
2165 .dsize = sizeof(guid_key)
2167 const int flags = LDB_UNPACK_DATA_FLAG_NO_ATTRS;
2168 struct ldb_message *rec = ldb_msg_new(ldb);
2170 return LDB_ERR_OPERATIONS_ERROR;
2173 ret = ltdb_idx_to_key(module, ltdb,
2176 if (ret != LDB_SUCCESS) {
2182 ret = ltdb_search_key(module, ltdb, key,
2184 if (key.dptr != guid_key) {
2185 TALLOC_FREE(key.dptr);
2187 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2189 * the record has disappeared?
2190 * yes, this can happen
2196 if (ret != LDB_SUCCESS) {
2197 /* an internal error */
2200 return LDB_ERR_OPERATIONS_ERROR;
2203 * The DN we are trying to add to the DB and index
2204 * is already here, so we must deny the addition
2206 if (ldb_dn_compare(msg->dn, rec->dn) == 0) {
2209 return LDB_ERR_CONSTRAINT_VIOLATION;
2215 * Check for duplicates in unique indexes
2217 * We don't need to do a loop test like the @IDXDN case
2218 * above as we have a ban on long unique index values
2219 * at the start of this function.
2221 if (list->count > 0 &&
2223 && (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX ||
2224 (el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX))))) {
2226 * We do not want to print info about a possibly
2227 * confidential DN that the conflict was with in the
2228 * user-visible error string
2231 if (ltdb->cache->GUID_index_attribute == NULL) {
2232 ldb_debug(ldb, LDB_DEBUG_WARNING,
2234 ": unique index violation on %s in %s, "
2235 "conficts with %*.*s in %s",
2236 el->name, ldb_dn_get_linearized(msg->dn),
2237 (int)list->dn[0].length,
2238 (int)list->dn[0].length,
2240 ldb_dn_get_linearized(dn_key));
2242 /* This can't fail, gives a default at worst */
2243 const struct ldb_schema_attribute *attr
2244 = ldb_schema_attribute_by_name(
2246 ltdb->cache->GUID_index_attribute);
2248 ret = attr->syntax->ldif_write_fn(ldb, list,
2250 if (ret == LDB_SUCCESS) {
2251 ldb_debug(ldb, LDB_DEBUG_WARNING,
2253 ": unique index violation on %s in "
2254 "%s, conficts with %s %*.*s in %s",
2256 ldb_dn_get_linearized(msg->dn),
2257 ltdb->cache->GUID_index_attribute,
2261 ldb_dn_get_linearized(dn_key));
2264 ldb_asprintf_errstring(ldb,
2265 __location__ ": unique index violation "
2268 ldb_dn_get_linearized(msg->dn));
2270 return LDB_ERR_CONSTRAINT_VIOLATION;
2273 /* overallocate the list a bit, to reduce the number of
2274 * realloc trigered copies */
2275 alloc_len = ((list->count+1)+7) & ~7;
2276 list->dn = talloc_realloc(list, list->dn, struct ldb_val, alloc_len);
2277 if (list->dn == NULL) {
2279 return LDB_ERR_OPERATIONS_ERROR;
2282 if (ltdb->cache->GUID_index_attribute == NULL) {
2283 const char *dn_str = ldb_dn_get_linearized(msg->dn);
2284 list->dn[list->count].data
2285 = (uint8_t *)talloc_strdup(list->dn, dn_str);
2286 if (list->dn[list->count].data == NULL) {
2288 return LDB_ERR_OPERATIONS_ERROR;
2290 list->dn[list->count].length = strlen(dn_str);
2292 const struct ldb_val *key_val;
2293 struct ldb_val *exact = NULL, *next = NULL;
2294 key_val = ldb_msg_find_ldb_val(msg,
2295 ltdb->cache->GUID_index_attribute);
2296 if (key_val == NULL) {
2298 return ldb_module_operr(module);
2301 if (key_val->length != LTDB_GUID_SIZE) {
2303 return ldb_module_operr(module);
2306 BINARY_ARRAY_SEARCH_GTE(list->dn, list->count,
2307 *key_val, ldb_val_equal_exact_ordered,
2311 * Give a warning rather than fail, this could be a
2312 * duplicate value in the record allowed by a caller
2313 * forcing in the value with
2314 * LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK
2316 if (exact != NULL && truncation == KEY_NOT_TRUNCATED) {
2317 /* This can't fail, gives a default at worst */
2318 const struct ldb_schema_attribute *attr
2319 = ldb_schema_attribute_by_name(
2321 ltdb->cache->GUID_index_attribute);
2323 ret = attr->syntax->ldif_write_fn(ldb, list,
2325 if (ret == LDB_SUCCESS) {
2326 ldb_debug(ldb, LDB_DEBUG_WARNING,
2328 ": duplicate attribute value in %s "
2330 "duplicate of %s %*.*s in %s",
2331 ldb_dn_get_linearized(msg->dn),
2333 ltdb->cache->GUID_index_attribute,
2337 ldb_dn_get_linearized(dn_key));
2342 next = &list->dn[list->count];
2344 memmove(&next[1], next,
2345 sizeof(*next) * (list->count - (next - list->dn)));
2347 *next = ldb_val_dup(list->dn, key_val);
2348 if (next->data == NULL) {
2350 return ldb_module_operr(module);
2355 ret = ltdb_dn_list_store(module, dn_key, list);
2363 add index entries for one elements in a message
2365 static int ltdb_index_add_el(struct ldb_module *module,
2366 struct ltdb_private *ltdb,
2367 const struct ldb_message *msg,
2368 struct ldb_message_element *el)
2371 for (i = 0; i < el->num_values; i++) {
2372 int ret = ltdb_index_add1(module, ltdb,
2374 if (ret != LDB_SUCCESS) {
2383 add index entries for all elements in a message
2385 static int ltdb_index_add_all(struct ldb_module *module,
2386 struct ltdb_private *ltdb,
2387 const struct ldb_message *msg)
2389 struct ldb_message_element *elements = msg->elements;
2394 if (ldb_dn_is_special(msg->dn)) {
2398 dn_str = ldb_dn_get_linearized(msg->dn);
2399 if (dn_str == NULL) {
2400 return LDB_ERR_OPERATIONS_ERROR;
2403 ret = ltdb_write_index_dn_guid(module, msg, 1);
2404 if (ret != LDB_SUCCESS) {
2408 if (!ltdb->cache->attribute_indexes) {
2409 /* no indexed fields */
2413 for (i = 0; i < msg->num_elements; i++) {
2414 if (!ltdb_is_indexed(module, ltdb, elements[i].name)) {
2417 ret = ltdb_index_add_el(module, ltdb,
2419 if (ret != LDB_SUCCESS) {
2420 struct ldb_context *ldb = ldb_module_get_ctx(module);
2421 ldb_asprintf_errstring(ldb,
2422 __location__ ": Failed to re-index %s in %s - %s",
2423 elements[i].name, dn_str,
2424 ldb_errstring(ldb));
2434 insert a DN index for a message
2436 static int ltdb_modify_index_dn(struct ldb_module *module,
2437 struct ltdb_private *ltdb,
2438 const struct ldb_message *msg,
2440 const char *index, int add)
2442 struct ldb_message_element el;
2446 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(dn));
2447 if (val.data == NULL) {
2448 const char *dn_str = ldb_dn_get_linearized(dn);
2449 ldb_asprintf_errstring(ldb_module_get_ctx(module),
2451 ": Failed to modify %s "
2452 "against %s in %s: failed "
2453 "to get casefold DN",
2455 ltdb->cache->GUID_index_attribute,
2457 return LDB_ERR_OPERATIONS_ERROR;
2460 val.length = strlen((char *)val.data);
2466 ret = ltdb_index_add1(module, ltdb, msg, &el, 0);
2467 } else { /* delete */
2468 ret = ltdb_index_del_value(module, ltdb, msg, &el, 0);
2471 if (ret != LDB_SUCCESS) {
2472 struct ldb_context *ldb = ldb_module_get_ctx(module);
2473 const char *dn_str = ldb_dn_get_linearized(dn);
2474 ldb_asprintf_errstring(ldb,
2476 ": Failed to modify %s "
2477 "against %s in %s - %s",
2479 ltdb->cache->GUID_index_attribute,
2480 dn_str, ldb_errstring(ldb));
2487 insert a one level index for a message
2489 static int ltdb_index_onelevel(struct ldb_module *module,
2490 const struct ldb_message *msg, int add)
2492 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module),
2493 struct ltdb_private);
2497 /* We index for ONE Level only if requested */
2498 if (!ltdb->cache->one_level_indexes) {
2502 pdn = ldb_dn_get_parent(module, msg->dn);
2504 return LDB_ERR_OPERATIONS_ERROR;
2506 ret = ltdb_modify_index_dn(module, ltdb,
2507 msg, pdn, LTDB_IDXONE, add);
2515 insert a one level index for a message
2517 static int ltdb_write_index_dn_guid(struct ldb_module *module,
2518 const struct ldb_message *msg,
2522 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module),
2523 struct ltdb_private);
2525 /* We index for DN only if using a GUID index */
2526 if (ltdb->cache->GUID_index_attribute == NULL) {
2530 ret = ltdb_modify_index_dn(module, ltdb, msg, msg->dn,
2533 if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
2534 ldb_asprintf_errstring(ldb_module_get_ctx(module),
2535 "Entry %s already exists",
2536 ldb_dn_get_linearized(msg->dn));
2537 ret = LDB_ERR_ENTRY_ALREADY_EXISTS;
2543 add the index entries for a new element in a record
2544 The caller guarantees that these element values are not yet indexed
2546 int ltdb_index_add_element(struct ldb_module *module,
2547 struct ltdb_private *ltdb,
2548 const struct ldb_message *msg,
2549 struct ldb_message_element *el)
2551 if (ldb_dn_is_special(msg->dn)) {
2554 if (!ltdb_is_indexed(module, ltdb, el->name)) {
2557 return ltdb_index_add_el(module, ltdb, msg, el);
2561 add the index entries for a new record
2563 int ltdb_index_add_new(struct ldb_module *module,
2564 struct ltdb_private *ltdb,
2565 const struct ldb_message *msg)
2569 if (ldb_dn_is_special(msg->dn)) {
2573 ret = ltdb_index_add_all(module, ltdb, msg);
2574 if (ret != LDB_SUCCESS) {
2576 * Because we can't trust the caller to be doing
2577 * transactions properly, clean up any index for this
2578 * entry rather than relying on a transaction
2582 ltdb_index_delete(module, msg);
2586 ret = ltdb_index_onelevel(module, msg, 1);
2587 if (ret != LDB_SUCCESS) {
2589 * Because we can't trust the caller to be doing
2590 * transactions properly, clean up any index for this
2591 * entry rather than relying on a transaction
2594 ltdb_index_delete(module, msg);
2602 delete an index entry for one message element
2604 int ltdb_index_del_value(struct ldb_module *module,
2605 struct ltdb_private *ltdb,
2606 const struct ldb_message *msg,
2607 struct ldb_message_element *el, unsigned int v_idx)
2609 struct ldb_context *ldb;
2610 struct ldb_dn *dn_key;
2614 struct dn_list *list;
2615 struct ldb_dn *dn = msg->dn;
2616 enum key_truncation truncation = KEY_NOT_TRUNCATED;
2618 ldb = ldb_module_get_ctx(module);
2620 dn_str = ldb_dn_get_linearized(dn);
2621 if (dn_str == NULL) {
2622 return LDB_ERR_OPERATIONS_ERROR;
2625 if (dn_str[0] == '@') {
2629 dn_key = ltdb_index_key(ldb, ltdb,
2630 el->name, &el->values[v_idx],
2633 * We ignore key truncation in ltdb_index_add1() so
2634 * match that by ignoring it here as well
2636 * Multiple values are legitimate and accepted
2639 return LDB_ERR_OPERATIONS_ERROR;
2642 list = talloc_zero(dn_key, struct dn_list);
2644 talloc_free(dn_key);
2645 return LDB_ERR_OPERATIONS_ERROR;
2648 ret = ltdb_dn_list_load(module, ltdb, dn_key, list);
2649 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2650 /* it wasn't indexed. Did we have an earlier error? If we did then
2652 talloc_free(dn_key);
2656 if (ret != LDB_SUCCESS) {
2657 talloc_free(dn_key);
2662 * Find one of the values matching this message to remove
2664 i = ltdb_dn_list_find_msg(ltdb, list, msg);
2666 /* nothing to delete */
2667 talloc_free(dn_key);
2671 j = (unsigned int) i;
2672 if (j != list->count - 1) {
2673 memmove(&list->dn[j], &list->dn[j+1], sizeof(list->dn[0])*(list->count - (j+1)));
2676 if (list->count == 0) {
2677 talloc_free(list->dn);
2680 list->dn = talloc_realloc(list, list->dn, struct ldb_val, list->count);
2683 ret = ltdb_dn_list_store(module, dn_key, list);
2685 talloc_free(dn_key);
2691 delete the index entries for a element
2692 return -1 on failure
2694 int ltdb_index_del_element(struct ldb_module *module,
2695 struct ltdb_private *ltdb,
2696 const struct ldb_message *msg,
2697 struct ldb_message_element *el)
2703 if (!ltdb->cache->attribute_indexes) {
2704 /* no indexed fields */
2708 dn_str = ldb_dn_get_linearized(msg->dn);
2709 if (dn_str == NULL) {
2710 return LDB_ERR_OPERATIONS_ERROR;
2713 if (dn_str[0] == '@') {
2717 if (!ltdb_is_indexed(module, ltdb, el->name)) {
2720 for (i = 0; i < el->num_values; i++) {
2721 ret = ltdb_index_del_value(module, ltdb, msg, el, i);
2722 if (ret != LDB_SUCCESS) {
2731 delete the index entries for a record
2732 return -1 on failure
2734 int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg)
2736 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
2740 if (ldb_dn_is_special(msg->dn)) {
2744 ret = ltdb_index_onelevel(module, msg, 0);
2745 if (ret != LDB_SUCCESS) {
2749 ret = ltdb_write_index_dn_guid(module, msg, 0);
2750 if (ret != LDB_SUCCESS) {
2754 if (!ltdb->cache->attribute_indexes) {
2755 /* no indexed fields */
2759 for (i = 0; i < msg->num_elements; i++) {
2760 ret = ltdb_index_del_element(module, ltdb,
2761 msg, &msg->elements[i]);
2762 if (ret != LDB_SUCCESS) {
2772 traversal function that deletes all @INDEX records in the in-memory
2775 This does not touch the actual DB, that is done at transaction
2776 commit, which in turn greatly reduces DB churn as we will likely
2777 be able to do a direct update into the old record.
2779 static int delete_index(struct ltdb_private *ltdb, struct ldb_val key, struct ldb_val data, void *state)
2781 struct ldb_module *module = state;
2782 const char *dnstr = "DN=" LTDB_INDEX ":";
2783 struct dn_list list;
2788 if (strncmp((char *)key.data, dnstr, strlen(dnstr)) != 0) {
2791 /* we need to put a empty list in the internal tdb for this
2796 /* the offset of 3 is to remove the DN= prefix. */
2797 v.data = key.data + 3;
2798 v.length = strnlen((char *)key.data, key.length) - 3;
2800 dn = ldb_dn_from_ldb_val(ltdb, ldb_module_get_ctx(module), &v);
2803 * This does not actually touch the DB quite yet, just
2804 * the in-memory index cache
2806 ret = ltdb_dn_list_store(module, dn, &list);
2807 if (ret != LDB_SUCCESS) {
2808 ldb_asprintf_errstring(ldb_module_get_ctx(module),
2809 "Unable to store null index for %s\n",
2810 ldb_dn_get_linearized(dn));
2819 traversal function that adds @INDEX records during a re index TODO wrong comment
2821 static int re_key(struct ltdb_private *ltdb, struct ldb_val ldb_key, struct ldb_val val, void *state)
2823 struct ldb_context *ldb;
2824 struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
2825 struct ldb_module *module = ctx->module;
2826 struct ldb_message *msg;
2827 unsigned int nb_elements_in_db;
2832 .dptr = ldb_key.data,
2833 .dsize = ldb_key.length
2836 ldb = ldb_module_get_ctx(module);
2838 if (key.dsize > 4 &&
2839 memcmp(key.dptr, "DN=@", 4) == 0) {
2843 is_record = ltdb_key_is_record(key);
2844 if (is_record == false) {
2848 msg = ldb_msg_new(module);
2853 ret = ldb_unpack_data_only_attr_list_flags(ldb, &val,
2856 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC,
2857 &nb_elements_in_db);
2859 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
2860 ldb_dn_get_linearized(msg->dn));
2866 if (msg->dn == NULL) {
2867 ldb_debug(ldb, LDB_DEBUG_ERROR,
2868 "Refusing to re-index as GUID "
2869 "key %*.*s with no DN\n",
2870 (int)key.dsize, (int)key.dsize,
2876 /* check if the DN key has changed, perhaps due to the case
2877 insensitivity of an element changing, or a change from DN
2879 key2 = ltdb_key_msg(module, msg, msg);
2880 if (key2.dptr == NULL) {
2881 /* probably a corrupt record ... darn */
2882 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s",
2883 ldb_dn_get_linearized(msg->dn));
2887 if (key.dsize != key2.dsize ||
2888 (memcmp(key.dptr, key2.dptr, key.dsize) != 0)) {
2889 struct ldb_val ldb_key2 = {
2891 .length = key2.dsize
2893 ltdb->kv_ops->update_in_iterate(ltdb, ldb_key, ldb_key2, val, ctx);
2895 talloc_free(key2.dptr);
2900 if (ctx->count % 10000 == 0) {
2901 ldb_debug(ldb, LDB_DEBUG_WARNING,
2902 "Reindexing: re-keyed %u records so far",
2910 traversal function that adds @INDEX records during a re index
2912 static int re_index(struct ltdb_private *ltdb, struct ldb_val ldb_key, struct ldb_val val, void *state)
2914 struct ldb_context *ldb;
2915 struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
2916 struct ldb_module *module = ctx->module;
2917 struct ldb_message *msg;
2918 unsigned int nb_elements_in_db;
2920 .dptr = ldb_key.data,
2921 .dsize = ldb_key.length
2926 ldb = ldb_module_get_ctx(module);
2928 if (key.dsize > 4 &&
2929 memcmp(key.dptr, "DN=@", 4) == 0) {
2933 is_record = ltdb_key_is_record(key);
2934 if (is_record == false) {
2938 msg = ldb_msg_new(module);
2943 ret = ldb_unpack_data_only_attr_list_flags(ldb, &val,
2946 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC,
2947 &nb_elements_in_db);
2949 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
2950 ldb_dn_get_linearized(msg->dn));
2956 if (msg->dn == NULL) {
2957 ldb_debug(ldb, LDB_DEBUG_ERROR,
2958 "Refusing to re-index as GUID "
2959 "key %*.*s with no DN\n",
2960 (int)key.dsize, (int)key.dsize,
2966 ret = ltdb_index_onelevel(module, msg, 1);
2967 if (ret != LDB_SUCCESS) {
2968 ldb_debug(ldb, LDB_DEBUG_ERROR,
2969 "Adding special ONE LEVEL index failed (%s)!",
2970 ldb_dn_get_linearized(msg->dn));
2975 ret = ltdb_index_add_all(module, ltdb, msg);
2977 if (ret != LDB_SUCCESS) {
2986 if (ctx->count % 10000 == 0) {
2987 ldb_debug(ldb, LDB_DEBUG_WARNING,
2988 "Reindexing: re-indexed %u records so far",
2996 force a complete reindex of the database
2998 int ltdb_reindex(struct ldb_module *module)
3000 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
3002 struct ltdb_reindex_context ctx;
3005 * Only triggered after a modification, but make clear we do
3006 * not re-index a read-only DB
3008 if (ltdb->read_only) {
3009 return LDB_ERR_UNWILLING_TO_PERFORM;
3012 if (ltdb_cache_reload(module) != 0) {
3013 return LDB_ERR_OPERATIONS_ERROR;
3017 * Ensure we read (and so remove) the entries from the real
3018 * DB, no values stored so far are any use as we want to do a
3021 ltdb_index_transaction_cancel(module);
3023 ret = ltdb_index_transaction_start(module);
3024 if (ret != LDB_SUCCESS) {
3028 /* first traverse the database deleting any @INDEX records by
3029 * putting NULL entries in the in-memory tdb
3031 ret = ltdb->kv_ops->iterate(ltdb, delete_index, module);
3033 struct ldb_context *ldb = ldb_module_get_ctx(module);
3034 ldb_asprintf_errstring(ldb, "index deletion traverse failed: %s",
3035 ldb_errstring(ldb));
3036 return LDB_ERR_OPERATIONS_ERROR;
3039 ctx.module = module;
3043 ret = ltdb->kv_ops->iterate(ltdb, re_key, &ctx);
3045 struct ldb_context *ldb = ldb_module_get_ctx(module);
3046 ldb_asprintf_errstring(ldb, "key correction traverse failed: %s",
3047 ldb_errstring(ldb));
3048 return LDB_ERR_OPERATIONS_ERROR;
3051 if (ctx.error != LDB_SUCCESS) {
3052 struct ldb_context *ldb = ldb_module_get_ctx(module);
3053 ldb_asprintf_errstring(ldb, "reindexing failed: %s", ldb_errstring(ldb));
3060 /* now traverse adding any indexes for normal LDB records */
3061 ret = ltdb->kv_ops->iterate(ltdb, re_index, &ctx);
3063 struct ldb_context *ldb = ldb_module_get_ctx(module);
3064 ldb_asprintf_errstring(ldb, "reindexing traverse failed: %s",
3065 ldb_errstring(ldb));
3066 return LDB_ERR_OPERATIONS_ERROR;
3069 if (ctx.error != LDB_SUCCESS) {
3070 struct ldb_context *ldb = ldb_module_get_ctx(module);
3071 ldb_asprintf_errstring(ldb, "reindexing failed: %s", ldb_errstring(ldb));
3075 if (ctx.count > 10000) {
3076 ldb_debug(ldb_module_get_ctx(module),
3077 LDB_DEBUG_WARNING, "Reindexing: re_index successful on %s, "
3078 "final index write-out will be in transaction commit",
3079 ltdb->kv_ops->name(ltdb));