s4-repl: ensure we don't starve pending replication ops
authorAndrew Tridgell <tridge@samba.org>
Wed, 17 Nov 2010 12:12:10 +0000 (23:12 +1100)
committerAndrew Tridgell <tridge@samba.org>
Wed, 17 Nov 2010 12:55:39 +0000 (23:55 +1100)
when there was a continuous sequence of notify ops, we could leave the
replication ops starving. This ensures we run whichever was queued
first

source4/dsdb/repl/drepl_notify.c
source4/dsdb/repl/drepl_out_pull.c
source4/dsdb/repl/drepl_periodic.c
source4/dsdb/repl/drepl_service.h

index 0178e97e5596fd37ff35e5133dfd0721b427c3a9..25378129dac153bac63f3cf8cd55a3a27bebffd1 100644 (file)
@@ -228,7 +228,7 @@ static void dreplsrv_notify_op_callback(struct tevent_req *subreq)
 
        talloc_free(op);
        s->ops.n_current = NULL;
-       dreplsrv_notify_run_ops(s);
+       dreplsrv_run_pending_ops(s);
 }
 
 /*
@@ -343,6 +343,7 @@ static WERROR dreplsrv_schedule_notify_sync(struct dreplsrv_service *service,
        op->uSN           = uSN;
        op->is_urgent     = is_urgent;
        op->replica_flags = replica_flags;
+       op->schedule_time = time(NULL);
 
        DLIST_ADD_END(service->ops.notifies, op, struct dreplsrv_notify_operation *);
        talloc_steal(service, op);
@@ -499,5 +500,4 @@ static void dreplsrv_notify_run(struct dreplsrv_service *service)
        talloc_free(mem_ctx);
 
        dreplsrv_run_pending_ops(service);
-       dreplsrv_notify_run_ops(service);
 }
index 3e59ee95ac11ec64fa5d09aa91ed462d548822e2..0af232c67fd6be8add0cec4019219645a59aa406 100644 (file)
@@ -52,6 +52,7 @@ WERROR dreplsrv_schedule_partition_pull_source(struct dreplsrv_service *s,
        op->fsmo_info   = fsmo_info;
        op->callback    = callback;
        op->cb_data     = cb_data;
+       op->schedule_time = time(NULL);
 
        DLIST_ADD_END(s->ops.pending, op, struct dreplsrv_out_operation *);
 
@@ -126,17 +127,16 @@ done:
        talloc_free(op);
        s->ops.current = NULL;
        dreplsrv_run_pending_ops(s);
-       dreplsrv_notify_run_ops(s);
 }
 
-void dreplsrv_run_pending_ops(struct dreplsrv_service *s)
+void dreplsrv_run_pull_ops(struct dreplsrv_service *s)
 {
        struct dreplsrv_out_operation *op;
        time_t t;
        NTTIME now;
        struct tevent_req *subreq;
 
-       if (s->ops.current || s->ops.n_current) {
+       if (s->ops.current) {
                /* if there's still one running, we're done */
                return;
        }
index 60f3581f5fdf47f34853e9b52b099bc7942df7a4..fe0fb6dd1cba7a52fc675e71dfe5f9021cb8ea2f 100644 (file)
@@ -116,5 +116,21 @@ static void dreplsrv_periodic_run(struct dreplsrv_service *service)
        dreplsrv_ridalloc_check_rid_pool(service);
 
        dreplsrv_run_pending_ops(service);
-       dreplsrv_notify_run_ops(service);
+}
+
+/*
+  run the next pending op, either a notify or a pull
+ */
+void dreplsrv_run_pending_ops(struct dreplsrv_service *s)
+{
+       if (!s->ops.notifies && !s->ops.pending) {
+               return;
+       }
+       if (!s->ops.notifies ||
+           (s->ops.pending &&
+            s->ops.notifies->schedule_time > s->ops.pending->schedule_time)) {
+               dreplsrv_run_pull_ops(s);
+       } else {
+               dreplsrv_notify_run_ops(s);
+       }
 }
index 9ad62fd538d65939acec6ce81d0f727527ddb089..d69c64117815b4ded40e526c002af9a5cd3a8f35 100644 (file)
@@ -119,6 +119,7 @@ typedef void (*dreplsrv_extended_callback_t)(struct dreplsrv_service *,
 
 struct dreplsrv_out_operation {
        struct dreplsrv_out_operation *prev, *next;
+       time_t schedule_time;
 
        struct dreplsrv_service *service;
 
@@ -133,6 +134,7 @@ struct dreplsrv_out_operation {
 
 struct dreplsrv_notify_operation {
        struct dreplsrv_notify_operation *prev, *next;
+       time_t schedule_time;
 
        struct dreplsrv_service *service;
        uint64_t uSN;