1
0
This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
Files
2024-07-22 01:58:46 -03:00

384 lines
8.7 KiB
C
Executable File

/*
* Event handler
*
* $Id: //BBN_Linux/Branch/Branch_for_Rel_TP_ASEAN_20161216/tclinux_phoenix/apps/public/linux-atm/lane/events.c#1 $
*
*/
/* System includes */
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
/* Local includes */
#include "events.h"
#include "load.h"
#include "dump.h"
#include "mem.h"
#include "timers.h"
#include "connect.h"
/* Type definitions */
typedef struct _EventList_t {
const Event_t *event;
struct _EventList_t *next;
struct _EventList_t *prev;
} EventList_t;
typedef struct _HFList_t {
const char *name;
HandlerFunc_t h;
void *funcdata;
struct _HFList_t *next;
} HFList_t;
typedef struct _FDList_t {
int fd;
void *data;
struct _FDList_t *next;
} FDList_t;
/* Local function prototypes */
static void events_init0(void);
static void events_init1(void);
static void events_dump(void);
static void events_release(void);
static void event_get_fds(fd_set *dest);
/* Data */
static const char *rcsid="$Id: //BBN_Linux/Branch/Branch_for_Rel_TP_ASEAN_20161216/tclinux_phoenix/apps/public/linux-atm/lane/events.c#1 $";
const Unit_t events_unit = {
"events",
&events_init0,
&events_init1,
&events_dump,
&events_release
};
/*static mutex_t event_mutex;*/
static EventList_t *eventhead, *eventtail;
static HFList_t *handlers[CE_MAX + 1];
static FDList_t *fdlist;
/* Functions */
/* Initialize local data */
static void
events_init0(void)
{
unsigned int i;
eventhead = NULL;
eventtail = NULL;
for (i = 0; i <= CE_MAX; i++) {
handlers[i] = NULL;
}
fdlist = NULL;
}
/* Initialization for data that needs other units */
static void
events_init1(void)
{
set_var_str(&events_unit, "version", rcsid);
Debug_unit(&events_unit, "Initialized.");
}
/* Dump status, local data etc. */
static void
events_dump(void)
{
const EventList_t *tmp;
const HFList_t *htmp;
const FDList_t *ftmp;
unsigned int i;
for (tmp = eventhead; tmp != NULL; tmp = tmp->next) {
assert(tmp->event != NULL);
assert(tmp->event->unit != NULL);
assert(tmp->event->unit->name != NULL);
Debug_unit(&events_unit, "unit %s type %s data 0x%x", tmp->event->unit->name, dump_event_type(tmp->event->type), tmp->event->data);
}
for (i = 0; i <= CE_MAX; i++) {
for (htmp = handlers[i]; htmp != NULL; htmp = htmp->next) {
Debug_unit(&events_unit, "type %s func 0x%x name %s data 0x%x", dump_event_type(i), htmp->h, htmp->name, htmp->funcdata);
}
}
for (ftmp = fdlist; ftmp != NULL; ftmp = ftmp->next) {
Debug_unit(&events_unit, "polled fd %d", ftmp->fd);
}
}
/* Release allocated memory, close files etc. */
static void
events_release(void)
{
unsigned int i;
HFList_t *htmp;
FDList_t *ftmp;
EventList_t *tmp;
/* Lock list */
for (tmp = eventhead; tmp != NULL; ) {
assert(eventhead->event != NULL);
assert(eventhead->event->unit != NULL);
assert(eventhead->event->unit->name != NULL);
Debug_unit(&events_unit, "discarding unread event, unit %s type %s data 0x%x", eventhead->event->unit->name, dump_event_type(eventhead->event->type), eventhead->event->data);
tmp = eventhead->next;
mem_free(&events_unit, eventhead->event);
mem_free(&events_unit, eventhead);
eventhead = tmp;
}
eventtail = NULL;
/* Unlock list */
for (i = 0; i <= CE_MAX; i++) {
for (htmp = handlers[i]; htmp != NULL; htmp = htmp->next) {
handlers[i] = htmp->next;
mem_free(&events_unit, htmp);
}
}
for (ftmp = fdlist; ftmp != NULL; ftmp = ftmp->next) {
printf("Closing:%d\n",ftmp->fd);
close(ftmp->fd);
fdlist = ftmp->next;
mem_free(&events_unit, ftmp);
}
}
void
add_event_handler(EventType_t type, HandlerFunc_t func, const char *name, void *funcdata)
{
HFList_t *tmp;
tmp = (HFList_t *)mem_alloc(&events_unit, sizeof(HFList_t));
tmp->name = name;
tmp->h = func;
tmp->funcdata = funcdata;
assert(type <= CE_MAX);
tmp->next = handlers[type];
handlers[type] = tmp;
}
static const char *typetable[CE_MAX + 1] = {
"New SVC",
"SVC closed",
"Data arrived",
"Timer expired",
"Dump",
"Restart",
"Termination"
};
/* Return event type as string */
const char *
dump_event_type(EventType_t type)
{
assert(type >= CE_SVC_CLOSE && type <= CE_MAX);
return typetable[type];
}
/* Get next event from queue */
const Event_t *
event_get_next(void)
{
const Event_t *event = NULL;
EventList_t *tmplist;
const FDList_t *tmp;
int poll_ret;
Timer_t *soonest;
fd_set to_select;
struct timeval *rolex;
while (eventtail == NULL && sig_hup == 0 &&
sig_usr1 == 0 && sig_alarm == 0 &&
sig_usr2 == 0) {
/* No events waiting, sleep on select() or poll() */
if (fdlist != NULL) {
soonest = timer_find_soonest(&events_unit);
if (soonest != NULL) {
rolex = (struct timeval *)mem_alloc(&events_unit,
sizeof(struct timeval));
rolex->tv_sec = soonest->alarm_time - time(NULL);
rolex->tv_usec = 0;
Debug_unit(&events_unit, "Sleeping %d s...", rolex->tv_sec);
}
else {
rolex = NULL;
Debug_unit(&events_unit, "Sleeping forever...");
}
event_get_fds(&to_select);
poll_ret = select(FD_SETSIZE, &to_select, NULL, NULL, rolex);
if (rolex)
mem_free(&events_unit,rolex);
Debug_unit(&events_unit, "Select: %d", poll_ret);
switch (poll_ret) {
case -1:
/* Error occurred */
dump_error(&events_unit, "select");
break;
case 0:
/* Timeout */
timer_ack(&events_unit, soonest);
event_put(&events_unit, CE_TIMER, (void*)soonest->data);
break;
default:
/* Data arrival / SVC creation */
Debug_unit(&events_unit,"fdlist:%d",fdlist);
for (tmp = fdlist; tmp != NULL; tmp = tmp->next) {
dump_printf(EL_DEBUG,"FD:%d",tmp->fd);
if (FD_ISSET(tmp->fd, &to_select)) {
Debug_unit(&events_unit, "Event on fd %d", tmp->fd);
conn_set_active(tmp->data, tmp->fd);
event_put(&events_unit, CE_DATA, tmp->data);
}
}
break;
}
}
else {
Debug_unit(&events_unit, "No fds, restarting after 10 s");
sleep(10);
event_put(&events_unit, CE_RESTART, NULL);
}
}
if (sig_hup != 0) {
event_put(&events_unit, CE_RESTART, NULL);
sig_hup = 0;
}
if (sig_usr1 != 0) {
event_put(&events_unit, CE_DUMP, NULL);
sig_usr1 = 0;
}
if (sig_usr2 != 0) {
event_put(&events_unit, CE_EXIT, NULL);
sig_usr2 = 0;
}
if (sig_alarm != 0) {
event_put(&events_unit, CE_TIMER, NULL);
sig_alarm = 0;
}
Debug_unit(&events_unit, "get event %s", dump_event_type(eventtail->event->type));
/* Lock list */
event = eventhead->event;
if (eventhead->next != NULL) {
eventhead->next->prev = NULL;
}
else {
/* This was the last */
eventtail = NULL;
}
tmplist = eventhead;
eventhead = eventhead->next;
/* Unlock list */
mem_free(&events_unit, tmplist);
return event;
}
/* Add event to queue */
void
event_put(const Unit_t *unit, EventType_t type, void *data)
{
Event_t *event;
EventList_t *tmplist;
Debug_unit(&events_unit, "unit %s puts event %s", unit->name, dump_event_type(type));
event = (Event_t *)mem_alloc(&events_unit, sizeof(Event_t));
event->unit = unit;
event->type = type;
event->data = data;
tmplist = (EventList_t *)mem_alloc(&events_unit, sizeof(EventList_t));
tmplist->event = event;
tmplist->next = NULL;
/* Lock list */
tmplist->prev = eventtail;
if (eventtail != NULL) {
eventtail->next = tmplist;
}
else {
/* This is the first one */
eventhead = tmplist;
}
eventtail = tmplist;
/* Unlock list */
}
/* Call handlers until one returns nonzero */
int
dispatch_handlers(const Event_t *event)
{
int handled = 0;
const HFList_t *htmp;
assert(event != NULL);
for (htmp = handlers[event->type]; htmp != NULL; htmp = htmp->next) {
Debug_unit(&events_unit, "trying handler %s", htmp->name);
handled = (htmp->h(event, htmp->funcdata));
if (handled != 0) {
Debug_unit(&events_unit, "success.");
break;
}
else {
Debug_unit(&events_unit, "failed.");
}
}
return handled;
}
static void
event_get_fds(fd_set *dest)
{
FDList_t *tmp;
FD_ZERO(dest);
for(tmp = fdlist; tmp != NULL; tmp = tmp->next)
FD_SET(tmp->fd, dest);
}
void
event_add_fd(int fd, void *data)
{
FDList_t *tmp;
tmp = mem_alloc(&events_unit, sizeof(FDList_t));
tmp->fd = fd;
tmp->data = data;
tmp->next = fdlist;
fdlist = tmp;
}
void
event_remove_fd(int fd)
{
FDList_t *tmp, *prev = NULL;
for (tmp = fdlist; tmp != NULL; prev = tmp, tmp = tmp->next) {
if (tmp->fd == fd) {
break;
}
}
if (tmp == NULL) {
Debug_unit(&events_unit, "Could not find fd %d for removal", fd);
return;
}
else {
if (prev != NULL) {
prev->next = tmp->next;
}
else {
fdlist = tmp->next;
}
mem_free(&events_unit, tmp);
}
}