mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +00:00
da8a23277e
All the 'dump something' CLI commands now have a new mandatory argument -- name of the file where to dump the data. This allows for more flexible dumping even for production deployments where the debug output is by default off. Also the dump commands are now restricted (they weren't before) to assure that only the appropriate users can run these time consuming commands.
202 lines
4.2 KiB
C
202 lines
4.2 KiB
C
/*
|
|
* BIRD Library -- Event Processing
|
|
*
|
|
* (c) 1999 Martin Mares <mj@ucw.cz>
|
|
*
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
*/
|
|
|
|
/**
|
|
* DOC: Events
|
|
*
|
|
* Events are there to keep track of deferred execution.
|
|
* Since BIRD is single-threaded, it requires long lasting tasks to be split to smaller
|
|
* parts, so that no module can monopolize the CPU. To split such a task, just create
|
|
* an &event resource, point it to the function you want to have called and call ev_schedule()
|
|
* to ask the core to run the event when nothing more important requires attention.
|
|
*
|
|
* You can also define your own event lists (the &event_list structure), enqueue your
|
|
* events in them and explicitly ask to run them.
|
|
*/
|
|
|
|
#include "nest/bird.h"
|
|
#include "lib/event.h"
|
|
|
|
event_list global_event_list;
|
|
event_list global_work_list;
|
|
|
|
inline void
|
|
ev_postpone(event *e)
|
|
{
|
|
if (ev_active(e))
|
|
{
|
|
rem_node(&e->n);
|
|
e->n.next = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
ev_dump(struct dump_request *dreq, resource *r)
|
|
{
|
|
event *e = (event *) r;
|
|
|
|
RDUMP("(code %p, data %p, %s)\n",
|
|
e->hook,
|
|
e->data,
|
|
e->n.next ? "scheduled" : "inactive");
|
|
}
|
|
|
|
static struct resclass ev_class = {
|
|
"Event",
|
|
sizeof(event),
|
|
(void (*)(resource *)) ev_postpone,
|
|
ev_dump,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
/**
|
|
* ev_new - create a new event
|
|
* @p: resource pool
|
|
*
|
|
* This function creates a new event resource. To use it,
|
|
* you need to fill the structure fields and call ev_schedule().
|
|
*/
|
|
event *
|
|
ev_new(pool *p)
|
|
{
|
|
event *e = ralloc(p, &ev_class);
|
|
return e;
|
|
}
|
|
|
|
/**
|
|
* ev_run - run an event
|
|
* @e: an event
|
|
*
|
|
* This function explicitly runs the event @e (calls its hook
|
|
* function) and removes it from an event list if it's linked to any.
|
|
*
|
|
* From the hook function, you can call ev_enqueue() or ev_schedule()
|
|
* to re-add the event.
|
|
*/
|
|
inline void
|
|
ev_run(event *e)
|
|
{
|
|
ev_postpone(e);
|
|
e->hook(e->data);
|
|
}
|
|
|
|
/**
|
|
* ev_enqueue - enqueue an event
|
|
* @l: an event list
|
|
* @e: an event
|
|
*
|
|
* ev_enqueue() stores the event @e to the specified event
|
|
* list @l which can be run by calling ev_run_list().
|
|
*/
|
|
inline void
|
|
ev_enqueue(event_list *l, event *e)
|
|
{
|
|
ev_postpone(e);
|
|
add_tail(l, &e->n);
|
|
}
|
|
|
|
/**
|
|
* ev_schedule - schedule an event
|
|
* @e: an event
|
|
*
|
|
* This function schedules an event by enqueueing it to a system-wide
|
|
* event list which is run by the platform dependent code whenever
|
|
* appropriate.
|
|
*/
|
|
void
|
|
ev_schedule(event *e)
|
|
{
|
|
ev_enqueue(&global_event_list, e);
|
|
}
|
|
|
|
/**
|
|
* ev_schedule_work - schedule a work-event.
|
|
* @e: an event
|
|
*
|
|
* This function schedules an event by enqueueing it to a system-wide work-event
|
|
* list which is run by the platform dependent code whenever appropriate. This
|
|
* is designated for work-events instead of regular events. They are executed
|
|
* less often in order to not clog I/O loop.
|
|
*/
|
|
void
|
|
ev_schedule_work(event *e)
|
|
{
|
|
if (!ev_active(e))
|
|
add_tail(&global_work_list, &e->n);
|
|
}
|
|
|
|
void io_log_event(void *hook, void *data);
|
|
|
|
/**
|
|
* ev_run_list - run an event list
|
|
* @l: an event list
|
|
*
|
|
* This function calls ev_run() for all events enqueued in the list @l.
|
|
*/
|
|
int
|
|
ev_run_list(event_list *l)
|
|
{
|
|
node *n;
|
|
list tmp_list;
|
|
|
|
init_list(&tmp_list);
|
|
add_tail_list(&tmp_list, l);
|
|
init_list(l);
|
|
WALK_LIST_FIRST(n, tmp_list)
|
|
{
|
|
event *e = SKIP_BACK(event, n, n);
|
|
|
|
/* This is ugly hack, we want to log just events executed from the main I/O loop */
|
|
if ((l == &global_event_list) || (l == &global_work_list))
|
|
io_log_event(e->hook, e->data);
|
|
|
|
ev_run(e);
|
|
tmp_flush();
|
|
}
|
|
|
|
return !EMPTY_LIST(*l);
|
|
}
|
|
|
|
int
|
|
ev_run_list_limited(event_list *l, uint limit)
|
|
{
|
|
node *n;
|
|
list tmp_list;
|
|
|
|
init_list(&tmp_list);
|
|
add_tail_list(&tmp_list, l);
|
|
init_list(l);
|
|
|
|
WALK_LIST_FIRST(n, tmp_list)
|
|
{
|
|
event *e = SKIP_BACK(event, n, n);
|
|
|
|
if (!limit)
|
|
break;
|
|
|
|
/* This is ugly hack, we want to log just events executed from the main I/O loop */
|
|
if ((l == &global_event_list) || (l == &global_work_list))
|
|
io_log_event(e->hook, e->data);
|
|
|
|
ev_run(e);
|
|
tmp_flush();
|
|
limit--;
|
|
}
|
|
|
|
if (!EMPTY_LIST(tmp_list))
|
|
{
|
|
/* Attach new items after the unprocessed old items */
|
|
add_tail_list(&tmp_list, l);
|
|
init_list(l);
|
|
add_tail_list(l, &tmp_list);
|
|
}
|
|
|
|
return !EMPTY_LIST(*l);
|
|
}
|