[PATCH][WIP] LDB changes for index handling and private event loops

Andrew Bartlett abartlet at samba.org
Tue May 30 09:26:16 UTC 2017


On Tue, 2017-05-30 at 10:14 +0200, Andreas Schneider via samba-
technical wrote:
> 
> Could you please document new public function using doxygen?

None of the new functions are public, so they don't show up in doxygen
as far as I can tell, but in the hope that Doxygen extends to
ldb_module.h in the future, I've done this and some others to make a
start.

Please review/push (or at least review the Doxygen patches). 

Thanks!

Andrew Bartlett
-- 
Andrew Bartlett                       http://samba.org/~abartlet/
Authentication Developer, Samba Team  http://samba.org
Samba Developer, Catalyst IT          http://catalyst.net.nz/services/samba
-------------- next part --------------
From ff1c46d7d9018210a2aef1d9b1f9baa390aa7c4e Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Thu, 30 Mar 2017 13:10:08 +1300
Subject: [PATCH 01/25] ldb_tdb: Split index load out into a sub-funciton:
 ltdb_index_load

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/ldb_tdb/ldb_cache.c | 73 +++++++++++++++++++++++++++------------------
 1 file changed, 44 insertions(+), 29 deletions(-)

diff --git a/lib/ldb/ldb_tdb/ldb_cache.c b/lib/ldb/ldb_tdb/ldb_cache.c
index 388b461..cf25d9a 100644
--- a/lib/ldb/ldb_tdb/ldb_cache.c
+++ b/lib/ldb/ldb_tdb/ldb_cache.c
@@ -226,6 +226,49 @@ failed:
 	return -1;
 }
 
+/*
+  register any index records we find for the DB
+*/
+static int ltdb_index_load(struct ldb_module *module,
+			   struct ltdb_private *ltdb)
+{
+	struct ldb_context *ldb = ldb_module_get_ctx(module);
+	struct ldb_dn *indexlist_dn;
+	int r;
+
+	talloc_free(ltdb->cache->indexlist);
+
+	ltdb->cache->indexlist = ldb_msg_new(ltdb->cache);
+	if (ltdb->cache->indexlist == NULL) {
+		return -1;
+	}
+	ltdb->cache->one_level_indexes = false;
+	ltdb->cache->attribute_indexes = false;
+
+	indexlist_dn = ldb_dn_new(ltdb, ldb, LTDB_INDEXLIST);
+	if (indexlist_dn == NULL) {
+		return -1;
+	}
+
+	r = ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist,
+			    LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
+			    |LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC
+			    |LDB_UNPACK_DATA_FLAG_NO_DN);
+	TALLOC_FREE(indexlist_dn);
+
+	if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
+		return -1;
+	}
+
+	if (ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXONE) != NULL) {
+		ltdb->cache->one_level_indexes = true;
+	}
+	if (ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXATTR) != NULL) {
+		ltdb->cache->attribute_indexes = true;
+	}
+
+	return 0;
+}
 
 /*
   initialise the baseinfo record
@@ -316,7 +359,6 @@ int ltdb_cache_load(struct ldb_module *module)
 	void *data = ldb_module_get_private(module);
 	struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
 	struct ldb_dn *baseinfo_dn = NULL, *options_dn = NULL;
-	struct ldb_dn *indexlist_dn = NULL;
 	uint64_t seq;
 	struct ldb_message *baseinfo = NULL, *options = NULL;
 	int r;
@@ -332,10 +374,6 @@ int ltdb_cache_load(struct ldb_module *module)
 	if (ltdb->cache == NULL) {
 		ltdb->cache = talloc_zero(ltdb, struct ltdb_cache);
 		if (ltdb->cache == NULL) goto failed;
-		ltdb->cache->indexlist = ldb_msg_new(ltdb->cache);
-		if (ltdb->cache->indexlist == NULL) {
-			goto failed;
-		}
 	}
 
 	baseinfo = ldb_msg_new(ltdb->cache);
@@ -403,7 +441,6 @@ int ltdb_cache_load(struct ldb_module *module)
 		ltdb->disallow_dn_filter = false;
 	}
 
-	talloc_free(ltdb->cache->indexlist);
 	/*
 	 * ltdb_attributes_unload() calls internally talloc_free() on
 	 * any non-fixed elemnts in ldb->schema.attributes.
@@ -413,31 +450,11 @@ int ltdb_cache_load(struct ldb_module *module)
 	 * partition module.
 	 */
 	ltdb_attributes_unload(module);
-	ltdb->cache->indexlist = ldb_msg_new(ltdb->cache);
-	if (ltdb->cache->indexlist == NULL) {
-		goto failed;
-	}
-	ltdb->cache->one_level_indexes = false;
-	ltdb->cache->attribute_indexes = false;
-	    
-	indexlist_dn = ldb_dn_new(module, ldb, LTDB_INDEXLIST);
-	if (indexlist_dn == NULL) goto failed;
 
-	r = ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist,
-			    LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
-			    |LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC
-			    |LDB_UNPACK_DATA_FLAG_NO_DN);
-	if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
+	if (ltdb_index_load(module, ltdb) == -1) {
 		goto failed;
 	}
 
-	if (ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXONE) != NULL) {
-		ltdb->cache->one_level_indexes = true;
-	}
-	if (ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXATTR) != NULL) {
-		ltdb->cache->attribute_indexes = true;
-	}
-
 	/*
 	 * NOTE WELL: This is per-ldb, not per module, so overwrites
 	 * the handlers across all databases when used under Samba's
@@ -450,13 +467,11 @@ int ltdb_cache_load(struct ldb_module *module)
 done:
 	talloc_free(options);
 	talloc_free(baseinfo);
-	talloc_free(indexlist_dn);
 	return 0;
 
 failed:
 	talloc_free(options);
 	talloc_free(baseinfo);
-	talloc_free(indexlist_dn);
 	return -1;
 }
 
-- 
2.9.4


From e75ed75ee3a8b7aa78a43add272939d8084d8d0d Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Thu, 30 Mar 2017 13:07:16 +1300
Subject: [PATCH 02/25] ldb_tdb: change the arguments to ldb_is_indexed() to
 provide the ltdb_private

By doing this, we can be more efficient in locating if we have an index in
the future.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/ldb_tdb/ldb_index.c | 49 +++++++++++++++++++++++----------------------
 1 file changed, 25 insertions(+), 24 deletions(-)

diff --git a/lib/ldb/ldb_tdb/ldb_index.c b/lib/ldb/ldb_tdb/ldb_index.c
index 53fcde5..fc21bac 100644
--- a/lib/ldb/ldb_tdb/ldb_index.c
+++ b/lib/ldb/ldb_tdb/ldb_index.c
@@ -445,12 +445,14 @@ static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
 /*
   see if a attribute value is in the list of indexed attributes
 */
-static bool ltdb_is_indexed(const struct ldb_message *index_list, const char *attr)
+static bool ltdb_is_indexed(struct ldb_module *module,
+			    struct ltdb_private *ltdb,
+			    const char *attr)
 {
 	unsigned int i;
 	struct ldb_message_element *el;
 
-	el = ldb_msg_find_element(index_list, LTDB_IDXATTR);
+	el = ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXATTR);
 	if (el == NULL) {
 		return false;
 	}
@@ -481,8 +483,8 @@ static bool ltdb_is_indexed(const struct ldb_message *index_list, const char *at
   equality search only)
  */
 static int ltdb_index_dn_simple(struct ldb_module *module,
+				struct ltdb_private *ltdb,
 				const struct ldb_parse_tree *tree,
-				const struct ldb_message *index_list,
 				struct dn_list *list)
 {
 	struct ldb_context *ldb;
@@ -496,7 +498,7 @@ static int ltdb_index_dn_simple(struct ldb_module *module,
 
 	/* if the attribute isn't in the list of indexed attributes then
 	   this node needs a full search */
-	if (!ltdb_is_indexed(index_list, tree->u.equality.attr)) {
+	if (!ltdb_is_indexed(module, ltdb, tree->u.equality.attr)) {
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
 
@@ -517,12 +519,10 @@ static bool list_union(struct ldb_context *, struct dn_list *, const struct dn_l
   return a list of dn's that might match a leaf indexed search
  */
 static int ltdb_index_dn_leaf(struct ldb_module *module,
+			      struct ltdb_private *ltdb,
 			      const struct ldb_parse_tree *tree,
-			      const struct ldb_message *index_list,
 			      struct dn_list *list)
 {
-	struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module),
-						    struct ltdb_private);
 	if (ltdb->disallow_dn_filter &&
 	    (ldb_attr_cmp(tree->u.equality.attr, "dn") == 0)) {
 		/* in AD mode we do not support "(dn=...)" search filters */
@@ -540,7 +540,7 @@ static int ltdb_index_dn_leaf(struct ldb_module *module,
 		list->count = 1;
 		return LDB_SUCCESS;
 	}
-	return ltdb_index_dn_simple(module, tree, index_list, list);
+	return ltdb_index_dn_simple(module, ltdb, tree, list);
 }
 
 
@@ -653,8 +653,8 @@ static bool list_union(struct ldb_context *ldb,
 }
 
 static int ltdb_index_dn(struct ldb_module *module,
+			 struct ltdb_private *ltdb,
 			 const struct ldb_parse_tree *tree,
-			 const struct ldb_message *index_list,
 			 struct dn_list *list);
 
 
@@ -662,8 +662,8 @@ static int ltdb_index_dn(struct ldb_module *module,
   process an OR list (a union)
  */
 static int ltdb_index_dn_or(struct ldb_module *module,
+			    struct ltdb_private *ltdb,
 			    const struct ldb_parse_tree *tree,
-			    const struct ldb_message *index_list,
 			    struct dn_list *list)
 {
 	struct ldb_context *ldb;
@@ -683,7 +683,8 @@ static int ltdb_index_dn_or(struct ldb_module *module,
 			return LDB_ERR_OPERATIONS_ERROR;
 		}
 
-		ret = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2);
+		ret = ltdb_index_dn(module, ltdb,
+				    tree->u.list.elements[i], list2);
 
 		if (ret == LDB_ERR_NO_SUCH_OBJECT) {
 			/* X || 0 == X */
@@ -715,8 +716,8 @@ static int ltdb_index_dn_or(struct ldb_module *module,
   NOT an index results
  */
 static int ltdb_index_dn_not(struct ldb_module *module,
+			     struct ltdb_private *ltdb,
 			     const struct ldb_parse_tree *tree,
-			     const struct ldb_message *index_list,
 			     struct dn_list *list)
 {
 	/* the only way to do an indexed not would be if we could
@@ -746,8 +747,8 @@ static bool ltdb_index_unique(struct ldb_context *ldb,
   process an AND expression (intersection)
  */
 static int ltdb_index_dn_and(struct ldb_module *module,
+			     struct ltdb_private *ltdb,
 			     const struct ldb_parse_tree *tree,
-			     const struct ldb_message *index_list,
 			     struct dn_list *list)
 {
 	struct ldb_context *ldb;
@@ -771,7 +772,7 @@ static int ltdb_index_dn_and(struct ldb_module *module,
 			continue;
 		}
 
-		ret = ltdb_index_dn(module, subtree, index_list, list);
+		ret = ltdb_index_dn(module, ltdb, subtree, list);
 		if (ret == LDB_ERR_NO_SUCH_OBJECT) {
 			/* 0 && X == 0 */
 			return LDB_ERR_NO_SUCH_OBJECT;
@@ -798,7 +799,7 @@ static int ltdb_index_dn_and(struct ldb_module *module,
 			return ldb_module_oom(module);
 		}
 
-		ret = ltdb_index_dn(module, subtree, index_list, list2);
+		ret = ltdb_index_dn(module, ltdb, subtree, list2);
 
 		if (ret == LDB_ERR_NO_SUCH_OBJECT) {
 			/* X && 0 == 0 */
@@ -884,27 +885,27 @@ static int ltdb_index_dn_one(struct ldb_module *module,
   an error. return LDB_ERR_NO_SUCH_OBJECT for no matches, or LDB_SUCCESS for matches
  */
 static int ltdb_index_dn(struct ldb_module *module,
+			 struct ltdb_private *ltdb,
 			 const struct ldb_parse_tree *tree,
-			 const struct ldb_message *index_list,
 			 struct dn_list *list)
 {
 	int ret = LDB_ERR_OPERATIONS_ERROR;
 
 	switch (tree->operation) {
 	case LDB_OP_AND:
-		ret = ltdb_index_dn_and(module, tree, index_list, list);
+		ret = ltdb_index_dn_and(module, ltdb, tree, list);
 		break;
 
 	case LDB_OP_OR:
-		ret = ltdb_index_dn_or(module, tree, index_list, list);
+		ret = ltdb_index_dn_or(module, ltdb, tree, list);
 		break;
 
 	case LDB_OP_NOT:
-		ret = ltdb_index_dn_not(module, tree, index_list, list);
+		ret = ltdb_index_dn_not(module, ltdb, tree, list);
 		break;
 
 	case LDB_OP_EQUALITY:
-		ret = ltdb_index_dn_leaf(module, tree, index_list, list);
+		ret = ltdb_index_dn_leaf(module, ltdb, tree, list);
 		break;
 
 	case LDB_OP_SUBSTRING:
@@ -1087,7 +1088,7 @@ int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
 			talloc_free(dn_list);
 			return LDB_ERR_OPERATIONS_ERROR;
 		}
-		ret = ltdb_index_dn(ac->module, ac->tree, ltdb->cache->indexlist, dn_list);
+		ret = ltdb_index_dn(ac->module, ltdb, ac->tree, dn_list);
 		if (ret != LDB_SUCCESS) {
 			talloc_free(dn_list);
 			return ret;
@@ -1228,7 +1229,7 @@ static int ltdb_index_add_all(struct ldb_module *module, const char *dn,
 
 	for (i = 0; i < num_el; i++) {
 		int ret;
-		if (!ltdb_is_indexed(ltdb->cache->indexlist, elements[i].name)) {
+		if (!ltdb_is_indexed(module, ltdb, elements[i].name)) {
 			continue;
 		}
 		ret = ltdb_index_add_el(module, dn, &elements[i], is_new);
@@ -1306,7 +1307,7 @@ int ltdb_index_add_element(struct ldb_module *module, struct ldb_dn *dn,
 	if (ldb_dn_is_special(dn)) {
 		return LDB_SUCCESS;
 	}
-	if (!ltdb_is_indexed(ltdb->cache->indexlist, el->name)) {
+	if (!ltdb_is_indexed(module, ltdb, el->name)) {
 		return LDB_SUCCESS;
 	}
 	return ltdb_index_add_el(module, ldb_dn_get_linearized(dn), el, true);
@@ -1439,7 +1440,7 @@ int ltdb_index_del_element(struct ldb_module *module, struct ldb_dn *dn,
 		return LDB_SUCCESS;
 	}
 
-	if (!ltdb_is_indexed(ltdb->cache->indexlist, el->name)) {
+	if (!ltdb_is_indexed(module, ltdb, el->name)) {
 		return LDB_SUCCESS;
 	}
 	for (i = 0; i < el->num_values; i++) {
-- 
2.9.4


From 1fde2dadda6cfc81e74852eea1e473b2711e27c4 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Thu, 30 Mar 2017 13:21:34 +1300
Subject: [PATCH 03/25] ldb_tdb: consistently use
 ltdb->cache->attribute_indexes to determine if we have indexes

This is instead of checking the number of elements via ltdb->cache->indexlist->num_elements

In turn, this allows us to avoid fetching ltdb->cache->indexlist in the future

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/ldb_tdb/ldb_index.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/lib/ldb/ldb_tdb/ldb_index.c b/lib/ldb/ldb_tdb/ldb_index.c
index fc21bac..46ba725 100644
--- a/lib/ldb/ldb_tdb/ldb_index.c
+++ b/lib/ldb/ldb_tdb/ldb_index.c
@@ -452,6 +452,10 @@ static bool ltdb_is_indexed(struct ldb_module *module,
 	unsigned int i;
 	struct ldb_message_element *el;
 
+	if (!ltdb->cache->attribute_indexes) {
+		return false;
+	}
+
 	el = ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXATTR);
 	if (el == NULL) {
 		return false;
@@ -1222,7 +1226,7 @@ static int ltdb_index_add_all(struct ldb_module *module, const char *dn,
 		return LDB_SUCCESS;
 	}
 
-	if (ltdb->cache->indexlist->num_elements == 0) {
+	if (!ltdb->cache->attribute_indexes) {
 		/* no indexed fields */
 		return LDB_SUCCESS;
 	}
@@ -1640,7 +1644,7 @@ int ltdb_reindex(struct ldb_module *module)
 	}
 
 	/* if we don't have indexes we have nothing todo */
-	if (ltdb->cache->indexlist->num_elements == 0) {
+	if (!ltdb->cache->attribute_indexes) {
 		return LDB_SUCCESS;
 	}
 
-- 
2.9.4


From 1d85d2357c824e52022b72dd0f2cfbf031078edb Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Thu, 30 Mar 2017 13:23:44 +1300
Subject: [PATCH 04/25] ldb: Allow a caller (in particular Samba) to handle the
 list of attributes with an index

By doing that, Samba will use a binary search to locate the attributes
rather than an O(n) search, during every search or modify of the database.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/ABI/ldb-1.1.29.sigs     |  1 +
 lib/ldb/common/ldb_attributes.c | 12 ++++++++++++
 lib/ldb/include/ldb.h           |  5 +++++
 lib/ldb/include/ldb_module.h    |  2 ++
 lib/ldb/include/ldb_private.h   |  7 +++++++
 lib/ldb/ldb_tdb/ldb_index.c     | 16 ++++++++++++++++
 6 files changed, 43 insertions(+)

diff --git a/lib/ldb/ABI/ldb-1.1.29.sigs b/lib/ldb/ABI/ldb-1.1.29.sigs
index 0ea968d..9b865ed8 100644
--- a/lib/ldb/ABI/ldb-1.1.29.sigs
+++ b/lib/ldb/ABI/ldb-1.1.29.sigs
@@ -225,6 +225,7 @@ ldb_schema_attribute_fill_with_syntax: int (struct ldb_context *, TALLOC_CTX *,
 ldb_schema_attribute_remove: void (struct ldb_context *, const char *)
 ldb_schema_attribute_remove_flagged: void (struct ldb_context *, unsigned int)
 ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *)
+ldb_schema_set_override_indexlist: void (struct ldb_context *, bool)
 ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...)
 ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *)
 ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *)
diff --git a/lib/ldb/common/ldb_attributes.c b/lib/ldb/common/ldb_attributes.c
index 2021a0b..98ec5a4 100644
--- a/lib/ldb/common/ldb_attributes.c
+++ b/lib/ldb/common/ldb_attributes.c
@@ -383,3 +383,15 @@ void ldb_schema_attribute_set_override_handler(struct ldb_context *ldb,
 	ldb->schema.attribute_handler_override_private = private_data;
 	ldb->schema.attribute_handler_override = override;
 }
+
+/*
+  set that the attribute handler override function - used to delegate
+  schema handling to external code, is handling setting
+  LDB_ATTR_FLAG_INDEXED
+ */
+void ldb_schema_set_override_indexlist(struct ldb_context *ldb,
+				       bool one_level_indexes)
+{
+	ldb->schema.index_handler_override = true;
+	ldb->schema.one_level_indexes = one_level_indexes;
+}
diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h
index 1160a48..3fab929 100644
--- a/lib/ldb/include/ldb.h
+++ b/lib/ldb/include/ldb.h
@@ -441,6 +441,11 @@ const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_c
  */
 #define LDB_ATTR_FLAG_FROM_DB      (1<<6)
 
+/*
+ * The attribute was loaded from a DB, rather than via the C API
+ */
+#define LDB_ATTR_FLAG_INDEXED      (1<<7)
+
 /**
   LDAP attribute syntax for a DN
 
diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index 833d5a8..75f3fcb 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -125,6 +125,8 @@ typedef const struct ldb_schema_attribute *(*ldb_attribute_handler_override_fn_t
 void ldb_schema_attribute_set_override_handler(struct ldb_context *ldb,
 					       ldb_attribute_handler_override_fn_t override,
 					       void *private_data);
+void ldb_schema_set_override_indexlist(struct ldb_context *ldb,
+				       bool one_level_indexes);
 
 /* A useful function to build comparison functions with */
 int ldb_any_comparison(struct ldb_context *ldb, void *mem_ctx, 
diff --git a/lib/ldb/include/ldb_private.h b/lib/ldb/include/ldb_private.h
index 644d49c..bd975b8 100644
--- a/lib/ldb/include/ldb_private.h
+++ b/lib/ldb/include/ldb_private.h
@@ -88,6 +88,13 @@ struct ldb_schema {
 
 	unsigned num_dn_extended_syntax;
 	struct ldb_dn_extended_syntax *dn_extended_syntax;
+
+	/*
+	 * If set, the attribute_handler_override has the details of
+	 * what attributes have an index
+	 */
+	bool index_handler_override;
+	bool one_level_indexes;
 };
 
 /*
diff --git a/lib/ldb/ldb_tdb/ldb_index.c b/lib/ldb/ldb_tdb/ldb_index.c
index 46ba725..721ec1c 100644
--- a/lib/ldb/ldb_tdb/ldb_index.c
+++ b/lib/ldb/ldb_tdb/ldb_index.c
@@ -449,9 +449,25 @@ static bool ltdb_is_indexed(struct ldb_module *module,
 			    struct ltdb_private *ltdb,
 			    const char *attr)
 {
+	struct ldb_context *ldb = ldb_module_get_ctx(module);
 	unsigned int i;
 	struct ldb_message_element *el;
 
+	if (ldb->schema.index_handler_override) {
+		const struct ldb_schema_attribute *a
+			= ldb_schema_attribute_by_name(ldb, attr);
+
+		if (a == NULL) {
+			return false;
+		}
+
+		if (a->flags & LDB_ATTR_FLAG_INDEXED) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
 	if (!ltdb->cache->attribute_indexes) {
 		return false;
 	}
-- 
2.9.4


From 8ff2e6d7ec0b73cd43a546c0c9b21db6ec605f7d Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Thu, 30 Mar 2017 13:10:22 +1300
Subject: [PATCH 05/25] ldb_tdb: Avoid reading the index list from the DB if we
 are already set to override it

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/ldb_tdb/ldb_cache.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/lib/ldb/ldb_tdb/ldb_cache.c b/lib/ldb/ldb_tdb/ldb_cache.c
index cf25d9a..f08e073 100644
--- a/lib/ldb/ldb_tdb/ldb_cache.c
+++ b/lib/ldb/ldb_tdb/ldb_cache.c
@@ -236,6 +236,16 @@ static int ltdb_index_load(struct ldb_module *module,
 	struct ldb_dn *indexlist_dn;
 	int r;
 
+	if (ldb->schema.index_handler_override) {
+		/*
+		 * we skip loading the @INDEXLIST record when a module is
+		 * supplying its own attribute handling
+		 */
+		ltdb->cache->attribute_indexes = true;
+		ltdb->cache->one_level_indexes = ldb->schema.one_level_indexes;
+		return 0;
+	}
+
 	talloc_free(ltdb->cache->indexlist);
 
 	ltdb->cache->indexlist = ldb_msg_new(ltdb->cache);
-- 
2.9.4


From a0d8f96a2e3a2a5c49b96db0b3b698dbdbbee72c Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 30 May 2017 12:47:58 +1200
Subject: [PATCH 06/25] ldb: Move test_ldb_attrs_case_insensitive closer to
 setup/teardown functions

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/tests/ldb_mod_op_test.c | 47 +++++++++++++++++++++--------------------
 1 file changed, 24 insertions(+), 23 deletions(-)

diff --git a/lib/ldb/tests/ldb_mod_op_test.c b/lib/ldb/tests/ldb_mod_op_test.c
index 84043cb..878cf5c 100644
--- a/lib/ldb/tests/ldb_mod_op_test.c
+++ b/lib/ldb/tests/ldb_mod_op_test.c
@@ -1463,6 +1463,30 @@ static int ldb_case_test_teardown(void **state)
 	return 0;
 }
 
+static void test_ldb_attrs_case_insensitive(void **state)
+{
+	int cnt;
+	struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
+			struct ldbtest_ctx);
+
+	/* cn matches exact case */
+	cnt = sub_search_count(ldb_test_ctx, "", "cn=CaseInsensitiveValue");
+	assert_int_equal(cnt, 1);
+
+	/* cn matches lower case */
+	cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
+	assert_int_equal(cnt, 1);
+
+	/* uid matches exact case */
+	cnt = sub_search_count(ldb_test_ctx, "", "uid=CaseSensitiveValue");
+	assert_int_equal(cnt, 1);
+
+	/* uid does not match lower case */
+	cnt = sub_search_count(ldb_test_ctx, "", "uid=casesensitivevalue");
+	assert_int_equal(cnt, 0);
+}
+
+
 struct rename_test_ctx {
 	struct ldbtest_ctx *ldb_test_ctx;
 
@@ -1526,29 +1550,6 @@ static int ldb_rename_test_teardown(void **state)
 	return 0;
 }
 
-static void test_ldb_attrs_case_insensitive(void **state)
-{
-	int cnt;
-	struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
-			struct ldbtest_ctx);
-
-	/* cn matches exact case */
-	cnt = sub_search_count(ldb_test_ctx, "", "cn=CaseInsensitiveValue");
-	assert_int_equal(cnt, 1);
-
-	/* cn matches lower case */
-	cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
-	assert_int_equal(cnt, 1);
-
-	/* uid matches exact case */
-	cnt = sub_search_count(ldb_test_ctx, "", "uid=CaseSensitiveValue");
-	assert_int_equal(cnt, 1);
-
-	/* uid does not match lower case */
-	cnt = sub_search_count(ldb_test_ctx, "", "uid=casesensitivevalue");
-	assert_int_equal(cnt, 0);
-}
-
 static void test_ldb_rename(void **state)
 {
 	struct rename_test_ctx *rename_test_ctx =
-- 
2.9.4


From f95466784bab507f73c9a9d11b5c4a1913961994 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 30 May 2017 13:53:01 +1200
Subject: [PATCH 07/25] ldb: Add tests for the schema and index override hooks

Because this uses ldb_private.h we no longer build the
test binary if we are building against a system ldb

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>

fixup: ldb: Add tests for the schema and index override hooks

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 lib/ldb/tests/ldb_mod_op_test.c | 196 ++++++++++++++++++++++++++++++++++++++++
 lib/ldb/wscript                 |  10 +-
 2 files changed, 201 insertions(+), 5 deletions(-)

diff --git a/lib/ldb/tests/ldb_mod_op_test.c b/lib/ldb/tests/ldb_mod_op_test.c
index 878cf5c..be1a13c 100644
--- a/lib/ldb/tests/ldb_mod_op_test.c
+++ b/lib/ldb/tests/ldb_mod_op_test.c
@@ -26,6 +26,8 @@
 #include <tevent.h>
 
 #include <ldb.h>
+#include <ldb_module.h>
+#include <ldb_private.h>
 #include <string.h>
 #include <ctype.h>
 
@@ -1486,6 +1488,194 @@ static void test_ldb_attrs_case_insensitive(void **state)
 	assert_int_equal(cnt, 0);
 }
 
+static struct ldb_schema_attribute cn_attr_1;
+static struct ldb_schema_attribute cn_attr_2;
+static struct ldb_schema_attribute default_attr;
+
+/*
+  override the name to attribute handler function
+ */
+static const struct ldb_schema_attribute *ldb_test_attribute_handler_override(struct ldb_context *ldb,
+									      void *private_data,
+									      const char *name)
+{
+	if (private_data != NULL && ldb_attr_cmp(name, "cn") == 0) {
+		return &cn_attr_1;
+	} else if (private_data == NULL && ldb_attr_cmp(name, "cn") == 0) {
+		return &cn_attr_2;
+	} else if (ldb_attr_cmp(name, "uid") == 0) {
+		return &cn_attr_2;
+	}
+	return &default_attr;
+}
+
+static void test_ldb_attrs_case_handler(void **state)
+{
+	int cnt;
+	int ret;
+	const struct ldb_schema_syntax *syntax;
+
+	struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
+			struct ldbtest_ctx);
+	struct ldb_context *ldb = ldb_test_ctx->ldb;
+
+	/* cn matches lower case */
+	cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
+	assert_int_equal(cnt, 1);
+
+	syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_OCTET_STRING);
+	assert_non_null(syntax);
+
+	ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb,
+						    "*", 0,
+						    syntax, &default_attr);
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_OCTET_STRING);
+	assert_non_null(syntax);
+
+	ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb,
+						    "cn", 0,
+						    syntax, &cn_attr_1);
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	/*
+	 * Set an attribute handler, which will fail to match as we
+	 * force case sensitive
+	 */
+	ldb_schema_attribute_set_override_handler(ldb,
+						  ldb_test_attribute_handler_override,
+						  (void *)1);
+
+	/* cn does not matche lower case */
+	cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
+	assert_int_equal(cnt, 0);
+
+	syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_DIRECTORY_STRING);
+	assert_non_null(syntax);
+
+	ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb,
+						    "cn", 0,
+						    syntax, &cn_attr_2);
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	/*
+	 * Set an attribute handler, which will match as we
+	 * force case insensitive
+	 */
+	ldb_schema_attribute_set_override_handler(ldb,
+						  ldb_test_attribute_handler_override,
+						  NULL);
+
+	/* cn matches lower case */
+	cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
+	assert_int_equal(cnt, 1);
+
+}
+
+
+static void test_ldb_attrs_index_handler(void **state)
+{
+	int cnt;
+	int ret;
+	const struct ldb_schema_syntax *syntax;
+	struct ldb_ldif *ldif;
+
+	const char *index_ldif =  \
+		"dn: @INDEXLIST\n"
+		"@IDXATTR: cn\n"
+		"\n";
+
+	struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
+			struct ldbtest_ctx);
+	struct ldb_context *ldb = ldb_test_ctx->ldb;
+
+	/* cn matches lower case */
+	cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
+	assert_int_equal(cnt, 1);
+
+	syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_OCTET_STRING);
+	assert_non_null(syntax);
+
+	ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb,
+						    "cn", 0,
+						    syntax, &cn_attr_1);
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_DIRECTORY_STRING);
+	assert_non_null(syntax);
+
+	ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb,
+						    "cn", LDB_ATTR_FLAG_INDEXED,
+						    syntax, &cn_attr_2);
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	/*
+	 * Set an attribute handler
+	 */
+	ldb_schema_attribute_set_override_handler(ldb,
+						  ldb_test_attribute_handler_override,
+						  NULL);
+
+	/* cn matches lower case */
+	cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
+	assert_int_equal(cnt, 1);
+
+	/* Add the index (actually any modify will do) */
+	while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &index_ldif))) {
+		ret = ldb_add(ldb_test_ctx->ldb, ldif->msg);
+		assert_int_equal(ret, LDB_SUCCESS);
+	}
+
+	ldb_schema_set_override_indexlist(ldb, false);
+
+	/* cn does match as there is an index now */
+	cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
+	assert_int_equal(cnt, 1);
+
+	/*
+	 * Set an attribute handler, which will later fail to match as we
+	 * didn't re-index the DB
+	 */
+	ldb_schema_attribute_set_override_handler(ldb,
+						  ldb_test_attribute_handler_override,
+						  (void *)1);
+
+	/*
+	 * cn does not match as we changed the case sensitivity, but
+	 * didn't re-index
+	 *
+	 * This shows that the override is in control
+	 */
+	cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
+	assert_int_equal(cnt, 0);
+
+}
+
+static int ldb_case_attrs_index_test_teardown(void **state)
+{
+	int ret;
+	struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
+			struct ldbtest_ctx);
+	struct ldb_dn *del_dn;
+
+	del_dn = ldb_dn_new_fmt(ldb_test_ctx,
+				ldb_test_ctx->ldb,
+				"@INDEXLIST");
+	assert_non_null(del_dn);
+
+	ret = ldb_delete(ldb_test_ctx->ldb, del_dn);
+	if (ret != LDB_ERR_NO_SUCH_OBJECT) {
+		assert_int_equal(ret, LDB_SUCCESS);
+	}
+
+	assert_dn_doesnt_exist(ldb_test_ctx,
+			       "@INDEXLIST");
+
+	ldb_case_test_teardown(state);
+	return 0;
+}
+
 
 struct rename_test_ctx {
 	struct ldbtest_ctx *ldb_test_ctx;
@@ -1763,6 +1953,12 @@ int main(int argc, const char **argv)
 		cmocka_unit_test_setup_teardown(test_ldb_attrs_case_insensitive,
 						ldb_case_test_setup,
 						ldb_case_test_teardown),
+		cmocka_unit_test_setup_teardown(test_ldb_attrs_case_handler,
+						ldb_case_test_setup,
+						ldb_case_test_teardown),
+		cmocka_unit_test_setup_teardown(test_ldb_attrs_index_handler,
+						ldb_case_test_setup,
+						ldb_case_attrs_index_test_teardown),
 		cmocka_unit_test_setup_teardown(test_ldb_rename,
 						ldb_rename_test_setup,
 						ldb_rename_test_teardown),
diff --git a/lib/ldb/wscript b/lib/ldb/wscript
index c5c887f..de22dc8 100644
--- a/lib/ldb/wscript
+++ b/lib/ldb/wscript
@@ -315,11 +315,11 @@ def build(bld):
                           deps='ldb dl popt',
                           private_library=True)
 
-    bld.SAMBA_BINARY('ldb_tdb_mod_op_test',
-                     source='tests/ldb_mod_op_test.c',
-                     cflags='-DTEST_BE=\"tdb\"',
-                     deps='cmocka ldb',
-                     install=False)
+        bld.SAMBA_BINARY('ldb_tdb_mod_op_test',
+                         source='tests/ldb_mod_op_test.c',
+                         cflags='-DTEST_BE=\"tdb\"',
+                         deps='cmocka ldb',
+                         install=False)
 
 def test(ctx):
     '''run ldb testsuite'''
-- 
2.9.4


From b66c23f81da8bb219db6ed893dfa242b1640498e Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Thu, 4 May 2017 22:27:24 +0200
Subject: [PATCH 08/25] ldb: Add ldb_build_req_common() helper function

Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/common/ldb.c | 171 ++++++++++++++-------------------------------------
 1 file changed, 47 insertions(+), 124 deletions(-)

diff --git a/lib/ldb/common/ldb.c b/lib/ldb/common/ldb.c
index 6067256..01324e3 100644
--- a/lib/ldb/common/ldb.c
+++ b/lib/ldb/common/ldb.c
@@ -1146,6 +1146,41 @@ int ldb_op_default_callback(struct ldb_request *req, struct ldb_reply *ares)
 	return ldb_request_done(req, LDB_SUCCESS);
 }
 
+static struct ldb_request *ldb_build_req_common(TALLOC_CTX *mem_ctx,
+				struct ldb_context *ldb,
+				struct ldb_control **controls,
+				void *context,
+				ldb_request_callback_t callback,
+				struct ldb_request *parent)
+{
+	struct ldb_request *req = NULL;
+
+	req = talloc_zero(mem_ctx, struct ldb_request);
+	if (req == NULL) {
+		return NULL;
+	}
+	req->controls = controls;
+	req->context = context;
+	req->callback = callback;
+
+	ldb_set_timeout_from_prev_req(ldb, parent, req);
+
+	req->handle = ldb_handle_new(req, ldb);
+	if (req->handle == NULL) {
+		TALLOC_FREE(req);
+		return NULL;
+	}
+
+	if (parent != NULL) {
+		req->handle->nesting++;
+		req->handle->parent = parent;
+		req->handle->flags = parent->handle->flags;
+		req->handle->custom_flags = parent->handle->custom_flags;
+	}
+
+	return req;
+}
+
 int ldb_build_search_req_ex(struct ldb_request **ret_req,
 			struct ldb_context *ldb,
 			TALLOC_CTX *mem_ctx,
@@ -1162,7 +1197,8 @@ int ldb_build_search_req_ex(struct ldb_request **ret_req,
 
 	*ret_req = NULL;
 
-	req = talloc(mem_ctx, struct ldb_request);
+	req = ldb_build_req_common(mem_ctx, ldb, controls,
+				   context, callback, parent);
 	if (req == NULL) {
 		ldb_oom(ldb);
 		return LDB_ERR_OPERATIONS_ERROR;
@@ -1184,25 +1220,6 @@ int ldb_build_search_req_ex(struct ldb_request **ret_req,
 	}
 
 	req->op.search.attrs = attrs;
-	req->controls = controls;
-	req->context = context;
-	req->callback = callback;
-
-	ldb_set_timeout_from_prev_req(ldb, parent, req);
-
-	req->handle = ldb_handle_new(req, ldb);
-	if (req->handle == NULL) {
-		ldb_oom(ldb);
-		return LDB_ERR_OPERATIONS_ERROR;
-	}
-
-	if (parent) {
-		req->handle->nesting++;
-		req->handle->parent = parent;
-		req->handle->flags = parent->handle->flags;
-		req->handle->custom_flags = parent->handle->custom_flags;
-	}
-
 	*ret_req = req;
 	return LDB_SUCCESS;
 }
@@ -1250,7 +1267,8 @@ int ldb_build_add_req(struct ldb_request **ret_req,
 
 	*ret_req = NULL;
 
-	req = talloc(mem_ctx, struct ldb_request);
+	req = ldb_build_req_common(mem_ctx, ldb, controls,
+				   context, callback, parent);
 	if (req == NULL) {
 		ldb_set_errstring(ldb, "Out of Memory");
 		return LDB_ERR_OPERATIONS_ERROR;
@@ -1258,27 +1276,7 @@ int ldb_build_add_req(struct ldb_request **ret_req,
 
 	req->operation = LDB_ADD;
 	req->op.add.message = message;
-	req->controls = controls;
-	req->context = context;
-	req->callback = callback;
-
-	ldb_set_timeout_from_prev_req(ldb, parent, req);
-
-	req->handle = ldb_handle_new(req, ldb);
-	if (req->handle == NULL) {
-		ldb_oom(ldb);
-		return LDB_ERR_OPERATIONS_ERROR;
-	}
-
-	if (parent) {
-		req->handle->nesting++;
-		req->handle->parent = parent;
-		req->handle->flags = parent->handle->flags;
-		req->handle->custom_flags = parent->handle->custom_flags;
-	}
-
 	*ret_req = req;
-
 	return LDB_SUCCESS;
 }
 
@@ -1295,7 +1293,8 @@ int ldb_build_mod_req(struct ldb_request **ret_req,
 
 	*ret_req = NULL;
 
-	req = talloc(mem_ctx, struct ldb_request);
+	req = ldb_build_req_common(mem_ctx, ldb, controls,
+				   context, callback, parent);
 	if (req == NULL) {
 		ldb_set_errstring(ldb, "Out of Memory");
 		return LDB_ERR_OPERATIONS_ERROR;
@@ -1303,27 +1302,8 @@ int ldb_build_mod_req(struct ldb_request **ret_req,
 
 	req->operation = LDB_MODIFY;
 	req->op.mod.message = message;
-	req->controls = controls;
-	req->context = context;
-	req->callback = callback;
-
-	ldb_set_timeout_from_prev_req(ldb, parent, req);
-
-	req->handle = ldb_handle_new(req, ldb);
-	if (req->handle == NULL) {
-		ldb_oom(ldb);
-		return LDB_ERR_OPERATIONS_ERROR;
-	}
-
-	if (parent) {
-		req->handle->nesting++;
-		req->handle->parent = parent;
-		req->handle->flags = parent->handle->flags;
-		req->handle->custom_flags = parent->handle->custom_flags;
-	}
 
 	*ret_req = req;
-
 	return LDB_SUCCESS;
 }
 
@@ -1340,7 +1320,8 @@ int ldb_build_del_req(struct ldb_request **ret_req,
 
 	*ret_req = NULL;
 
-	req = talloc(mem_ctx, struct ldb_request);
+	req = ldb_build_req_common(mem_ctx, ldb, controls,
+				   context, callback, parent);
 	if (req == NULL) {
 		ldb_set_errstring(ldb, "Out of Memory");
 		return LDB_ERR_OPERATIONS_ERROR;
@@ -1348,27 +1329,7 @@ int ldb_build_del_req(struct ldb_request **ret_req,
 
 	req->operation = LDB_DELETE;
 	req->op.del.dn = dn;
-	req->controls = controls;
-	req->context = context;
-	req->callback = callback;
-
-	ldb_set_timeout_from_prev_req(ldb, parent, req);
-
-	req->handle = ldb_handle_new(req, ldb);
-	if (req->handle == NULL) {
-		ldb_oom(ldb);
-		return LDB_ERR_OPERATIONS_ERROR;
-	}
-
-	if (parent) {
-		req->handle->nesting++;
-		req->handle->parent = parent;
-		req->handle->flags = parent->handle->flags;
-		req->handle->custom_flags = parent->handle->custom_flags;
-	}
-
 	*ret_req = req;
-
 	return LDB_SUCCESS;
 }
 
@@ -1386,7 +1347,8 @@ int ldb_build_rename_req(struct ldb_request **ret_req,
 
 	*ret_req = NULL;
 
-	req = talloc(mem_ctx, struct ldb_request);
+	req = ldb_build_req_common(mem_ctx, ldb, controls,
+				   context, callback, parent);
 	if (req == NULL) {
 		ldb_set_errstring(ldb, "Out of Memory");
 		return LDB_ERR_OPERATIONS_ERROR;
@@ -1395,27 +1357,7 @@ int ldb_build_rename_req(struct ldb_request **ret_req,
 	req->operation = LDB_RENAME;
 	req->op.rename.olddn = olddn;
 	req->op.rename.newdn = newdn;
-	req->controls = controls;
-	req->context = context;
-	req->callback = callback;
-
-	ldb_set_timeout_from_prev_req(ldb, parent, req);
-
-	req->handle = ldb_handle_new(req, ldb);
-	if (req->handle == NULL) {
-		ldb_oom(ldb);
-		return LDB_ERR_OPERATIONS_ERROR;
-	}
-
-	if (parent) {
-		req->handle->nesting++;
-		req->handle->parent = parent;
-		req->handle->flags = parent->handle->flags;
-		req->handle->custom_flags = parent->handle->custom_flags;
-	}
-
 	*ret_req = req;
-
 	return LDB_SUCCESS;
 }
 
@@ -1462,7 +1404,8 @@ int ldb_build_extended_req(struct ldb_request **ret_req,
 
 	*ret_req = NULL;
 
-	req = talloc(mem_ctx, struct ldb_request);
+	req = ldb_build_req_common(mem_ctx, ldb, controls,
+				   context, callback, parent);
 	if (req == NULL) {
 		ldb_set_errstring(ldb, "Out of Memory");
 		return LDB_ERR_OPERATIONS_ERROR;
@@ -1471,27 +1414,7 @@ int ldb_build_extended_req(struct ldb_request **ret_req,
 	req->operation = LDB_EXTENDED;
 	req->op.extended.oid = oid;
 	req->op.extended.data = data;
-	req->controls = controls;
-	req->context = context;
-	req->callback = callback;
-
-	ldb_set_timeout_from_prev_req(ldb, parent, req);
-
-	req->handle = ldb_handle_new(req, ldb);
-	if (req->handle == NULL) {
-		ldb_oom(ldb);
-		return LDB_ERR_OPERATIONS_ERROR;
-	}
-
-	if (parent) {
-		req->handle->nesting++;
-		req->handle->parent = parent;
-		req->handle->flags = parent->handle->flags;
-		req->handle->custom_flags = parent->handle->custom_flags;
-	}
-
 	*ret_req = req;
-
 	return LDB_SUCCESS;
 }
 
-- 
2.9.4


From 8e7c9067d54f2c921b2203d745687c73c8cb5989 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Thu, 4 May 2017 11:39:21 +0200
Subject: [PATCH 09/25] ldb: Add ldb_handle_get_event_context()

This will allow us to obtain a private event context for use while we hold
locks in ldb_tdb, that is not shared with the global state of the application.

This will ensure we do not perform other operations while we hold the lock

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/ABI/ldb-1.1.29.sigs   |  1 +
 lib/ldb/common/ldb.c          | 13 +++++++++++++
 lib/ldb/include/ldb_module.h  |  7 +++++++
 lib/ldb/include/ldb_private.h |  3 +++
 4 files changed, 24 insertions(+)

diff --git a/lib/ldb/ABI/ldb-1.1.29.sigs b/lib/ldb/ABI/ldb-1.1.29.sigs
index 9b865ed8..70688cf 100644
--- a/lib/ldb/ABI/ldb-1.1.29.sigs
+++ b/lib/ldb/ABI/ldb-1.1.29.sigs
@@ -94,6 +94,7 @@ ldb_get_opaque: void *(struct ldb_context *, const char *)
 ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *)
 ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *)
 ldb_global_init: int (void)
+ldb_handle_get_event_context: struct tevent_context *(struct ldb_handle *)
 ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *)
 ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
 ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
diff --git a/lib/ldb/common/ldb.c b/lib/ldb/common/ldb.c
index 01324e3..5aec1f4 100644
--- a/lib/ldb/common/ldb.c
+++ b/lib/ldb/common/ldb.c
@@ -745,6 +745,19 @@ int ldb_request_get_status(struct ldb_request *req)
 	return req->handle->status;
 }
 
+/*
+ * This function obtains the private event context for the handle,
+ * which may have been created to avoid nested event loops during
+ * ldb_tdb with the locks held
+ */
+struct tevent_context *ldb_handle_get_event_context(struct ldb_handle *handle)
+{
+	if (handle->event_context != NULL) {
+		return handle->event_context;
+	}
+	return ldb_get_event_context(handle->ldb);
+}
+
 
 /*
   trace a ldb request
diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index 75f3fcb..fc8575c 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -210,6 +210,13 @@ int ldb_register_backend(const char *url_prefix, ldb_connect_fn, bool);
 
 struct ldb_handle *ldb_handle_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb);
 
+/*
+ * This function obtains the private event context for the handle,
+ * which may have been created to avoid nested event loops during
+ * ldb_tdb with the locks held
+ */
+struct tevent_context *ldb_handle_get_event_context(struct ldb_handle *handle);
+
 int ldb_module_send_entry(struct ldb_request *req,
 			  struct ldb_message *msg,
 			  struct ldb_control **ctrls);
diff --git a/lib/ldb/include/ldb_private.h b/lib/ldb/include/ldb_private.h
index bd975b8..6e82b3b 100644
--- a/lib/ldb/include/ldb_private.h
+++ b/lib/ldb/include/ldb_private.h
@@ -62,6 +62,9 @@ struct ldb_handle {
 	uint32_t custom_flags;
 	unsigned nesting;
 
+	/* Private event context (if not NULL) */
+	struct tevent_context *event_context;
+
 	/* used for debugging */
 	struct ldb_request *parent;
 	const char *location;
-- 
2.9.4


From 327f0d02f0920f5239289c6fcc5d26890508c1ec Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Fri, 12 May 2017 02:21:28 +0200
Subject: [PATCH 10/25] ldb: Add ldb_set_require_private_event_context()

This will allow us to force use of the global event context for use when Samba
must make an IRPC call from within the ldb stack, to another part of the same
process

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/ABI/ldb-1.1.29.sigs   | 1 +
 lib/ldb/common/ldb.c          | 4 ++++
 lib/ldb/include/ldb_module.h  | 2 ++
 lib/ldb/include/ldb_private.h | 7 +++++++
 4 files changed, 14 insertions(+)

diff --git a/lib/ldb/ABI/ldb-1.1.29.sigs b/lib/ldb/ABI/ldb-1.1.29.sigs
index 70688cf..5e84b0a 100644
--- a/lib/ldb/ABI/ldb-1.1.29.sigs
+++ b/lib/ldb/ABI/ldb-1.1.29.sigs
@@ -239,6 +239,7 @@ ldb_set_event_context: void (struct ldb_context *, struct tevent_context *)
 ldb_set_flags: void (struct ldb_context *, unsigned int)
 ldb_set_modules_dir: void (struct ldb_context *, const char *)
 ldb_set_opaque: int (struct ldb_context *, const char *, void *)
+ldb_set_require_private_event_context: void (struct ldb_context *)
 ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int)
 ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *)
 ldb_set_utf8_default: void (struct ldb_context *)
diff --git a/lib/ldb/common/ldb.c b/lib/ldb/common/ldb.c
index 5aec1f4..628e661 100644
--- a/lib/ldb/common/ldb.c
+++ b/lib/ldb/common/ldb.c
@@ -758,6 +758,10 @@ struct tevent_context *ldb_handle_get_event_context(struct ldb_handle *handle)
 	return ldb_get_event_context(handle->ldb);
 }
 
+void ldb_set_require_private_event_context(struct ldb_context *ldb)
+{
+	ldb->require_private_event_context = true;
+}
 
 /*
   trace a ldb request
diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index fc8575c..54fa989 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -199,6 +199,8 @@ typedef int (*ldb_connect_fn)(struct ldb_context *ldb, const char *url,
 			      unsigned int flags, const char *options[],
 			      struct ldb_module **module);
 
+void ldb_set_require_private_event_context(struct ldb_context *ldb);
+
 struct ldb_backend_ops {
 	const char *name;
 	ldb_connect_fn connect_fn;
diff --git a/lib/ldb/include/ldb_private.h b/lib/ldb/include/ldb_private.h
index 6e82b3b..8b233d3 100644
--- a/lib/ldb/include/ldb_private.h
+++ b/lib/ldb/include/ldb_private.h
@@ -140,6 +140,13 @@ struct ldb_context {
 
 	struct tevent_context *ev_ctx;
 
+	/*
+	 * If the backend holds locks, we must not use a global event
+	 * context, so this flag will be set and ldb_handle_new() will
+	 * build a new event context
+	 */
+	bool require_private_event_context;
+
 	bool prepare_commit_done;
 
 	char *partial_debug;
-- 
2.9.4


From 6c26e43ef98ffaabe95c3d86c49f72c4f22d694c Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Fri, 12 May 2017 02:26:04 +0200
Subject: [PATCH 11/25] ldb: Create private event contexts in top level
 requests, chain to children

We must ensure that the ldb_request we call ldb_wait() will share an event context with all
the eventual request that the ldb backend creates events on

Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/common/ldb.c         | 77 ++++++++++++++++++++++++++++++++++++++------
 lib/ldb/common/ldb_modules.c | 20 ------------
 2 files changed, 67 insertions(+), 30 deletions(-)

diff --git a/lib/ldb/common/ldb.c b/lib/ldb/common/ldb.c
index 628e661..3b2dbe7 100644
--- a/lib/ldb/common/ldb.c
+++ b/lib/ldb/common/ldb.c
@@ -711,6 +711,62 @@ int ldb_set_timeout_from_prev_req(struct ldb_context *ldb,
 }
 
 
+struct ldb_handle *ldb_handle_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb)
+{
+	struct ldb_handle *h;
+
+	h = talloc_zero(mem_ctx, struct ldb_handle);
+	if (h == NULL) {
+		ldb_set_errstring(ldb, "Out of Memory");
+		return NULL;
+	}
+
+	h->status = LDB_SUCCESS;
+	h->state = LDB_ASYNC_INIT;
+	h->ldb = ldb;
+	h->flags = 0;
+	h->location = NULL;
+	h->parent = NULL;
+
+	if (h->ldb->require_private_event_context == true) {
+		h->event_context = tevent_context_init(h);
+		if (h->event_context == NULL) {
+			ldb_set_errstring(ldb,
+					  "Out of Memory allocating "
+					  "event context for new handle");
+			return NULL;
+		}
+		tevent_set_debug(h->event_context, ldb_tevent_debug, ldb);
+		tevent_loop_allow_nesting(h->event_context);
+	}
+
+	return h;
+}
+
+static struct ldb_handle *ldb_handle_new_child(TALLOC_CTX *mem_ctx,
+					       struct ldb_request *parent_req)
+{
+	struct ldb_handle *h;
+
+	h = talloc_zero(mem_ctx, struct ldb_handle);
+	if (h == NULL) {
+		ldb_set_errstring(parent_req->handle->ldb,
+				  "Out of Memory");
+		return NULL;
+	}
+
+	h->status = LDB_SUCCESS;
+	h->state = LDB_ASYNC_INIT;
+	h->ldb = parent_req->handle->ldb;
+	h->parent = parent_req;
+	h->nesting = parent_req->handle->nesting + 1;
+	h->flags = parent_req->handle->flags;
+	h->custom_flags = parent_req->handle->custom_flags;
+	h->event_context = parent_req->handle->event_context;
+
+	return h;
+}
+
 /*
    set the permissions for new files to be passed to open() in
    backends that use local files
@@ -1182,17 +1238,18 @@ static struct ldb_request *ldb_build_req_common(TALLOC_CTX *mem_ctx,
 
 	ldb_set_timeout_from_prev_req(ldb, parent, req);
 
-	req->handle = ldb_handle_new(req, ldb);
-	if (req->handle == NULL) {
-		TALLOC_FREE(req);
-		return NULL;
-	}
-
 	if (parent != NULL) {
-		req->handle->nesting++;
-		req->handle->parent = parent;
-		req->handle->flags = parent->handle->flags;
-		req->handle->custom_flags = parent->handle->custom_flags;
+		req->handle = ldb_handle_new_child(req, parent);
+		if (req->handle == NULL) {
+			TALLOC_FREE(req);
+			return NULL;
+		}
+	} else {
+		req->handle = ldb_handle_new(req, ldb);
+		if (req->handle == NULL) {
+			TALLOC_FREE(req);
+			return NULL;
+		}
 	}
 
 	return req;
diff --git a/lib/ldb/common/ldb_modules.c b/lib/ldb/common/ldb_modules.c
index 62f20af..ca93299 100644
--- a/lib/ldb/common/ldb_modules.c
+++ b/lib/ldb/common/ldb_modules.c
@@ -684,26 +684,6 @@ int ldb_next_del_trans(struct ldb_module *module)
 	return ret;
 }
 
-struct ldb_handle *ldb_handle_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb)
-{
-	struct ldb_handle *h;
-
-	h = talloc_zero(mem_ctx, struct ldb_handle);
-	if (h == NULL) {
-		ldb_set_errstring(ldb, "Out of Memory");
-		return NULL;
-	}
-
-	h->status = LDB_SUCCESS;
-	h->state = LDB_ASYNC_INIT;
-	h->ldb = ldb;
-	h->flags = 0;
-	h->location = NULL;
-	h->parent = NULL;
-
-	return h;
-}
-
 /* calls the request callback to send an entry
  *
  * params:
-- 
2.9.4


From e27b2d7d403c1732cfc504cb97e374a88882eb76 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Fri, 12 May 2017 02:28:02 +0200
Subject: [PATCH 12/25] ldb: Force use of a private event context in ldb_tdb

ldb_tdb holds locks while making callbacks, so force the use of a per-request event context

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/ldb_tdb/ldb_tdb.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/lib/ldb/ldb_tdb/ldb_tdb.c b/lib/ldb/ldb_tdb/ldb_tdb.c
index 3dfd1cc..aed6044a 100644
--- a/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -1556,6 +1556,13 @@ static int ltdb_connect(struct ldb_context *ldb, const char *url,
 	int tdb_flags, open_flags;
 	struct ltdb_private *ltdb;
 
+	/*
+	 * We hold locks, so we must use a private event context
+	 * on each returned handle
+	 */
+
+	ldb_set_require_private_event_context(ldb);
+
 	/* parse the url */
 	if (strchr(url, ':')) {
 		if (strncmp(url, "tdb://", 6) != 0) {
-- 
2.9.4


From d567d45a7d1c61f7ac982bbf46c657fcc15853d8 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Fri, 12 May 2017 02:30:01 +0200
Subject: [PATCH 13/25] ldb: Use the private event context in ldb_tdb and
 ldb_wait()

This enables the previous commits, and ensures that ldb_tdb is safe from operations while locks
are held

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/common/ldb.c      | 2 +-
 lib/ldb/ldb_tdb/ldb_tdb.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/ldb/common/ldb.c b/lib/ldb/common/ldb.c
index 3b2dbe7..a033382 100644
--- a/lib/ldb/common/ldb.c
+++ b/lib/ldb/common/ldb.c
@@ -605,7 +605,7 @@ int ldb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
 		return handle->status;
 	}
 
-	ev = ldb_get_event_context(handle->ldb);
+	ev = ldb_handle_get_event_context(handle);
 	if (NULL == ev) {
 		return ldb_oom(handle->ldb);
 	}
diff --git a/lib/ldb/ldb_tdb/ldb_tdb.c b/lib/ldb/ldb_tdb/ldb_tdb.c
index aed6044a..261011e 100644
--- a/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -1476,7 +1476,7 @@ static int ltdb_handle_request(struct ldb_module *module,
 		return LDB_ERR_TIME_LIMIT_EXCEEDED;
 	}
 
-	ev = ldb_get_event_context(ldb);
+	ev = ldb_handle_get_event_context(req->handle);
 
 	ac = talloc_zero(ldb, struct ltdb_context);
 	if (ac == NULL) {
-- 
2.9.4


From 3e6d834bb8ca77862869a3c39b49b80de178917f Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Fri, 5 May 2017 08:25:40 +0200
Subject: [PATCH 14/25] ldb: Add ldb_handle_use_global_event_context()

This will allow the IRPC to be processed in the main event loop of the
server, not the private event context for this request

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/ABI/ldb-1.1.29.sigs  |  1 +
 lib/ldb/common/ldb.c         | 15 +++++++++++++++
 lib/ldb/include/ldb_module.h | 12 ++++++++++++
 3 files changed, 28 insertions(+)

diff --git a/lib/ldb/ABI/ldb-1.1.29.sigs b/lib/ldb/ABI/ldb-1.1.29.sigs
index 5e84b0a..ef9c53e 100644
--- a/lib/ldb/ABI/ldb-1.1.29.sigs
+++ b/lib/ldb/ABI/ldb-1.1.29.sigs
@@ -96,6 +96,7 @@ ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *)
 ldb_global_init: int (void)
 ldb_handle_get_event_context: struct tevent_context *(struct ldb_handle *)
 ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *)
+ldb_handle_use_global_event_context: void (struct ldb_handle *)
 ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
 ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
 ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *)
diff --git a/lib/ldb/common/ldb.c b/lib/ldb/common/ldb.c
index a033382..a3a0002 100644
--- a/lib/ldb/common/ldb.c
+++ b/lib/ldb/common/ldb.c
@@ -814,6 +814,21 @@ struct tevent_context *ldb_handle_get_event_context(struct ldb_handle *handle)
 	return ldb_get_event_context(handle->ldb);
 }
 
+/*
+ * This function forces a specific ldb handle to use the global event
+ * context.  This allows a nested event loop to operate, so any open
+ * transaction also needs to be aborted.
+ *
+ * Any events on this event context will be lost
+ *
+ * This is used in Samba when sending an IRPC to another part of the
+ * same process instead of making a local DB modification.
+ */
+void ldb_handle_use_global_event_context(struct ldb_handle *handle)
+{
+	TALLOC_FREE(handle->event_context);
+}
+
 void ldb_set_require_private_event_context(struct ldb_context *ldb)
 {
 	ldb->require_private_event_context = true;
diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index 54fa989..91887de 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -447,4 +447,16 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
 #define LDB_UNPACK_DATA_FLAG_NO_DN           0x0002
 #define LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC 0x0004
 
+/*
+ * This function forces a specific ldb handle to use the global event
+ * context.  This allows a nested event loop to operate, so any open
+ * transaction also needs to be aborted.
+ *
+ * Any events on this event context will be lost
+ *
+ * This is used in Samba when sending an IRPC to another part of the
+ * same process instead of making a local DB modification.
+ */
+void ldb_handle_use_global_event_context(struct ldb_handle *handle);
+
 #endif
-- 
2.9.4


From b6d8570bc472dd3c85102dadc7e51dd8bf2c47ae Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 30 May 2017 14:39:49 +1200
Subject: [PATCH 15/25] ldb: Add tests for new ldb handle and event context
 behaviour

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/tests/ldb_mod_op_test.c | 54 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/lib/ldb/tests/ldb_mod_op_test.c b/lib/ldb/tests/ldb_mod_op_test.c
index be1a13c..7d8b074 100644
--- a/lib/ldb/tests/ldb_mod_op_test.c
+++ b/lib/ldb/tests/ldb_mod_op_test.c
@@ -367,6 +367,57 @@ static void test_ldb_del_noexist(void **state)
 	assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
 }
 
+static void test_ldb_handle(void **state)
+{
+	int ret;
+	struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
+							struct ldbtest_ctx);
+	TALLOC_CTX *tmp_ctx;
+	struct ldb_dn *basedn;
+	struct ldb_request *request = NULL;
+	struct ldb_request *request2 = NULL;
+	struct ldb_result *res = NULL;
+	const char *attrs[] = { "cn", NULL };
+
+	tmp_ctx = talloc_new(test_ctx);
+	assert_non_null(tmp_ctx);
+
+	basedn = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "dc=test");
+	assert_non_null(basedn);
+
+	res = talloc_zero(tmp_ctx, struct ldb_result);
+	assert_non_null(res);
+
+	ret = ldb_build_search_req(&request, test_ctx->ldb, tmp_ctx,
+				   basedn, LDB_SCOPE_BASE,
+				   NULL, attrs, NULL, res,
+				   ldb_search_default_callback,
+				   NULL);
+	assert_int_equal(ret, 0);
+
+	/* We are against ldb_tdb, so expect private event contexts */
+	assert_ptr_not_equal(ldb_handle_get_event_context(request->handle),
+			     ldb_get_event_context(test_ctx->ldb));
+
+	ret = ldb_build_search_req(&request2, test_ctx->ldb, tmp_ctx,
+				   basedn, LDB_SCOPE_BASE,
+				   NULL, attrs, NULL, res,
+				   ldb_search_default_callback,
+				   request);
+	assert_int_equal(ret, 0);
+
+	/* Expect that same event context will be chained */
+	assert_ptr_equal(ldb_handle_get_event_context(request->handle),
+			 ldb_handle_get_event_context(request2->handle));
+
+	/* Now force this to use the global context */
+	ldb_handle_use_global_event_context(request2->handle);
+	assert_ptr_equal(ldb_handle_get_event_context(request2->handle),
+			 ldb_get_event_context(test_ctx->ldb));
+
+	talloc_free(tmp_ctx);
+}
+
 static void add_keyval(struct ldbtest_ctx *test_ctx,
 		       const char *key,
 		       const char *val)
@@ -1902,6 +1953,9 @@ int main(int argc, const char **argv)
 		cmocka_unit_test_setup_teardown(test_ldb_del_noexist,
 						ldbtest_setup,
 						ldbtest_teardown),
+		cmocka_unit_test_setup_teardown(test_ldb_handle,
+						ldbtest_setup,
+						ldbtest_teardown),
 		cmocka_unit_test_setup_teardown(test_transactions,
 						ldbtest_setup,
 						ldbtest_teardown),
-- 
2.9.4


From 1144a615fb12fea26810daec37ae5d31a45d3dbb Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 30 May 2017 14:59:16 +1200
Subject: [PATCH 16/25] ldb: Add test for ldb_build_search_req()

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/tests/ldb_mod_op_test.c | 52 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/lib/ldb/tests/ldb_mod_op_test.c b/lib/ldb/tests/ldb_mod_op_test.c
index 7d8b074..9bcbb2f 100644
--- a/lib/ldb/tests/ldb_mod_op_test.c
+++ b/lib/ldb/tests/ldb_mod_op_test.c
@@ -418,6 +418,55 @@ static void test_ldb_handle(void **state)
 	talloc_free(tmp_ctx);
 }
 
+static void test_ldb_build_search_req(void **state)
+{
+	int ret;
+	struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
+							struct ldbtest_ctx);
+	TALLOC_CTX *tmp_ctx;
+	struct ldb_dn *basedn;
+	struct ldb_request *request = NULL;
+	struct ldb_request *request2 = NULL;
+	struct ldb_result *res = NULL;
+	const char *attrs[] = { "cn", NULL };
+
+	tmp_ctx = talloc_new(test_ctx);
+	assert_non_null(tmp_ctx);
+
+	basedn = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "dc=test");
+	assert_non_null(basedn);
+
+	res = talloc_zero(tmp_ctx, struct ldb_result);
+	assert_non_null(res);
+
+	ret = ldb_build_search_req(&request, test_ctx->ldb, tmp_ctx,
+				   basedn, LDB_SCOPE_BASE,
+				   NULL, attrs, NULL, res,
+				   ldb_search_default_callback,
+				   NULL);
+	assert_int_equal(ret, 0);
+
+	assert_int_equal(request->operation, LDB_SEARCH);
+	assert_ptr_equal(request->op.search.base, basedn);
+	assert_int_equal(request->op.search.scope, LDB_SCOPE_BASE);
+	assert_non_null(request->op.search.tree);
+	assert_ptr_equal(request->op.search.attrs, attrs);
+	assert_ptr_equal(request->context, res);
+	assert_ptr_equal(request->callback, ldb_search_default_callback);
+
+	ret = ldb_build_search_req(&request2, test_ctx->ldb, tmp_ctx,
+				   basedn, LDB_SCOPE_BASE,
+				   NULL, attrs, NULL, res,
+				   ldb_search_default_callback,
+				   request);
+	assert_int_equal(ret, 0);
+	assert_ptr_equal(request, request2->handle->parent);
+	assert_int_equal(request->starttime, request2->starttime);
+	assert_int_equal(request->timeout, request2->timeout);
+
+	talloc_free(tmp_ctx);
+}
+
 static void add_keyval(struct ldbtest_ctx *test_ctx,
 		       const char *key,
 		       const char *val)
@@ -1956,6 +2005,9 @@ int main(int argc, const char **argv)
 		cmocka_unit_test_setup_teardown(test_ldb_handle,
 						ldbtest_setup,
 						ldbtest_teardown),
+		cmocka_unit_test_setup_teardown(test_ldb_build_search_req,
+						ldbtest_setup,
+						ldbtest_teardown),
 		cmocka_unit_test_setup_teardown(test_transactions,
 						ldbtest_setup,
 						ldbtest_teardown),
-- 
2.9.4


From 05b143e5f5cbbda97a1a70877ec0c56f90e45c78 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 30 May 2017 20:57:23 +1200
Subject: [PATCH 17/25] ldb: Add Doxygen comments for ldb_req_*trusted()
 functions

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 lib/ldb/include/ldb_module.h | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index 91887de..97d9a32 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -247,19 +247,32 @@ void ldb_set_default_dns(struct ldb_context *ldb);
 int ldb_reply_add_control(struct ldb_reply *ares, const char *oid, bool critical, void *data);
 
 /**
-  mark a request as untrusted. This tells the rootdse module to remove
-  unregistered controls
- */
+  mark a request as untrusted. 
+
+  This tells the rootdse module to remove unregistered controls
+
+  \param req the request to mark as untrusted
+*/
 void ldb_req_mark_untrusted(struct ldb_request *req);
 
 /**
-  mark a request as trusted.
- */
+  mark a request as trusted. 
+
+  This tells the rootdse module to allow unregistered controls
+
+  \param req the request to mark as trusted
+*/
 void ldb_req_mark_trusted(struct ldb_request *req);
 
 /**
    return true is a request is untrusted
- */
+
+   This indicates the request came across a trust boundary
+   for example over LDAP
+
+  \param req the request check
+  \return is req trusted
+*/
 bool ldb_req_is_untrusted(struct ldb_request *req);
 
 /**
-- 
2.9.4


From b7f81dc9c0af454b9d43ce056326d0dce614de15 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 30 May 2017 21:00:34 +1200
Subject: [PATCH 18/25] ldb: Add Doxygen docs for
 ldb_schema_attribute_set_override_handler

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 lib/ldb/include/ldb_module.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index 97d9a32..6b394ad 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -122,6 +122,14 @@ void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name);
 /* we allow external code to override the name -> schema_attribute function */
 typedef const struct ldb_schema_attribute *(*ldb_attribute_handler_override_fn_t)(struct ldb_context *, void *, const char *);
 
+/**
+  Allow the caller to define a callback for the attribute handler
+
+  \param ldb The ldb context
+  \param override The callback to be used for attribute lookups
+  \param private_data Private data for the callback
+
+*/
 void ldb_schema_attribute_set_override_handler(struct ldb_context *ldb,
 					       ldb_attribute_handler_override_fn_t override,
 					       void *private_data);
-- 
2.9.4


From d45728f2f31a0d0777267f06a89f366f61bc0187 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 30 May 2017 21:04:02 +1200
Subject: [PATCH 19/25] ldb: Add Doxygen docs for
 ldb_schema_set_override_indexlist()

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 lib/ldb/include/ldb_module.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index 6b394ad..ccd948f 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -133,6 +133,16 @@ typedef const struct ldb_schema_attribute *(*ldb_attribute_handler_override_fn_t
 void ldb_schema_attribute_set_override_handler(struct ldb_context *ldb,
 					       ldb_attribute_handler_override_fn_t override,
 					       void *private_data);
+
+/**
+  Allow the caller to define that the callback for the attribute handler
+  also overrides the index list
+
+  \param ldb The ldb context
+  \param one_level_indexes Indicates that the index for SCOPE_ONELEVEL
+         should also be maintained
+
+*/
 void ldb_schema_set_override_indexlist(struct ldb_context *ldb,
 				       bool one_level_indexes);
 
-- 
2.9.4


From 7db747c38e19ddb34aeca6ceeb3a3f44355fb72e Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Thu, 4 May 2017 11:39:21 +0200
Subject: [PATCH 20/25] ldb: Add Doxygen docs for
 ldb_handle_get_event_context()

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 lib/ldb/include/ldb_module.h | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index ccd948f..4a339ba 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -230,10 +230,15 @@ int ldb_register_backend(const char *url_prefix, ldb_connect_fn, bool);
 
 struct ldb_handle *ldb_handle_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb);
 
-/*
- * This function obtains the private event context for the handle,
- * which may have been created to avoid nested event loops during
- * ldb_tdb with the locks held
+/**
+ Obtains the private event context for the handle,
+
+ A private event context may have been created to avoid nested event
+ loops during ldb_tdb with the locks held.  Otherwise return the
+ global one.
+
+ \param handle The ldb handle to obtain the event context for
+ \return the tevent event context for this handle (private or global)
  */
 struct tevent_context *ldb_handle_get_event_context(struct ldb_handle *handle);
 
-- 
2.9.4


From 271dd60b912feda99b2ed5cd2e62ecc83a4158d5 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 30 May 2017 21:17:57 +1200
Subject: [PATCH 21/25] ldb: Add Doxygen docs for
 ldb_set_require_private_event_context()

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 lib/ldb/include/ldb_module.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index 4a339ba..b844aca 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -217,6 +217,15 @@ typedef int (*ldb_connect_fn)(struct ldb_context *ldb, const char *url,
 			      unsigned int flags, const char *options[],
 			      struct ldb_module **module);
 
+/**
+ Require that LDB use a private event context for each request
+
+ A private event context may need to be created to avoid nested event
+ loops during ldb_tdb with the locks held.  This indicates that a
+ backend is in use that requires this to hold locks safely.
+
+ \param handle The ldb handle to set the flag on
+ */
 void ldb_set_require_private_event_context(struct ldb_context *ldb);
 
 struct ldb_backend_ops {
-- 
2.9.4


From dc92381e062fd51c06125644cf023f85c6208856 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 30 May 2017 21:12:33 +1200
Subject: [PATCH 22/25] ldb: Add Doxygen documentation for
 ldb_handle_use_global_event_context()

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 lib/ldb/include/ldb_module.h | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index b844aca..f5ee04c 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -492,15 +492,19 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
 #define LDB_UNPACK_DATA_FLAG_NO_DN           0x0002
 #define LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC 0x0004
 
-/*
- * This function forces a specific ldb handle to use the global event
- * context.  This allows a nested event loop to operate, so any open
- * transaction also needs to be aborted.
- *
- * Any events on this event context will be lost
- *
- * This is used in Samba when sending an IRPC to another part of the
- * same process instead of making a local DB modification.
+/**
+ For orces a specific ldb handle to use the global event context.  
+
+ This allows a nested event loop to operate, so any open
+ transaction also needs to be aborted.
+
+ Any events on this event context will be lost
+ 
+ This is used in Samba when sending an IRPC to another part of the
+ same process instead of making a local DB modification.
+
+ \param handle The ldb handle to force to use the global context
+
  */
 void ldb_handle_use_global_event_context(struct ldb_handle *handle);
 
-- 
2.9.4


From a0910faa2a0348d91dfd9c393c42085deb0ca575 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Thu, 30 Mar 2017 13:54:58 +1300
Subject: [PATCH 23/25] ldb: Version 1.1.30

* let ldbdump parse the -i option
* don't allow the reveal_internals control for ldbedit
* only allow --show-binary for ldbsearch
* don't let ldbsearch create non-existing files
* fix ldb_tdb search inconsistencies
* add cmocka based tests
* provide an interface for improved indexing for callers
  like Samba, which will allow much better performance.
* Makes ldb access to tdb:// databases use a private event context
  rather than the global event context passed in by the caller.
  This is because running other operations while locks are held
  or a search is being conducted is not safe.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 lib/ldb/ABI/ldb-1.1.29.sigs            |   4 -
 lib/ldb/ABI/ldb-1.1.30.sigs            | 272 +++++++++++++++++++++++++++++++++
 lib/ldb/ABI/pyldb-util-1.1.30.sigs     |   2 +
 lib/ldb/ABI/pyldb-util.py3-1.1.30.sigs |   2 +
 lib/ldb/wscript                        |   2 +-
 5 files changed, 277 insertions(+), 5 deletions(-)
 create mode 100644 lib/ldb/ABI/ldb-1.1.30.sigs
 create mode 100644 lib/ldb/ABI/pyldb-util-1.1.30.sigs
 create mode 100644 lib/ldb/ABI/pyldb-util.py3-1.1.30.sigs

diff --git a/lib/ldb/ABI/ldb-1.1.29.sigs b/lib/ldb/ABI/ldb-1.1.29.sigs
index ef9c53e..0ea968d 100644
--- a/lib/ldb/ABI/ldb-1.1.29.sigs
+++ b/lib/ldb/ABI/ldb-1.1.29.sigs
@@ -94,9 +94,7 @@ ldb_get_opaque: void *(struct ldb_context *, const char *)
 ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *)
 ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *)
 ldb_global_init: int (void)
-ldb_handle_get_event_context: struct tevent_context *(struct ldb_handle *)
 ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *)
-ldb_handle_use_global_event_context: void (struct ldb_handle *)
 ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
 ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
 ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *)
@@ -227,7 +225,6 @@ ldb_schema_attribute_fill_with_syntax: int (struct ldb_context *, TALLOC_CTX *,
 ldb_schema_attribute_remove: void (struct ldb_context *, const char *)
 ldb_schema_attribute_remove_flagged: void (struct ldb_context *, unsigned int)
 ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *)
-ldb_schema_set_override_indexlist: void (struct ldb_context *, bool)
 ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...)
 ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *)
 ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *)
@@ -240,7 +237,6 @@ ldb_set_event_context: void (struct ldb_context *, struct tevent_context *)
 ldb_set_flags: void (struct ldb_context *, unsigned int)
 ldb_set_modules_dir: void (struct ldb_context *, const char *)
 ldb_set_opaque: int (struct ldb_context *, const char *, void *)
-ldb_set_require_private_event_context: void (struct ldb_context *)
 ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int)
 ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *)
 ldb_set_utf8_default: void (struct ldb_context *)
diff --git a/lib/ldb/ABI/ldb-1.1.30.sigs b/lib/ldb/ABI/ldb-1.1.30.sigs
new file mode 100644
index 0000000..ef9c53e
--- /dev/null
+++ b/lib/ldb/ABI/ldb-1.1.30.sigs
@@ -0,0 +1,272 @@
+ldb_add: int (struct ldb_context *, const struct ldb_message *)
+ldb_any_comparison: int (struct ldb_context *, void *, ldb_attr_handler_t, const struct ldb_val *, const struct ldb_val *)
+ldb_asprintf_errstring: void (struct ldb_context *, const char *, ...)
+ldb_attr_casefold: char *(TALLOC_CTX *, const char *)
+ldb_attr_dn: int (const char *)
+ldb_attr_in_list: int (const char * const *, const char *)
+ldb_attr_list_copy: const char **(TALLOC_CTX *, const char * const *)
+ldb_attr_list_copy_add: const char **(TALLOC_CTX *, const char * const *, const char *)
+ldb_base64_decode: int (char *)
+ldb_base64_encode: char *(TALLOC_CTX *, const char *, int)
+ldb_binary_decode: struct ldb_val (TALLOC_CTX *, const char *)
+ldb_binary_encode: char *(TALLOC_CTX *, struct ldb_val)
+ldb_binary_encode_string: char *(TALLOC_CTX *, const char *)
+ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_del_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_extended_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const char *, void *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_mod_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_rename_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_search_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, const char *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_search_req_ex: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_casefold: char *(struct ldb_context *, TALLOC_CTX *, const char *, size_t)
+ldb_casefold_default: char *(void *, TALLOC_CTX *, const char *, size_t)
+ldb_check_critical_controls: int (struct ldb_control **)
+ldb_comparison_binary: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *)
+ldb_comparison_fold: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *)
+ldb_connect: int (struct ldb_context *, const char *, unsigned int, const char **)
+ldb_control_to_string: char *(TALLOC_CTX *, const struct ldb_control *)
+ldb_controls_except_specified: struct ldb_control **(struct ldb_control **, TALLOC_CTX *, struct ldb_control *)
+ldb_debug: void (struct ldb_context *, enum ldb_debug_level, const char *, ...)
+ldb_debug_add: void (struct ldb_context *, const char *, ...)
+ldb_debug_end: void (struct ldb_context *, enum ldb_debug_level)
+ldb_debug_set: void (struct ldb_context *, enum ldb_debug_level, const char *, ...)
+ldb_delete: int (struct ldb_context *, struct ldb_dn *)
+ldb_dn_add_base: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_add_base_fmt: bool (struct ldb_dn *, const char *, ...)
+ldb_dn_add_child: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_add_child_fmt: bool (struct ldb_dn *, const char *, ...)
+ldb_dn_alloc_casefold: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_alloc_linearized: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_canonical_ex_string: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_canonical_string: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_check_local: bool (struct ldb_module *, struct ldb_dn *)
+ldb_dn_check_special: bool (struct ldb_dn *, const char *)
+ldb_dn_compare: int (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_compare_base: int (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_copy: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_escape_value: char *(TALLOC_CTX *, struct ldb_val)
+ldb_dn_extended_add_syntax: int (struct ldb_context *, unsigned int, const struct ldb_dn_extended_syntax *)
+ldb_dn_extended_filter: void (struct ldb_dn *, const char * const *)
+ldb_dn_extended_syntax_by_name: const struct ldb_dn_extended_syntax *(struct ldb_context *, const char *)
+ldb_dn_from_ldb_val: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const struct ldb_val *)
+ldb_dn_get_casefold: const char *(struct ldb_dn *)
+ldb_dn_get_comp_num: int (struct ldb_dn *)
+ldb_dn_get_component_name: const char *(struct ldb_dn *, unsigned int)
+ldb_dn_get_component_val: const struct ldb_val *(struct ldb_dn *, unsigned int)
+ldb_dn_get_extended_comp_num: int (struct ldb_dn *)
+ldb_dn_get_extended_component: const struct ldb_val *(struct ldb_dn *, const char *)
+ldb_dn_get_extended_linearized: char *(TALLOC_CTX *, struct ldb_dn *, int)
+ldb_dn_get_ldb_context: struct ldb_context *(struct ldb_dn *)
+ldb_dn_get_linearized: const char *(struct ldb_dn *)
+ldb_dn_get_parent: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_get_rdn_name: const char *(struct ldb_dn *)
+ldb_dn_get_rdn_val: const struct ldb_val *(struct ldb_dn *)
+ldb_dn_has_extended: bool (struct ldb_dn *)
+ldb_dn_is_null: bool (struct ldb_dn *)
+ldb_dn_is_special: bool (struct ldb_dn *)
+ldb_dn_is_valid: bool (struct ldb_dn *)
+ldb_dn_map_local: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_map_rebase_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_map_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_minimise: bool (struct ldb_dn *)
+ldb_dn_new: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *)
+ldb_dn_new_fmt: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *, ...)
+ldb_dn_remove_base_components: bool (struct ldb_dn *, unsigned int)
+ldb_dn_remove_child_components: bool (struct ldb_dn *, unsigned int)
+ldb_dn_remove_extended_components: void (struct ldb_dn *)
+ldb_dn_replace_components: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_set_component: int (struct ldb_dn *, int, const char *, const struct ldb_val)
+ldb_dn_set_extended_component: int (struct ldb_dn *, const char *, const struct ldb_val *)
+ldb_dn_update_components: int (struct ldb_dn *, const struct ldb_dn *)
+ldb_dn_validate: bool (struct ldb_dn *)
+ldb_dump_results: void (struct ldb_context *, struct ldb_result *, FILE *)
+ldb_error_at: int (struct ldb_context *, int, const char *, const char *, int)
+ldb_errstring: const char *(struct ldb_context *)
+ldb_extended: int (struct ldb_context *, const char *, void *, struct ldb_result **)
+ldb_extended_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_filter_from_tree: char *(TALLOC_CTX *, const struct ldb_parse_tree *)
+ldb_get_config_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_create_perms: unsigned int (struct ldb_context *)
+ldb_get_default_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_event_context: struct tevent_context *(struct ldb_context *)
+ldb_get_flags: unsigned int (struct ldb_context *)
+ldb_get_opaque: void *(struct ldb_context *, const char *)
+ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_global_init: int (void)
+ldb_handle_get_event_context: struct tevent_context *(struct ldb_handle *)
+ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *)
+ldb_handle_use_global_event_context: void (struct ldb_handle *)
+ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
+ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
+ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *)
+ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *)
+ldb_ldif_parse_modrdn: int (struct ldb_context *, const struct ldb_ldif *, TALLOC_CTX *, struct ldb_dn **, struct ldb_dn **, bool *, struct ldb_dn **, struct ldb_dn **)
+ldb_ldif_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *)
+ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *)
+ldb_ldif_read_file_state: struct ldb_ldif *(struct ldb_context *, struct ldif_read_file_state *)
+ldb_ldif_read_free: void (struct ldb_context *, struct ldb_ldif *)
+ldb_ldif_read_string: struct ldb_ldif *(struct ldb_context *, const char **)
+ldb_ldif_write: int (struct ldb_context *, int (*)(void *, const char *, ...), void *, const struct ldb_ldif *)
+ldb_ldif_write_file: int (struct ldb_context *, FILE *, const struct ldb_ldif *)
+ldb_ldif_write_redacted_trace_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *)
+ldb_ldif_write_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *)
+ldb_load_modules: int (struct ldb_context *, const char **)
+ldb_map_add: int (struct ldb_module *, struct ldb_request *)
+ldb_map_delete: int (struct ldb_module *, struct ldb_request *)
+ldb_map_init: int (struct ldb_module *, const struct ldb_map_attribute *, const struct ldb_map_objectclass *, const char * const *, const char *, const char *)
+ldb_map_modify: int (struct ldb_module *, struct ldb_request *)
+ldb_map_rename: int (struct ldb_module *, struct ldb_request *)
+ldb_map_search: int (struct ldb_module *, struct ldb_request *)
+ldb_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope)
+ldb_match_msg_error: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope, bool *)
+ldb_match_msg_objectclass: int (const struct ldb_message *, const char *)
+ldb_mod_register_control: int (struct ldb_module *, const char *)
+ldb_modify: int (struct ldb_context *, const struct ldb_message *)
+ldb_modify_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_module_call_chain: char *(struct ldb_request *, TALLOC_CTX *)
+ldb_module_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **)
+ldb_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int)
+ldb_module_flags: uint32_t (struct ldb_context *)
+ldb_module_get_ctx: struct ldb_context *(struct ldb_module *)
+ldb_module_get_name: const char *(struct ldb_module *)
+ldb_module_get_ops: const struct ldb_module_ops *(struct ldb_module *)
+ldb_module_get_private: void *(struct ldb_module *)
+ldb_module_init_chain: int (struct ldb_context *, struct ldb_module *)
+ldb_module_load_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **)
+ldb_module_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *)
+ldb_module_next: struct ldb_module *(struct ldb_module *)
+ldb_module_popt_options: struct poptOption **(struct ldb_context *)
+ldb_module_send_entry: int (struct ldb_request *, struct ldb_message *, struct ldb_control **)
+ldb_module_send_referral: int (struct ldb_request *, char *)
+ldb_module_set_next: void (struct ldb_module *, struct ldb_module *)
+ldb_module_set_private: void (struct ldb_module *, void *)
+ldb_modules_hook: int (struct ldb_context *, enum ldb_module_hook_type)
+ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, const char *)
+ldb_modules_load: int (const char *, const char *)
+ldb_msg_add: int (struct ldb_message *, const struct ldb_message_element *, int)
+ldb_msg_add_empty: int (struct ldb_message *, const char *, int, struct ldb_message_element **)
+ldb_msg_add_fmt: int (struct ldb_message *, const char *, const char *, ...)
+ldb_msg_add_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *)
+ldb_msg_add_steal_string: int (struct ldb_message *, const char *, char *)
+ldb_msg_add_steal_value: int (struct ldb_message *, const char *, struct ldb_val *)
+ldb_msg_add_string: int (struct ldb_message *, const char *, const char *)
+ldb_msg_add_value: int (struct ldb_message *, const char *, const struct ldb_val *, struct ldb_message_element **)
+ldb_msg_canonicalize: struct ldb_message *(struct ldb_context *, const struct ldb_message *)
+ldb_msg_check_string_attribute: int (const struct ldb_message *, const char *, const char *)
+ldb_msg_copy: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *)
+ldb_msg_copy_attr: int (struct ldb_message *, const char *, const char *)
+ldb_msg_copy_shallow: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *)
+ldb_msg_diff: struct ldb_message *(struct ldb_context *, struct ldb_message *, struct ldb_message *)
+ldb_msg_difference: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message *, struct ldb_message *, struct ldb_message **)
+ldb_msg_element_compare: int (struct ldb_message_element *, struct ldb_message_element *)
+ldb_msg_element_compare_name: int (struct ldb_message_element *, struct ldb_message_element *)
+ldb_msg_element_equal_ordered: bool (const struct ldb_message_element *, const struct ldb_message_element *)
+ldb_msg_find_attr_as_bool: int (const struct ldb_message *, const char *, int)
+ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, const char *)
+ldb_msg_find_attr_as_double: double (const struct ldb_message *, const char *, double)
+ldb_msg_find_attr_as_int: int (const struct ldb_message *, const char *, int)
+ldb_msg_find_attr_as_int64: int64_t (const struct ldb_message *, const char *, int64_t)
+ldb_msg_find_attr_as_string: const char *(const struct ldb_message *, const char *, const char *)
+ldb_msg_find_attr_as_uint: unsigned int (const struct ldb_message *, const char *, unsigned int)
+ldb_msg_find_attr_as_uint64: uint64_t (const struct ldb_message *, const char *, uint64_t)
+ldb_msg_find_element: struct ldb_message_element *(const struct ldb_message *, const char *)
+ldb_msg_find_ldb_val: const struct ldb_val *(const struct ldb_message *, const char *)
+ldb_msg_find_val: struct ldb_val *(const struct ldb_message_element *, struct ldb_val *)
+ldb_msg_new: struct ldb_message *(TALLOC_CTX *)
+ldb_msg_normalize: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_message **)
+ldb_msg_remove_attr: void (struct ldb_message *, const char *)
+ldb_msg_remove_element: void (struct ldb_message *, struct ldb_message_element *)
+ldb_msg_rename_attr: int (struct ldb_message *, const char *, const char *)
+ldb_msg_sanity_check: int (struct ldb_context *, const struct ldb_message *)
+ldb_msg_sort_elements: void (struct ldb_message *)
+ldb_next_del_trans: int (struct ldb_module *)
+ldb_next_end_trans: int (struct ldb_module *)
+ldb_next_init: int (struct ldb_module *)
+ldb_next_prepare_commit: int (struct ldb_module *)
+ldb_next_remote_request: int (struct ldb_module *, struct ldb_request *)
+ldb_next_request: int (struct ldb_module *, struct ldb_request *)
+ldb_next_start_trans: int (struct ldb_module *)
+ldb_op_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_options_find: const char *(struct ldb_context *, const char **, const char *)
+ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *)
+ldb_parse_control_from_string: struct ldb_control *(struct ldb_context *, TALLOC_CTX *, const char *)
+ldb_parse_control_strings: struct ldb_control **(struct ldb_context *, TALLOC_CTX *, const char **)
+ldb_parse_tree: struct ldb_parse_tree *(TALLOC_CTX *, const char *)
+ldb_parse_tree_attr_replace: void (struct ldb_parse_tree *, const char *, const char *)
+ldb_parse_tree_copy_shallow: struct ldb_parse_tree *(TALLOC_CTX *, const struct ldb_parse_tree *)
+ldb_parse_tree_walk: int (struct ldb_parse_tree *, int (*)(struct ldb_parse_tree *, void *), void *)
+ldb_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t)
+ldb_register_backend: int (const char *, ldb_connect_fn, bool)
+ldb_register_extended_match_rule: int (struct ldb_context *, const struct ldb_extended_match_rule *)
+ldb_register_hook: int (ldb_hook_fn)
+ldb_register_module: int (const struct ldb_module_ops *)
+ldb_rename: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *)
+ldb_reply_add_control: int (struct ldb_reply *, const char *, bool, void *)
+ldb_reply_get_control: struct ldb_control *(struct ldb_reply *, const char *)
+ldb_req_get_custom_flags: uint32_t (struct ldb_request *)
+ldb_req_is_untrusted: bool (struct ldb_request *)
+ldb_req_location: const char *(struct ldb_request *)
+ldb_req_mark_trusted: void (struct ldb_request *)
+ldb_req_mark_untrusted: void (struct ldb_request *)
+ldb_req_set_custom_flags: void (struct ldb_request *, uint32_t)
+ldb_req_set_location: void (struct ldb_request *, const char *)
+ldb_request: int (struct ldb_context *, struct ldb_request *)
+ldb_request_add_control: int (struct ldb_request *, const char *, bool, void *)
+ldb_request_done: int (struct ldb_request *, int)
+ldb_request_get_control: struct ldb_control *(struct ldb_request *, const char *)
+ldb_request_get_status: int (struct ldb_request *)
+ldb_request_replace_control: int (struct ldb_request *, const char *, bool, void *)
+ldb_request_set_state: void (struct ldb_request *, int)
+ldb_reset_err_string: void (struct ldb_context *)
+ldb_save_controls: int (struct ldb_control *, struct ldb_request *, struct ldb_control ***)
+ldb_schema_attribute_add: int (struct ldb_context *, const char *, unsigned int, const char *)
+ldb_schema_attribute_add_with_syntax: int (struct ldb_context *, const char *, unsigned int, const struct ldb_schema_syntax *)
+ldb_schema_attribute_by_name: const struct ldb_schema_attribute *(struct ldb_context *, const char *)
+ldb_schema_attribute_fill_with_syntax: int (struct ldb_context *, TALLOC_CTX *, const char *, unsigned int, const struct ldb_schema_syntax *, struct ldb_schema_attribute *)
+ldb_schema_attribute_remove: void (struct ldb_context *, const char *)
+ldb_schema_attribute_remove_flagged: void (struct ldb_context *, unsigned int)
+ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *)
+ldb_schema_set_override_indexlist: void (struct ldb_context *, bool)
+ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...)
+ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *)
+ldb_set_create_perms: void (struct ldb_context *, unsigned int)
+ldb_set_debug: int (struct ldb_context *, void (*)(void *, enum ldb_debug_level, const char *, va_list), void *)
+ldb_set_debug_stderr: int (struct ldb_context *)
+ldb_set_default_dns: void (struct ldb_context *)
+ldb_set_errstring: void (struct ldb_context *, const char *)
+ldb_set_event_context: void (struct ldb_context *, struct tevent_context *)
+ldb_set_flags: void (struct ldb_context *, unsigned int)
+ldb_set_modules_dir: void (struct ldb_context *, const char *)
+ldb_set_opaque: int (struct ldb_context *, const char *, void *)
+ldb_set_require_private_event_context: void (struct ldb_context *)
+ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int)
+ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *)
+ldb_set_utf8_default: void (struct ldb_context *)
+ldb_set_utf8_fns: void (struct ldb_context *, void *, char *(*)(void *, void *, const char *, size_t))
+ldb_setup_wellknown_attributes: int (struct ldb_context *)
+ldb_should_b64_encode: int (struct ldb_context *, const struct ldb_val *)
+ldb_standard_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *)
+ldb_strerror: const char *(int)
+ldb_string_to_time: time_t (const char *)
+ldb_string_utc_to_time: time_t (const char *)
+ldb_timestring: char *(TALLOC_CTX *, time_t)
+ldb_timestring_utc: char *(TALLOC_CTX *, time_t)
+ldb_transaction_cancel: int (struct ldb_context *)
+ldb_transaction_cancel_noerr: int (struct ldb_context *)
+ldb_transaction_commit: int (struct ldb_context *)
+ldb_transaction_prepare_commit: int (struct ldb_context *)
+ldb_transaction_start: int (struct ldb_context *)
+ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *)
+ldb_unpack_data_only_attr_list: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, const char * const *, unsigned int, unsigned int *)
+ldb_unpack_data_only_attr_list_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, const char * const *, unsigned int, unsigned int, unsigned int *)
+ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *)
+ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *)
+ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
+ldb_val_map_remote: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
+ldb_val_string_cmp: int (const struct ldb_val *, const char *)
+ldb_val_to_time: int (const struct ldb_val *, time_t *)
+ldb_valid_attr_name: int (const char *)
+ldb_vdebug: void (struct ldb_context *, enum ldb_debug_level, const char *, va_list)
+ldb_wait: int (struct ldb_handle *, enum ldb_wait_type)
diff --git a/lib/ldb/ABI/pyldb-util-1.1.30.sigs b/lib/ldb/ABI/pyldb-util-1.1.30.sigs
new file mode 100644
index 0000000..74d6719
--- /dev/null
+++ b/lib/ldb/ABI/pyldb-util-1.1.30.sigs
@@ -0,0 +1,2 @@
+pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
+pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
diff --git a/lib/ldb/ABI/pyldb-util.py3-1.1.30.sigs b/lib/ldb/ABI/pyldb-util.py3-1.1.30.sigs
new file mode 100644
index 0000000..74d6719
--- /dev/null
+++ b/lib/ldb/ABI/pyldb-util.py3-1.1.30.sigs
@@ -0,0 +1,2 @@
+pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
+pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
diff --git a/lib/ldb/wscript b/lib/ldb/wscript
index de22dc8..635a787 100644
--- a/lib/ldb/wscript
+++ b/lib/ldb/wscript
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 APPNAME = 'ldb'
-VERSION = '1.1.29'
+VERSION = '1.1.30'
 
 blddir = 'bin'
 
-- 
2.9.4


From 0a1536963d35aa90e9dc5b2985411c6b0d140fbe Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Thu, 30 Mar 2017 13:25:35 +1300
Subject: [PATCH 24/25] schema: Use ldb_schema_set_override_indexlist for
 faster index selection

This allows Samba to provide a binary tree lookup for the existance of an index on the attribute
rather than the O(n) lookup that was being done for each attribute during a search or modify

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 source4/dsdb/schema/schema_init.c | 4 ++++
 source4/dsdb/schema/schema_set.c  | 1 +
 2 files changed, 5 insertions(+)

diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c
index 256c467..c76b57c 100644
--- a/source4/dsdb/schema/schema_init.c
+++ b/source4/dsdb/schema/schema_init.c
@@ -514,6 +514,10 @@ static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb,
 		a->flags |= LDB_ATTR_FLAG_SINGLE_VALUE;
 	}
 	
+	if (attr->searchFlags & SEARCH_FLAG_ATTINDEX) {
+		a->flags |= LDB_ATTR_FLAG_INDEXED;
+	}
+
 	
 	return LDB_SUCCESS;
 }
diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c
index d3e3cc8..e6d5ce6 100644
--- a/source4/dsdb/schema/schema_set.c
+++ b/source4/dsdb/schema/schema_set.c
@@ -71,6 +71,7 @@ int dsdb_schema_set_indices_and_attributes(struct ldb_context *ldb,
 
 	/* setup our own attribute name to schema handler */
 	ldb_schema_attribute_set_override_handler(ldb, dsdb_attribute_handler_override, schema);
+	ldb_schema_set_override_indexlist(ldb, true);
 
 	if (!write_indices_and_attributes) {
 		return ret;
-- 
2.9.4


From 59254e14258bb82acf63b55df374bf0fc17fd2df Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Fri, 12 May 2017 01:55:45 +0200
Subject: [PATCH 25/25] dsdb: Use ldb_handle_use_global_event_context for
 rootdse modifies

The modify operations on the rootDSE turn into IRPC messages, and these need
to be handled on the global event context, not the per-operation context

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
---
 source4/dsdb/samdb/ldb_modules/rootdse.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c
index d3483fc..d1a4409 100644
--- a/source4/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c
@@ -1520,6 +1520,12 @@ static int rootdse_become_master(struct ldb_module *module,
 	 */
 	rootdse_del_trans(module);
 
+	/*
+	 * We must use the global event loop to run this IRPC in
+	 * single process mode
+	 */
+	ldb_handle_use_global_event_context(req->handle);
+
 	msg = imessaging_client_init(tmp_ctx, lp_ctx,
 				    ldb_get_event_context(ldb));
 	if (!msg) {
-- 
2.9.4



More information about the samba-technical mailing list