From 4263983cad2d9e3f0f536a3aa41352552ffa5ef8 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 14 Jan 2010 14:41:49 +0100 Subject: tevent: Added basic doxygen documentation. --- lib/tevent/doc/mainpage.dox | 42 +++++ lib/tevent/tevent.h | 390 ++++++++++++++++++++++++++++++++++++++++++-- lib/tevent/tevent_req.c | 184 +-------------------- 3 files changed, 426 insertions(+), 190 deletions(-) create mode 100644 lib/tevent/doc/mainpage.dox diff --git a/lib/tevent/doc/mainpage.dox b/lib/tevent/doc/mainpage.dox new file mode 100644 index 0000000000..5cd3969c78 --- /dev/null +++ b/lib/tevent/doc/mainpage.dox @@ -0,0 +1,42 @@ +/** + * @mainpage + * + * Tevent is an event system based on the talloc memory management library. It + * is the core event system used in Samba. + * + * The low level tevent has support for many event types, including timers, + * signals, and the classic file descriptor events. + * + * Tevent also provide helpers to deal with asynchronous code providing the + * tevent_req (tevent tequest) functions. + * + * @section tevent_download Download + * + * You can download the latest releases of tevent from the + * tevent directory + * on the samba public source archive. + * + * @section tevent_bugs Discussion and bug reports + * + * tevent does not currently have its own mailing list or bug tracking system. + * For now, please use the + * samba-technical + * mailing list, and the + * Samba bugzilla + * bug tracking system. + * + * @section tevent_devel Development + * You can download the latest code either via git or rsync. + * + * To fetch via git see the following guide: + * + * Using Git for Samba Development + * + * Once you have cloned the tree switch to the master branch and cd into the + * lib/tevent directory. + * + * To fetch via rsync use this command: + * + * rsync -Pavz samba.org::ftp/unpacked/standalone_projects/lib/tevent . + * + */ diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index ad1f2c9cc3..edddcdf1d5 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -40,6 +40,16 @@ struct tevent_timer; struct tevent_immediate; struct tevent_signal; +/** + * @defgroup tevent The tevent API + * + * The tevent low-level API + * + * @todo description + * + * @{ + */ + /* event handler types */ typedef void (*tevent_fd_handler_t)(struct tevent_context *ev, struct tevent_fd *fde, @@ -63,11 +73,86 @@ typedef void (*tevent_signal_handler_t)(struct tevent_context *ev, void *siginfo, void *private_data); +/** + * @brief Create a event_context structure. + * + * This must be the first events call, and all subsequent calls pass this + * event_context as the first element. Event handlers also receive this as + * their first argument. + * + * @param[in] mem_ctx The memory context to use. + * + * @return An allocated tevent context, NULL on error. + * + * @see tevent_context_init() + */ struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx); + +/** + * @brief Create a event_context structure and name it. + * + * This must be the first events call, and all subsequent calls pass this + * event_context as the first element. Event handlers also receive this as + * their first argument. + * + * @param[in] mem_ctx The memory context to use. + * + * @param[in] name The name for the tevent context. + * + * @return An allocated tevent context, NULL on error. + */ struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx, const char *name); + +/** + * @brief List available backends. + * + * @param[in] mem_ctx The memory context to use. + * + * @return A string vector with a terminating NULL element, NULL + * on error. + */ const char **tevent_backend_list(TALLOC_CTX *mem_ctx); + +/** + * @brief Set the default tevent backent. + * + * @param[in] backend The name of the backend to set. + */ void tevent_set_default_backend(const char *backend); +#if DOXYGEN +/** + * @brief Add a file descriptor based event. + * + * If flags contains TEVENT_FD_AUTOCLOSE then the fd will be closed when + * the returned fd_event context is freed. + * + * @param[in] ev The event context to work on. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] fd The file descriptor to base the event on. + * + * @param[in] flags + * + * @param[in] handler The callback handler for the event. + * + * @param[in] private_data The private data passed to the callback handler. + * + * @param[in] handler_name The name to identify the callback handler. + * + * @return The file descriptor based event, NULL on error. + * + * @todo Document flags + */ +struct tevent_fd *tevent_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, + uint16_t flags, + tevent_fd_handler_t handler, + void *private_data, + const char *handler_name); +#else struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, int fd, @@ -79,6 +164,7 @@ struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, #define tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data) \ _tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data, \ #handler, __location__) +#endif struct tevent_timer *_tevent_add_timer(struct tevent_context *ev, TALLOC_CTX *mem_ctx, @@ -150,7 +236,9 @@ void tevent_set_abort_fn(void (*abort_fn)(const char *reason)); #define TEVENT_FD_NOT_READABLE(fde) \ tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) & ~TEVENT_FD_READ) -/* DEBUG */ +/** + * Debug level of tevent + */ enum tevent_debug_level { TEVENT_DEBUG_FATAL, TEVENT_DEBUG_ERROR, @@ -166,6 +254,28 @@ int tevent_set_debug(struct tevent_context *ev, void *context); int tevent_set_debug_stderr(struct tevent_context *ev); +/** + * @} + */ + +/** + * @defgroup tevent_request The tevent request functions. + * @ingroup tevent + * + * This represents an async request being processed by callbacks via an event + * context. A user can issue for example a write request to a socket, giving + * an implementation function the fd, the buffer and the number of bytes to + * transfer. The function issuing the request will immediately return without + * blocking most likely without having sent anything. The API user then fills + * in req->async.fn and req->async.private_data, functions that are called + * when the request is finished. + * + * It is up to the user of the async request to talloc_free it after it has + * finished. This can happen while the completion function is called. + * + * @{ + */ + /** * An async request moves between the following 4 states: */ @@ -202,50 +312,132 @@ enum tevent_req_state { /** * @brief An async request - * - * This represents an async request being processed by callbacks via an event - * context. A user can issue for example a write request to a socket, giving - * an implementation function the fd, the buffer and the number of bytes to - * transfer. The function issuing the request will immediately return without - * blocking most likely without having sent anything. The API user then fills - * in req->async.fn and req->async.private_data, functions that are called - * when the request is finished. - * - * It is up to the user of the async request to talloc_free it after it has - * finished. This can happen while the completion function is called. */ - struct tevent_req; typedef void (*tevent_req_fn)(struct tevent_req *); void tevent_req_set_callback(struct tevent_req *req, tevent_req_fn fn, void *pvt); -void *_tevent_req_callback_data(struct tevent_req *req); -void *_tevent_req_data(struct tevent_req *req); +void *_tevent_req_callback_data(struct tevent_req *req); #define tevent_req_callback_data(_req, _type) \ talloc_get_type_abort(_tevent_req_callback_data(_req), _type) + #define tevent_req_callback_data_void(_req) \ _tevent_req_callback_data(_req) + +void *_tevent_req_data(struct tevent_req *req); #define tevent_req_data(_req, _type) \ talloc_get_type_abort(_tevent_req_data(_req), _type) typedef char *(*tevent_req_print_fn)(struct tevent_req *, TALLOC_CTX *); +/** + * @brief This function sets a print function for the given request. + * + * This function can be used to setup a print function for the given request. + * This will be triggered if the tevent_req_print() function was + * called on the given request. + * + * @param[in] req The request to use. + * + * @param[in] fn A pointer to the print function + * + * @note This function should only be used for debugging. + */ void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn); +/** + * @brief The default print function for creating debug messages. + * + * The function should not be used by users of the async API, + * but custom print function can use it and append custom text + * to the string. + * + * @param[in] req The request to be printed. + * + * @param[in] mem_ctx The memory context for the result. + * + * @return Text representation of request. + * + */ char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx); +/** + * @brief Print an tevent_req structure in debug messages. + * + * This function should be used by callers of the async API. + * + * @param[in] mem_ctx The memory context for the result. + * + * @param[in] req The request to be printed. + * + * @return Text representation of request. + */ char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req); typedef bool (*tevent_req_cancel_fn)(struct tevent_req *); +/** + * @brief This function sets a cancel function for the given tevent request. + * + * This function can be used to setup a cancel function for the given request. + * This will be triggered if the tevent_req_cancel() function was + * called on the given request. + * + * @param[in] req The request to use. + * + * @param[in] fn A pointer to the cancel function. + */ void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn); +#ifdef DOXYGEN +/** + * @brief Try to cancel the given tevent request. + * + * This function can be used to cancel the given request. + * + * It is only possible to cancel a request when the implementation + * has registered a cancel function via the tevent_req_set_cancel_fn(). + * + * @param[in] req The request to use. + * + * @return This function returns true is the request is cancelable, + * othererwise false is returned. + * + * @note Even if the function returns true, the caller need to wait + * for the function to complete normally. + * Only the _recv() function of the given request indicates + * if the request was really canceled. + */ +bool tevent_req_cancel(struct tevent_req *req); +#else bool _tevent_req_cancel(struct tevent_req *req, const char *location); #define tevent_req_cancel(req) \ _tevent_req_cancel(req, __location__) +#endif +#if DOXYGEN +/** + * @brief Create an async tevent request. + * + * The new async request will be initialized in state ASYNC_REQ_IN_PROGRESS. + * + * @param[in] mem_ctx The memory context for the result. + * + * @param[in] pstate The private state of the request. + * + * @param[in] state_size The size of the private state of the request. + * + * @param[in] type The name of the request. + * + * @return A new async request. NULL on error. + */ +struct tevent_req *tevent_req_create(TALLOC_CTX *mem_ctx, + void *pstate, + size_t state_size, + const char *type); +#else struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, void *pstate, size_t state_size, @@ -255,6 +447,7 @@ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, #define tevent_req_create(_mem_ctx, _pstate, _type) \ _tevent_req_create((_mem_ctx), (_pstate), sizeof(_type), \ #_type, __location__) +#endif bool tevent_req_set_endtime(struct tevent_req *req, struct tevent_context *ev, @@ -264,28 +457,152 @@ void _tevent_req_notify_callback(struct tevent_req *req, const char *location); #define tevent_req_notify_callback(req) \ _tevent_req_notify_callback(req, __location__) +#ifdef DOXYGEN +/** + * @brief An async request has successfully finished. + * + * This function is to be used by implementors of async requests. When a + * request is successfully finished, this function calls the user's completion + * function. + * + * @param[in] req The finished request. + */ +void tevent_req_done(struct tevent_req *req); +#else void _tevent_req_done(struct tevent_req *req, const char *location); #define tevent_req_done(req) \ _tevent_req_done(req, __location__) +#endif +#ifdef DOXYGEN +/** + * @brief An async request has seen an error. + * + * This function is to be used by implementors of async requests. When a + * request can not successfully completed, the implementation should call this + * function with the appropriate status code. + * + * If error is 0 the function returns false and does nothing more. + * + * @param[in] req The request with an error. + * + * @param[in] error The error code. + * + * @return On success true is returned, false if error is 0. + * + * @code + * int error = first_function(); + * if (tevent_req_error(req, error)) { + * return; + * } + * + * error = second_function(); + * if (tevent_req_error(req, error)) { + * return; + * } + * + * tevent_req_done(req); + * return; + * @endcode + */ +bool tevent_req_error(struct tevent_req *req, + uint64_t error); +#else bool _tevent_req_error(struct tevent_req *req, uint64_t error, const char *location); #define tevent_req_error(req, error) \ _tevent_req_error(req, error, __location__) +#endif +#ifdef DOXYGEN +/** + * @brief Helper function for nomem check. + * + * Convenience helper to easily check alloc failure within a callback + * implementing the next step of an async request. + * + * @param[in] p The pointer to be checked. + * + * @param[in] req The request being processed. + * + * @code + * p = talloc(mem_ctx, bla); + * if (tevent_req_nomem(p, req)) { + * return; + * } + * @endcode + */ +bool tevent_req_nomem(const void *p, + struct tevent_req *req); +#else bool _tevent_req_nomem(const void *p, struct tevent_req *req, const char *location); #define tevent_req_nomem(p, req) \ _tevent_req_nomem(p, req, __location__) +#endif +/** + * @brief Finish a request before the caller had the change to set the callback. + * + * An implementation of an async request might find that it can either finish + * the request without waiting for an external event, or it can't even start + * the engine. To present the illusion of a callback to the user of the API, + * the implementation can call this helper function which triggers an + * immediate timed event. This way the caller can use the same calling + * conventions, independent of whether the request was actually deferred. + * + * @param[in] req The finished request. + * + * @param[in] ev The tevent_context for the timed event. + * + * @return The given request will be returned. + */ struct tevent_req *tevent_req_post(struct tevent_req *req, struct tevent_context *ev); +/** + * @brief Check if the given request is still in progress. + * + * It is typically used by sync wrapper functions. + * + * This function destroys the attached private data. + * + * @param[in] req The request to poll. + * + * @return The boolean form of "is in progress". + */ bool tevent_req_is_in_progress(struct tevent_req *req); +/** + * @brief Actively poll for the given request to finish. + * + * This function is typically used by sync wrapper functions. + * + * @param[in] req The request to poll. + * + * @param[in] ev The tevent_context to be used. + * + * @return On success true is returned. If a critical error has + * happened in the tevent loop layer false is returned. + * This is not the return value of the given request! + * + * @note This should only be used if the given tevent context was created by the + * caller, to avoid event loop nesting. + * + * @code + * req = tstream_writev_queue_send(mem_ctx, + * ev_ctx, + * tstream, + * send_queue, + * iov, 2); + * ok = tevent_req_poll(req, tctx->ev); + * rc = tstream_writev_queue_recv(req, &sys_errno); + * TALLOC_FREE(req); + * @endcode + */ bool tevent_req_poll(struct tevent_req *req, struct tevent_context *ev); @@ -293,6 +610,13 @@ bool tevent_req_is_error(struct tevent_req *req, enum tevent_req_state *state, uint64_t *error); +/** + * @brief Use as the last action of a _recv() function. + * + * This function destroys the attached private data. + * + * @param[in] req The finished request. + */ void tevent_req_received(struct tevent_req *req); struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, @@ -300,6 +624,17 @@ struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, struct timeval wakeup_time); bool tevent_wakeup_recv(struct tevent_req *req); +/* @} */ + +/** + * @defgroup tevent_helpers The tevent helper functiions + * @ingroup tevent + * + * @todo description + * + * @{ + */ + int tevent_timeval_compare(const struct timeval *tv1, const struct timeval *tv2); @@ -319,6 +654,16 @@ struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs, struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs); +/* @} */ + + +/** + * @defgroup tevent_queue The tevent queue functions + * @ingroup tevent + * + * @{ + */ + struct tevent_queue; struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, @@ -368,11 +713,16 @@ int _tevent_loop_until(struct tevent_context *ev, int tevent_re_initialise(struct tevent_context *ev); +/* @} */ /** + * @defgroup tevent_ops The tevent operation functions + * @ingroup tevent + * * The following structure and registration functions are exclusively * needed for people writing and pluggin a different event engine. * There is nothing useful for normal tevent user in here. + * @{ */ struct tevent_ops { @@ -425,11 +775,19 @@ struct tevent_ops { bool tevent_register_backend(const char *name, const struct tevent_ops *ops); +/* @} */ /** + * @defgroup tevent_compat The tevent compatibility functions + * @ingroup tevent + * * The following definitions are usueful only for compatibility with the * implementation originally developed within the samba4 code and will be * soon removed. Please NEVER use in new code. + * + * @todo Ignore it? + * + * @{ */ #ifdef TEVENT_COMPAT_DEFINES @@ -506,4 +864,6 @@ bool tevent_register_backend(const char *name, const struct tevent_ops *ops); #endif /* TEVENT_COMPAT_DEFINES */ +/* @} */ + #endif /* __TEVENT_H__ */ diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index f61ef53423..b0c9c57dde 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -27,17 +27,6 @@ #include "tevent_internal.h" #include "tevent_util.h" -/** - * @brief The default print function for creating debug messages - * @param[in] req The request to be printed - * @param[in] mem_ctx The memory context for the result - * @retval Text representation of req - * - * The function should not be used by users of the asynx API, - * but custom print function can use it and append custom text - * to the string. - */ - char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) { return talloc_asprintf(mem_ctx, @@ -53,15 +42,6 @@ char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) ); } -/** - * @brief Print an tevent_req structure in debug messages - * @param[in] mem_ctx The memory context for the result - * @param[in] req The request to be printed - * @retval Text representation of req - * - * This function should be used by callers of the async API - */ - char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) { if (!req->private_print) { @@ -71,15 +51,6 @@ char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) return req->private_print(req, mem_ctx); } -/** - * @brief Create an async request - * @param[in] mem_ctx The memory context for the result - * @param[in] ev The event context this async request will be driven by - * @retval A new async request - * - * The new async request will be initialized in state ASYNC_REQ_IN_PROGRESS - */ - struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, void *pdata, size_t data_size, @@ -133,49 +104,12 @@ static void tevent_req_finish(struct tevent_req *req, _tevent_req_notify_callback(req, location); } -/** - * @brief An async request has successfully finished - * @param[in] req The finished request - * - * tevent_req_done is to be used by implementors of async requests. When a - * request is successfully finished, this function calls the user's completion - * function. - */ - void _tevent_req_done(struct tevent_req *req, const char *location) { tevent_req_finish(req, TEVENT_REQ_DONE, location); } -/** - * @brief An async request has seen an error - * @param[in] req The request with an error - * @param[in] error The error code - * - * tevent_req_done is to be used by implementors of async requests. When a - * request can not successfully completed, the implementation should call this - * function with the appropriate status code. - * - * If error is 0 the function returns false and does nothing more. - * - * Call pattern would be - * \code - * int error = first_function(); - * if (tevent_req_error(req, error)) { - * return; - * } - * - * error = second_function(); - * if (tevent_req_error(req, error)) { - * return; - * } - * - * tevent_req_done(req); - * return; - * \endcode - */ - bool _tevent_req_error(struct tevent_req *req, uint64_t error, const char *location) @@ -189,23 +123,6 @@ bool _tevent_req_error(struct tevent_req *req, return true; } -/** - * @brief Helper function for nomem check - * @param[in] p The pointer to be checked - * @param[in] req The request being processed - * - * Convenience helper to easily check alloc failure within a callback - * implementing the next step of an async request. - * - * Call pattern would be - * \code - * p = talloc(mem_ctx, bla); - * if (tevent_req_nomem(p, req)) { - * return; - * } - * \endcode - */ - bool _tevent_req_nomem(const void *p, struct tevent_req *req, const char *location) @@ -218,10 +135,15 @@ bool _tevent_req_nomem(const void *p, } /** - * @brief Immediate event callback - * @param[in] ev Event context - * @param[in] im The immediate event - * @param[in] priv The async request to be finished + * @internal + * + * @brief Immediate event callback. + * + * @param[in] ev The event context to use. + * + * @param[in] im The immediate event. + * + * @param[in] priv The async request to be finished. */ static void tevent_req_trigger(struct tevent_context *ev, struct tevent_immediate *im, @@ -234,20 +156,6 @@ static void tevent_req_trigger(struct tevent_context *ev, req->internal.finish_location); } -/** - * @brief Finish a request before the caller had the change to set the callback - * @param[in] req The finished request - * @param[in] ev The tevent_context for the timed event - * @retval req will be returned - * - * An implementation of an async request might find that it can either finish - * the request without waiting for an external event, or it can't even start - * the engine. To present the illusion of a callback to the user of the API, - * the implementation can call this helper function which triggers an - * immediate timed event. This way the caller can use the same calling - * conventions, independent of whether the request was actually deferred. - */ - struct tevent_req *tevent_req_post(struct tevent_req *req, struct tevent_context *ev) { @@ -256,16 +164,6 @@ struct tevent_req *tevent_req_post(struct tevent_req *req, return req; } -/** - * @brief This function destroys the attached private data - * @param[in] req The request to poll - * @retval The boolean form of "is in progress". - * - * This function can be used to ask if the given request - * is still in progress. - * - * This function is typically used by sync wrapper functions. - */ bool tevent_req_is_in_progress(struct tevent_req *req) { if (req->internal.state == TEVENT_REQ_IN_PROGRESS) { @@ -275,13 +173,6 @@ bool tevent_req_is_in_progress(struct tevent_req *req) return false; } -/** - * @brief This function destroys the attached private data - * @param[in] req The finished request - * - * This function can be called as last action of a _recv() - * function, it destroys the data attached to the tevent_req. - */ void tevent_req_received(struct tevent_req *req) { TALLOC_FREE(req->data); @@ -293,23 +184,6 @@ void tevent_req_received(struct tevent_req *req) req->internal.state = TEVENT_REQ_RECEIVED; } -/** - * @brief This function destroys the attached private data - * @param[in] req The request to poll - * @param[in] ev The tevent_context to be used - * @retval If a critical error has happened in the - * tevent loop layer false is returned. - * Otherwise true is returned. - * This is not the return value of the given request! - * - * This function can be used to actively poll for the - * given request to finish. - * - * Note: this should only be used if the given tevent context - * was created by the caller, to avoid event loop nesting. - * - * This function is typically used by sync wrapper functions. - */ bool tevent_req_poll(struct tevent_req *req, struct tevent_context *ev) { @@ -383,56 +257,16 @@ void *_tevent_req_data(struct tevent_req *req) return req->data; } -/** - * @brief This function sets a print function for the given request - * @param[in] req The given request - * @param[in] fn A pointer to the print function - * - * This function can be used to setup a print function for the given request. - * This will be triggered if the tevent_req_print() function was - * called on the given request. - * - * Note: this function should only be used for debugging. - */ void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn) { req->private_print = fn; } -/** - * @brief This function sets a cancel function for the given request - * @param[in] req The given request - * @param[in] fn A pointer to the cancel function - * - * This function can be used to setup a cancel function for the given request. - * This will be triggered if the tevent_req_cancel() function was - * called on the given request. - * - */ void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn) { req->private_cancel = fn; } -/** - * @brief This function tries to cancel the given request - * @param[in] req The given request - * @param[in] location Automatically filled with the __location__ macro - * via the tevent_req_cancel() macro. This is for debugging - * only! - * @retval This function returns true is the request is cancelable. - * Otherwise false is returned. - * - * This function can be used to cancel the given request. - * - * It is only possible to cancel a request when the implementation - * has registered a cancel function via the tevent_req_set_cancel_fn(). - * - * Note: Even if the function returns true, the caller need to wait - * for the function to complete normally. - * Only the _recv() function of the given request indicates - * if the request was really canceled. - */ bool _tevent_req_cancel(struct tevent_req *req, const char *location) { if (req->private_cancel == NULL) { -- cgit