s4-drepl: Use tevent_schedule_immediate() in DsReplicaSync handler
authorAndrew Bartlett <abartlet@samba.org>
Fri, 21 Jul 2017 05:52:04 +0000 (17:52 +1200)
committerStefan Metzmacher <metze@samba.org>
Fri, 21 Jul 2017 15:45:12 +0000 (17:45 +0200)
When we are sent a DsReplicaSync() we should work on inbound replication
(ideally from the requested source, but so far we just start the whole queue)
right away, not after 1 second.

We should also target inbound replication, not any outbound replication
notification that may happen to be due.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12921

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
source4/dsdb/repl/drepl_periodic.c
source4/dsdb/repl/drepl_service.c
source4/dsdb/repl/drepl_service.h

index d6b94679e0e7f548f8f0e4183c8e50a720720d9e..64a53e085199784f18d06a128fbe4b76ce8f87b9 100644 (file)
@@ -134,63 +134,21 @@ void dreplsrv_run_pending_ops(struct dreplsrv_service *s)
        }
 }
 
-static void dreplsrv_pending_run(struct dreplsrv_service *service);
-
-static void dreplsrv_pending_handler_te(struct tevent_context *ev, struct tevent_timer *te,
-                                       struct timeval t, void *ptr)
+static void dreplsrv_pending_pull_handler_im(struct tevent_context *ev,
+                                            struct tevent_immediate *im,
+                                            void *ptr)
 {
        struct dreplsrv_service *service = talloc_get_type(ptr, struct dreplsrv_service);
 
-       service->pending.te = NULL;
-
-       dreplsrv_pending_run(service);
+       dreplsrv_run_pull_ops(service);
 }
 
-WERROR dreplsrv_pendingops_schedule(struct dreplsrv_service *service, uint32_t next_interval)
+void dreplsrv_pendingops_schedule_pull_now(struct dreplsrv_service *service)
 {
-       TALLOC_CTX *tmp_mem;
-       struct tevent_timer *new_te;
-       struct timeval next_time;
+       tevent_schedule_immediate(service->pending.im, service->task->event_ctx,
+                                 dreplsrv_pending_pull_handler_im,
+                                 service);
 
-       /* prevent looping */
-       if (next_interval == 0) {
-               next_interval = 1;
-       }
-
-       next_time = timeval_current_ofs(next_interval, 50);
-
-       if (service->pending.te) {
-               /*
-                * if the timestamp of the new event is higher,
-                * as current next we don't need to reschedule
-                */
-               if (timeval_compare(&next_time, &service->pending.next_event) > 0) {
-                       return WERR_OK;
-               }
-       }
-
-       /* reset the next scheduled timestamp */
-       service->pending.next_event = next_time;
-
-       new_te = tevent_add_timer(service->task->event_ctx, service,
-                                 service->pending.next_event,
-                                dreplsrv_pending_handler_te, service);
-       W_ERROR_HAVE_NO_MEMORY(new_te);
-
-       tmp_mem = talloc_new(service);
-       DEBUG(4,("dreplsrv_pending_schedule(%u) %sscheduled for: %s\n",
-               next_interval,
-               (service->pending.te?"re":""),
-               nt_time_string(tmp_mem, timeval_to_nttime(&next_time))));
-       talloc_free(tmp_mem);
-
-       talloc_free(service->pending.te);
-       service->pending.te = new_te;
-
-       return WERR_OK;
+       return;
 }
 
-static void dreplsrv_pending_run(struct dreplsrv_service *service)
-{
-       dreplsrv_run_pending_ops(service);
-}
index 39791b44aa8be38979e430f7b1511b5a1de2c727..5b2836324945cd40ff2ad5918a969a37e1279c9b 100644 (file)
@@ -339,7 +339,7 @@ static NTSTATUS drepl_replica_sync(struct irpc_message *msg,
         * schedule replication event to force
         * replication as soon as possible
         */
-       dreplsrv_pendingops_schedule(service, 0);
+       dreplsrv_pendingops_schedule_pull_now(service);
 
 done:
        return NT_STATUS_OK;
@@ -486,6 +486,15 @@ static void dreplsrv_task_init(struct task_server *task)
                return;
        }
 
+       service->pending.im = tevent_create_immediate(service);
+       if (service->pending.im == NULL) {
+               task_server_terminate(task,
+                                     "dreplsrv: Failed to create immediate "
+                                     "task for future DsReplicaSync\n",
+                                     true);
+               return;
+       }
+
        /* if we are a RODC then we do not send DSReplicaSync*/
        if (!service->am_rodc) {
                service->notify.interval = lpcfg_parm_int(task->lp_ctx, NULL, "dreplsrv",
index 6b85ad6c672567efcd9e780f6f308a49a6876f5a..dc8a7f67455892272b06337ce4be179fdc729f8c 100644 (file)
@@ -187,21 +187,13 @@ struct dreplsrv_service {
                struct tevent_timer *te;
        } periodic;
 
-       /* some stuff for running only the pendings ops */
+       /* some stuff for running only the incoming notify ops */
        struct {
                /*
-                * the interval between notify runs
+                * here we have a reference to the immidicate event that was
+                * scheduled from the DsReplicaSync
                 */
-               uint32_t interval;
-
-               /*
-                * the timestamp for the next event,
-                * this is the timstamp passed to event_add_timed()
-                */
-               struct timeval next_event;
-
-               /* here we have a reference to the timed event the schedules the notifies */
-               struct tevent_timer *te;
+               struct tevent_immediate *im;
        } pending;
 
        /* some stuff for notify processing */