ldb_kv: Skip @ records early in a search full scan
authorAndrew Bartlett <abartlet@samba.org>
Thu, 4 Apr 2019 21:46:50 +0000 (10:46 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 10 Apr 2019 06:23:39 +0000 (06:23 +0000)
@ records like @IDXLIST are only available via a base search on the specific name
but the method by which they were excluded was expensive, after the unpack the
DN is exploded and ldb_match_msg_error() would reject it for failing to match the
scope.

This uses the fact that @ records have the DN=@ prefix on their TDB/LMDB key
to quickly exclude them from consideration.

Based on analysis by Garming Sam.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13893

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Wed Apr 10 06:23:39 UTC 2019 on sn-devel-144

lib/ldb/ldb_key_value/ldb_kv.c
lib/ldb/ldb_key_value/ldb_kv.h
lib/ldb/ldb_key_value/ldb_kv_index.c
lib/ldb/ldb_key_value/ldb_kv_search.c

index bd35feed14b1a08454ed7c323dc593ec3d911dc3..2fc3aa7d030f2ca754b907e7ac2d452e60be4064 100644 (file)
@@ -63,12 +63,22 @@ struct ldb_kv_req_spy {
  * Determine if this key could hold a record.  We allow the new GUID
  * index, the old DN index and a possible future ID=
  */
-bool ldb_kv_key_is_record(struct ldb_val key)
+bool ldb_kv_key_is_normal_record(struct ldb_val key)
 {
        if (key.length < 4) {
                return false;
        }
 
+       /*
+        * @ records are not normal records, we don't want to index
+        * them nor search on them
+        */
+       if (key.length > 4 &&
+           memcmp(key.data, "DN=@", 4) == 0) {
+               return false;
+       }
+
+       /* All other DN= records are however */
        if (memcmp(key.data, "DN=", 3) == 0) {
                return true;
        }
index 2fa931a0b7ab39c8854bf9d07fa1d082d1ee4332..92106caae85a24c71ce0d08b17f069ac47edf817 100644 (file)
@@ -253,10 +253,11 @@ int ldb_kv_search(struct ldb_kv_context *ctx);
 /*
  * The following definitions come from lib/ldb/ldb_key_value/ldb_kv.c  */
 /*
- * Determine if this key could hold a record.  We allow the new GUID
- * index, the old DN index and a possible future ID=
+ * Determine if this key could hold a normal record.  We allow the new
+ * GUID index, the old DN index and a possible future ID= but not
+ * DN=@.
  */
-bool ldb_kv_key_is_record(struct ldb_val key);
+bool ldb_kv_key_is_normal_record(struct ldb_val key);
 struct ldb_val ldb_kv_key_dn(struct ldb_module *module,
                             TALLOC_CTX *mem_ctx,
                             struct ldb_dn *dn);
index 2627d79d5fd540e5aa0bb390e1e0d2f9c4d012ad..350289a78e372a6a74770b5bff851a2bf8562da2 100644 (file)
@@ -3265,12 +3265,7 @@ static int re_key(struct ldb_kv_private *ldb_kv,
 
        ldb = ldb_module_get_ctx(module);
 
-       if (key.length > 4 &&
-           memcmp(key.data, "DN=@", 4) == 0) {
-               return 0;
-       }
-
-       is_record = ldb_kv_key_is_record(key);
+       is_record = ldb_kv_key_is_normal_record(key);
        if (is_record == false) {
                return 0;
        }
@@ -3352,12 +3347,7 @@ static int re_index(struct ldb_kv_private *ldb_kv,
 
        ldb = ldb_module_get_ctx(module);
 
-       if (key.length > 4 &&
-           memcmp(key.data, "DN=@", 4) == 0) {
-               return 0;
-       }
-
-       is_record = ldb_kv_key_is_record(key);
+       is_record = ldb_kv_key_is_normal_record(key);
        if (is_record == false) {
                return 0;
        }
index f77e0ca2fdc805e418c8b3c16f910e557466b14e..aa086a88d9a6ce4e9e951223cd18b95b69014f18 100644 (file)
@@ -512,7 +512,24 @@ static int search_func(struct ldb_kv_private *ldb_kv,
        ac = talloc_get_type(state, struct ldb_kv_context);
        ldb = ldb_module_get_ctx(ac->module);
 
-       if (ldb_kv_key_is_record(key) == false) {
+       /*
+        * We want to skip @ records early in a search full scan
+        *
+        * @ records like @IDXLIST are only available via a base
+        * search on the specific name but the method by which they
+        * were excluded was expensive, after the unpack the DN is
+        * exploded and ldb_match_msg_error() would reject it for
+        * failing to match the scope.
+        *
+        * ldb_kv_key_is_normal_record() uses the fact that @ records
+        * have the DN=@ prefix on their TDB/LMDB key to quickly
+        * exclude them from consideration.
+        *
+        * (any other non-records are also excluded by the same key
+        * match)
+        */
+
+       if (ldb_kv_key_is_normal_record(key) == false) {
                return 0;
        }