]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4-repl: we should only update uSNChanged when replication data changes
authorAndrew Tridgell <tridge@samba.org>
Sat, 12 Sep 2009 01:10:19 +0000 (11:10 +1000)
committerAndrew Tridgell <tridge@samba.org>
Sat, 12 Sep 2009 01:15:27 +0000 (11:15 +1000)
When changing non-replicated attributes we should not update the
uSNChanged attribute on the record, otherwise the DRS server will
think this record needs replicating.

source4/dsdb/samdb/ldb_modules/repl_meta_data.c

index b9de04a6843babf1f9e1d80f756017ee86b72388..5000c56d4e01c3b049d33721e21e7b103c5cc4aa 100644 (file)
@@ -280,7 +280,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
        schema = dsdb_get_schema(ldb);
        if (!schema) {
                ldb_debug_set(ldb, LDB_DEBUG_FATAL,
-                             "replmd_modify: no dsdb_schema loaded");
+                             "replmd_add: no dsdb_schema loaded");
                return LDB_ERR_CONSTRAINT_VIOLATION;
        }
 
@@ -475,10 +475,9 @@ static int replmd_update_rpmd_element(struct ldb_context *ldb,
                                      struct ldb_message_element *el,
                                      struct replPropertyMetaDataBlob *omd,
                                      struct dsdb_schema *schema,
-                                     uint64_t seq_num,
+                                     uint64_t *seq_num,
                                      const struct GUID *our_invocation_id,
-                                     NTTIME now,
-                                     bool *modified)
+                                     NTTIME now)
 {
        int i;
        const struct dsdb_attribute *a;
@@ -512,15 +511,25 @@ static int replmd_update_rpmd_element(struct ldb_context *ldb,
                omd->ctr.ctr1.count++;
        }
 
+       /* Get a new sequence number from the backend. We only do this
+        * if we have a change that requires a new
+        * replPropertyMetaData element 
+        */
+       if (*seq_num == 0) {
+               int ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, seq_num);
+               if (ret != LDB_SUCCESS) {
+                       return LDB_ERR_OPERATIONS_ERROR;
+               }
+       }
+
        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;
+       md1->originating_usn           = *seq_num;
+       md1->local_usn                 = *seq_num;
        
-       *modified = true;
        return LDB_SUCCESS;
 }
 
@@ -530,13 +539,12 @@ static int replmd_update_rpmd_element(struct ldb_context *ldb,
  * client is based on this object 
  */
 static int replmd_update_rpmd(struct ldb_context *ldb, struct ldb_message *msg,
-                             uint64_t seq_num)
+                             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;
@@ -590,13 +598,17 @@ static int replmd_update_rpmd(struct ldb_context *ldb, struct ldb_message *msg,
 
        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);
+                                                our_invocation_id, now);
                if (ret != LDB_SUCCESS) {
                        return ret;
                }
        }
 
-       if (modified) {
+       /*
+        * replmd_update_rpmd_element has done an update if the
+        * seq_num is set
+        */
+       if (*seq_num != 0) {
                struct ldb_val *md_value;
                struct ldb_message_element *el;
 
@@ -640,7 +652,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
        struct ldb_message *msg;
        int ret;
        time_t t = time(NULL);
-       uint64_t seq_num;
+       uint64_t seq_num = 0;
 
        /* do not manipulate our control entries */
        if (ldb_dn_is_special(req->op.mod.message->dn)) {
@@ -683,27 +695,11 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
         *   attribute was changed
         */
 
-       /* 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);
+       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;
-       }
-
-       if (add_uint64_element(msg, "uSNChanged", seq_num) != LDB_SUCCESS) {
-               talloc_free(ac);
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-
        /* TODO:
         * - sort the attributes by attid with replmd_ldb_message_sort()
         * - replace the old object with the newly constructed one
@@ -719,6 +715,20 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
        }
        talloc_steal(down_req, msg);
 
+       /* we only change whenChanged and uSNChanged if the seq_num
+          has changed */
+       if (seq_num != 0) {
+               if (add_time_element(msg, "whenChanged", t) != 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;
+               }
+       }
+
        /* go on with the call chain */
        return ldb_next_request(module, down_req);
 }