s4-repl: don't do double replication
authorAndrew Tridgell <tridge@samba.org>
Tue, 15 Sep 2009 21:06:07 +0000 (14:06 -0700)
committerAndrew Tridgell <tridge@samba.org>
Tue, 15 Sep 2009 21:52:23 +0000 (14:52 -0700)
When we replicate from a remote DC, we need to note the new uSN that
the local changes have resulted in, and modify the uSN that the notify
task uses to determine if it should send a ReplicaSync message back to
the remote DC. Otherwise we end up always triggering a ReplicaSync
every time we replicate from another DC

source4/dsdb/repl/drepl_out_helpers.c
source4/dsdb/repl/replicated_objects.c
source4/libnet/libnet_vampire.c
source4/torture/libnet/libnet_BecomeDC.c

index 168aacdde9844bc5ca6920b0b5a6de58a1e90294..5c63c111f3af0f4b6de77c90c6f432971dc48e28 100644 (file)
@@ -414,7 +414,8 @@ static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_s
                                                         &rf1,
                                                         uptodateness_vector,
                                                         &drsuapi->gensec_skey,
-                                                        st, NULL);
+                                                        st, NULL, 
+                                                        &st->op->source_dsa->notify_uSN);
        if (!W_ERROR_IS_OK(status)) {
                DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
                composite_error(c, werror_to_ntstatus(status));
index 2f4efc0fee947d019b954c81d096aa00658db7c0..5ae622eeaad300b50cc72dcd395d9f6fae664c98 100644 (file)
@@ -212,7 +212,8 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb,
                                               const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector,
                                               const DATA_BLOB *gensec_skey,
                                               TALLOC_CTX *mem_ctx,
-                                              struct dsdb_extended_replicated_objects **_out)
+                                              struct dsdb_extended_replicated_objects **_out,
+                                              uint64_t *notify_uSN)
 {
        WERROR status;
        const struct dsdb_schema *schema;
@@ -221,6 +222,7 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb,
        const struct drsuapi_DsReplicaObjectListItemEx *cur;
        uint32_t i;
        int ret;
+       uint64_t seq_num1, seq_num2;
 
        schema = dsdb_get_schema(ldb);
        if (!schema) {
@@ -280,6 +282,14 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb,
                return WERR_FOOBAR;
        }
 
+       ret = dsdb_load_partition_usn(ldb, out->partition_dn, &seq_num1);
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0,(__location__ " Failed to load partition uSN\n"));
+               talloc_free(out);
+               ldb_transaction_cancel(ldb);
+               return WERR_FOOBAR;             
+       }
+
        ret = ldb_extended(ldb, DSDB_EXTENDED_REPLICATED_OBJECTS_OID, out, &ext_res);
        if (ret != LDB_SUCCESS) {
                DEBUG(0,("Failed to apply records: %s: %s\n",
@@ -290,6 +300,28 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb,
        }
        talloc_free(ext_res);
 
+       ret = ldb_transaction_prepare_commit(ldb);
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0,(__location__ " Failed to prepare commit of transaction\n"));
+               talloc_free(out);
+               return WERR_FOOBAR;
+       }
+
+       ret = dsdb_load_partition_usn(ldb, out->partition_dn, &seq_num2);
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0,(__location__ " Failed to load partition uSN\n"));
+               talloc_free(out);
+               ldb_transaction_cancel(ldb);
+               return WERR_FOOBAR;             
+       }
+
+       /* if this replication partner didn't need to be notified
+          before this transaction then it still doesn't need to be
+          notified, as the changes came from this server */    
+       if (seq_num2 > seq_num1 && seq_num1 <= *notify_uSN) {
+               *notify_uSN = seq_num2;
+       }
+
        ret = ldb_transaction_commit(ldb);
        if (ret != LDB_SUCCESS) {
                DEBUG(0,(__location__ " Failed to commit transaction\n"));
@@ -297,6 +329,7 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb,
                return WERR_FOOBAR;
        }
 
+
        DEBUG(2,("Replicated %u objects (%u linked attributes) for %s\n",
                 out->num_objects, out->linked_attributes_count,
                 ldb_dn_get_linearized(out->partition_dn)));
index 5e516afaee4157213f79ef86305fd9bbc98f7376..327a64daea3bf0932a7728b82fced206dcc88f74 100644 (file)
@@ -168,6 +168,7 @@ static NTSTATUS vampire_apply_schema(struct vampire_state *s,
        uint32_t i;
        int ret;
        bool ok;
+       uint64_t seq_num;
 
        DEBUG(0,("Analyze and apply schema objects\n"));
 
@@ -301,7 +302,7 @@ static NTSTATUS vampire_apply_schema(struct vampire_state *s,
                                                         s_dsa,
                                                         uptodateness_vector,
                                                         c->gensec_skey,
-                                                        s, &objs);
+                                                        s, &objs, &seq_num);
        if (!W_ERROR_IS_OK(status)) {
                DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
                return werror_to_ntstatus(status);
@@ -465,6 +466,7 @@ static NTSTATUS vampire_store_chunk(void *private_data,
        struct repsFromTo1 *s_dsa;
        char *tmp_dns_name;
        uint32_t i;
+       uint64_t seq_num;
 
        s_dsa                   = talloc_zero(s, struct repsFromTo1);
        NT_STATUS_HAVE_NO_MEMORY(s_dsa);
@@ -541,7 +543,7 @@ static NTSTATUS vampire_store_chunk(void *private_data,
                                                         s_dsa,
                                                         uptodateness_vector,
                                                         c->gensec_skey,
-                                                        s, &objs);
+                                                        s, &objs, &seq_num);
        if (!W_ERROR_IS_OK(status)) {
                DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
                return werror_to_ntstatus(status);
index 7d1c025f18833aeff72e18954d91d4ffd2e99399..81bdf342b210d959a648481e835b8d9d9b819269 100644 (file)
@@ -140,6 +140,7 @@ static NTSTATUS test_apply_schema(struct test_become_dc_state *s,
        uint32_t i;
        int ret;
        bool ok;
+       uint64_t seq_num;
 
        DEBUG(0,("Analyze and apply schema objects\n"));
 
@@ -273,7 +274,7 @@ static NTSTATUS test_apply_schema(struct test_become_dc_state *s,
                                                         s_dsa,
                                                         uptodateness_vector,
                                                         c->gensec_skey,
-                                                        s, &objs);
+                                                        s, &objs, &seq_num);
        if (!W_ERROR_IS_OK(status)) {
                DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
                return werror_to_ntstatus(status);
@@ -447,6 +448,7 @@ static NTSTATUS test_become_dc_store_chunk(void *private_data,
        struct repsFromTo1 *s_dsa;
        char *tmp_dns_name;
        uint32_t i;
+       uint64_t seq_num;
 
        s_dsa                   = talloc_zero(s, struct repsFromTo1);
        NT_STATUS_HAVE_NO_MEMORY(s_dsa);
@@ -514,7 +516,7 @@ static NTSTATUS test_become_dc_store_chunk(void *private_data,
                                                         s_dsa,
                                                         uptodateness_vector,
                                                         c->gensec_skey,
-                                                        s, &objs);
+                                                        s, &objs, &seq_num);
        if (!W_ERROR_IS_OK(status)) {
                DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
                return werror_to_ntstatus(status);