static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct ldb_reply *ares, int (*callback)(struct ldb_request *req, struct ldb_reply *ares))
{
	struct ldb_dn *conflict_dn;
	struct replmd_replicated_request *ar =
		talloc_get_type_abort(req->context, struct replmd_replicated_request);
	struct ldb_result *res;
	int ret;
	bool rename_incoming_record;
	struct ldb_message *msg;
	struct ldb_request *down_req = NULL;

	/* call the normal callback for success */
	if (ares->error == LDB_SUCCESS) {
		return callback(req, ares);
	}

	/*
	 * we have a conflict, and need to decide if we will keep the
	 * new record or the old record
	 */

	msg = ar->objs->objects[ar->index_current].msg;
	conflict_dn = msg->dn;

	/* For failures other than conflicts, fail the whole operation here */
	if (ares->error != LDB_ERR_ENTRY_ALREADY_EXISTS) {
		ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), "Failed to locally apply remote add of %s: %s",
				       ldb_dn_get_linearized(conflict_dn),
				       ldb_errstring(ldb_module_get_ctx(ar->module)));

		return ldb_module_done(ar->req, NULL, NULL,
				       LDB_ERR_OPERATIONS_ERROR);
	}


	ret = incoming_dn_should_be_renamed(req, ar, conflict_dn, &res,
					    &rename_incoming_record);
	if (ret != LDB_SUCCESS) {
		goto failed;
	}

	if (rename_incoming_record) {
		struct GUID guid;
		struct ldb_dn *new_dn;

		guid = samdb_result_guid(msg, "objectGUID");
		if (GUID_all_zero(&guid)) {
			DEBUG(0,(__location__ ": Failed to find objectGUID for conflicting incoming record %s\n",
				 ldb_dn_get_linearized(conflict_dn)));
			goto failed;
		}
		new_dn = replmd_conflict_dn(req,
					    ldb_module_get_ctx(ar->module),
					    conflict_dn, &guid);
		if (new_dn == NULL) {
			DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n",
				 ldb_dn_get_linearized(conflict_dn)));
			goto failed;
		}

		DEBUG(2,(__location__ ": Resolving conflict record via incoming rename '%s' -> '%s'\n",
			 ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));

		/* re-submit the request, but with the new DN */
		callback = replmd_op_name_modify_callback;
		msg->dn = new_dn;
	} else {
		/* we are renaming the existing record */
		struct GUID guid;
		struct ldb_dn *new_dn;

		guid = samdb_result_guid(res->msgs[0], "objectGUID");
		if (GUID_all_zero(&guid)) {
			DEBUG(0,(__location__ ": Failed to find objectGUID for existing conflict record %s\n",
				 ldb_dn_get_linearized(conflict_dn)));
			goto failed;
		}

		new_dn = replmd_conflict_dn(req,
					    ldb_module_get_ctx(ar->module),
					    conflict_dn, &guid);
		if (new_dn == NULL) {
			DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n",
				 ldb_dn_get_linearized(conflict_dn)));
			goto failed;
		}

		DEBUG(2,(__location__ ": Resolving conflict record via existing-record rename '%s' -> '%s'\n",
			 ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));

		ret = dsdb_module_rename(ar->module, conflict_dn, new_dn,
					 DSDB_FLAG_OWN_MODULE, req);
		if (ret != LDB_SUCCESS) {
			DEBUG(0,(__location__ ": Failed to rename conflict dn '%s' to '%s' - %s\n",
				 ldb_dn_get_linearized(conflict_dn),
				 ldb_dn_get_linearized(new_dn),
				 ldb_errstring(ldb_module_get_ctx(ar->module))));
			goto failed;
		}

		/*
		 * now we need to ensure that the rename is seen as an
		 * originating update. We do that with a modify.
		 */
		ret = replmd_name_modify(ar, req, new_dn);
		if (ret != LDB_SUCCESS) {
			goto failed;
		}

		DEBUG(2,(__location__ ": With conflicting record renamed, re-apply replicated creation of '%s'\n",
			 ldb_dn_get_linearized(req->op.add.message->dn)));
	}

	ret = ldb_build_add_req(&down_req,
				ldb_module_get_ctx(ar->module),
				req,
				msg,
				ar->controls,
				ar,
				callback,
				req);
	if (ret != LDB_SUCCESS) {
		goto failed;
	}
	LDB_REQ_SET_LOCATION(down_req);

	/* current partition control needed by "repmd_op_callback" */
	ret = ldb_request_add_control(down_req,
				      DSDB_CONTROL_CURRENT_PARTITION_OID,
				      false, NULL);
	if (ret != LDB_SUCCESS) {
		return replmd_replicated_request_error(ar, ret);
	}

	if (ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PARTIAL_REPLICA) {
		/* this tells the partition module to make it a
		   partial replica if creating an NC */
		ret = ldb_request_add_control(down_req,
					      DSDB_CONTROL_PARTIAL_REPLICA,
					      false, NULL);
		if (ret != LDB_SUCCESS) {
			return replmd_replicated_request_error(ar, ret);
		}
	}

	/*
	 * Finally we re-run the add, otherwise the new record won't
	 * exist, as we are here because of that exact failure!
	 */
	return ldb_next_request(ar->module, down_req);
failed:

	/* on failure make the caller get the error. This means
	 * replication will stop with an error, but there is not much
	 * else we can do.
	 */
	if (ret == LDB_SUCCESS) {
		ret = LDB_ERR_OPERATIONS_ERROR;
	}
	return ldb_module_done(ar->req, NULL, NULL,
			       ret);
}
static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct ldb_reply *ares, int (*callback)(struct ldb_request *req, struct ldb_reply *ares))
{
	struct ldb_dn *conflict_dn;
	struct replmd_replicated_request *ar =
		talloc_get_type_abort(req->context, struct replmd_replicated_request);
	struct ldb_result *res;
	int ret;
	bool rename_incoming_record;
	struct ldb_message *msg;
	struct ldb_request *down_req = NULL;

	 
	if (ares->error == LDB_SUCCESS) {
		return callback(req, ares);
	}

	 

	msg = ar->objs->objects[ar->index_current].msg;
	conflict_dn = msg->dn;

	 
	if (ares->error != LDB_ERR_ENTRY_ALREADY_EXISTS) {
		ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), "Failed to locally apply remote add of %s: %s",
				       ldb_dn_get_linearized(conflict_dn),
				       ldb_errstring(ldb_module_get_ctx(ar->module)));

		return ldb_module_done(ar->req, NULL, NULL,
				       LDB_ERR_OPERATIONS_ERROR);
	}


	ret = incoming_dn_should_be_renamed(req, ar, conflict_dn, &res,
					    &rename_incoming_record);
	if (ret != LDB_SUCCESS) {
		goto failed;
	}

	if (rename_incoming_record) {
		struct GUID guid;
		struct ldb_dn *new_dn;

		guid = samdb_result_guid(msg, "objectGUID");
		if (GUID_all_zero(&guid)) {
			DEBUG(0,(__location__ ": Failed to find objectGUID for conflicting incoming record %s\n",
				 ldb_dn_get_linearized(conflict_dn)));
			goto failed;
		}
		new_dn = replmd_conflict_dn(req,
					    ldb_module_get_ctx(ar->module),
					    conflict_dn, &guid);
		if (new_dn == NULL) {
			DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n",
				 ldb_dn_get_linearized(conflict_dn)));
			goto failed;
		}

		DEBUG(2,(__location__ ": Resolving conflict record via incoming rename '%s' -> '%s'\n",
			 ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));

		 
		callback = replmd_op_name_modify_callback;
		msg->dn = new_dn;
	} else {
		 
		struct GUID guid;
		struct ldb_dn *new_dn;

		guid = samdb_result_guid(res->msgs[0], "objectGUID");
		if (GUID_all_zero(&guid)) {
			DEBUG(0,(__location__ ": Failed to find objectGUID for existing conflict record %s\n",
				 ldb_dn_get_linearized(conflict_dn)));
			goto failed;
		}

		new_dn = replmd_conflict_dn(req,
					    ldb_module_get_ctx(ar->module),
					    conflict_dn, &guid);
		if (new_dn == NULL) {
			DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n",
				 ldb_dn_get_linearized(conflict_dn)));
			goto failed;
		}

		DEBUG(2,(__location__ ": Resolving conflict record via existing-record rename '%s' -> '%s'\n",
			 ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));

		ret = dsdb_module_rename(ar->module, conflict_dn, new_dn,
					 DSDB_FLAG_OWN_MODULE, req);
		if (ret != LDB_SUCCESS) {
			DEBUG(0,(__location__ ": Failed to rename conflict dn '%s' to '%s' - %s\n",
				 ldb_dn_get_linearized(conflict_dn),
				 ldb_dn_get_linearized(new_dn),
				 ldb_errstring(ldb_module_get_ctx(ar->module))));
			goto failed;
		}

		 
		ret = replmd_name_modify(ar, req, new_dn);
		if (ret != LDB_SUCCESS) {
			goto failed;
		}

		DEBUG(2,(__location__ ": With conflicting record renamed, re-apply replicated creation of '%s'\n",
			 ldb_dn_get_linearized(req->op.add.message->dn)));
	}

	ret = ldb_build_add_req(&down_req,
				ldb_module_get_ctx(ar->module),
				req,
				msg,
				ar->controls,
				ar,
				callback,
				req);
	if (ret != LDB_SUCCESS) {
		goto failed;
	}
	LDB_REQ_SET_LOCATION(down_req);

	 
	ret = ldb_request_add_control(down_req,
				      DSDB_CONTROL_CURRENT_PARTITION_OID,
				      false, NULL);
	if (ret != LDB_SUCCESS) {
		return replmd_replicated_request_error(ar, ret);
	}

	if (ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PARTIAL_REPLICA) {
		 
		ret = ldb_request_add_control(down_req,
					      DSDB_CONTROL_PARTIAL_REPLICA,
					      false, NULL);
		if (ret != LDB_SUCCESS) {
			return replmd_replicated_request_error(ar, ret);
		}
	}

	 
	return ldb_next_request(ar->module, down_req);
failed:

	 
	if (ret == LDB_SUCCESS) {
		ret = LDB_ERR_OPERATIONS_ERROR;
	}
	return ldb_module_done(ar->req, NULL, NULL,
			       ret);
}