lib/tsocket: add generic socket abstraction layer
[ira/wip.git] / lib / async_req / async_req.c
index 1b9fc5517bebd78b07fbb4bf0adde38edeedbc43..4dfe809738e516f14cbc9423b65873a03f4c621a 100644 (file)
@@ -70,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
@@ -81,30 +89,23 @@ struct async_req *async_req_new(TALLOC_CTX *mem_ctx)
 
 void async_req_done(struct async_req *req)
 {
-       req->error = 0;
-       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, uint32_t error)
+void async_req_error(struct async_req *req, uint64_t error)
 {
        req->error = error;
-       req->state = ASYNC_REQ_ERROR;
-       if (req->async.fn != NULL) {
-               req->async.fn(req);
-       }
+       async_req_finish(req, ASYNC_REQ_USER_ERROR);
 }
 
 /**
@@ -129,6 +130,32 @@ static void async_trigger(struct tevent_context *ev, struct tevent_timer *te,
        }
 }
 
+/**
+ * @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 (async_req_ntnomem(p, req)) {
+ *     return;
+ * }
+ * \endcode
+ */
+
+bool async_req_nomem(const void *p, struct async_req *req)
+{
+       if (p != NULL) {
+               return false;
+       }
+       async_req_finish(req, ASYNC_REQ_NO_MEMORY);
+       return true;
+}
+
 /**
  * @brief Finish a request before it started processing
  * @param[in] req      The finished request
@@ -143,68 +170,27 @@ static void async_trigger(struct tevent_context *ev, struct tevent_timer *te,
  */
 
 bool async_post_error(struct async_req *req, struct tevent_context *ev,
-                     uint32_t error)
+                     uint64_t error)
 {
        req->error = error;
 
-       if (tevent_add_timer(ev, req, timeval_zero(),
+       if (tevent_add_timer(ev, req, tevent_timeval_zero(),
                            async_trigger, req) == NULL) {
                return false;
        }
        return true;
 }
 
-bool async_req_is_error(struct async_req *req, uint32_t *error)
+bool async_req_is_error(struct async_req *req, enum async_req_state *state,
+                       uint64_t *error)
 {
-       if (req->state < ASYNC_REQ_DONE) {
-               return true;
+       if (req->state == ASYNC_REQ_DONE) {
+               return false;
        }
-       if (req->state == ASYNC_REQ_ERROR) {
+       if (req->state == ASYNC_REQ_USER_ERROR) {
                *error = req->error;
-               return true;
-       }
-       return false;
-}
-
-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);
-       TALLOC_FREE(te);
-       async_req_nterror(req, NT_STATUS_IO_TIMEOUT);
-}
-
-bool async_req_set_timeout(struct async_req *req, struct tevent_context *ev,
-                          struct timeval to)
-{
-       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 tevent_context *ev,
-                                 struct timeval to)
-{
-       struct async_req *result;
-
-       result = async_req_new(mem_ctx);
-       if (result == NULL) {
-               return result;
        }
-       if (!async_req_set_timeout(result, ev, to)) {
-               TALLOC_FREE(result);
-               return NULL;
-       }
-       return result;
-}
-
-bool async_wait_recv(struct async_req *req)
-{
+       *state = req->state;
        return true;
 }
 
@@ -273,7 +259,7 @@ bool async_req_enqueue(struct async_req_queue *queue, struct tevent_context *ev,
        if (!busy) {
                struct tevent_timer *te;
 
-               te = tevent_add_timer(ev, e, timeval_zero(),
+               te = tevent_add_timer(ev, e, tevent_timeval_zero(),
                                     async_req_immediate_trigger,
                                     e);
                if (te == NULL) {