From 6cd252666dafdded0f8cedd7d2e86709179dd4f9 Mon Sep 17 00:00:00 2001 From: Marek Vavrusa <marek@vavrusa.com> Date: Thu, 28 Apr 2011 18:09:57 +0200 Subject: [PATCH] Event scheduler runnable in server, see server_t. Example: evsched_schedule_cb(server->sched, mycallback, data, 1000); // dt=1s Commit refs #799. --- src/common/evqueue.h | 1 + src/common/evsched.c | 23 ++++++++++----- src/common/evsched.h | 20 +++++++++++++- src/knot/server/server.c | 60 ++++++++++++++++++++++++++++++++++++++-- src/knot/server/server.h | 4 +++ 5 files changed, 98 insertions(+), 10 deletions(-) diff --git a/src/common/evqueue.h b/src/common/evqueue.h index eb57ca7904..bbba5ac7de 100644 --- a/src/common/evqueue.h +++ b/src/common/evqueue.h @@ -45,6 +45,7 @@ typedef struct event_t { struct timeval tv; /*!< Event scheduled time. */ void *data; /*!< Usable data ptr. */ event_cb_t cb; /*!< Event callback. */ + void *caller; /*!< Pointer to caller. */ } event_t; /*! diff --git a/src/common/evsched.c b/src/common/evsched.c index cd0222c80b..9e9426350a 100644 --- a/src/common/evsched.c +++ b/src/common/evsched.c @@ -28,6 +28,9 @@ static void evsched_settimer(event_t *e, int dt) } } +/*! \brief Singleton application-wide event scheduler. */ +evsched_t *s_evsched = 0; + evsched_t *evsched_new() { evsched_t *s = malloc(sizeof(evsched_t)); @@ -143,12 +146,15 @@ event_t* evsched_next(evsched_t *s) } -int evsched_schedule(evsched_t *s, event_t *ev) +int evsched_schedule(evsched_t *s, event_t *ev, int dt) { - if (!s || !ev) { + if (!s || !ev || dt < 0) { return -1; } + /* Update event timer. */ + evsched_settimer(ev, dt); + /* Lock calendar. */ pthread_mutex_lock(&s->mx); @@ -184,15 +190,16 @@ event_t* evsched_schedule_cb(evsched_t *s, event_cb_t cb, void *data, int dt) return 0; } + /* Create event. */ event_t *e = evsched_event_new(s, EVSCHED_CB); if (!e) { return 0; } - e->cb = cb; e->data = data; - evsched_settimer(e, dt); - if (evsched_schedule(s, e) != 0) { + + /* Schedule. */ + if (evsched_schedule(s, e, dt) != 0) { evsched_event_free(s, e); e = 0; } @@ -206,13 +213,14 @@ event_t* evsched_schedule_term(evsched_t *s, int dt) return 0; } + /* Create event. */ event_t *e = evsched_event_new(s, EVSCHED_TERM); if (!e) { return 0; } - evsched_settimer(e, dt); - if (evsched_schedule(s, e) != 0) { + /* Schedule. */ + if (evsched_schedule(s, e, dt) != 0) { evsched_event_free(s, e); e = 0; } @@ -238,3 +246,4 @@ int evsched_cancel(evsched_t *s, event_t *ev) return 0; } + diff --git a/src/common/evsched.h b/src/common/evsched.h index 967ac1d86f..3f6cef82d0 100644 --- a/src/common/evsched.h +++ b/src/common/evsched.h @@ -134,11 +134,12 @@ event_t* evsched_next(evsched_t *s); * * \param s Event scheduler. * \param ev Prepared event. + * \param dt Time difference in milliseconds from now (dt is relative). * * \retval 0 on success. * \retval <0 on error. */ -int evsched_schedule(evsched_t *s, event_t *ev); +int evsched_schedule(evsched_t *s, event_t *ev, int dt); /*! * \brief Schedule callback event. @@ -179,6 +180,23 @@ event_t* evsched_schedule_term(evsched_t *s, int dt); */ int evsched_cancel(evsched_t *s, event_t *ev); +/* Singleton event scheduler pointer. */ +extern evsched_t *s_evsched; + +/*! + * \brief Event scheduler singleton. + */ +static inline evsched_t *evsched() { + return s_evsched; +} + +/*! + * \brief Set event scheduler singleton. + */ +static inline void evsched_set(evsched_t *s) { + s_evsched = s; +} + #endif /* _KNOT_COMMON_EVSCHED_H_ */ diff --git a/src/knot/server/server.c b/src/knot/server/server.c index 0046f96e44..4913414d1d 100644 --- a/src/knot/server/server.c +++ b/src/knot/server/server.c @@ -22,6 +22,47 @@ #include "knot/conf/conf.h" #include "knot/server/zones.h" +/*! \brief Event scheduler loop. */ +static int evsched_run(dthread_t *thread) +{ + iohandler_t *sched_h = (iohandler_t *)thread->data; + evsched_t *s = (evsched_t*)sched_h->data; + if (!s) { + return KNOT_EINVAL; + } + + /* Run event loop. */ + event_t *ev = 0; + while((ev = evsched_next(s))) { + + /* Error. */ + if (!ev) { + return KNOT_ERROR; + } + + /* Process termination event. */ + if (ev->type == EVSCHED_TERM) { + evsched_event_free(s, ev); + break; + } + + /* Process event. */ + if (ev->type == EVSCHED_CB && ev->cb) { + ev->caller = s; + ev->cb(ev); + } else { + evsched_event_free(s, ev); + } + + /* Check for thread cancellation. */ + if (dt_is_cancelled(thread)) { + break; + } + } + + return KNOT_EOK; +} + /*! \brief List item for generic pointers. */ typedef struct pnode_t { struct node *next, *prev; /* Keep the ordering for lib/lists.h */ @@ -330,6 +371,13 @@ server_t *server_create() server->ifaces = malloc(sizeof(list)); init_list(server->ifaces); + // Create event scheduler + debug_server("Creating event scheduler...\n"); + server->sched = evsched_new(); + dt_unit_t *unit = dt_create_coherent(1, evsched_run, 0); + iohandler_t *h = server_create_handler(server, -1, unit); + h->data = server->sched; + // Create name server debug_server("Creating Name Server structure...\n"); server->nameserver = ns_create(); @@ -413,8 +461,10 @@ int server_remove_handler(server_t *server, iohandler_t *h) } // Close socket - socket_close(h->fd); - h->fd = -1; + if (h->fd >= 0) { + socket_close(h->fd); + h->fd = -1; + } // Update interface if (h->iface) { @@ -520,6 +570,9 @@ int server_wait(server_t *server) void server_stop(server_t *server) { + /* Send termination event. */ + evsched_schedule_term(server->sched, 0); + /* Lock RCU. */ rcu_read_lock(); @@ -559,6 +612,9 @@ void server_destroy(server_t **server) // Free XFR master xfr_free((*server)->xfr_h); + // Delete event scheduler + evsched_delete(&(*server)->sched); + stat_static_gath_free(); ns_destroy(&(*server)->nameserver); diff --git a/src/knot/server/server.h b/src/knot/server/server.h index 2da017c1b7..2c8ed139b7 100644 --- a/src/knot/server/server.h +++ b/src/knot/server/server.h @@ -27,6 +27,7 @@ #include "knot/server/socket.h" #include "knot/server/dthreads.h" #include "dnslib/zonedb.h" +#include "common/evsched.h" #include "common/lists.h" /* Forwad declarations. */ @@ -93,6 +94,9 @@ typedef struct server_t { /*! \brief XFR handler. */ xfrhandler_t *xfr_h; + /*! \brief Event scheduler. */ + evsched_t *sched; + /*! \brief I/O handlers list. */ list handlers; -- GitLab