4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 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, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Component: ldb tdb backend - indexing
30 * Description: indexing routines for ldb tdb backend
32 * Author: Andrew Tridgell
36 #include "ldb/include/includes.h"
38 #include "ldb/ldb_tdb/ldb_tdb.h"
41 find an element in a list, using the given comparison function and
42 assuming that the list is already sorted using comp_fn
44 return -1 if not found, or the index of the first occurance of needle if found
46 static int ldb_list_find(const void *needle
,
47 const void *base
, size_t nmemb
, size_t size
,
48 comparison_fn_t comp_fn
)
50 const char *base_p
= base
;
51 size_t min_i
, max_i
, test_i
;
60 while (min_i
< max_i
) {
63 test_i
= (min_i
+ max_i
) / 2;
64 /* the following cast looks strange, but is
65 correct. The key to understanding it is that base_p
66 is a pointer to an array of pointers, so we have to
67 dereference it after casting to void **. The strange
68 const in the middle gives us the right type of pointer
69 after the dereference (tridge) */
70 r
= comp_fn(needle
, *(void * const *)(base_p
+ (size
* test_i
)));
72 /* scan back for first element */
74 comp_fn(needle
, *(void * const *)(base_p
+ (size
* (test_i
-1)))) == 0) {
90 if (comp_fn(needle
, *(void * const *)(base_p
+ (size
* min_i
))) == 0) {
103 return the dn key to be used for an index
106 static struct ldb_dn
*ltdb_index_key(struct ldb_context
*ldb
,
107 const char *attr
, const struct ldb_val
*value
)
111 const struct ldb_attrib_handler
*h
;
115 attr_folded
= ldb_attr_casefold(ldb
, attr
);
120 h
= ldb_attrib_handler(ldb
, attr
);
121 r
= h
->canonicalise_fn(ldb
, ldb
, value
, &v
);
122 if (r
!= LDB_SUCCESS
) {
123 /* canonicalisation can be refused. For example,
124 a attribute that takes wildcards will refuse to canonicalise
125 if the value contains a wildcard */
126 ldb_asprintf_errstring(ldb
, "Failed to create index key for attribute '%s':%s:%s",
127 attr
, ldb_strerror(r
), ldb_errstring(ldb
));
128 talloc_free(attr_folded
);
131 if (ldb_should_b64_encode(&v
)) {
132 char *vstr
= ldb_base64_encode(ldb
, (char *)v
.data
, v
.length
);
133 if (!vstr
) return NULL
;
134 ret
= ldb_dn_new_fmt(ldb
, ldb
, "%s:%s::%s", LTDB_INDEX
, attr_folded
, vstr
);
137 ret
= ldb_dn_new_fmt(ldb
, ldb
, "%s:%s:%.*s", LTDB_INDEX
, attr_folded
, (int)v
.length
, (char *)v
.data
);
140 if (v
.data
!= value
->data
) {
143 talloc_free(attr_folded
);
149 see if a attribute value is in the list of indexed attributes
151 static int ldb_msg_find_idx(const struct ldb_message
*msg
, const char *attr
,
152 unsigned int *v_idx
, const char *key
)
155 for (i
=0;i
<msg
->num_elements
;i
++) {
156 if (ldb_attr_cmp(msg
->elements
[i
].name
, key
) == 0) {
157 const struct ldb_message_element
*el
=
159 for (j
=0;j
<el
->num_values
;j
++) {
160 if (ldb_attr_cmp((char *)el
->values
[j
].data
, attr
) == 0) {
172 /* used in sorting dn lists */
173 static int list_cmp(const char **s1
, const char **s2
)
175 return strcmp(*s1
, *s2
);
179 return a list of dn's that might match a simple indexed search or
181 static int ltdb_index_dn_simple(struct ldb_module
*module
,
182 const struct ldb_parse_tree
*tree
,
183 const struct ldb_message
*index_list
,
184 struct dn_list
*list
)
186 struct ldb_context
*ldb
= module
->ldb
;
190 struct ldb_message
*msg
;
195 /* if the attribute isn't in the list of indexed attributes then
196 this node needs a full search */
197 if (ldb_msg_find_idx(index_list
, tree
->u
.equality
.attr
, NULL
, LTDB_IDXATTR
) == -1) {
201 /* the attribute is indexed. Pull the list of DNs that match the
203 dn
= ltdb_index_key(ldb
, tree
->u
.equality
.attr
, &tree
->u
.equality
.value
);
206 msg
= talloc(list
, struct ldb_message
);
211 ret
= ltdb_search_dn1(module
, dn
, msg
);
213 if (ret
== 0 || ret
== -1) {
217 for (i
=0;i
<msg
->num_elements
;i
++) {
218 struct ldb_message_element
*el
;
220 if (strcmp(msg
->elements
[i
].name
, LTDB_IDX
) != 0) {
224 el
= &msg
->elements
[i
];
226 list
->dn
= talloc_array(list
, char *, el
->num_values
);
232 for (j
=0;j
<el
->num_values
;j
++) {
233 list
->dn
[list
->count
] =
234 talloc_strdup(list
->dn
, (char *)el
->values
[j
].data
);
235 if (!list
->dn
[list
->count
]) {
245 if (list
->count
> 1) {
246 qsort(list
->dn
, list
->count
, sizeof(char *), (comparison_fn_t
) list_cmp
);
253 static int list_union(struct ldb_context
*, struct dn_list
*, const struct dn_list
*);
256 return a list of dn's that might match a simple indexed search on
257 the special objectclass attribute
259 static int ltdb_index_dn_objectclass(struct ldb_module
*module
,
260 const struct ldb_parse_tree
*tree
,
261 const struct ldb_message
*index_list
,
262 struct dn_list
*list
)
264 struct ldb_context
*ldb
= module
->ldb
;
267 const char *target
= (const char *)tree
->u
.equality
.value
.data
;
268 const char **subclasses
;
273 ret
= ltdb_index_dn_simple(module
, tree
, index_list
, list
);
275 subclasses
= ldb_subclass_list(module
->ldb
, target
);
277 if (subclasses
== NULL
) {
281 for (i
=0;subclasses
[i
];i
++) {
282 struct ldb_parse_tree tree2
;
283 struct dn_list
*list2
;
284 tree2
.operation
= LDB_OP_EQUALITY
;
285 tree2
.u
.equality
.attr
= LTDB_OBJECTCLASS
;
286 if (!tree2
.u
.equality
.attr
) {
289 tree2
.u
.equality
.value
.data
=
290 (uint8_t *)talloc_strdup(list
, subclasses
[i
]);
291 if (tree2
.u
.equality
.value
.data
== NULL
) {
294 tree2
.u
.equality
.value
.length
= strlen(subclasses
[i
]);
295 list2
= talloc(list
, struct dn_list
);
297 talloc_free(tree2
.u
.equality
.value
.data
);
300 if (ltdb_index_dn_objectclass(module
, &tree2
,
301 index_list
, list2
) == 1) {
302 if (list
->count
== 0) {
306 list_union(ldb
, list
, list2
);
310 talloc_free(tree2
.u
.equality
.value
.data
);
317 return a list of dn's that might match a leaf indexed search
319 static int ltdb_index_dn_leaf(struct ldb_module
*module
,
320 const struct ldb_parse_tree
*tree
,
321 const struct ldb_message
*index_list
,
322 struct dn_list
*list
)
324 if (ldb_attr_cmp(tree
->u
.equality
.attr
, LTDB_OBJECTCLASS
) == 0) {
325 return ltdb_index_dn_objectclass(module
, tree
, index_list
, list
);
327 if (ldb_attr_dn(tree
->u
.equality
.attr
) == 0) {
328 list
->dn
= talloc_array(list
, char *, 1);
329 if (list
->dn
== NULL
) {
330 ldb_oom(module
->ldb
);
333 list
->dn
[0] = talloc_strdup(list
, (char *)tree
->u
.equality
.value
.data
);
334 if (list
->dn
[0] == NULL
) {
335 ldb_oom(module
->ldb
);
341 return ltdb_index_dn_simple(module
, tree
, index_list
, list
);
348 relies on the lists being sorted
350 static int list_intersect(struct ldb_context
*ldb
,
351 struct dn_list
*list
, const struct dn_list
*list2
)
353 struct dn_list
*list3
;
356 if (list
->count
== 0 || list2
->count
== 0) {
361 list3
= talloc(ldb
, struct dn_list
);
366 list3
->dn
= talloc_array(list3
, char *, list
->count
);
373 for (i
=0;i
<list
->count
;i
++) {
374 if (ldb_list_find(list
->dn
[i
], list2
->dn
, list2
->count
,
375 sizeof(char *), (comparison_fn_t
)strcmp
) != -1) {
376 list3
->dn
[list3
->count
] = talloc_move(list3
->dn
, &list
->dn
[i
]);
379 talloc_free(list
->dn
[i
]);
383 talloc_free(list
->dn
);
384 list
->dn
= talloc_move(list
, &list3
->dn
);
385 list
->count
= list3
->count
;
395 relies on the lists being sorted
397 static int list_union(struct ldb_context
*ldb
,
398 struct dn_list
*list
, const struct dn_list
*list2
)
402 unsigned int count
= list
->count
;
404 if (list
->count
== 0 && list2
->count
== 0) {
409 d
= talloc_realloc(list
, list
->dn
, char *, list
->count
+ list2
->count
);
415 for (i
=0;i
<list2
->count
;i
++) {
416 if (ldb_list_find(list2
->dn
[i
], list
->dn
, count
,
417 sizeof(char *), (comparison_fn_t
)strcmp
) == -1) {
418 list
->dn
[list
->count
] = talloc_strdup(list
->dn
, list2
->dn
[i
]);
419 if (!list
->dn
[list
->count
]) {
426 if (list
->count
!= count
) {
427 qsort(list
->dn
, list
->count
, sizeof(char *), (comparison_fn_t
)list_cmp
);
433 static int ltdb_index_dn(struct ldb_module
*module
,
434 const struct ldb_parse_tree
*tree
,
435 const struct ldb_message
*index_list
,
436 struct dn_list
*list
);
442 static int ltdb_index_dn_or(struct ldb_module
*module
,
443 const struct ldb_parse_tree
*tree
,
444 const struct ldb_message
*index_list
,
445 struct dn_list
*list
)
447 struct ldb_context
*ldb
= module
->ldb
;
455 for (i
=0;i
<tree
->u
.list
.num_elements
;i
++) {
456 struct dn_list
*list2
;
459 list2
= talloc(module
, struct dn_list
);
464 v
= ltdb_index_dn(module
, tree
->u
.list
.elements
[i
], index_list
, list2
);
477 talloc_free(list
->dn
);
484 list
->dn
= talloc_move(list
, &list2
->dn
);
485 list
->count
= list2
->count
;
487 if (list_union(ldb
, list
, list2
) == -1) {
496 if (list
->count
== 0) {
507 static int ltdb_index_dn_not(struct ldb_module
*module
,
508 const struct ldb_parse_tree
*tree
,
509 const struct ldb_message
*index_list
,
510 struct dn_list
*list
)
512 /* the only way to do an indexed not would be if we could
513 negate the not via another not or if we knew the total
514 number of database elements so we could know that the
515 existing expression covered the whole database.
517 instead, we just give up, and rely on a full index scan
518 (unless an outer & manages to reduce the list)
524 AND two index results
526 static int ltdb_index_dn_and(struct ldb_module
*module
,
527 const struct ldb_parse_tree
*tree
,
528 const struct ldb_message
*index_list
,
529 struct dn_list
*list
)
531 struct ldb_context
*ldb
= module
->ldb
;
539 for (i
=0;i
<tree
->u
.list
.num_elements
;i
++) {
540 struct dn_list
*list2
;
543 list2
= talloc(module
, struct dn_list
);
548 v
= ltdb_index_dn(module
, tree
->u
.list
.elements
[i
], index_list
, list2
);
552 talloc_free(list
->dn
);
564 talloc_free(list
->dn
);
565 list
->dn
= talloc_move(list
, &list2
->dn
);
566 list
->count
= list2
->count
;
568 if (list_intersect(ldb
, list
, list2
) == -1) {
576 if (list
->count
== 0) {
577 talloc_free(list
->dn
);
586 return a list of dn's that might match a indexed search or
587 -1 if an error. return 0 for no matches, or 1 for matches
589 static int ltdb_index_dn(struct ldb_module
*module
,
590 const struct ldb_parse_tree
*tree
,
591 const struct ldb_message
*index_list
,
592 struct dn_list
*list
)
596 switch (tree
->operation
) {
598 ret
= ltdb_index_dn_and(module
, tree
, index_list
, list
);
602 ret
= ltdb_index_dn_or(module
, tree
, index_list
, list
);
606 ret
= ltdb_index_dn_not(module
, tree
, index_list
, list
);
609 case LDB_OP_EQUALITY
:
610 ret
= ltdb_index_dn_leaf(module
, tree
, index_list
, list
);
613 case LDB_OP_SUBSTRING
:
618 case LDB_OP_EXTENDED
:
619 /* we can't index with fancy bitops yet */
628 filter a candidate dn_list from an indexed search into a set of results
629 extracting just the given attributes
631 static int ltdb_index_filter(const struct dn_list
*dn_list
,
632 struct ldb_handle
*handle
)
634 struct ltdb_context
*ac
= talloc_get_type(handle
->private_data
, struct ltdb_context
);
635 struct ldb_reply
*ares
= NULL
;
638 for (i
= 0; i
< dn_list
->count
; i
++) {
642 ares
= talloc_zero(ac
, struct ldb_reply
);
644 handle
->status
= LDB_ERR_OPERATIONS_ERROR
;
645 handle
->state
= LDB_ASYNC_DONE
;
646 return LDB_ERR_OPERATIONS_ERROR
;
649 ares
->message
= ldb_msg_new(ares
);
650 if (!ares
->message
) {
651 handle
->status
= LDB_ERR_OPERATIONS_ERROR
;
652 handle
->state
= LDB_ASYNC_DONE
;
654 return LDB_ERR_OPERATIONS_ERROR
;
658 dn
= ldb_dn_new(ares
->message
, ac
->module
->ldb
, dn_list
->dn
[i
]);
661 return LDB_ERR_OPERATIONS_ERROR
;
664 ret
= ltdb_search_dn1(ac
->module
, dn
, ares
->message
);
667 /* the record has disappeared? yes, this can happen */
673 /* an internal error */
675 return LDB_ERR_OPERATIONS_ERROR
;
678 if (!ldb_match_msg(ac
->module
->ldb
, ares
->message
, ac
->tree
, ac
->base
, ac
->scope
)) {
683 /* filter the attributes that the user wants */
684 ret
= ltdb_filter_attrs(ares
->message
, ac
->attrs
);
687 handle
->status
= LDB_ERR_OPERATIONS_ERROR
;
688 handle
->state
= LDB_ASYNC_DONE
;
690 return LDB_ERR_OPERATIONS_ERROR
;
693 ares
->type
= LDB_REPLY_ENTRY
;
694 handle
->state
= LDB_ASYNC_PENDING
;
695 handle
->status
= ac
->callback(ac
->module
->ldb
, ac
->context
, ares
);
697 if (handle
->status
!= LDB_SUCCESS
) {
698 handle
->state
= LDB_ASYNC_DONE
;
699 return handle
->status
;
707 search the database with a LDAP-like expression using indexes
708 returns -1 if an indexed search is not possible, in which
709 case the caller should call ltdb_search_full()
711 int ltdb_search_indexed(struct ldb_handle
*handle
)
713 struct ltdb_context
*ac
= talloc_get_type(handle
->private_data
, struct ltdb_context
);
714 struct ltdb_private
*ltdb
= talloc_get_type(ac
->module
->private_data
, struct ltdb_private
);
715 struct dn_list
*dn_list
;
718 if (ltdb
->cache
->indexlist
->num_elements
== 0 &&
719 ac
->scope
!= LDB_SCOPE_BASE
) {
720 /* no index list? must do full search */
724 dn_list
= talloc(handle
, struct dn_list
);
725 if (dn_list
== NULL
) {
729 if (ac
->scope
== LDB_SCOPE_BASE
) {
730 /* with BASE searches only one DN can match */
731 dn_list
->dn
= talloc_array(dn_list
, char *, 1);
732 if (dn_list
->dn
== NULL
) {
733 ldb_oom(ac
->module
->ldb
);
736 dn_list
->dn
[0] = ldb_dn_alloc_linearized(dn_list
, ac
->base
);
737 if (dn_list
->dn
[0] == NULL
) {
738 ldb_oom(ac
->module
->ldb
);
744 ret
= ltdb_index_dn(ac
->module
, ac
->tree
, ltdb
->cache
->indexlist
, dn_list
);
748 /* we've got a candidate list - now filter by the full tree
749 and extract the needed attributes */
750 ret
= ltdb_index_filter(dn_list
, handle
);
751 handle
->status
= ret
;
752 handle
->state
= LDB_ASYNC_DONE
;
755 talloc_free(dn_list
);
761 add a index element where this is the first indexed DN for this value
763 static int ltdb_index_add1_new(struct ldb_context
*ldb
,
764 struct ldb_message
*msg
,
765 struct ldb_message_element
*el
,
768 struct ldb_message_element
*el2
;
770 /* add another entry */
771 el2
= talloc_realloc(msg
, msg
->elements
,
772 struct ldb_message_element
, msg
->num_elements
+1);
778 msg
->elements
[msg
->num_elements
].name
= talloc_strdup(msg
->elements
, LTDB_IDX
);
779 if (!msg
->elements
[msg
->num_elements
].name
) {
782 msg
->elements
[msg
->num_elements
].num_values
= 0;
783 msg
->elements
[msg
->num_elements
].values
= talloc(msg
->elements
, struct ldb_val
);
784 if (!msg
->elements
[msg
->num_elements
].values
) {
787 msg
->elements
[msg
->num_elements
].values
[0].length
= strlen(dn
);
788 msg
->elements
[msg
->num_elements
].values
[0].data
= discard_const_p(uint8_t, dn
);
789 msg
->elements
[msg
->num_elements
].num_values
= 1;
797 add a index element where this is not the first indexed DN for this
800 static int ltdb_index_add1_add(struct ldb_context
*ldb
,
801 struct ldb_message
*msg
,
802 struct ldb_message_element
*el
,
809 /* for multi-valued attributes we can end up with repeats */
810 for (i
=0;i
<msg
->elements
[idx
].num_values
;i
++) {
811 if (strcmp(dn
, (char *)msg
->elements
[idx
].values
[i
].data
) == 0) {
816 v2
= talloc_realloc(msg
->elements
, msg
->elements
[idx
].values
,
818 msg
->elements
[idx
].num_values
+1);
822 msg
->elements
[idx
].values
= v2
;
824 msg
->elements
[idx
].values
[msg
->elements
[idx
].num_values
].length
= strlen(dn
);
825 msg
->elements
[idx
].values
[msg
->elements
[idx
].num_values
].data
= discard_const_p(uint8_t, dn
);
826 msg
->elements
[idx
].num_values
++;
832 add an index entry for one message element
834 static int ltdb_index_add1(struct ldb_module
*module
, const char *dn
,
835 struct ldb_message_element
*el
, int v_idx
)
837 struct ldb_context
*ldb
= module
->ldb
;
838 struct ldb_message
*msg
;
839 struct ldb_dn
*dn_key
;
843 msg
= talloc(module
, struct ldb_message
);
849 dn_key
= ltdb_index_key(ldb
, el
->name
, &el
->values
[v_idx
]);
854 talloc_steal(msg
, dn_key
);
856 ret
= ltdb_search_dn1(module
, dn_key
, msg
);
864 msg
->num_elements
= 0;
865 msg
->elements
= NULL
;
868 for (i
=0;i
<msg
->num_elements
;i
++) {
869 if (strcmp(LTDB_IDX
, msg
->elements
[i
].name
) == 0) {
874 if (i
== msg
->num_elements
) {
875 ret
= ltdb_index_add1_new(ldb
, msg
, el
, dn
);
877 ret
= ltdb_index_add1_add(ldb
, msg
, el
, i
, dn
);
881 ret
= ltdb_store(module
, msg
, TDB_REPLACE
);
889 static int ltdb_index_add0(struct ldb_module
*module
, const char *dn
,
890 struct ldb_message_element
*elements
, int num_el
)
892 struct ltdb_private
*ltdb
= module
->private_data
;
900 if (ltdb
->cache
->indexlist
->num_elements
== 0) {
901 /* no indexed fields */
905 for (i
= 0; i
< num_el
; i
++) {
906 ret
= ldb_msg_find_idx(ltdb
->cache
->indexlist
, elements
[i
].name
,
911 for (j
= 0; j
< elements
[i
].num_values
; j
++) {
912 ret
= ltdb_index_add1(module
, dn
, &elements
[i
], j
);
923 add the index entries for a new record
926 int ltdb_index_add(struct ldb_module
*module
, const struct ldb_message
*msg
)
931 dn
= ldb_dn_get_linearized(msg
->dn
);
936 ret
= ltdb_index_add0(module
, dn
, msg
->elements
, msg
->num_elements
);
943 delete an index entry for one message element
945 int ltdb_index_del_value(struct ldb_module
*module
, const char *dn
,
946 struct ldb_message_element
*el
, int v_idx
)
948 struct ldb_context
*ldb
= module
->ldb
;
949 struct ldb_message
*msg
;
950 struct ldb_dn
*dn_key
;
958 dn_key
= ltdb_index_key(ldb
, el
->name
, &el
->values
[v_idx
]);
963 msg
= talloc(dn_key
, struct ldb_message
);
969 ret
= ltdb_search_dn1(module
, dn_key
, msg
);
976 /* it wasn't indexed. Did we have an earlier error? If we did then
982 i
= ldb_msg_find_idx(msg
, dn
, &j
, LTDB_IDX
);
984 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
985 "ERROR: dn %s not found in %s\n", dn
,
986 ldb_dn_get_linearized(dn_key
));
987 /* it ain't there. hmmm */
992 if (j
!= msg
->elements
[i
].num_values
- 1) {
993 memmove(&msg
->elements
[i
].values
[j
],
994 &msg
->elements
[i
].values
[j
+1],
995 (msg
->elements
[i
].num_values
-(j
+1)) *
996 sizeof(msg
->elements
[i
].values
[0]));
998 msg
->elements
[i
].num_values
--;
1000 if (msg
->elements
[i
].num_values
== 0) {
1001 ret
= ltdb_delete_noindex(module
, dn_key
);
1003 ret
= ltdb_store(module
, msg
, TDB_REPLACE
);
1006 talloc_free(dn_key
);
1012 delete the index entries for a record
1013 return -1 on failure
1015 int ltdb_index_del(struct ldb_module
*module
, const struct ldb_message
*msg
)
1017 struct ltdb_private
*ltdb
= module
->private_data
;
1022 /* find the list of indexed fields */
1023 if (ltdb
->cache
->indexlist
->num_elements
== 0) {
1024 /* no indexed fields */
1028 if (ldb_dn_is_special(msg
->dn
)) {
1032 dn
= ldb_dn_get_linearized(msg
->dn
);
1037 for (i
= 0; i
< msg
->num_elements
; i
++) {
1038 ret
= ldb_msg_find_idx(ltdb
->cache
->indexlist
, msg
->elements
[i
].name
,
1039 NULL
, LTDB_IDXATTR
);
1043 for (j
= 0; j
< msg
->elements
[i
].num_values
; j
++) {
1044 ret
= ltdb_index_del_value(module
, dn
, &msg
->elements
[i
], j
);
1056 traversal function that deletes all @INDEX records
1058 static int delete_index(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1060 const char *dn
= "DN=" LTDB_INDEX
":";
1061 if (strncmp((char *)key
.dptr
, dn
, strlen(dn
)) == 0) {
1062 return tdb_delete(tdb
, key
);
1068 traversal function that adds @INDEX records during a re index
1070 static int re_index(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA data
, void *state
)
1072 struct ldb_module
*module
= state
;
1073 struct ldb_message
*msg
;
1074 const char *dn
= NULL
;
1078 if (strncmp((char *)key
.dptr
, "DN=@", 4) == 0 ||
1079 strncmp((char *)key
.dptr
, "DN=", 3) != 0) {
1083 msg
= talloc(module
, struct ldb_message
);
1088 ret
= ltdb_unpack_data(module
, &data
, msg
);
1094 /* check if the DN key has changed, perhaps due to the
1095 case insensitivity of an element changing */
1096 key2
= ltdb_key(module
, msg
->dn
);
1097 if (key2
.dptr
== NULL
) {
1098 /* probably a corrupt record ... darn */
1099 ldb_debug(module
->ldb
, LDB_DEBUG_ERROR
, "Invalid DN in re_index: %s\n",
1100 ldb_dn_get_linearized(msg
->dn
));
1104 if (strcmp((char *)key2
.dptr
, (char *)key
.dptr
) != 0) {
1105 tdb_delete(tdb
, key
);
1106 tdb_store(tdb
, key2
, data
, 0);
1108 talloc_free(key2
.dptr
);
1110 if (msg
->dn
== NULL
) {
1111 dn
= (char *)key
.dptr
+ 3;
1113 dn
= ldb_dn_get_linearized(msg
->dn
);
1116 ret
= ltdb_index_add0(module
, dn
, msg
->elements
, msg
->num_elements
);
1124 force a complete reindex of the database
1126 int ltdb_reindex(struct ldb_module
*module
)
1128 struct ltdb_private
*ltdb
= module
->private_data
;
1131 if (ltdb_cache_reload(module
) != 0) {
1135 /* first traverse the database deleting any @INDEX records */
1136 ret
= tdb_traverse(ltdb
->tdb
, delete_index
, NULL
);
1141 /* now traverse adding any indexes for normal LDB records */
1142 ret
= tdb_traverse(ltdb
->tdb
, re_index
, module
);