]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
ldb: Avoid inefficient one-level searches
authorTim Beale <timbeale@catalyst.net.nz>
Sun, 3 Feb 2019 21:49:03 +0000 (10:49 +1300)
committerStefan Metzmacher <metze@samba.org>
Wed, 13 Feb 2019 10:43:25 +0000 (11:43 +0100)
Commit 88ae60ed186c9 introduced a problem that made one-level
searches inefficient if there were a lot of child objects in the same
level, and the requested object didn't exist. Basically, it ignored the
case where ldb_kv_index_dn() returned LDB_ERR_NO_SUCH_OBJECT, i.e. the
indexed lookup was successful, but didn't find a match. At which point,
there was no more processing we needed to do.

The behaviour after 88ae60ed186c9 was to fall-through and run the
ldb_kv_index_filter() function over *all* the children. This still
returned the correct result, but could be costly if there were a lot of
children.

The case 88ae60ed186c9 was trying to fix was where we could not do
an indexed search (e.g. trying to match on a 'attribute=*' filter). In
which case we want to ignore the LDB_ERR_OPERATIONS_ERROR and just run
ldb_kv_index_filter() over all the children. This is still more
efficient than the fallback of doing a full database scan.

This patch adds in a short-circuit for the NO_SUCH_OBJECT case, so we
can skip the unnecessary ldb_kv_index_filter() work.

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

Signed-off-by: Tim Beale <timbeale@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(Manual merge of commit 9a893f9613bd6440ab in master)

lib/ldb/ldb_tdb/ldb_index.c

index 429c8f5aa247da6edff698d6acfffbb94d21ab9e..f07c9a818c43e0a121b0800af0d53e0fcdcf18e3 100644 (file)
@@ -1835,13 +1835,23 @@ int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
                        }
                        /*
                         * Here we load the index for the tree.
-                        *
-                        * We only care if this is successful, if the
-                        * index can't trim the result list down then
-                        * the ONELEVEL index is still good enough.
                         */
                        ret = ltdb_index_dn(ac->module, ltdb, ac->tree,
                                            idx_one_tree_list);
+
+                       /*
+                        * We can stop if we're sure the object doesn't exist
+                        */
+                       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+                               talloc_free(idx_one_tree_list);
+                               talloc_free(dn_list);
+                               return LDB_ERR_NO_SUCH_OBJECT;
+                       }
+
+                       /* We only care if this is successful, if the
+                        * index can't trim the result list down then
+                        * the ONELEVEL index is still good enough.
+                        */
                        if (ret == LDB_SUCCESS) {
                                if (!list_intersect(ldb, ltdb,
                                                    dn_list,