sp_aio added
Signed-off-by: Martin Sustrik <sustrik@250bpm.com>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 82a0d4f..04db63d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -37,6 +37,8 @@
core/sock.c
utils/addr.h
utils/addr.c
+ utils/aio.h
+ utils/aio.c
utils/alloc.h
utils/alloc.c
utils/clock.h
diff --git a/src/utils/aio.c b/src/utils/aio.c
new file mode 100644
index 0000000..7206503
--- /dev/null
+++ b/src/utils/aio.c
@@ -0,0 +1,160 @@
+/*
+ Copyright (c) 2012 250bpm s.r.o.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom
+ the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+*/
+
+#include "aio.h"
+
+#if !defined SP_HAVE_WINDOWS
+
+#include "err.h"
+#include "fast.h"
+#include "cont.h"
+
+#include <stdint.h>
+#include <sys/socket.h>
+
+void sp_aio_init (struct sp_aio *self)
+{
+ sp_poller_init (&self->poller);
+}
+
+void sp_aio_term (struct sp_aio *self)
+{
+ sp_poller_term (&self->poller);
+}
+
+void sp_aio_register (struct sp_aio *self, int fd, struct sp_aio_hndl *hndl)
+{
+ hndl->fd = fd;
+
+ /* Start polling on the file descriptor. */
+ sp_poller_add_fd (&self->poller, fd, &hndl->hndl);
+
+ /* Mark that there's no in or out operation in progress. */
+ hndl->in.flags = 0;
+ hndl->out.flags = 0;
+}
+
+void sp_aio_unregister (struct sp_aio *self, struct sp_aio_hndl *hndl)
+{
+ sp_assert (0);
+}
+
+int sp_aio_send (struct sp_aio *self, struct sp_aio_hndl *hndl,
+ const void *buf, size_t len, int flags)
+{
+ /* If there's out operation already in progress, don't start a new one. */
+ if (sp_slow (hndl->out.flags))
+ return -EAGAIN;
+
+ /* Store the info about the asynchronous operation requested. */
+ hndl->out.flags = SP_AIO_IN_PROGRESS | flags;
+ hndl->out.buf = buf;
+ hndl->out.len = len;
+
+ return 0;
+}
+
+int sp_aio_recv (struct sp_aio *self, struct sp_aio_hndl *hndl,
+ void *buf, size_t len, int flags)
+{
+ /* If there's in operation already in progress, don't start a new one. */
+ if (sp_slow (hndl->in.flags))
+ return -EAGAIN;
+
+ /* Store the info about the asynchronous operation requested. */
+ hndl->in.flags = SP_AIO_IN_PROGRESS | flags;
+ hndl->in.buf = buf;
+ hndl->in.len = len;
+
+ return 0;
+}
+
+int sp_aio_wait (struct sp_aio *self, int timeout, int *event,
+ struct sp_aio_hndl **hndl)
+{
+ int rc;
+ int pevent;
+ struct sp_poller_hndl *phndl;
+ struct sp_aio_hndl *ahndl;
+ ssize_t nbytes;
+
+ /* Get one event. */
+ rc = sp_poller_wait (&self->poller, timeout, &pevent, &phndl);
+ if (sp_slow (rc < 0))
+ return rc;
+ ahndl = sp_cont (phndl, struct sp_aio_hndl, hndl);
+
+ switch (pevent) {
+
+ case SP_POLLER_IN:
+
+ /* Process inbound data. */
+ if (ahndl->in.len <= 0)
+ goto recv_done;
+ nbytes = recv (ahndl->fd, ahndl->in.buf, ahndl->in.len, 0);
+ errno_assert (nbytes >= 0);
+ if (sp_slow (nbytes == 0))
+ goto error;
+ ahndl->in.buf = ((uint8_t*) ahndl->in.buf) + nbytes;
+ ahndl->in.len -= nbytes;
+ if (ahndl->in.len > 0)
+ return -ETIMEDOUT;
+recv_done:
+ ahndl->in.flags = 0;
+ *event = SP_AIO_IN;
+ *hndl = ahndl;
+ return 0;
+
+ case SP_POLLER_OUT:
+
+ /* Process outbound data. */
+ if (ahndl->out.len <= 0)
+ goto send_done;
+ nbytes = send (ahndl->fd, ahndl->in.buf, ahndl->in.len, 0);
+ errno_assert (nbytes >= 0);
+ ahndl->out.buf = ((uint8_t*) ahndl->out.buf) + nbytes;
+ ahndl->out.len -= nbytes;
+ if (ahndl->out.len > 0)
+ return -ETIMEDOUT;
+send_done:
+ ahndl->out.flags = 0;
+ *event = SP_AIO_OUT;
+ *hndl = ahndl;
+ return 0;
+
+ case SP_POLLER_ERR:
+error:
+ /* Socket error. */
+ *event = SP_AIO_ERR;
+ *hndl = ahndl;
+ return 0;
+
+ default:
+
+ /* Invalid event. */
+ sp_assert (0);
+ return 0;
+ }
+}
+
+#endif
+
diff --git a/src/utils/aio.h b/src/utils/aio.h
new file mode 100644
index 0000000..2bd6de7
--- /dev/null
+++ b/src/utils/aio.h
@@ -0,0 +1,75 @@
+/*
+ Copyright (c) 2012 250bpm s.r.o.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom
+ the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+*/
+
+#ifndef SP_AIO_INCLUDED
+#define SP_AIO_INCLUDED
+
+#if !defined SP_HAVE_WINDOWS
+
+#include "poller.h"
+
+#include <stddef.h>
+
+#define SP_AIO_IN_PROGRESS 1
+#define SP_AIO_PARTIAL 2
+
+#define SP_AIO_IN 1
+#define SP_AIO_OUT 2
+#define SP_AIO_ERR 3
+
+struct sp_aio_hndl {
+ int fd;
+ struct sp_poller_hndl hndl;
+ struct {
+ int flags;
+ void *buf;
+ size_t len;
+ } in;
+ struct {
+ int flags;
+ const void *buf;
+ size_t len;
+ } out;
+};
+
+struct sp_aio {
+ struct sp_poller poller;
+};
+
+void sp_aio_init (struct sp_aio *self);
+void sp_aio_term (struct sp_aio *self);
+
+void sp_aio_register (struct sp_aio *self, int fd, struct sp_aio_hndl *hndl);
+void sp_aio_unregister (struct sp_aio *self, struct sp_aio_hndl *hndl);
+
+int sp_aio_send (struct sp_aio *self, struct sp_aio_hndl *hndl,
+ const void *buf, size_t len, int flags);
+int sp_aio_recv (struct sp_aio *self, struct sp_aio_hndl *hndl,
+ void *buf, size_t len, int flags);
+
+int sp_aio_wait (struct sp_aio *self, int timeout, int *event,
+ struct sp_aio_hndl **hndl);
+
+#endif
+
+#endif
+