[SCM] Samba Shared Repository - branch master updated - release-4-0-0alpha8-1336-g9f03135

Andrew Tridgell tridge at samba.org
Wed Sep 2 02:20:11 MDT 2009


The branch, master has been updated
       via  9f031352c6e9439922284fc853611964b33ea4af (commit)
       via  b5f63160d474b1fc8484a1a9112aa4f248d1e814 (commit)
       via  ca45847edab3a5897c0e0d3b4c486ad9ae0848c6 (commit)
       via  199be936d8920fce31e18d6663f8ba36f573d26f (commit)
       via  69802b3a3b934407d898088c8b3fbee64919b668 (commit)
       via  10bd56b34a51cb10f48646584d58f0fdffe85e94 (commit)
       via  1e552770ee25fb34b680ef01bc64e21dc9803782 (commit)
       via  29320bc6e0f364047686b76f26dbd8135ab87377 (commit)
       via  79255a9384e16a37602028fb0960acf9fc1eb257 (commit)
       via  67bf17598bd755ac07952fc44ce27031478d5503 (commit)
       via  4b336fed94b953cd78087a1ffcf75b65cb846c0f (commit)
       via  a19ad210332008c25e24dd6aba6a3479ba9ffe3f (commit)
       via  132242fe7ebbf7bba9fb5a361788b0157cc704ac (commit)
       via  90b694bc6114cbb652b11a136a8fc3657861d790 (commit)
       via  b5bf4400659a59b6508ede2e9d1b7fbd253c0b07 (commit)
      from  aec03eda93d3db8723c79f062c80db0267ac2e59 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 9f031352c6e9439922284fc853611964b33ea4af
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 18:18:33 2009 +1000

    traverse the ac list in reverse order
    
    items are added to the linked attribute list using DLIST_ADD(), which
    means to commit them to the database in the same order they came from
    the server we need to walk the list backwards when we traverse it

commit b5f63160d474b1fc8484a1a9112aa4f248d1e814
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 17:08:52 2009 +1000

    repl_meta_data should only be included when we are a DC

commit ca45847edab3a5897c0e0d3b4c486ad9ae0848c6
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 17:02:56 2009 +1000

    s4:dsdb rewrite the linked_atrributes code to commit in the end_transaction hook
    
    linked attribute changes can come in any order. This means it is
    possible for a forward link to come over the wire in DRS before the
    target even exists. To make this work this patch changed the linked
    attributes module to gather up all the changes it needs to make in a
    linked list, then execute the changes in the end_transaction hook for
    the module.
    
    During that commit phase we also fix up all the DNs that we got by
    searching for their GUID, as the objects may have moved after the
    linked attribute was sent, but before the end of the transaction

commit 199be936d8920fce31e18d6663f8ba36f573d26f
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 16:58:04 2009 +1000

    move the repl_meta_data module up the ldb module stack
    
    The repl_meta_data module needs to be above the linked_attributes
    module, to allow linked_attributes to do its magic

commit 69802b3a3b934407d898088c8b3fbee64919b668
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 16:57:25 2009 +1000

    wrap the entire vampire operation in a transaction
    
    We want to grab the whole database, or none of it.
    This is also needed to get linked attributes right

commit 10bd56b34a51cb10f48646584d58f0fdffe85e94
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 16:56:39 2009 +1000

    use ldb_cmdline_help() in ldbsearch

commit 1e552770ee25fb34b680ef01bc64e21dc9803782
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 16:56:20 2009 +1000

    added ldb_cmdline_help()
    
    This allows the ldb tools to show their full command line options

commit 29320bc6e0f364047686b76f26dbd8135ab87377
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 16:55:57 2009 +1000

    add the partition_control control to replication requests
    
    We know the partition DN from the DRS objects, we need to pass this
    down the modules below us to ensure they operate on the right
    partition

commit 79255a9384e16a37602028fb0960acf9fc1eb257
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 13:36:54 2009 +1000

    change the dsdb_control_current_partition to not include internal variables
    
    This structures was used in two ways. In one way it held variables
    that are logically internal to the partition module, and in the other
    way it was used to pass the partition DN down to other modules. This
    change makes the structure contain just the dn which is being passed
    down.
    
    This change is part of the support for linked attributes. We will be
    passing this control down from above the partition module to force
    which partition a request acts upon. The partition module now only
    adds this control if it isn't already there.

commit 67bf17598bd755ac07952fc44ce27031478d5503
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 13:33:37 2009 +1000

    don't allow two controls to be added with the same OID
    
    Two controls with the same OID makes no sense, as they may
    have different data attached

commit 4b336fed94b953cd78087a1ffcf75b65cb846c0f
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 11:20:26 2009 +1000

    Display ldif formatted versions of all DRS changes at log level 4
    
    This helps a lot with debugging the DRS replication code

commit a19ad210332008c25e24dd6aba6a3479ba9ffe3f
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 11:17:43 2009 +1000

    Wrap DRS changes in a transaction
    
    We should always apply a whole set of DRS changes or none of them. See
    [MS-DRSR] 3.3.2

commit 132242fe7ebbf7bba9fb5a361788b0157cc704ac
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 11:15:44 2009 +1000

    add a ref to the WSPP docs

commit 90b694bc6114cbb652b11a136a8fc3657861d790
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 11:15:29 2009 +1000

    fixed spelling

commit b5bf4400659a59b6508ede2e9d1b7fbd253c0b07
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Sep 2 11:14:33 2009 +1000

    added ldb_ldif_message_string()
    
    This function provides a easy function for displaying a ldb_message
    structure in a human readable format. It is especially useful for
    calling in gdb.

-----------------------------------------------------------------------

Summary of changes:
 librpc/idl/drsuapi.idl                             |    1 +
 source4/dsdb/repl/replicated_objects.c             |   18 +
 source4/dsdb/samdb/ldb_modules/linked_attributes.c |  395 ++++++++++++++------
 source4/dsdb/samdb/ldb_modules/partition.c         |  162 +++++----
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c    |   40 ++
 source4/dsdb/samdb/samdb.h                         |    8 +-
 source4/lib/ldb/common/ldb_controls.c              |    8 +-
 source4/lib/ldb/common/ldb_ldif.c                  |   16 +
 source4/lib/ldb/include/ldb.h                      |   12 +
 source4/lib/ldb/tools/cmdline.c                    |   65 ++--
 source4/lib/ldb/tools/cmdline.h                    |    2 +
 source4/lib/ldb/tools/ldbsearch.c                  |    9 +-
 source4/libnet/libnet_vampire.c                    |   37 ++-
 source4/scripting/python/samba/provision.py        |    3 +-
 14 files changed, 534 insertions(+), 242 deletions(-)


Changeset truncated at 500 lines:

diff --git a/librpc/idl/drsuapi.idl b/librpc/idl/drsuapi.idl
index 9e1f17b..6ca870a 100644
--- a/librpc/idl/drsuapi.idl
+++ b/librpc/idl/drsuapi.idl
@@ -608,6 +608,7 @@ interface drsuapi
 		drsuapi_DsReplicaMetaData meta_data;
 	} drsuapi_DsReplicaLinkedAttribute;
 
+	/* [MS-DRSR] section 4.1.10.2.11 DRS_MSG_GETCHGREPLY_V6 */
 	typedef [public,gensize] struct {
 		GUID source_dsa_guid; /* the 'objectGUID' field of the CN=NTDS Settings object */
 		GUID source_dsa_invocation_id; /* the 'invocationId' field of the CN=NTDS Settings object */
diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c
index d96a063..8018254 100644
--- a/source4/dsdb/repl/replicated_objects.c
+++ b/source4/dsdb/repl/replicated_objects.c
@@ -245,15 +245,33 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb,
 
 	/* TODO: handle linked attributes */
 
+	/* wrap the extended operation in a transaction 
+	   See [MS-DRSR] 3.3.2 Transactions
+	 */
+	ret = ldb_transaction_start(ldb);
+	if (ret != LDB_SUCCESS) {
+		DEBUG(0,(__location__ " Failed to start transaction\n"));
+		talloc_free(out);
+		return WERR_FOOBAR;
+	}
+
 	ret = ldb_extended(ldb, DSDB_EXTENDED_REPLICATED_OBJECTS_OID, out, &ext_res);
 	if (ret != LDB_SUCCESS) {
 		DEBUG(0,("Failed to apply records: %s: %s\n",
 			 ldb_errstring(ldb), ldb_strerror(ret)));
 		talloc_free(out);
+		ldb_transaction_cancel(ldb);
 		return WERR_FOOBAR;
 	}
 	talloc_free(ext_res);
 
+	ret = ldb_transaction_commit(ldb);
+	if (ret != LDB_SUCCESS) {
+		DEBUG(0,(__location__ " Failed to commit transaction\n"));
+		talloc_free(out);
+		return WERR_FOOBAR;
+	}
+
 	if (_out) {
 		*_out = out;
 	} else {
diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c
index 9ed06a9..3486b7f 100644
--- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c
+++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c
@@ -33,6 +33,10 @@
 #include "dlinklist.h"
 #include "dsdb/samdb/samdb.h"
 
+struct la_private {
+	struct la_context *la_list;
+};
+
 struct la_op_store {
 	struct la_op_store *next;
 	struct la_op_store *prev;
@@ -49,9 +53,11 @@ struct replace_context {
 };
 
 struct la_context {
+	struct la_context *next, *prev;
 	const struct dsdb_schema *schema;
 	struct ldb_module *module;
 	struct ldb_request *req;
+	struct ldb_dn *partition_dn;
 	struct ldb_dn *add_dn;
 	struct ldb_dn *del_dn;
 	struct replace_context *rc;
@@ -65,6 +71,7 @@ static struct la_context *linked_attributes_init(struct ldb_module *module,
 {
 	struct ldb_context *ldb;
 	struct la_context *ac;
+	const struct ldb_control *partition_ctrl;
 
 	ldb = ldb_module_get_ctx(module);
 
@@ -78,6 +85,17 @@ static struct la_context *linked_attributes_init(struct ldb_module *module,
 	ac->module = module;
 	ac->req = req;
 
+	/* remember the partition DN that came in, if given */
+	partition_ctrl = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID);
+	if (partition_ctrl) {
+		const struct dsdb_control_current_partition *partition;
+		partition = talloc_get_type(partition_ctrl->data,
+					    struct dsdb_control_current_partition);
+		SMB_ASSERT(partition && partition->version == DSDB_CONTROL_CURRENT_PARTITION_VERSION);
+	
+		ac->partition_dn = ldb_dn_copy(ac, partition->dn);
+	}
+
 	return ac;
 }
 
@@ -130,9 +148,7 @@ static int la_store_op(struct la_context *ac,
 
 static int la_op_search_callback(struct ldb_request *req,
 				 struct ldb_reply *ares);
-static int la_do_mod_request(struct la_context *ac);
-static int la_mod_callback(struct ldb_request *req,
-			   struct ldb_reply *ares);
+static int la_queue_mod_request(struct la_context *ac);
 static int la_down_req(struct la_context *ac);
 
 
@@ -181,7 +197,7 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request *
 		}
 		
 		if ((schema_attr->linkID & 1) == 1) {
-			/* Odd is for the target.  Illigal to modify */
+			/* Odd is for the target.  Illegal to modify */
 			ldb_asprintf_errstring(ldb, 
 					       "attribute %s must not be modified directly, it is a linked attribute", el->name);
 			return LDB_ERR_UNWILLING_TO_PERFORM;
@@ -328,7 +344,7 @@ static int la_mod_search_callback(struct ldb_request *req, struct ldb_reply *are
 
 		if (ac->req->operation == LDB_ADD) {
 			/* Start the modifies to the backlinks */
-			ret = la_do_mod_request(ac);
+			ret = la_queue_mod_request(ac);
 
 			if (ret != LDB_SUCCESS) {
 				return ldb_module_done(ac->req, NULL, NULL,
@@ -745,7 +761,7 @@ static int la_op_search_callback(struct ldb_request *req,
 
 		case LDB_RENAME:	
 			/* start the mod requests chain */
-			ret = la_do_mod_request(ac);
+			ret = la_queue_mod_request(ac);
 			if (ret != LDB_SUCCESS) {
 				return ldb_module_done(ac->req, NULL, NULL,
 						       ret);
@@ -765,112 +781,23 @@ static int la_op_search_callback(struct ldb_request *req,
 	return LDB_SUCCESS;
 }
 
-/* do a linked attributes modify request */
-static int la_do_mod_request(struct la_context *ac)
+/* queue a linked attributes modify request in the la_private
+   structure */
+static int la_queue_mod_request(struct la_context *ac)
 {
-	struct ldb_message_element *ret_el;
-	struct ldb_request *mod_req;
-	struct ldb_message *new_msg;
-	struct ldb_context *ldb;
-	int ret;
-
-	/* If we have no modifies in the queue, we are done! */
-	if (!ac->ops) {
-		return ldb_module_done(ac->req, ac->op_controls,
-				       ac->op_response, LDB_SUCCESS);
-	}
-
-	ldb = ldb_module_get_ctx(ac->module);
+	struct la_private *la_private = 
+		talloc_get_type(ldb_module_get_private(ac->module), struct la_private);
 
-	/* Create the modify request */
-	new_msg = ldb_msg_new(ac);
-	if (!new_msg) {
-		ldb_oom(ldb);
-		return LDB_ERR_OPERATIONS_ERROR;
-	}
-	new_msg->dn = ac->ops->dn;
-
-	if (ac->ops->op == LA_OP_ADD) {
-		ret = ldb_msg_add_empty(new_msg, ac->ops->name,
-					LDB_FLAG_MOD_ADD, &ret_el);
-	} else {
-		ret = ldb_msg_add_empty(new_msg, ac->ops->name,
-					LDB_FLAG_MOD_DELETE, &ret_el);
-	}
-	if (ret != LDB_SUCCESS) {
-		return ret;
-	}
-	ret_el->values = talloc_array(new_msg, struct ldb_val, 1);
-	if (!ret_el->values) {
-		ldb_oom(ldb);
+	if (la_private == NULL) {
+		ldb_debug(ldb_module_get_ctx(ac->module), LDB_DEBUG_ERROR, __location__ ": No la_private transaction setup\n");
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
-	ret_el->num_values = 1;
-	if (ac->ops->op == LA_OP_ADD) {
-		ret_el->values[0] = data_blob_string_const(ldb_dn_get_extended_linearized(new_msg, ac->add_dn, 1));
-	} else {
-		ret_el->values[0] = data_blob_string_const(ldb_dn_get_extended_linearized(new_msg, ac->del_dn, 1));
-	}
-
-#if 0
-	ldb_debug(ldb, LDB_DEBUG_WARNING,
-		  "link on %s %s: %s %s\n", 
-		  ldb_dn_get_linearized(new_msg->dn), ret_el->name, 
-		  ret_el->values[0].data, ac->ops->op == LA_OP_ADD ? "added" : "deleted");
-#endif	
-
-	/* use ac->ops as the mem_ctx so that the request will be freed
-	 * in the callback as soon as completed */
-	ret = ldb_build_mod_req(&mod_req, ldb, ac->ops,
-				new_msg,
-				NULL,
-				ac, la_mod_callback,
-				ac->req);
-	if (ret != LDB_SUCCESS) {
-		return ret;
-	}
-	talloc_steal(mod_req, new_msg);
-
-	/* Run the new request */
-	return ldb_next_request(ac->module, mod_req);
-}
-
-static int la_mod_callback(struct ldb_request *req, struct ldb_reply *ares)
-{
-	struct la_context *ac;
-	struct ldb_context *ldb;
-	struct la_op_store *os;
-
-	ac = talloc_get_type(req->context, struct la_context);
-	ldb = ldb_module_get_ctx(ac->module);
-
-	if (!ares) {
-		return ldb_module_done(ac->req, NULL, NULL,
-					LDB_ERR_OPERATIONS_ERROR);
-	}
-	if (ares->error != LDB_SUCCESS) {
-		return ldb_module_done(ac->req, ares->controls,
-					ares->response, ares->error);
-	}
 
-	if (ares->type != LDB_REPLY_DONE) {
-		ldb_set_errstring(ldb,
-				  "invalid ldb_reply_type in callback");
-		talloc_free(ares);
-		return ldb_module_done(ac->req, NULL, NULL,
-					LDB_ERR_OPERATIONS_ERROR);
-	}
-
-	talloc_free(ares);
+	talloc_steal(la_private, ac);
+	DLIST_ADD(la_private->la_list, ac);
 
-	os = ac->ops;
-	DLIST_REMOVE(ac->ops, os);
-
-	/* this frees the request too
-	 * DO NOT access 'req' after this point */
-	talloc_free(os);
-
-	return la_do_mod_request(ac);
+	return ldb_module_done(ac->req, ac->op_controls,
+			       ac->op_response, LDB_SUCCESS);
 }
 
 /* Having done the original operation, then try to fix up all the linked attributes for modify and delete */
@@ -904,14 +831,14 @@ static int la_mod_del_callback(struct ldb_request *req, struct ldb_reply *ares)
 	ac->op_response = talloc_steal(ac, ares->response);
 
 	/* If we have modfies to make, this is the time to do them for modify and delete */
-	ret = la_do_mod_request(ac);
+	ret = la_queue_mod_request(ac);
 	
 	if (ret != LDB_SUCCESS) {
 		return ldb_module_done(ac->req, NULL, NULL, ret);
 	}
 	talloc_free(ares);
 
-	/* la_do_mod_request has already sent the callbacks */
+	/* la_queue_mod_request has already sent the callbacks */
 	return LDB_SUCCESS;
 
 }
@@ -1094,6 +1021,255 @@ static int la_down_req(struct la_context *ac)
 	return ldb_next_request(ac->module, down_req);
 }
 
+/*
+  use the GUID part of an extended DN to find the target DN, in case
+  it has moved
+ */
+static int la_find_dn_target(struct ldb_module *module, struct la_context *ac, struct ldb_dn **dn)
+{
+	const struct ldb_val *guid;
+	struct ldb_context *ldb;
+	int ret;
+	struct ldb_result *res;
+	const char *attrs[] = { NULL };
+	struct ldb_request *search_req;
+	char *expression;
+	struct ldb_search_options_control *options;
+
+	ldb = ldb_module_get_ctx(ac->module);
+
+	guid = ldb_dn_get_extended_component(*dn, "GUID");
+	if (guid == NULL) {
+		return LDB_SUCCESS;
+	}
+
+	expression = talloc_asprintf(ac, "objectGUID=%s", ldb_binary_encode(ac, *guid));
+	if (!expression) {
+		ldb_oom(ldb);
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	res = talloc_zero(ac, struct ldb_result);
+	if (!res) {
+		ldb_oom(ldb);
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	ret = ldb_build_search_req(&search_req, ldb, ac,
+				   ldb_get_default_basedn(ldb),
+				   LDB_SCOPE_SUBTREE,
+				   expression, attrs,
+				   NULL,
+				   res, ldb_search_default_callback,
+				   NULL);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+
+	/* we need to cope with cross-partition links, so search for
+	   the GUID over all partitions */
+	options = talloc(search_req, struct ldb_search_options_control);
+	if (options == NULL) {
+		ldb_oom(ldb);
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+	options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
+
+	ret = ldb_request_add_control(search_req,
+				      LDB_CONTROL_SEARCH_OPTIONS_OID,
+				      true, options);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+
+	ret = ldb_next_request(module, search_req);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+
+	ret = ldb_wait(search_req->handle, LDB_WAIT_ALL);
+	if (ret != LDB_SUCCESS) {
+		ldb_debug(ldb, LDB_DEBUG_ERROR, "GUID search failed (%s) for %s\n", 
+			  ldb_errstring(ldb), ldb_dn_get_extended_linearized(ac, *dn, 1));
+		return ret;
+	}
+
+	/* this really should be exactly 1, but there is a bug in the
+	   partitions module that can return two here with the
+	   search_options control set */
+	if (res->count < 1) {
+		ldb_debug(ldb, LDB_DEBUG_ERROR, "GUID search gave count=%d for %s\n", 
+			  res->count, ldb_dn_get_extended_linearized(ac, *dn, 1));
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	*dn = res->msgs[0]->dn;
+
+	return LDB_SUCCESS;
+}
+
+/* apply one la_context op change */
+static int la_do_op_request(struct ldb_module *module, struct la_context *ac, struct la_op_store *op)
+{
+	struct ldb_message_element *ret_el;
+	struct ldb_request *mod_req;
+	struct ldb_message *new_msg;
+	struct ldb_context *ldb;
+	int ret;
+
+	ldb = ldb_module_get_ctx(ac->module);
+
+	/* Create the modify request */
+	new_msg = ldb_msg_new(ac);
+	if (!new_msg) {
+		ldb_oom(ldb);
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	new_msg->dn = op->dn;
+	ret = la_find_dn_target(module, ac, &new_msg->dn);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+
+	if (op->op == LA_OP_ADD) {
+		ret = ldb_msg_add_empty(new_msg, op->name,
+					LDB_FLAG_MOD_ADD, &ret_el);
+	} else {
+		ret = ldb_msg_add_empty(new_msg, op->name,
+					LDB_FLAG_MOD_DELETE, &ret_el);
+	}
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	ret_el->values = talloc_array(new_msg, struct ldb_val, 1);
+	if (!ret_el->values) {
+		ldb_oom(ldb);
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+	ret_el->num_values = 1;
+	if (op->op == LA_OP_ADD) {
+		ret_el->values[0] = data_blob_string_const(ldb_dn_get_extended_linearized(new_msg, ac->add_dn, 1));
+	} else {
+		ret_el->values[0] = data_blob_string_const(ldb_dn_get_extended_linearized(new_msg, ac->del_dn, 1));
+	}
+
+#if 0
+	ldb_debug(ldb, LDB_DEBUG_WARNING,
+		  "link on %s %s: %s %s\n", 
+		  ldb_dn_get_linearized(new_msg->dn), ret_el->name, 
+		  ret_el->values[0].data, ac->ops->op == LA_OP_ADD ? "added" : "deleted");
+#endif	
+
+	ret = ldb_build_mod_req(&mod_req, ldb, op,
+				new_msg,
+				NULL,
+				NULL, 
+				ldb_op_default_callback,
+				NULL);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	talloc_steal(mod_req, new_msg);
+
+	if (DEBUGLVL(4)) {
+		DEBUG(4,("Applying linked attribute change:\n%s\n",
+			 ldb_ldif_message_string(ldb, op, LDB_CHANGETYPE_MODIFY, new_msg)));
+	}
+
+	/* Run the new request */
+	ret = ldb_next_request(module, mod_req);
+
+	/* we need to wait for this to finish, as we are being called
+	   from the synchronous end_transaction hook of this module */
+	if (ret == LDB_SUCCESS) {
+		ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
+	}
+
+	if (ret != LDB_SUCCESS) {
+		ldb_debug(ldb, LDB_DEBUG_WARNING, "Failed to apply linked attribute change '%s' %s\n",
+			  ldb_errstring(ldb),
+			  ldb_ldif_message_string(ldb, op, LDB_CHANGETYPE_MODIFY, new_msg));
+	}
+
+	return ret;
+}
+
+/* apply one set of la_context changes */
+static int la_do_mod_request(struct ldb_module *module, struct la_context *ac)
+{
+	struct la_op_store *op;
+
+	for (op = ac->ops; op; op=op->next) {
+		int ret = la_do_op_request(module, ac, op);
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
+	}
+
+	return LDB_SUCCESS;
+}
+
+
+/*
+  we hook into the transaction operations to allow us to 
+  perform the linked attribute updates at the end of the whole
+  transaction. This allows a forward linked attribute to be created
+  before the target is created, as long as the target is created
+  in the same transaction
+ */
+static int linked_attributes_start_transaction(struct ldb_module *module)
+{
+	/* create our private structure for this transaction */
+	struct la_private *la_private = talloc_get_type(ldb_module_get_private(module),
+							struct la_private);
+	talloc_free(la_private);
+	la_private = talloc(module, struct la_private);
+	if (la_private == NULL) {
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+	la_private->la_list = NULL;
+	ldb_module_set_private(module, la_private);
+	return LDB_SUCCESS;
+}
+
+/*
+  on end transaction we loop over our queued la_context structures and


-- 
Samba Shared Repository


More information about the samba-cvs mailing list