From 1bce2510ca9a2eec20f2a32499f0839b768f7c4a Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20Ko=C5=88a=C5=99?= Date: Wed, 12 Jun 2013 13:54:36 +0200 Subject: [PATCH] tevent: Add tevent tutorial files. Reviewed-by: Andreas Schneider Reviewed-by: Volker Lendecke --- lib/tevent/doc/img/tevent_context_stucture.png | Bin 0 -> 21888 bytes lib/tevent/doc/img/tevent_subrequest.png | Bin 0 -> 22453 bytes lib/tevent/doc/tevent_context.dox | 75 ++++++ lib/tevent/doc/tevent_data.dox | 133 ++++++++++ lib/tevent/doc/tevent_events.dox | 341 +++++++++++++++++++++++++ lib/tevent/doc/tevent_queue.dox | 274 ++++++++++++++++++++ lib/tevent/doc/tevent_request.dox | 191 ++++++++++++++ lib/tevent/doc/tevent_tutorial.dox | 20 ++ 8 files changed, 1034 insertions(+) create mode 100644 lib/tevent/doc/img/tevent_context_stucture.png create mode 100644 lib/tevent/doc/img/tevent_subrequest.png create mode 100644 lib/tevent/doc/tevent_context.dox create mode 100644 lib/tevent/doc/tevent_data.dox create mode 100644 lib/tevent/doc/tevent_events.dox create mode 100644 lib/tevent/doc/tevent_queue.dox create mode 100644 lib/tevent/doc/tevent_request.dox create mode 100644 lib/tevent/doc/tevent_tutorial.dox diff --git a/lib/tevent/doc/img/tevent_context_stucture.png b/lib/tevent/doc/img/tevent_context_stucture.png new file mode 100644 index 0000000000000000000000000000000000000000..fba8161572d5af6b18e266e88cc2eb20ac76c495 GIT binary patch literal 21888 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

D4#Zku>)_NRcz9+uHYB*X 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 P0e>dO=0^Fu>@WQdtoGQ5 literal 0 HcwPel00001 diff --git a/lib/tevent/doc/img/tevent_subrequest.png b/lib/tevent/doc/img/tevent_subrequest.png new file mode 100644 index 0000000000000000000000000000000000000000..ea79223d4dc1f6c524d40b566e9895003ec4df34 GIT binary patch literal 22453 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 belong to talloc library +knowledge but because of the fact that tevent uses the talloc library for its +mechanisms it is necessary to understand a bit talloc as well. For more +information about working with talloc, please visit talloc website where tutorial and +documentation are located. + +Tevent context structure *event_ctx represents the unit which will +further contain information about registered events. It is created via calling +tevent_context_init(). + +@code +TALLOC_CTX *mem_ctx = talloc_new(NULL); +if (mem_ctx == NULL) { + // error handling +} + +struct tevent_context *ev_ctx = tevent_context_init(mem_ctx); +if(ev_ctx == NULL) { + // error handling +} +@endcode + +Tevent context has a structure containing lots of information. It include lists +of all events which are divided according their type and are in order showing +the sequence as they came. + +@image html tevent_context_stucture.png + +In addition to the lists shown in the diagram, the tevent context also contains +many other data (e.g. information about the available system mechanism for +triggering callbacks). + +@section tevent_loops Tevent loops + +Tevent loops are the dispatcher for events. They catch them and trigger the +handlers. In the case of longer processes, the program spends most of its time +at this point waiting for events, invoking handlers and waiting for another +event again. There are 2 types of loop available for use in tevent library: + +

    +
  • int tevent_loop_wait()
  • +
  • int tevent_loop_once()
  • +
+ +Both of functions accept just one parametr (tevent context) and the only +difference lies in the fact that the first loop can theoretically last for ever +but the second one will wait just for a single one event to catch and then the +loop breaks and the program continue. + +*/ diff --git a/lib/tevent/doc/tevent_data.dox b/lib/tevent/doc/tevent_data.dox new file mode 100644 index 00000000000..4ee4ac22667 --- /dev/null +++ b/lib/tevent/doc/tevent_data.dox @@ -0,0 +1,133 @@ +/** +@page tevent_data Chapter 3: Accessing data +@section data Accessing data with tevent + +A tevent request is (usually) created together with a structure for storing the +data necessary for an asynchronous computation. For these private data, tevent +library uses void (generic) pointers, therefore any data type can be very +simply pointed at. However, this attitude requires clear and guaranteed +knowledge of the data type that will be handled, in advance. Private data can +be of 2 types: connected with a request itself or given as an individual +argument to a callback. It is necessary to differentiate these types, because +there is a slightly different method of data access for each. There are two +possibilities how to access data that is given as an argument directly to a +callback. The difference lies in the pointer that is returned. In one case it +is the data type specified in the function’s argument, in another void* is +returned. + +@code +void tevent_req_callback_data (struct tevent_req *req, #type) +void tevent_req_callback_data_void (struct tevent_req *req) +@endcode + + +To obtain data that are strictly bound to a request, this function is the only +direct procedure. + +@code +void *tevent_req_data (struct tevent_req *req, #type) +@endcode + +Example with both calls which differs between private data within tevent +request and data handed over as an argument. + +@code +#include +#include +#include + +struct foo_state { + int x; +}; + +struct testA { + int y; +}; + + +static void foo_done(struct tevent_req *req) { +// a->x contains 9 +struct foo_state *a = tevent_req_data(req, struct foo_state); + +// b->y contains 10 +struct testA *b = tevent_req_callback_data(req, struct testA); + +// c->y contains 10 +struct testA *c = (struct testA *)tevent_req_callback_data_void(req); + +printf("a->x: %d\n", a->x); +printf("b->y: %d\n", b->y); +printf("c->y: %d\n", c->y); +} + + +struct tevent_req * foo_send(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx) { + +printf("_send\n"); +struct tevent_req *req; +struct foo_state *state; + +req = tevent_req_create(event_ctx, &state, struct foo_state); +state->x = 10; + +return req; +} + +static void run(struct tevent_context *ev, struct tevent_timer *te, + struct timeval current_time, void *private_data) { + struct tevent_req *req; + struct testA *tmp = talloc(ev, struct testA); + tmp->y = 9; + req = foo_send(ev, ev); + + tevent_req_set_callback(req, foo_done, tmp); + tevent_req_done(req); + +} + +int main (int argc, char **argv) { + + struct tevent_context *event_ctx; + struct testA *data; + TALLOC_CTX *mem_ctx; + struct tevent_timer *time_event; + + mem_ctx = talloc_new(NULL); //parent + if (mem_ctx == NULL) + return EXIT_FAILURE; + + event_ctx = tevent_context_init(mem_ctx); + if (event_ctx == NULL) + return EXIT_FAILURE; + + data = talloc(mem_ctx, struct testA); + data->y = 10; + + time_event = tevent_add_timer(event_ctx, + mem_ctx, + tevent_timeval_current(), + run, + data); + if (time_event == NULL) { + fprintf(stderr, " FAILED\n"); + return EXIT_FAILURE; + } + + tevent_loop_once(event_ctx); + + talloc_free(mem_ctx); + + printf("Quit\n"); + return EXIT_SUCCESS; +} +@endcode + +Output of this example is: + +@code +a->x: 9 +b->y: 10 +c->y: 10 +@endcode + +*/ diff --git a/lib/tevent/doc/tevent_events.dox b/lib/tevent/doc/tevent_events.dox new file mode 100644 index 00000000000..8e350d2b93e --- /dev/null +++ b/lib/tevent/doc/tevent_events.dox @@ -0,0 +1,341 @@ +/** +@page tevent_events Chapter 2: Tevent events +@section pools Tevent events + +Ok, after reading previous chapter we can start doing something useful. So, the +way of creating events is similar for all types - signals, file descriptors, +time or immediate events. At the beginning it is good to know about some +typedefs which are set in tevent library and which specify the arguments for +each callback. These callbacks are: + +- tevent_timer_handler_t() + +- tevent_immediate_handler_t() + +- tevent_signal_handler_t() + +- tevent_fd_handler_t() + +According their names it is obvious that for creating callback for e.g. time +event, tevent_timer_handler_t will be used. + +The best way how to introduce registering an event and setting up a callback +would be example, so examples describing all the types of events follow. + +@subsection Time Time event + +This example shows how to set up an event which will be repeated for a minute +with interval of 2 seconds (will be triggered 30 times). After exceeding this +limit, the event loop will finish and all the memory resources will be freed. +This is just example describing repeated activity, nothing usefull is done +within foo function + +@code +#include +#include +#include +#include + +struct state { + struct timeval endtime; + int counter; + TALLOC_CTX *ctx; +}; + +static void callback(struct tevent_context *ev, struct tevent_timer *tim, + struct timeval current_time, void *private_data) +{ + struct state *data = talloc_get_type(private_data, struct state); + struct tevent_timer *time_event; + struct timeval schedule; + + printf("Data value: %d\n", data->counter); + data->counter += 1; // increase counter + + // if time has not reached its limit, set another event + if (tevent_timeval_compare(¤t_time, &(data->endtime)) < 0) { + // do something + // set repeat with delay 2 seconds + schedule = tevent_timeval_current_ofs(2, 0); + time_event = tevent_add_timer(ev, data->ctx, schedule, callback, data); + if (time_event == NULL) { // error ... + fprintf(stderr, "MEMORY PROBLEM\n"); + return; + } + } else { + // time limit exceeded + } +} + +int main(void) { + struct tevent_context *event_ctx; + TALLOC_CTX *mem_ctx; + struct tevent_timer *time_event; + struct timeval schedule; + + mem_ctx = talloc_new(NULL); // parent + event_ctx = tevent_context_init(mem_ctx); + + struct state *data = talloc(mem_ctx, struct state); + + schedule = tevent_timeval_current_ofs(2, 0); // +2 second time value + data->endtime = tevent_timeval_add(&schedule, 60, 0); // one minute time limit + data->ctx = mem_ctx; + data->counter = 0; + + // add time event + time_event = tevent_add_timer(event_ctx, mem_ctx, schedule, callback, data); + if (time_event == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + + tevent_loop_wait(event_ctx); + talloc_free(mem_ctx); + return EXIT_SUCCESS; +} +@endcode + +Variable counter is only used for counting the number of triggered +functions. List of all available functions which tevent offers for working with +time are listed +here together +with their description. More detailed view at these functions is unnecessary +because their purpose and usage is quite simple and clear. + +@subsection Immediate Immediate event + +These events are, as their name indicates, activated and performed immediately. +It means that this kind of events have priority over others (except signal +events). So if there is a bulk of events registered and after that a +tevent loop is launched, then all the immediate events will be triggered before +the other events. Except other immediate events (and signal events) because +they are also processed sequentially - according the order they were scheduled. +Signals have the highest priority and therefore they are processed +preferentially. Therefore the expression immediate may not correspond exactly +to the dictionary definition of "something without delay" but rather "as soon +as possible" after all preceding immediate events. + +For creating an immediate event there is a small different which lies in the +fact that the creation of such event is done in 2 steps. One represents the +creation (memory allocation), the second one represents registering as the +event within some tevent context. + +@code +struct tevent_immediate *run(TALLOC_CTX* mem_ctx, + struct tevent_context event_ctx, + void * data) +{ + struct tevent_immediate *im; + + im = tevent_create_immediate(mem_ctx); + if (im == NULL) { + return NULL; + } + tevent_schedule_immediate(im, event_ctx, foo, data); + + return im; +} +@endcode + +Example which may be compiled and run representing the creation of immediate event. + +@code + +#include +#include +#include + +struct info_struct { + int counter; +}; + +static void foo(struct tevent_context *ev, struct tevent_immediate *im, + void *private_data) +{ + struct info_struct *data = talloc_get_type(private_data, struct info_struct); + printf("Data value: %d\n", data->counter); +} + +int main (void) { + struct tevent_context *event_ctx; + TALLOC_CTX *mem_ctx; + struct tevent_immediate *im; + + printf("INIT\n"); + + mem_ctx = talloc_new(NULL); + event_ctx = tevent_context_init(mem_ctx); + + struct info_struct *data = talloc(mem_ctx, struct info_struct); + + // setting up private data + data->counter = 1; + + // first immediate event + im = tevent_create_immediate(mem_ctx); + if (im == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + tevent_schedule_immediate(im, event_ctx, foo, data); + + tevent_loop_wait(event_ctx); + talloc_free(mem_ctx); + + return 0; +} +@endcode + +@subsection Signal Signal event + +This is an alternative to standard C library functions signal() or sigaction(). +The main difference that distinguishes these ways of treating signals is their +setting up of handlers for different time intervals of the running program. + +While standard C library methods for dealing with signals offer sufficient +tools for most cases, they are inadequate for handling signals within the +tevent loop. It could be necessary to finish certain tevent requests within the +tevent loop without interruption. If a signal was sent to a program at a moment +when the tevent loop is in progress, a standard signal handler would not return +processing to the application at the very same place and it would quit the +tevent loop for ever. In such cases, tevent signal handlers offer the +possibility of dealing with these signals by masking them from the rest of +application and not quitting the loop, so the other events can still be +processed. + +Tevent offers also a control function, which enables us to verify whether it is +possible to handle signals via tevent, is defined within tevent library and it +returns a boolean value revealing the result of the verification. + +@code +bool tevent_signal_support (struct tevent_context *ev) +@endcode + +Checking for signal support is not necessary, but if it is not guaranteed, this +is a good and easy control to prevent unexpected behaviour or failure of the +program occurring. Such a test of course does not have to be run every single +time you wish to create a signal handler, but simply at the beginning - during +the initialization procedures of the program. Afterthat, simply adapt to each +situation that arises. + +@code + +#include +#include +#include + +static void handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + + // Do something usefull + + printf("handling signal...\n"); + exit(EXIT_SUCCESS); +} + +int main (void) +{ + struct tevent_context *event_ctx; + TALLOC_CTX *mem_ctx; + struct tevent_signal *sig; + + mem_ctx = talloc_new(NULL); //parent + if (mem_ctx == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + + event_ctx = tevent_context_init(mem_ctx); + if (event_ctx == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + + if (tevent_signal_support(event_ctx)) { + // create signal event + sig = tevent_add_signal(event_ctx, mem_ctx, SIGINT, 0, handler, NULL); + if (sig == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + tevent_loop_wait(event_ctx); + } + + talloc_free(mem_ctx); + return EXIT_SUCCESS; +} +@endcode + + +@subsection File File descriptor event + +Support of events on file descriptors is mainly useful for socket communication +but it certainly works flawlessly with standard streams (stdin, stdout, stderr) + as well. Working asynchronously with file descriptors enables switching + within processing I/O operations. This ability may rise with a greater + number of I/O operations and such overlapping leads to enhancement of the + throughput. + +There are several other functions included in tevent API related to handling +file descriptors (there are too many functions defined within tevent therefore +just some of them are fully described within this thesis. The +declaration of the rest can be easily found on the library’s website or +directly from the source code): + +
    +
  • tevent_fd_set_close_fn() - can add another function to be called at the + moment when a structure tevent fd is freed.
  • +
  • tevent_fd_set_auto_close() - calling this function can simplify the + maintenance of file descriptors, because it instructs tevent to close the + appropriate file descriptor when the tevent fd structure is about to be + freed.
  • +
  • tevent_fd_get_flags() - returns flags which are set on the file descriptor + connected with this tevent fd structure.
  • +
  • tevent_fd_set_flags() - sets specified flags on the event’s file + descriptor.
  • +
+ +@code + +static void close_fd(struct tevent_context *ev, struct tevent_fd *fd_event, + int fd, void *private_data) +{ + // processing when fd_event is freed +} + +struct static void handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + // handling event; reading from a file descriptor + tevent_fd_set_close_fn (fd_event, close_fd); +} + +int run(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx, + int fd, uint16_t flags, char *buffer) +{ + struct tevent_fd* fd_event = NULL; + + if (flags & TEVENT_FD_READ) { + fd_event = tevent_add_fd(event_ctx, + mem_ctx, + fd, + flags, + handler, + buffer); + } + if (fd_event == NULL) { + // error handling + } + return tevent_loop_once(); +} +@endcode + +*/ diff --git a/lib/tevent/doc/tevent_queue.dox b/lib/tevent/doc/tevent_queue.dox new file mode 100644 index 00000000000..fef98c81e06 --- /dev/null +++ b/lib/tevent/doc/tevent_queue.dox @@ -0,0 +1,274 @@ +/** +@page tevent_queue Chapter 5: Tevent queue +@section queue Tevent queue + +There is a possibility that the dispatcher and its handlers may not be able to +handle all the incoming events as quickly as they arrive. One way to deal with +this situation is to buffer the received events by introducing an event queue +into the events stream, between the events generator and the dispatcher. Events +are added to the queue as they arrive, and the dispatcher pops them off the +beginning of the queue as fast as possible. In tevent library it is +similar, but the queue is not automatically set for any event. The queue has to +be created on purpose, and events which should follow the order of the FIFO +queue have to be explicitly pinpointed. Creating such a queue is crucial in +situations when sequential processing is absolutely essential for the succesful +completion of a task, e.g. for a large quantity of data that are about to be +written from a buffer into a socket. The tevent library has its own queue +structure that is ready to use after it has been initialized and started up +once. + +@subsection cr_queue Creation of Queues + +The first and most important step is the creation of the tevent queue +(represented by struct tevent queue), which will then be in running mode. + +@code +struct tevent_queue* tevent_queue_create (TALLOC_CTX *mem_ctx, const char *name) +@endcode + +When the program returns from this function, the allocated memory, set +destructor and labeled queue as running has been done and the structure is +ready to be filled with entries. Stopping and starting queues on the run. If +you need to stop a queue from processing its entries, and then turn it on +again, a couple of functions which serve this purpose are: + +- bool tevent_queue_stop() +- bool tevent_queue_start() + +These functions actually only provide for the simple setting of a variable, +which indicates that the queue has been stopped/started. Returned value +indicates result. + +@subsection add_queue Adding Requests to a Queue + +Tevent in fact offers 3 possible ways of inserting a request into a queue. +There are no vast differences between them, but still there might be situations +where one of them is more suitable and desired than another. + +@code +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +@endcode + +This call is the simplest of all three. It offers only boolean verification of +whether the operation of adding the request into a queue was successful or not. +No additional deletion of an item from the queue is possible, i.e. it is only +possible to deallocate the whole tevent request, which would cause triggering +of destructor handling and also dropping the request from the queue. + +Extended Options + +Both of the following functions have a feature in common - they return tevent +queue entry structure representing the item in a queue. There is no further +possible handling with this structure except the use of the structure’s pointer +for its deallocation (which leads also its removal from the queue). The +difference lies in the possibility that with the following functions it is +possible to remove the tevent request from a queue without its deallocation. +The previous function can only deallocate the tevent request as it was from +memory, and thereby logically cause its removal from the queue as well. There +is no other utilization of this structure via API at this stage of tevent +library. The possibility of easier debugging while developing with tevent could +be considered to be an advantage of this returned pointer. + +@code +struct tevent_queue_entry *tevent_queue_add_entry(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +@endcode + +The feature that allows for the optimized addition of entries to a queue is +that a check for an empty queue with no items is first of all carried out. If +it is found that the queue is empty, then the request for inserting the entry +into a queue will be omitted and directly triggered. + +@code +struct tevent_queue_entry *tevent_queue_add_optimize_empty(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +@endcode + +When calling any of the functions serving for inserting an item into a queue, +it is possible to leave out the fourth argument (trigger) and instead of a +function pass a NULL pointer. This usage sets so-called blocking entries. +These entries, since they do not have any trigger operation to be activated, +just sit in their position until they are labeled as a done by another +function. Their purpose is to block other items in the queue from being +triggered. + +@subsection example_q Example of tevent queue + +@code +#include +#include +#include + +struct foo_state { + int local_var; + int x; +}; + +struct juststruct { + TALLOC_CTX * ctx; + struct tevent_context *ev; + int y; +}; + +int created = 0; + +static void timer_handler(struct tevent_context *ev, struct tevent_timer *te, + struct timeval current_time, void *private_data) +{ + // time event which after all sets request as done. Following item from + // the queue may be invoked. + struct tevent_req *req = private_data; + struct foo_state *stateX = tevent_req_data(req, struct foo_state); + + // processing some stuff + + printf("time_handler\n"); + + tevent_req_done(req); + talloc_free(req); + + printf("Request #%d set as done.\n", stateX->x); +} + +static void trigger(struct tevent_req *req, void *private_data) +{ + struct juststruct *priv = tevent_req_callback_data (req, struct juststruct); + struct foo_state *in = tevent_req_data(req, struct foo_state); + struct timeval schedule; + struct tevent_timer *tim; + schedule = tevent_timeval_current_ofs(1, 0); + printf("Processing request #%d\n", in->x); + + if (in->x % 3 == 0) { // just example; third request does not contain + // any further operation and will be finished right + // away. + tim = NULL; + } else { + tim = tevent_add_timer(priv->ev, req, schedule, timer_handler, req); + } + + if (tim == NULL) { + tevent_req_done(req); + talloc_free(req); + printf("Request #%d set as done.\n", in->x); + } +} + +struct tevent_req *foo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, + const char *name, int num) +{ + struct tevent_req *req; + struct foo_state *state; + struct foo_state *in; + struct tevent_timer *tim; + + printf("foo_send\n"); + req = tevent_req_create(mem_ctx, &state, struct foo_state); + if (req == NULL) { // check for appropriate allocation + tevent_req_error(req, 1); + return NULL; + } + + // exemplary filling of variables + state->local_var = 1; + state->x = num; + + return req; +} + +static void foo_done(struct tevent_req *req) { + + enum tevent_req_state state; + uint64_t err; + + if (tevent_req_is_error(req, &state, &err)) { + printf("ERROR WAS SET %d\n", state); + return; + } else { + // processing some stuff + printf("Callback is done...\n"); + } +} + +int main (int argc, char **argv) +{ + TALLOC_CTX *mem_ctx; + struct tevent_req* req[6]; + struct tevent_req* tmp; + struct tevent_context *ev; + struct tevent_queue *fronta = NULL; + struct juststruct *data; + int ret; + int i = 0; + + const char * const names[] = { + "first", "second", "third", "fourth", "fifth" + }; + + printf("INIT\n"); + + mem_ctx = talloc_new(NULL); //parent + talloc_parent(mem_ctx); + ev = tevent_context_init(mem_ctx); + if (ev == NULL) { + fprintf(stderr, "MEMORY ERROR\n"); + return EXIT_FAILURE; + } + + // setting up queue + fronta = tevent_queue_create(mem_ctx, "test_queue"); + tevent_queue_stop(fronta); + tevent_queue_start(fronta); + if (tevent_queue_running(fronta)) { + printf ("Queue is runnning (length: %d)\n", tevent_queue_length(fronta)); + } else { + printf ("Queue is not runnning\n"); + } + + data = talloc(ev, struct juststruct); + data->ctx = mem_ctx; + data->ev = ev; + + + // create 4 requests + for (i = 1; i < 5; i++) { + req[i] = foo_send(mem_ctx, ev, names[i], i); + tmp = req[i]; + if (req[i] == NULL) { + fprintf(stderr, "Request error! %d \n", ret); + break; + } + tevent_req_set_callback(req[i], foo_done, data); + created++; + } + + // add item to a queue + tevent_queue_add(fronta, ev, req[1], trigger, data); + tevent_queue_add(fronta, ev, req[2], trigger, data); + tevent_queue_add(fronta, ev, req[3], trigger, data); + tevent_queue_add(fronta, ev, req[4], trigger, data); + + printf("Queue length: %d\n", tevent_queue_length(fronta)); + while(tevent_queue_length(fronta) > 0) { + tevent_loop_once(ev); + printf("Queue: %d items left\n", tevent_queue_length(fronta)); + } + + talloc_free(mem_ctx); + printf("FINISH\n"); + + return EXIT_SUCCESS; +} +@endcode + +*/ diff --git a/lib/tevent/doc/tevent_request.dox b/lib/tevent/doc/tevent_request.dox new file mode 100644 index 00000000000..14613846a8e --- /dev/null +++ b/lib/tevent/doc/tevent_request.dox @@ -0,0 +1,191 @@ +/** +@page tevent_request Chapter 4: Tevent request +@section request Tevent requst + +A specific feature of the library is the tevent request API that provides for +asynchronous computation and allows much more interconnected working and +cooperation among func- tions and events. When working with tevent request it +is possible to nest one event under another and handle them bit by bit. This +enables the creation of sequences of steps, and provides an opportunity to +prepare for all problems which may unexpectedly happen within the different +phases. One way or another, subrequests split bigger tasks into smaller ones +which allow a clearer view of each task as a whole. + +@subsection name Naming conventions + +There is a naming convention which is not obligatory but it is followed in this +tutorial: + +- Functions triggered before the event happens. These establish a request. +- \b foo_send(...) - this function is called first and it includes the + creation of tevent request - tevent req structure. It does not block + anything, it simply creates a request, sets a callback (foo done) and lets + the program continue +- Functions as a result of event. +- \b foo_done(...) - this function contains code providing for handling itself + and based upon its results, the request is set either as a done or, if an + error occurs, the request is set as a failure. +- \b foo_recv(...) - this function contains code which should, if demanded, + access the result data and make them further visible. The foo state should + be deallocated from memory when the request’s processing is over and + therefore all computed data up to this point would be lost. + +As was already mentioned, specific naming subsumes not only functions but also +the data themselves: + +- \b foo_state - this is a structure. It contains all the data necessary for + the asynchronous task. + +@subsection cr_req Creating a New Asynchronous Request + +The first step for working asynchronously is the allocation of memory +requirements. As in previous cases, the talloc context is required, upon which +the asynchronous request will be tied. The next step is the creation of the +request itself. + +@code +struct tevent_req* tevent_req_create (TALLOC_CTX *mem_ctx, void **pstate, #type) +@endcode + +The pstate is the pointer to the private data. The necessary amount of memory +(based on data type) is allocated during this call. Within this same memory +area all the data from the asynchronous request that need to be preserved for +some time should be kept. + +Dealing with a lack of memory + +The verification of the returned pointer against NULL is necessary in order to +identify a potential lack of memory. There is a special function which helps +with this check tevent_req_nomem(). + +It handles verification both of the talloc memory allocation and of the +associated tevent request, and is therefore a very useful function for avoiding +unexpected situations. It can easily be used when checking the availability of +further memory resources that are required for a tevent request. Imagine an +example where additional memory needs arise although no memory resources are +currently available. + +@code +bar = talloc(mem_ctx, struct foo); +if(tevent_req_nomem (bar, req)) { + // handling a problem +} +@endcode + +This code ensures that the variable bar, which contains NULL as a result of the +unsuccessful satisfaction of its memory requirements, is noticed, and also that +the tevent request req declares it exceeds memory capacity, which implies the +impossibility of finishing the request as originally programmed. + + +@subsection fini_req Finishing a Request + +Marking each request as finished is an essential principle of the tevent +library. Without marking the request as completed - either successfully or with +an error - the tevent loop could not let the appropriate callback be triggered. +It is important to understand that this would be a significant threat, because +it is not usually a question of one single function which prints some text on a +screen, but rather the request is itself probably just a link in a series of +other requests. Stopping one request would stop the others, memory resources +would not be freed, file descriptors might remain open, communication via +socket could be interrupted, and so on. Therefore it is important to think +about finishing requests, either successfully or not, and also to prepare +functions for all possible scenarios, so that the the callbacks do not process +data that are actually invalid or, even worse, in fact non-existent meaning +that a segmentation fault may arise. + +
    +
  • \b Manually - This is the most common type of finishing request. Calling +this function sets the request as a TEVENT_REQ_DONE. This is the only purpose +of this function and it should be used when everything went well. Typically it +is used within the done functions. + +@code +void tevent_req_done (struct tevent_req *req) +@endcode +Alternatively, the request can end up being unsuccessful. +@code +bool tevent_req_error (struct tevent_req *req, uint64_t error) +@endcode + +The second argument takes the number of an error (declared by the programmer, +for example in an enumerated variable). The function tevent_req_error() sets +the status of the request as a TEVENT_REQ_USER_ERROR and also stores the code +of error within the structure so it can be used, for example for debugging. The +function returns true, if marking the request as an error was processed with no +problem - value error passed to this function is not equal to 1.
  • + +
  • +Setting up a timeout for request - A request can be finished virtually, +or if the process takes too much time, it can be timed out. This is considered +as an error of the request and it leads to calling callback. In the +background, this timeout is set through a time event (described in +@subpage tevent_events ) which eventually triggers an operation marking the +request as a TEVENT_REQ_TIMED_OUT (can not be considered as successfully +finished). In case a time out was already set, this operation will overwrite it +with a new time value (so the timeout may be lengthened) and if everything is +set properly, it returns true. + +@code +bool tevent_req_set_endtime(struct tevent_req *req, + struct tevent_context *ev, + struct timeval endtime); +@endcode +
  • + + +
  • Premature Triggering - Imagine a situation in which some part of a +nested subrequest ended up with a failure and it is still required to trigger a +callback. Such as example might result from lack of memory leading to the +impossibility of allocating enough memory requirements for the event to start +processing another subrequest, or from a clear intention to skip other +procedures and trigger the callback regardless of other progress. In these +cases, the function tevent_req_post() is very handy and offers this option. + +@code +struct tevent_req* tevent_req_post (struct tevent_req *req, + struct tevent_context *ev); +@endcode + +A request finished in this way does not behave as a time event nor as a file +descriptor event but as a immediately scheduled event, and therefore it will be +treated according the description laid down in @subpage tevent_events . +
  • +
+ + +@section nested Subrequests - Nested Requests + +To create more complex and interconnected asynchronous operations, it is +possible to submerge a request into another and thus create a so-called +subrequest. Subrequests are not represented by any other special structure but +they are created from tevent_req_create(). This diagram shows the nesting and +life time of each request. The table below describes the same in words, and +shows the triggering of functions during the application run. + +Wrapper represents the trigger of the whole cascade of (sub)requests. It +may be e.g. a time or file descriptor event, or another request that was +created at a specific time by the function tevent_wakeup_send() which is a +slightly exceptional method of creating + +@code +struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct timeval wakeup_time); +@endcode + +By calling this function, it is possible to create a tevent request which is +actually the return value of this function. In summary, it sets the time value +of the tevent request’s creation. While using this function it is necessary to +use another function in the subrequest’s callback to check for any problems +tevent_wakeup_recv() ) + +@image html tevent_subrequest.png + +Comprehensive example containing features from this chapter is especially by +reason of nested subrequests very long and therefore it is located as an +example on the attached CD. Description and explanation is placed within the +source code itself (subrequest.c) and enclosed file README. The example is +available here. + +*/ diff --git a/lib/tevent/doc/tevent_tutorial.dox b/lib/tevent/doc/tevent_tutorial.dox new file mode 100644 index 00000000000..9f01fa1062f --- /dev/null +++ b/lib/tevent/doc/tevent_tutorial.dox @@ -0,0 +1,20 @@ +/** +@page tevent_tutorial The Tutorial + +@section tevent_tutorial_introduction Introduction + +Tutorial describing working with tevent library. + +@section tevent_tutorial_toc Table of contents + +@subpage tevent_context + +@subpage tevent_events + +@subpage tevent_data + +@subpage tevent_request + +@subpage tevent_queue + +*/ -- 2.11.4.GIT