Skip to content
Snippets Groups Projects
Commit 6cd25266 authored by Marek Vavrusa's avatar Marek Vavrusa
Browse files

Event scheduler runnable in server, see server_t.

Example:
evsched_schedule_cb(server->sched, mycallback, data, 1000); // dt=1s

Commit refs #799.
parent 2249a42c
Branches
Tags
No related merge requests found
......@@ -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;
/*!
......
......@@ -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;
}
......@@ -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_ */
......
......@@ -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);
......
......@@ -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;
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment