s4-repl: save the result of the last replication in repsFrom/repsTo
authorAndrew Tridgell <tridge@samba.org>
Wed, 17 Nov 2010 12:13:32 +0000 (23:13 +1100)
committerAndrew Tridgell <tridge@samba.org>
Wed, 17 Nov 2010 12:55:39 +0000 (23:55 +1100)
when a replication fails, we should add the failure to repsFrom
when a notify fails, we need to save it to repsTo

this ensures showrepl always shows the latest status

source4/dsdb/repl/drepl_notify.c
source4/dsdb/repl/drepl_out_pull.c
source4/dsdb/samdb/ldb_modules/repl_meta_data.c

index 25378129dac153bac63f3cf8cd55a3a27bebffd1..4629357711cea34645edc5e41c48a722652ab217 100644 (file)
@@ -120,10 +120,6 @@ static void dreplsrv_op_notify_replica_sync_trigger(struct tevent_req *req)
                DRSUAPI_DRS_ASYNC_OP |
                DRSUAPI_DRS_UPDATE_NOTIFICATION |
                DRSUAPI_DRS_WRIT_REP;
-       if (state->op->service->syncall_workaround) {
-               DEBUG(3,("sending DsReplicaSync with SYNC_ALL workaround\n"));
-               r->in.req->req1.options |= DRSUAPI_DRS_SYNC_ALL;
-       }
 
        if (state->op->is_urgent) {
                r->in.req->req1.options |= DRSUAPI_DRS_SYNC_URGENT;
@@ -189,30 +185,13 @@ static void dreplsrv_notify_op_callback(struct tevent_req *subreq)
                struct dreplsrv_notify_operation);
        NTSTATUS status;
        struct dreplsrv_service *s = op->service;
+       WERROR werr;
 
        status = dreplsrv_op_notify_recv(subreq);
+       werr = ntstatus_to_werror(status);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
-               WERROR werr;
-               unsigned int msg_debug_level = 0;
-               werr = ntstatus_to_werror(status);
-               if (W_ERROR_EQUAL(werr, WERR_BADFILE)) {
-                       /*
-                        * TODO:
-                        *
-                        * we should better fix the bug regarding
-                        * non-linked attribute handling, instead
-                        * of just hiding the failures.
-                        *
-                        * we should also remove the dc from our repsTo
-                        * if it failed to often, instead of retrying
-                        * every few seconds
-                        */
-                       msg_debug_level = 2;
-               }
-
-               DEBUG(msg_debug_level,
-                       ("dreplsrv_notify: Failed to send DsReplicaSync to %s for %s - %s : %s\n",
+               DEBUG(4,("dreplsrv_notify: Failed to send DsReplicaSync to %s for %s - %s : %s\n",
                         op->source_dsa->repsFrom1->other_info->dns_name,
                         ldb_dn_get_linearized(op->source_dsa->partition->dn),
                         nt_errstr(status), win_errstr(werr)));
@@ -226,6 +205,10 @@ static void dreplsrv_notify_op_callback(struct tevent_req *subreq)
                op->source_dsa->notify_uSN = op->uSN;
        }
 
+       drepl_reps_update(s, "repsTo", op->source_dsa->partition->dn,
+                         &op->source_dsa->repsFrom1->source_dsa_obj_guid,
+                         werr);
+
        talloc_free(op);
        s->ops.n_current = NULL;
        dreplsrv_run_pending_ops(s);
index 0af232c67fd6be8add0cec4019219645a59aa406..874d44ef55b97b8342d33c1ad3dd4164a0ebc7a3 100644 (file)
 #include "libcli/composite/composite.h"
 #include "libcli/security/security.h"
 
+/*
+  update repsFrom/repsTo error information
+ */
+void drepl_reps_update(struct dreplsrv_service *s, const char *reps_attr,
+                      struct ldb_dn *dn,
+                      struct GUID *source_dsa_obj_guid, WERROR status)
+{
+       struct repsFromToBlob *reps;
+       uint32_t count, i;
+       WERROR werr;
+       TALLOC_CTX *tmp_ctx = talloc_new(s);
+       time_t t;
+       NTTIME now;
+
+       t = time(NULL);
+       unix_to_nt_time(&now, t);
+
+       werr = dsdb_loadreps(s->samdb, tmp_ctx, dn, reps_attr, &reps, &count);
+       if (!W_ERROR_IS_OK(werr)) {
+               talloc_free(tmp_ctx);
+               return;
+       }
+
+       for (i=0; i<count; i++) {
+               if (GUID_compare(source_dsa_obj_guid,
+                                &reps[i].ctr.ctr1.source_dsa_obj_guid) == 0) {
+                       break;
+               }
+       }
+
+       if (i == count) {
+               /* no record to update */
+               talloc_free(tmp_ctx);
+               return;
+       }
+
+       /* only update the status fields */
+       reps[i].ctr.ctr1.last_attempt = now;
+       reps[i].ctr.ctr1.result_last_attempt = status;
+       if (W_ERROR_IS_OK(status)) {
+               reps[i].ctr.ctr1.last_success = now;
+               reps[i].ctr.ctr1.consecutive_sync_failures = 0;
+       } else {
+               reps[i].ctr.ctr1.consecutive_sync_failures++;
+       }
+
+       werr = dsdb_savereps(s->samdb, tmp_ctx, dn, reps_attr, reps, count);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(2,("drepl_reps_update: Failed to save %s for %s: %s\n",
+                        reps_attr, ldb_dn_get_linearized(dn), win_errstr(werr)));
+       }
+       talloc_free(tmp_ctx);
+}
+
 WERROR dreplsrv_schedule_partition_pull_source(struct dreplsrv_service *s,
                                               struct dreplsrv_partition_source_dsa *source,
                                               enum drsuapi_DsExtendedOperation extended_op,
@@ -96,33 +150,21 @@ static void dreplsrv_pending_op_callback(struct tevent_req *subreq)
                                            struct dreplsrv_out_operation);
        struct repsFromTo1 *rf = op->source_dsa->repsFrom1;
        struct dreplsrv_service *s = op->service;
-       time_t t;
-       NTTIME now;
+       WERROR werr;
 
-       t = time(NULL);
-       unix_to_nt_time(&now, t);
-
-       rf->result_last_attempt = dreplsrv_op_pull_source_recv(subreq);
+       werr = dreplsrv_op_pull_source_recv(subreq);
        TALLOC_FREE(subreq);
-       if (W_ERROR_IS_OK(rf->result_last_attempt)) {
-               rf->consecutive_sync_failures   = 0;
-               rf->last_success                = now;
-               DEBUG(3,("dreplsrv_op_pull_source(%s)\n",
-                       win_errstr(rf->result_last_attempt)));
-               goto done;
-       }
 
-       rf->consecutive_sync_failures++;
+       DEBUG(4,("dreplsrv_op_pull_source(%s) for %s\n", win_errstr(werr),
+                ldb_dn_get_linearized(op->source_dsa->partition->dn)));
 
-       DEBUG(1,("dreplsrv_op_pull_source(%s/%s) for %s failures[%u]\n",
-                win_errstr(rf->result_last_attempt),
-                nt_errstr(werror_to_ntstatus(rf->result_last_attempt)),
-                ldb_dn_get_linearized(op->source_dsa->partition->dn),
-                rf->consecutive_sync_failures));
+       if (op->extended_op == DRSUAPI_EXOP_NONE) {
+               drepl_reps_update(s, "repsFrom", op->source_dsa->partition->dn,
+                                 &rf->source_dsa_obj_guid, werr);
+       }
 
-done:
        if (op->callback) {
-               op->callback(s, rf->result_last_attempt, op->extended_ret, op->cb_data);
+               op->callback(s, werr, op->extended_ret, op->cb_data);
        }
        talloc_free(op);
        s->ops.current = NULL;
@@ -159,8 +201,10 @@ void dreplsrv_run_pull_ops(struct dreplsrv_service *s)
        if (!subreq) {
                struct repsFromTo1 *rf = op->source_dsa->repsFrom1;
 
-               rf->result_last_attempt = WERR_NOMEM;
-               rf->consecutive_sync_failures++;
+               if (op->extended_op == DRSUAPI_EXOP_NONE) {
+                       drepl_reps_update(s, "repsFrom", op->source_dsa->partition->dn,
+                                         &rf->source_dsa_obj_guid, WERR_NOMEM);
+               }
                s->ops.current = NULL;
 
                /*
@@ -168,13 +212,8 @@ void dreplsrv_run_pull_ops(struct dreplsrv_service *s)
                 * to do its job just like in any other failure situation
                 */
                if (op->callback) {
-                       op->callback(s, rf->result_last_attempt, op->extended_ret, op->cb_data);
+                       op->callback(s, WERR_NOMEM, op->extended_ret, op->cb_data);
                }
-
-               DEBUG(1,("dreplsrv_op_pull_source(%s/%s) failures[%u]\n",
-                       win_errstr(rf->result_last_attempt),
-                       nt_errstr(werror_to_ntstatus(rf->result_last_attempt)),
-                       rf->consecutive_sync_failures));
                return;
        }
        tevent_req_set_callback(subreq, dreplsrv_pending_op_callback, op);
index 957ca3ccc543bebd2708b25c4651815fffd854b3..3db1fe95909d77ddcc1477e528f4041ae1e1aab3 100644 (file)
@@ -3547,11 +3547,6 @@ static int replmd_replicated_uptodate_modify(struct replmd_replicated_request *a
        ZERO_STRUCT(nrf);
        nrf.version                                     = 1;
        nrf.ctr.ctr1                                    = *ar->objs->source_dsa;
-       /* and fix some values... */
-       nrf.ctr.ctr1.consecutive_sync_failures          = 0;
-       nrf.ctr.ctr1.last_success                       = now;
-       nrf.ctr.ctr1.last_attempt                       = now;
-       nrf.ctr.ctr1.result_last_attempt                = WERR_OK;
        nrf.ctr.ctr1.highwatermark.highest_usn          = nrf.ctr.ctr1.highwatermark.tmp_highest_usn;
 
        /*