summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamen Mazdrashki <kamenim@samba.org>2010-06-28 04:33:40 +0300
committerKamen Mazdrashki <kamenim@samba.org>2010-06-28 04:43:29 +0300
commit431386f3278bfa6fa9b74db9a8a40fd300621c2b (patch)
tree3d04240439438447dc11fccc192f30c0492cfb09
parent46556432c067bfd651e79ecd370ff3d18ae83bd7 (diff)
downloadsamba-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.c71
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;