summaryrefslogtreecommitdiff
path: root/lib/async_req/async_req.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/async_req/async_req.c')
-rw-r--r--lib/async_req/async_req.c156
1 files changed, 77 insertions, 79 deletions
diff --git a/lib/async_req/async_req.c b/lib/async_req/async_req.c
index 011948a158..db47bd93ed 100644
--- a/lib/async_req/async_req.c
+++ b/lib/async_req/async_req.c
@@ -18,6 +18,14 @@
*/
#include "includes.h"
+#include "lib/tevent/tevent.h"
+#include "lib/talloc/talloc.h"
+#include "lib/util/dlinklist.h"
+#include "lib/async_req/async_req.h"
+
+#ifndef TALLOC_FREE
+#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
+#endif
/**
* @brief Print an async_req structure
@@ -35,8 +43,8 @@
char *async_req_print(TALLOC_CTX *mem_ctx, struct async_req *req)
{
- return talloc_asprintf(mem_ctx, "async_req: state=%d, status=%s, "
- "priv=%s", req->state, nt_errstr(req->status),
+ return talloc_asprintf(mem_ctx, "async_req: state=%d, error=%d, "
+ "priv=%s", req->state, (int)req->error,
talloc_get_name(req->private_data));
}
@@ -53,7 +61,7 @@ struct async_req *async_req_new(TALLOC_CTX *mem_ctx)
{
struct async_req *result;
- result = TALLOC_ZERO_P(mem_ctx, struct async_req);
+ result = talloc_zero(mem_ctx, struct async_req);
if (result == NULL) {
return NULL;
}
@@ -62,6 +70,14 @@ struct async_req *async_req_new(TALLOC_CTX *mem_ctx)
return result;
}
+static void async_req_finish(struct async_req *req, enum async_req_state state)
+{
+ req->state = state;
+ if (req->async.fn != NULL) {
+ req->async.fn(req);
+ }
+}
+
/**
* @brief An async request has successfully finished
* @param[in] req The finished request
@@ -73,30 +89,23 @@ struct async_req *async_req_new(TALLOC_CTX *mem_ctx)
void async_req_done(struct async_req *req)
{
- req->status = NT_STATUS_OK;
- req->state = ASYNC_REQ_DONE;
- if (req->async.fn != NULL) {
- req->async.fn(req);
- }
+ async_req_finish(req, ASYNC_REQ_DONE);
}
/**
* @brief An async request has seen an error
* @param[in] req The request with an error
- * @param[in] status The error code
+ * @param[in] error The error code
*
* async_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.
*/
-void async_req_error(struct async_req *req, NTSTATUS status)
+void async_req_error(struct async_req *req, uint64_t error)
{
- req->status = status;
- req->state = ASYNC_REQ_ERROR;
- if (req->async.fn != NULL) {
- req->async.fn(req);
- }
+ req->error = error;
+ async_req_finish(req, ASYNC_REQ_USER_ERROR);
}
/**
@@ -107,43 +116,18 @@ void async_req_error(struct async_req *req, NTSTATUS status)
* @param[in] priv The async request to be finished
*/
-static void async_trigger(struct event_context *ev, struct timed_event *te,
+static void async_trigger(struct tevent_context *ev, struct tevent_timer *te,
struct timeval now, void *priv)
{
struct async_req *req = talloc_get_type_abort(priv, struct async_req);
TALLOC_FREE(te);
- if (NT_STATUS_IS_OK(req->status)) {
+ if (req->error == 0) {
async_req_done(req);
}
else {
- async_req_error(req, req->status);
- }
-}
-
-/**
- * @brief Finish a request before it started processing
- * @param[in] req The finished request
- * @param[in] status The success code
- *
- * 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.
- */
-
-bool async_post_status(struct async_req *req, struct event_context *ev,
- NTSTATUS status)
-{
- req->status = status;
-
- if (event_add_timed(ev, req, timeval_zero(),
- async_trigger, req) == NULL) {
- return false;
+ async_req_error(req, req->error);
}
- return true;
}
/**
@@ -157,7 +141,7 @@ bool async_post_status(struct async_req *req, struct event_context *ev,
* Call pattern would be
* \code
* p = talloc(mem_ctx, bla);
- * if (async_req_nomem(p, req)) {
+ * if (async_req_ntnomem(p, req)) {
* return;
* }
* \endcode
@@ -168,55 +152,69 @@ bool async_req_nomem(const void *p, struct async_req *req)
if (p != NULL) {
return false;
}
- async_req_error(req, NT_STATUS_NO_MEMORY);
+ async_req_finish(req, ASYNC_REQ_NO_MEMORY);
return true;
}
-bool async_req_is_error(struct async_req *req, NTSTATUS *status)
+/**
+ * @brief Finish a request before it started processing
+ * @param[in] req The finished request
+ * @param[in] status The success code
+ *
+ * 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.
+ */
+
+bool async_post_error(struct async_req *req, struct tevent_context *ev,
+ uint64_t error)
{
- if (req->state < ASYNC_REQ_DONE) {
- *status = NT_STATUS_INTERNAL_ERROR;
- return true;
- }
- if (req->state == ASYNC_REQ_ERROR) {
- *status = req->status;
- return true;
+ req->error = error;
+
+ if (tevent_add_timer(ev, req, timeval_zero(),
+ async_trigger, req) == NULL) {
+ return false;
}
- return false;
+ return true;
}
-NTSTATUS async_req_simple_recv(struct async_req *req)
+bool async_req_is_error(struct async_req *req, enum async_req_state *state,
+ uint64_t *error)
{
- NTSTATUS status;
-
- if (async_req_is_error(req, &status)) {
- return status;
+ if (req->state == ASYNC_REQ_DONE) {
+ return false;
+ }
+ if (req->state == ASYNC_REQ_USER_ERROR) {
+ *error = req->error;
}
- return NT_STATUS_OK;
+ *state = req->state;
+ return true;
}
-static void async_req_timedout(struct event_context *ev,
- struct timed_event *te,
+static void async_req_timedout(struct tevent_context *ev,
+ struct tevent_timer *te,
struct timeval now,
void *priv)
{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
+ struct async_req *req = talloc_get_type_abort(priv, struct async_req);
TALLOC_FREE(te);
- async_req_error(req, NT_STATUS_IO_TIMEOUT);
+ async_req_finish(req, ASYNC_REQ_TIMED_OUT);
}
-bool async_req_set_timeout(struct async_req *req, struct event_context *ev,
+bool async_req_set_timeout(struct async_req *req, struct tevent_context *ev,
struct timeval to)
{
- return (event_add_timed(ev, req,
- timeval_current_ofs(to.tv_sec, to.tv_usec),
- async_req_timedout, req)
+ return (tevent_add_timer(
+ ev, req, timeval_current_ofs(to.tv_sec, to.tv_usec),
+ async_req_timedout, req)
!= NULL);
}
struct async_req *async_wait_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
+ struct tevent_context *ev,
struct timeval to)
{
struct async_req *result;
@@ -232,9 +230,9 @@ struct async_req *async_wait_send(TALLOC_CTX *mem_ctx,
return result;
}
-NTSTATUS async_wait_recv(struct async_req *req)
+bool async_wait_recv(struct async_req *req)
{
- return NT_STATUS_OK;
+ return true;
}
struct async_queue_entry {
@@ -250,7 +248,7 @@ struct async_req_queue {
struct async_req_queue *async_req_queue_init(TALLOC_CTX *mem_ctx)
{
- return TALLOC_ZERO_P(mem_ctx, struct async_req_queue);
+ return talloc_zero(mem_ctx, struct async_req_queue);
}
static int async_queue_entry_destructor(struct async_queue_entry *e)
@@ -266,8 +264,8 @@ static int async_queue_entry_destructor(struct async_queue_entry *e)
return 0;
}
-static void async_req_immediate_trigger(struct event_context *ev,
- struct timed_event *te,
+static void async_req_immediate_trigger(struct tevent_context *ev,
+ struct tevent_timer *te,
struct timeval now,
void *priv)
{
@@ -278,7 +276,7 @@ static void async_req_immediate_trigger(struct event_context *ev,
e->trigger(e->req);
}
-bool async_req_enqueue(struct async_req_queue *queue, struct event_context *ev,
+bool async_req_enqueue(struct async_req_queue *queue, struct tevent_context *ev,
struct async_req *req,
void (*trigger)(struct async_req *req))
{
@@ -300,9 +298,9 @@ bool async_req_enqueue(struct async_req_queue *queue, struct event_context *ev,
talloc_set_destructor(e, async_queue_entry_destructor);
if (!busy) {
- struct timed_event *te;
+ struct tevent_timer *te;
- te = event_add_timed(ev, e, timeval_zero(),
+ te = tevent_add_timer(ev, e, timeval_zero(),
async_req_immediate_trigger,
e);
if (te == NULL) {
@@ -330,7 +328,7 @@ bool _async_req_setup(TALLOC_CTX *mem_ctx, struct async_req **preq,
TALLOC_FREE(req);
return false;
}
- talloc_set_name(state, typename);
+ talloc_set_name_const(state, typename);
req->private_data = state;
*preq = req;