#include <cx/hash_map.h>
#include <cx/linked_list.h>
#include "../util/atomic.h"
#include "event.h"
static CxMap *event_handler_map =
NULL;
int numevhandlers =
0;
EVHandler *default_event_handler =
NULL;
EVHandler *last_handler_c =
NULL;
int create_event_handler(EventHandlerConfig *cfg) {
if(event_handler_map ==
NULL) {
event_handler_map = cxHashMapCreate(cxDefaultAllocator,
CX_STORE_POINTERS,
16);
}
CxHashKey key = cx_hash_key_bytes((
const unsigned char*)cfg->name.ptr, cfg->name.length);
if(cxMapGet(event_handler_map, key)) {
log_ereport(
LOG_DEBUG,
"event handler %s already exists", cfg->name.ptr);
return 0;
}
EVHandler *e = evhandler_create(cfg);
if(e ==
NULL) {
log_ereport(
LOG_FAILURE,
"evhandler_create failed");
return 1;
}
if(cfg->isdefault) {
if(default_event_handler) {
}
default_event_handler = e;
}
int ret = cxMapPut(event_handler_map, key, e);
if(ret ==
0) {
last_handler_c = e;
numevhandlers++;
}
return ret;
}
void shutdown_eventhandlers_wait(
void) {
log_ereport(
LOG_INFORM,
"shutdown eventhandlers");
CxIterator i = cxMapIteratorValues(event_handler_map);
cx_foreach(EVHandler *, e, i) {
evhandler_shutdown(e);
}
i = cxMapIteratorValues(event_handler_map);
cx_foreach(EVHandler *, e, i) {
evhandler_wait_and_destroy(e);
}
cxMapDestroy(event_handler_map);
log_ereport(
LOG_INFORM,
"all eventhandlers closed");
}
void evhandler_shutdown(EVHandler *h) {
for(
int i=
0;i<h->numins;i++) {
ev_instance_shutdown(h->instances[i]);
}
}
void evhandler_close(EVHandler *h) {
for(
int i=
0;i<h->numins;i++) {
ev_instance_close(h->instances[i]);
}
}
void evhandler_wait_and_destroy(EVHandler *h) {
for(
int i=
0;i<h->numins;i++) {
ev_instance_wait(h->instances[i]);
}
free(h->instances);
free(h);
}
int check_event_handler_cfg() {
if(numevhandlers >
0 ) {
if(default_event_handler) {
return 0;
}
else {
default_event_handler = last_handler_c;
return 0;
}
}
EventHandlerConfig cfg;
cfg.name = cx_str(
"default");
cfg.nthreads =
1;
cfg.isdefault =
1;
return create_event_handler(&cfg);
}
EVHandler* get_default_event_handler() {
return default_event_handler;
}
EVHandler* get_event_handler(
const char *name) {
return cxMapGet(event_handler_map, cx_hash_key_str(name));
}
EventHandler* ev_instance(EVHandler *ev) {
int nev = ev->numins;
if(nev ==
1) {
return ev->instances[
0];
}
int ins = ev->current & nev;
ws_atomic_inc32(&ev->current);
return ev->instances[ins];
}
int ev_free_event(EventHandler *h, Event *event) {
free(event);
return 0;
}
void ev_watchlist_add(EventHandler *h, EVWatchList *elm) {
watchlist_add(&h->watchlist_begin, &h->watchlist_end, elm);
}
void ev_watchlist_remove(EventHandler *h, EVWatchList *elm) {
watchlist_remove(&h->watchlist_begin, &h->watchlist_end, elm);
}
void ev_saf_return(EventHandler *h, Session *sn, Request *rq,
int ret) {
h->fnreturn[h->numret++] = (EVReturn){ sn, rq, ret };
}
void watchlist_add(EVWatchList **begin, EVWatchList **end, EVWatchList *elm) {
cx_linked_list_add(
(
void**)begin,
(
void**)end,
offsetof(EVWatchList, prev),
offsetof(EVWatchList, next),
elm);
}
void watchlist_remove(EVWatchList **begin, EVWatchList **end, EVWatchList *elm) {
cx_linked_list_remove(
(
void**)begin,
(
void**)end,
offsetof(EVWatchList, prev),
offsetof(EVWatchList, next),
elm);
}
void watchlist_check(EventHandler *h,
time_t t) {
if(t ==
0) {
t = time(
NULL);
}
log_ereport(
LOG_DEBUG,
"eventhandler: check watchlist");
EVWatchList *elm = h->watchlist_begin;
while(elm) {
EVWatchList *next = elm->next;
if(elm->expire < t) {
ev_watchlist_remove(h, elm);
if(elm->destroy) {
elm->destroy(h, elm);
}
}
elm = next;
}
}