#include <stdlib.h>
#include <inttypes.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/poll.h>
#include "error.h"
#include "event.h"
#include "hook.h"
#include "safeio.h"
#include "tab.h"
#include "worker.h"
extern int eventfd(unsigned int initval, int flags);
HOOK_USE(event);
static void event_run(const char *event, const char *type) {
event_t e;
e.event = event;
e.type = type;
hook_call(event_hook, &e);
}
static int fd = -1;
static void *event_worker(void *_) {
mpool_t *p;
s64 delay;
struct db *db;
char *event, *type;
s64 pause = 0;
uint64_t num = 0;
p = mpool_new(NULL);
worker_tmp_set(p);
for(;;) {
delay = INT64_MIN;
db = db_begin(p);
db_event_timetonext(db, &delay);
mpool_clear(p);
if(delay < 0)
delay = 0;
else if(delay > 60000000)
delay = 60000000;
if(safepoll(fd, POLLIN, delay) && read(fd, &num, sizeof num) == -1) {
if(errno != EINTR)
break;
sleep(++pause);
continue;
}
db = db_begin(p);
while(db_event_nextexpired(db, &event, &type) && event) {
event_run(event, type);
if(!db_event_del(db, event))
break;
}
if(db_commit(db)) {
mpool_clear(p);
pause = 0;
} else {
eputs("event transaction failed, sleeping");
mpool_clear(p);
sleep(++pause);
}
}
worker_tmp_del();
return NULL;
}
static void event_notify(void) {
uint64_t een = 1;
write(fd, &een, sizeof een);
}
static pthread_t draadje;
__attribute__((constructor))
static void event_init(void) {
fd = eventfd(0, 0);
if(fd == -1)
perror_exit("eventfd()");
pthread_create(&draadje, NULL, event_worker, NULL);
}
__attribute__((destructor))
static void event_exit(void) {
int i = fd;
if(i != -1) {
fd = -1;
close(i);
pthread_join(draadje, NULL);
}
}
static tab_entry_t notify_tab_entries[] = {
{"events", event_notify},
};
TAB_REGISTER(notify);