From 73016ad40523d4d41114c7b4d6bb2a46815bb597 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 17 Nov 2010 23:12:10 +1100 Subject: [PATCH] s4-repl: ensure we don't starve pending replication ops 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 | 4 ++-- source4/dsdb/repl/drepl_out_pull.c | 6 +++--- source4/dsdb/repl/drepl_periodic.c | 18 +++++++++++++++++- source4/dsdb/repl/drepl_service.h | 2 ++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/source4/dsdb/repl/drepl_notify.c b/source4/dsdb/repl/drepl_notify.c index 0178e97e559..25378129dac 100644 --- a/source4/dsdb/repl/drepl_notify.c +++ b/source4/dsdb/repl/drepl_notify.c @@ -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); } diff --git a/source4/dsdb/repl/drepl_out_pull.c b/source4/dsdb/repl/drepl_out_pull.c index 3e59ee95ac1..0af232c67fd 100644 --- a/source4/dsdb/repl/drepl_out_pull.c +++ b/source4/dsdb/repl/drepl_out_pull.c @@ -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; } diff --git a/source4/dsdb/repl/drepl_periodic.c b/source4/dsdb/repl/drepl_periodic.c index 60f3581f5fd..fe0fb6dd1cb 100644 --- a/source4/dsdb/repl/drepl_periodic.c +++ b/source4/dsdb/repl/drepl_periodic.c @@ -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); + } } diff --git a/source4/dsdb/repl/drepl_service.h b/source4/dsdb/repl/drepl_service.h index 9ad62fd538d..d69c6411781 100644 --- a/source4/dsdb/repl/drepl_service.h +++ b/source4/dsdb/repl/drepl_service.h @@ -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;