From: Stefan Metzmacher Date: Mon, 4 May 2009 09:20:41 +0000 (+0200) Subject: example_coro... X-Git-Url: http://git.samba.org/?p=metze%2Fsamba%2Fwip.git;a=commitdiff_plain;h=1efdd2469b7ae2b4c0dd4e78ec7c864b3cf47faa;hp=ced03d86f39a5f87af682f48defef5fc73d61388 example_coro... --- diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c index 6c58d380670c..aa1c5b2fdf19 100644 --- a/source4/ntvfs/ipc/vfs_ipc.c +++ b/source4/ntvfs/ipc/vfs_ipc.c @@ -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)