tevent_thread_call_depth - Man Page
The tevent call depth tracking functions
Synopsis
Topics
The tevent queue functions
Functions
void tevent_thread_call_depth_set_callback (tevent_call_depth_callback_t f, void *private_data)
Register callback function for request/subrequest call depth / flow tracking.
void tevent_thread_call_depth_reset_from_req (struct tevent_req *req)
Reset the external call depth to the call depth of the request.
Detailed Description
The call depth tracking consists of two parts.
Part 1 - storing the depth inside each tevent request.
Each instance of 'struct tevent_req' internally stores the value of the current depth. If a new subrequest is created via tevent_req_create(), the newly created subrequest gets the value from the parent incremented by 1.
Part 2 - updating external variable with the call depth of the currently processed tevent request.
The intended use of call depth is for the trace indentation. This is done by registering the address of an external size_t variable via tevent_thread_call_depth_activate(). And the tracing code just reads it's value.
The updates happen during:
tevent_req_create()
- external variable is set to the value of the newly created request (i.e. value of the parent incremented by 1)
tevent_req_notify_callback()
- external variable is set to the value of the parent tevent request, which is just about to be processed
tevent_queue_immediate_trigger()
- external variable is set to the value of the request coming from the queue
While 'Part 1' maintains the call depth value inside each teven request precisely, the value of the external variable depends on the call flow and can be changed after return from a function call, so it no longer matches the value of the request being processed in the current function.
struct tevent_req *foo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev) { struct tevent_req *req, *subreq; struct foo_state *state; // External variable has value 'X', which is the value in parent code // It is ok, since tracing starts often only after tevent_req_create() req = tevent_req_create(mem_ctx, &state, struct foo_state); // External variable has now value 'X + 1' D_DEBUG("foo_send(): the external variable has the expected value\n"); subreq = bar_send(state, ev, ...); tevent_req_set_callback(subreq, foo_done, req); // External variable has value 'X + 1 + n', where n > 0 and n is the // depth reached in bar_send(). // We want to reset it via tevent_thread_call_depth_reset_from_req(), // since we want the following D_DEBUG() to have the right trace //indentation. tevent_thread_call_depth_reset_from_req(req); // External variable has again value 'X + 1' taken from req. D_DEBUG("foo_send(): the external variable has the expected value\n"); return req; } static void foo_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct foo_state *state = tevent_req_data(req, struct foo_state); // external variable has value 'X + 1' D_DEBUG("foo_done(): the external variable has the expected value\n"); status = bar_recv(subreq, state, ...) tevent_req_done(req); } NTSTATUS foo_recv(struct tevent_req *req) { struct foo_state *state = tevent_req_data( req, struct foo_state); // external variable has value 'X' (not 'X + 1') // which is ok, if we consider _recv() to be an access function // called from the parent context D_DEBUG("foo_recv(): external variable has the value from parent\n"); return NT_STATUS_OK; }
Interface has 3 parts:
Part 1: activation/deactivation
void tevent_thread_call_depth_set_callback(f, private_data) Register a callback that can track 'call depth' and 'request flow' NULL as a function callback means deactivation.
Part 2: Mark the request (and its subrequests) to be tracked
tevent_thread_call_depth_start(struct tevent_req *req)
By default, all newly created requests have call depth set to 0. tevent_thread_call_depth_start() should be called shortly after tevent_req_create(). It sets the call depth to 1. Subrequest will have call depth 2 and so on.
Part 3: reset the external variable using value from tevent request
tevent_thread_call_depth_reset_from_req(struct tevent_req *req)
If the call depth is used for trace indentation, it might be useful to reset the external variable to the call depth of currently processed tevent request, since the ext. variable can be changed after return from a function call that has created subrequests.
THREADING
The state is thread specific, i.e. each thread can activate it and register its own external variable.
Function Documentation
void tevent_thread_call_depth_reset_from_req (struct tevent_req * req)
Reset the external call depth to the call depth of the request.
- Parameters
req Request from which the call depth is reset. variable.
void tevent_thread_call_depth_set_callback (tevent_call_depth_callback_t f, void * private_data)
Register callback function for request/subrequest call depth / flow tracking.
- Parameters
f External call depth and flow handling function
Author
Generated automatically by Doxygen for tevent from the source code.