ldb_tdb: sort GUID index list at add time by inserting in sorted order
authorAndrew Bartlett <abartlet@samba.org>
Mon, 21 Aug 2017 03:35:32 +0000 (15:35 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 22 Sep 2017 19:20:23 +0000 (21:20 +0200)
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
lib/ldb/ldb_tdb/ldb_index.c
lib/ldb/wscript

index fad88fb3a73214ebfa69fe475322a346b725c421..cb14462ad29ded8260c26eaeb2bf39f6eaec206b 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "ldb_tdb.h"
 #include "ldb_private.h"
+#include "lib/util/binsearch.h"
 
 struct dn_list {
        unsigned int count;
@@ -87,6 +88,22 @@ static int ldb_val_equal_exact_for_qsort(const struct ldb_val *v1,
        return memcmp(v1->data, v2->data, v1->length);
 }
 
+/*
+  see if two ldb_val structures contain exactly the same data
+  return -1 or 1 for a mismatch, 0 for match
+*/
+static int ldb_val_equal_exact_ordered(const struct ldb_val v1,
+                                      const struct ldb_val *v2)
+{
+       if (v1.length > v2->length) {
+               return -1;
+       }
+       if (v1.length < v2->length) {
+               return 1;
+       }
+       return memcmp(v1.data, v2->data, v1.length);
+}
+
 
 /*
   find a entry in a dn_list, using a ldb_val. Uses a case sensitive
@@ -1533,6 +1550,7 @@ static int ltdb_index_add1(struct ldb_module *module,
                list->dn[list->count].length = strlen(dn_str);
        } else {
                const struct ldb_val *key_val;
+               struct ldb_val *exact = NULL, *next = NULL;
                key_val = ldb_msg_find_ldb_val(msg,
                                               ltdb->cache->GUID_index_attribute);
                if (key_val == NULL) {
@@ -1544,8 +1562,23 @@ static int ltdb_index_add1(struct ldb_module *module,
                        talloc_free(list);
                        return ldb_module_operr(module);
                }
-               list->dn[list->count] = ldb_val_dup(list->dn, key_val);
-               if (list->dn[list->count].data == NULL) {
+
+               BINARY_ARRAY_SEARCH_GTE(list->dn, list->count,
+                                       *key_val, ldb_val_equal_exact_ordered,
+                                       exact, next);
+               if (exact != NULL) {
+                       talloc_free(list);
+                       return LDB_ERR_OPERATIONS_ERROR;
+               }
+
+               if (next == NULL) {
+                       next = &list->dn[list->count];
+               } else {
+                       memmove(&next[1], next,
+                               sizeof(*next) * (list->count - (next - list->dn)));
+               }
+               *next = ldb_val_dup(list->dn, key_val);
+               if (next->data == NULL) {
                        talloc_free(list);
                        return ldb_module_operr(module);
                }
index 5ea52317d4d5261607f35e28d4b8395c6daebacb..e41805974b6b9ce02f10fe86e5ea28c675232d0c 100644 (file)
@@ -21,6 +21,7 @@ samba_dist.DIST_DIRS('''lib/ldb:. lib/replace:lib/replace lib/talloc:lib/talloc
                         third_party/cmocka:third_party/cmocka
                         buildtools:buildtools third_party/waf:third_party/waf''')
 
+samba_dist.DIST_FILES('''lib/util/binsearch.h:lib/util/binsearch.h''')
 
 def set_options(opt):
     opt.BUILTIN_DEFAULT('replace')