[SCM] Samba Shared Repository - branch master updated - tevent-0-9-8-193-gc6647bf

Andrew Tridgell tridge at samba.org
Fri Sep 11 03:14:00 MDT 2009


The branch, master has been updated
       via  c6647bfd17539b9cca96e42b6871d16ef2fa728f (commit)
      from  741fe9d6a1833f358c32f91c5d7583c1c713110f (commit)

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


- Log -----------------------------------------------------------------
commit c6647bfd17539b9cca96e42b6871d16ef2fa728f
Author: Andrew Tridgell <tridge at samba.org>
Date:   Fri Sep 11 19:07:38 2009 +1000

    s4-repl: on every ldb modify we need to update replPropertyMetaData
    
    Every time we change a ldb object with the repl_meta_data module
    loaded we need to update the replPropertyMetaData attribute to fix the
    timestamps and USNs of the attributes being changed.

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

Summary of changes:
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c |  179 ++++++++++++++++++++++-
 1 files changed, 171 insertions(+), 8 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 6a2e6f2..c469936 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -466,6 +466,163 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
 	return ldb_next_request(module, down_req);
 }
 
+
+/*
+ * update the replPropertyMetaData for one element
+ */
+static int replmd_update_rpmd_element(struct ldb_context *ldb, 
+				      struct ldb_message *msg,
+				      struct ldb_message_element *el,
+				      struct replPropertyMetaDataBlob *omd,
+				      struct dsdb_schema *schema,
+				      uint64_t seq_num,
+				      const struct GUID *our_invocation_id,
+				      NTTIME now,
+				      bool *modified)
+{
+	int i;
+	const struct dsdb_attribute *a;
+	struct replPropertyMetaData1 *md1;
+
+	a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
+	if (a == NULL) {
+		DEBUG(0,(__location__ ": Unable to find attribute %s in schema\n",
+			 el->name));
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	for (i=0; i<omd->ctr.ctr1.count; i++) {
+		if (a->attributeID_id == omd->ctr.ctr1.array[i].attid) break;
+	}
+	if (i == omd->ctr.ctr1.count) {
+		/* we need to add a new one */
+		omd->ctr.ctr1.array = talloc_realloc(msg, omd->ctr.ctr1.array, 
+						     struct replPropertyMetaData1, omd->ctr.ctr1.count+1);
+		if (omd->ctr.ctr1.array == NULL) {
+			ldb_oom(ldb);
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
+		omd->ctr.ctr1.count++;
+	}
+
+	md1 = &omd->ctr.ctr1.array[i];
+	md1->version                   = 1;
+	md1->attid                     = a->attributeID_id;
+	md1->originating_change_time   = now;
+	md1->originating_invocation_id = *our_invocation_id;
+	md1->originating_usn           = seq_num;
+	md1->local_usn                 = seq_num;
+	
+	*modified = true;
+	return LDB_SUCCESS;
+}
+
+/*
+ * update the replPropertyMetaData object each time we modify an
+ * object. This is needed for DRS replication, as the merge on the
+ * client is based on this object 
+ */
+static int replmd_update_rpmd(struct ldb_context *ldb, struct ldb_message *msg,
+			      uint64_t seq_num)
+{
+	const struct ldb_val *omd_value;
+	enum ndr_err_code ndr_err;
+	struct replPropertyMetaDataBlob omd;
+	int i;
+	bool modified = false;
+	struct dsdb_schema *schema;
+	time_t t = time(NULL);
+	NTTIME now;
+	const struct GUID *our_invocation_id;
+	int ret;
+	const char *attrs[] = { "replPropertyMetaData" , NULL };
+	struct ldb_result *res;
+
+	our_invocation_id = samdb_ntds_invocation_id(ldb);
+	if (!our_invocation_id) {
+		ldb_debug_set(ldb, LDB_DEBUG_ERROR,
+			      __location__ ": replmd_update_rpmd: unable to find invocationId\n");
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	unix_to_nt_time(&now, t);
+
+	/* search for the existing replPropertyMetaDataBlob */
+	ret = ldb_search(ldb, msg, &res, msg->dn, LDB_SCOPE_BASE, attrs, NULL);
+	if (ret != LDB_SUCCESS || res->count < 1) {
+		DEBUG(0,(__location__ ": Object %s failed to find replPropertyMetaData\n",
+			 ldb_dn_get_linearized(msg->dn)));
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+		
+
+	omd_value = ldb_msg_find_ldb_val(res->msgs[0], "replPropertyMetaData");
+	if (!omd_value) {
+		DEBUG(0,(__location__ ": Object %s does not have a replPropertyMetaData attribute\n",
+			 ldb_dn_get_linearized(msg->dn)));
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	ndr_err = ndr_pull_struct_blob(omd_value, msg,
+				       lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), &omd,
+				       (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		DEBUG(0,(__location__ ": Failed to parse replPropertyMetaData for %s\n",
+			 ldb_dn_get_linearized(msg->dn)));
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	if (omd.version != 1) {
+		DEBUG(0,(__location__ ": bad version %u in replPropertyMetaData for %s\n",
+			 omd.version, ldb_dn_get_linearized(msg->dn)));
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	schema = dsdb_get_schema(ldb);
+
+	for (i=0; i<msg->num_elements; i++) {
+		ret = replmd_update_rpmd_element(ldb, msg, &msg->elements[i], &omd, schema, seq_num, 
+						 our_invocation_id, now, &modified);
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
+	}
+
+	if (modified) {
+		struct ldb_val *md_value;
+		struct ldb_message_element *el;
+
+		md_value = talloc(msg, struct ldb_val);
+		if (md_value == NULL) {
+			ldb_oom(ldb);
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
+
+		ndr_err = ndr_push_struct_blob(md_value, msg, 
+					       lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+					       &omd,
+					       (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			DEBUG(0,(__location__ ": Failed to marshall replPropertyMetaData for %s\n",
+				 ldb_dn_get_linearized(msg->dn)));
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
+
+		ret = ldb_msg_add_empty(msg, "replPropertyMetaData", LDB_FLAG_MOD_REPLACE, &el);
+		if (ret != LDB_SUCCESS) {
+			DEBUG(0,(__location__ ": Failed to add updated replPropertyMetaData %s\n",
+				 ldb_dn_get_linearized(msg->dn)));
+			return ret;
+		}
+
+		el->num_values = 1;
+		el->values = md_value;
+	}
+
+	return LDB_SUCCESS;	
+}
+
+
 static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
 {
 	struct ldb_context *ldb;
@@ -516,21 +673,27 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
 	 *   if the caller set values to the same value
 	 *   ignore the attribute, return success when no
 	 *   attribute was changed
-	 * - calculate the new replPropertyMetaData attribute
 	 */
 
+	/* Get a sequence number from the backend */
+	ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &seq_num);
+	if (ret != LDB_SUCCESS) {
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	ret = replmd_update_rpmd(ldb, msg, seq_num);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+
 	if (add_time_element(msg, "whenChanged", t) != LDB_SUCCESS) {
 		talloc_free(ac);
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
 
-	/* Get a sequence number from the backend */
-	ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &seq_num);
-	if (ret == LDB_SUCCESS) {
-		if (add_uint64_element(msg, "uSNChanged", seq_num) != LDB_SUCCESS) {
-			talloc_free(ac);
-			return LDB_ERR_OPERATIONS_ERROR;
-		}
+	if (add_uint64_element(msg, "uSNChanged", seq_num) != LDB_SUCCESS) {
+		talloc_free(ac);
+		return LDB_ERR_OPERATIONS_ERROR;
 	}
 
 	/* TODO:


-- 
Samba Shared Repository


More information about the samba-cvs mailing list