example_coro...
authorStefan Metzmacher <metze@samba.org>
Mon, 4 May 2009 09:20:41 +0000 (11:20 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 14 May 2009 20:18:47 +0000 (22:18 +0200)
source4/ntvfs/ipc/vfs_ipc.c

index 6c58d380670c7eb23f35b280f30d0c322f3725fc..aa1c5b2fdf197f55b1fb3685403a60d1d9c9b545 100644 (file)
@@ -36,6 +36,8 @@
 #include "auth/auth.h"
 #include "auth/auth_sam_reply.h"
 #include "lib/socket/socket.h"
+#include "../lib/util/tevent_unix.h"
+#include "../lib/util/tevent_coroutine.h"
 
 /* this is the private structure used to keep the state of an open
    ipc$ connection. It needs to keep information about all open
@@ -602,6 +604,149 @@ reply:
        req->async_states->send_fn(req);
 }
 
+struct example_ocor_state {
+       const char *string;
+};
+
+static struct tevent_coroutine_result *example_ocor_body(struct tevent_coroutine *coro,
+                                                        struct tevent_context *ev,
+                                                        void *private_data);
+
+static struct tevent_req *example_ocor_send(TALLOC_CTX *mem_ctx,
+                                    struct tevent_context *ev,
+                                    const char *string)
+{
+       struct tevent_req *req;
+       struct example_ocor_state *state;
+       struct tevent_coroutine *coro;
+
+       req = tevent_req_create(mem_ctx, &state, struct example_ocor_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       state->string = string;
+
+       coro = tevent_coroutine_create(req, ev, example_ocor_body);
+       if (tevent_req_nomem(coro, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_coroutine_run(coro);
+       if (!tevent_req_is_in_progress(req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       return req;
+}
+
+static struct tevent_coroutine_result *example_ocor_body(struct tevent_coroutine *coro,
+                                                        struct tevent_context *ev,
+                                                        void *private_data)
+{
+       struct example_ocor_state *state = talloc_get_type_abort(private_data,
+                                          struct example_ocor_state);
+       struct tevent_req *subreq;
+       bool ok;
+
+       DEBUG(0,("%s[%p]: 1. %s\n", __location__, coro, state->string));
+
+       subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(0,500));
+       if (tevent_coroutine_nomem(subreq, coro)) {
+               return tevent_coroutine_return(coro);
+       }
+       tevent_coroutine_yield(coro, subreq);
+       ok = tevent_wakeup_recv(subreq);
+
+       DEBUG(0,("%s[%p]: 2. %s wakeup[%d]\n", __location__, coro, state->string, ok));
+
+       tevent_coroutine_done(coro);
+       return tevent_coroutine_return(coro);
+}
+
+static int example_ocor_recv(struct tevent_req *req, int *perrno)
+{
+       if (tevent_req_is_unix_error(req, perrno)) {
+               return -1;
+       }
+
+       return 0;
+}
+
+struct example_coro_state {
+       const char *string;
+};
+
+static struct tevent_coroutine_result *example_coro_body(struct tevent_coroutine *coro,
+                                                        struct tevent_context *ev,
+                                                        void *private_data);
+
+static struct tevent_req *example_coro_send(TALLOC_CTX *mem_ctx,
+                                    struct tevent_context *ev,
+                                    const char *string)
+{
+       struct tevent_req *req;
+       struct example_coro_state *state;
+       struct tevent_coroutine *coro;
+
+       req = tevent_req_create(mem_ctx, &state, struct example_coro_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       state->string = string;
+
+       coro = tevent_coroutine_create(req, ev, example_coro_body);
+       if (tevent_req_nomem(coro, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_coroutine_run(coro);
+       if (!tevent_req_is_in_progress(req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       return req;
+}
+
+static struct tevent_coroutine_result *example_coro_body(struct tevent_coroutine *coro,
+                                                        struct tevent_context *ev,
+                                                        void *private_data)
+{
+       struct example_coro_state *state = talloc_get_type_abort(private_data,
+                                          struct example_coro_state);
+       struct tevent_req *subreq;
+       int ret;
+       int sys_errno;
+
+       DEBUG(0,("%s:%s[%p]: 1. %s\n", __location__, __FUNCTION__, coro, state->string));
+
+       subreq = example_ocor_send(state, ev, state->string);
+       if (tevent_coroutine_nomem(subreq, coro)) {
+               return tevent_coroutine_return(coro);
+       }
+       tevent_coroutine_yield(coro, subreq);
+       ret = example_ocor_recv(subreq, &sys_errno);
+       if (ret == -1) {
+               tevent_coroutine_error(coro, sys_errno);
+               return tevent_coroutine_return(coro);
+       }
+
+       DEBUG(0,("%s:%s[%p]: 2. %s example_ocor[%d]\n", __location__, __FUNCTION__, coro, state->string, ret));
+
+       tevent_coroutine_done(coro);
+       return tevent_coroutine_return(coro);
+}
+
+static int example_coro_recv(struct tevent_req *req, int *perrno)
+{
+       if (tevent_req_is_unix_error(req, perrno)) {
+               return -1;
+       }
+
+       return 0;
+}
+
 struct ipc_write_state {
        struct ipc_private *ipriv;
        struct pipe_state *p;
@@ -612,6 +757,8 @@ struct ipc_write_state {
 
 static void ipc_write_done(struct tevent_req *subreq);
 
+static void ipc_write_coro_done(struct tevent_req *subreq);
+
 /*
   write to a file
 */
@@ -643,16 +790,50 @@ static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs,
        state->iov.iov_base = discard_const_p(void, wr->writex.in.data);
        state->iov.iov_len = wr->writex.in.count;
 
+       subreq = example_coro_send(state,
+                                  ipriv->ntvfs->ctx->event_ctx,
+                                  "write_start");
+       NT_STATUS_HAVE_NO_MEMORY(subreq);
+       tevent_req_set_callback(subreq, ipc_write_coro_done, state);
+
+       req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
+       return NT_STATUS_OK;
+}
+
+static void ipc_write_coro_done(struct tevent_req *subreq)
+{
+       struct ipc_write_state *state =
+               tevent_req_callback_data(subreq,
+               struct ipc_write_state);
+       struct pipe_state *p = state->p;
+       struct ipc_private *ipriv = state->ipriv;
+       struct ntvfs_request *req = state->req;
+       int ret;
+       int sys_errno;
+       NTSTATUS status;
+
+       ret = example_coro_recv(subreq, &sys_errno);
+       TALLOC_FREE(subreq);
+       if (ret == -1) {
+               status = map_nt_error_from_unix(sys_errno);
+               goto reply;
+       }
+
        subreq = tstream_writev_queue_send(state,
                                           ipriv->ntvfs->ctx->event_ctx,
                                           p->npipe,
                                           p->write_queue,
                                           &state->iov, 1);
-       NT_STATUS_HAVE_NO_MEMORY(subreq);
+       if (!subreq) {
+               status = NT_STATUS_NO_MEMORY;
+               goto reply;
+       }
        tevent_req_set_callback(subreq, ipc_write_done, state);
+       return;
 
-       req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
-       return NT_STATUS_OK;
+reply:
+       req->async_states->status = status;
+       req->async_states->send_fn(req);
 }
 
 static void ipc_write_done(struct tevent_req *subreq)