diff options
author | Kamen Mazdrashki <kamenim@samba.org> | 2010-06-28 04:33:40 +0300 |
---|---|---|
committer | Kamen Mazdrashki <kamenim@samba.org> | 2010-06-28 04:43:29 +0300 |
commit | 431386f3278bfa6fa9b74db9a8a40fd300621c2b (patch) | |
tree | 3d04240439438447dc11fccc192f30c0492cfb09 | |
parent | 46556432c067bfd651e79ecd370ff3d18ae83bd7 (diff) | |
download | samba-431386f3278bfa6fa9b74db9a8a40fd300621c2b.tar.gz samba-431386f3278bfa6fa9b74db9a8a40fd300621c2b.tar.bz2 samba-431386f3278bfa6fa9b74db9a8a40fd300621c2b.zip |
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.
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 71 |
1 files changed, 53 insertions, 18 deletions
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; |