]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
events: add blocking scheduling
authorJan Hák <jan.hak@nic.cz>
Tue, 28 May 2019 11:28:57 +0000 (13:28 +0200)
committerDaniel Salzman <daniel.salzman@nic.cz>
Wed, 29 May 2019 18:45:25 +0000 (20:45 +0200)
src/knot/events/events.c
src/knot/events/events.h

index 83c61a906bde4d3daf4b2fbe1d0b8d51130ad36e..573812ab2d9c57a60f08a9cd56524783e9e25510 100644 (file)
@@ -17,6 +17,7 @@
 #include <assert.h>
 #include <stdarg.h>
 #include <time.h>
+#include <unistd.h>
 #include <urcu.h>
 
 #include "libknot/libknot.h"
@@ -211,6 +212,7 @@ static void event_wrap(task_t *task)
                pthread_mutex_unlock(&events->mx);
                return;
        }
+       events->type = type;
        event_set_time(events, type, 0);
        events->forced[type] = false;
        pthread_mutex_unlock(&events->mx);
@@ -235,6 +237,7 @@ static void event_wrap(task_t *task)
 
        pthread_mutex_lock(&events->mx);
        events->running = false;
+       events->type = ZONE_EVENT_INVALID;
        pthread_mutex_unlock(&events->mx);
        reschedule(events);
 }
@@ -358,6 +361,27 @@ void zone_events_schedule_user(zone_t *zone, zone_event_type_t type)
        reschedule(events);
 }
 
+void zone_events_schedule_blocking(zone_t *zone, zone_event_type_t type, bool user)
+{
+       if (!zone || !valid_event(type)) {
+               return;
+       }
+
+       if (user) {
+               zone_events_schedule_user(zone, type);
+       } else {
+               zone_events_schedule_now(zone, type);
+       }
+
+       time_t now = time(NULL);
+       time_t sched_time = zone_events_get_time(zone, type);
+       while ((zone->events.running && zone->events.type == type) ||
+              (sched_time > 0 && sched_time <= now)) {
+               usleep(20000);
+               sched_time = zone_events_get_time(zone, type);
+       }
+}
+
 void zone_events_enqueue(zone_t *zone, zone_event_type_t type)
 {
        if (!zone || !valid_event(type)) {
@@ -372,6 +396,7 @@ void zone_events_enqueue(zone_t *zone, zone_event_type_t type)
        if (!events->running && !events->frozen &&
            (!events->ufrozen || !ufreeze_applies(type))) {
                events->running = true;
+               events->type = type;
                event_set_time(events, type, ZONE_EVENT_IMMEDIATE);
                worker_pool_assign(events->pool, &events->task);
                pthread_mutex_unlock(&events->mx);
index b5d54f2ca1627dd63f2386ad930e37e740109c2f..5d797ac5803cade9e37c3ef7a38de0bc7fb6d168 100644 (file)
@@ -48,7 +48,10 @@ typedef enum zone_event_type {
 typedef struct zone_events {
        pthread_mutex_t mx;             //!< Mutex protecting the struct.
        pthread_mutex_t reschedule_lock;//!< Prevent concurrent reschedule() making mess.
+
+       zone_event_type_t type;         //!< Type of running event.
        bool running;                   //!< Some zone event is being run.
+
        bool frozen;                    //!< Terminated, don't schedule new events.
        bool ufrozen;                   //!< Updates to the zone temporarily frozen by user.
 
@@ -134,6 +137,16 @@ void _zone_events_schedule_at(struct zone *zone, ...);
  */
 void zone_events_schedule_user(struct zone *zone, zone_event_type_t type);
 
+/*!
+ * \brief Schedule new zone event as soon as possible and wait for it's
+ * completion (end of task run), with optional forced flag.
+ *
+ * \param zone  Zone to schedule new event for.
+ * \param type  Zone event type.
+ * \param user  Forced flag indication.
+ */
+void zone_events_schedule_blocking(struct zone *zone, zone_event_type_t type, bool user);
+
 /*!
  * \brief Freeze all zone events and prevent new events from running.
  *