dsdb-drepl: create a new schedulable event for running pending operations
authorMatthieu Patou <mat@matws.net>
Wed, 15 May 2013 11:46:33 +0000 (04:46 -0700)
committerStefan Metzmacher <metze@samba.org>
Wed, 15 May 2013 12:31:40 +0000 (14:31 +0200)
So instead of running dreplsrv_periodic_schedule when receiving a
DRS_REPLICA_SYNC request which will force the DC to look for changes
with all the DC it usually replicate to, we reduce it to the DC
specified in the DRS_REPLICA_SYNC request. It will allow also to do have the
correct options as set by the client who send the DRS_REPLICA_SYNC.

Signed-off-by: Matthieu Patou <mat@matws.net>
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 62b4092854719f8164b517e011880677219b6f0e..d6b94679e0e7f548f8f0e4183c8e50a720720d9e 100644 (file)
@@ -133,3 +133,64 @@ void dreplsrv_run_pending_ops(struct dreplsrv_service *s)
                dreplsrv_notify_run_ops(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)
+{
+       struct dreplsrv_service *service = talloc_get_type(ptr, struct dreplsrv_service);
+
+       service->pending.te = NULL;
+
+       dreplsrv_pending_run(service);
+}
+
+WERROR dreplsrv_pendingops_schedule(struct dreplsrv_service *service, uint32_t next_interval)
+{
+       TALLOC_CTX *tmp_mem;
+       struct tevent_timer *new_te;
+       struct timeval next_time;
+
+       /* 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;
+}
+
+static void dreplsrv_pending_run(struct dreplsrv_service *service)
+{
+       dreplsrv_run_pending_ops(service);
+}
index 3d28676b8f2575101da5712bc53c786c3af5e0ea..bd333779fa72f26768875cf3ec552bfe0c287eea 100644 (file)
@@ -338,7 +338,7 @@ static NTSTATUS drepl_replica_sync(struct irpc_message *msg,
         * schedule replication event to force
         * replication as soon as possible
         */
-       dreplsrv_periodic_schedule(service, 0);
+       dreplsrv_pendingops_schedule(service, 0);
 
 done:
        return NT_STATUS_OK;
index 6daf82d9f4eb0da7bffd03de4e6308dee6f0f16f..edba4c4a49b5c47b9fb124d6fe67b4603e495142 100644 (file)
@@ -187,6 +187,23 @@ struct dreplsrv_service {
                struct tevent_timer *te;
        } periodic;
 
+       /* some stuff for running only the pendings ops */
+       struct {
+               /*
+                * the interval between notify runs
+                */
+               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;
+       } pending;
+
        /* some stuff for notify processing */
        struct {
                /*