From 431386f3278bfa6fa9b74db9a8a40fd300621c2b Mon Sep 17 00:00:00 2001 From: Kamen Mazdrashki Date: Mon, 28 Jun 2010 04:33:40 +0300 Subject: s4/drs: re-implement 'renaming' object replication We should rename objects only after we make sure, that changes on the partner DC are newer than what we have. This fixes a bug, when we have following situation with 2 DCs: - we have an object O on the two DCs - we rename (delete) object O on DC1 - DC1 replicates from DC2 In the above scenario, object O will be renamed back to its original name (i.e. it will be restored). Now, we check that DC2 state is older than what we have, so nothing happens with object's DN. --- source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 71 ++++++++++++++++++------- 1 file changed, 53 insertions(+), 18 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules') diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index 8994ee4014..0a5655a6e7 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -2827,6 +2827,21 @@ static bool replmd_replPropertyMetaData1_is_newer(struct replPropertyMetaData1 * new_m->originating_change_time); } +static struct replPropertyMetaData1 * +replmd_replPropertyMetaData1_find_attid(struct replPropertyMetaDataBlob *md_blob, + enum drsuapi_DsAttributeId attid) +{ + int i; + struct replPropertyMetaDataCtr1 *rpmd_ctr = &md_blob->ctr.ctr1; + + for (i = 0; i < rpmd_ctr->count; i++) { + if (rpmd_ctr->array[i].attid == attid) { + return &rpmd_ctr->array[i]; + } + } + return NULL; +} + static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar) { struct ldb_context *ldb; @@ -2838,6 +2853,8 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar) const struct ldb_val *omd_value; struct replPropertyMetaDataBlob nmd; struct ldb_val nmd_value; + struct replPropertyMetaData1 *md_remote; + struct replPropertyMetaData1 *md_local; unsigned int i; uint32_t j,ni=0; unsigned int removed_attrs = 0; @@ -2849,24 +2866,6 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar) ZERO_STRUCT(omd); omd.version = 1; - /* - * TODO: check repl data is correct after a rename - */ - if (ldb_dn_compare(msg->dn, ar->search_msg->dn) != 0) { - ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_replicated_request rename %s => %s\n", - ldb_dn_get_linearized(ar->search_msg->dn), - ldb_dn_get_linearized(msg->dn)); - if (dsdb_module_rename(ar->module, - ar->search_msg->dn, msg->dn, - DSDB_FLAG_OWN_MODULE) != LDB_SUCCESS) { - ldb_debug(ldb, LDB_DEBUG_FATAL, "replmd_replicated_request rename %s => %s failed - %s\n", - ldb_dn_get_linearized(ar->search_msg->dn), - ldb_dn_get_linearized(msg->dn), - ldb_errstring(ldb)); - return replmd_replicated_request_werror(ar, WERR_DS_DRA_DB_ERROR); - } - } - /* find existing meta data */ omd_value = ldb_msg_find_ldb_val(ar->search_msg, "replPropertyMetaData"); if (omd_value) { @@ -2882,6 +2881,42 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar) } } + /* check if remote 'name' has change, + * which indicates a rename operation */ + md_remote = replmd_replPropertyMetaData1_find_attid(rmd, DRSUAPI_ATTRIBUTE_name); + if (md_remote) { + md_local = replmd_replPropertyMetaData1_find_attid(&omd, DRSUAPI_ATTRIBUTE_name); + SMB_ASSERT(md_local); + if (replmd_replPropertyMetaData1_is_newer(md_local, md_remote)) { + SMB_ASSERT(ldb_dn_compare(msg->dn, ar->search_msg->dn) != 0); + /* TODO: Find appropriate local name (dn) for the object + * and modify msg->dn appropriately */ + + DEBUG(4,("replmd_replicated_request rename %s => %s\n", + ldb_dn_get_linearized(ar->search_msg->dn), + ldb_dn_get_linearized(msg->dn))); +/* + ldb_debug(ldb, LDB_DEBUG_TRACE, + "replmd_replicated_request rename %s => %s\n", + ldb_dn_get_linearized(ar->search_msg->dn), + ldb_dn_get_linearized(msg->dn)); +*/ + /* pass rename to the next module + * so it doesn't appear as an originating update */ + ret = dsdb_module_rename(ar->module, + ar->search_msg->dn, msg->dn, + 0); + if (ret != LDB_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_FATAL, + "replmd_replicated_request rename %s => %s failed - %s\n", + ldb_dn_get_linearized(ar->search_msg->dn), + ldb_dn_get_linearized(msg->dn), + ldb_errstring(ldb)); + return replmd_replicated_request_werror(ar, WERR_DS_DRA_DB_ERROR); + } + } + } + ZERO_STRUCT(nmd); nmd.version = 1; nmd.ctr.ctr1.count = omd.ctr.ctr1.count + rmd->ctr.ctr1.count; -- cgit