diff options
author | Konstantin Ananyev <konstantin.ananyev@intel.com> | 2017-10-31 12:40:17 +0000 |
---|---|---|
committer | Konstantin Ananyev <konstantin.ananyev@intel.com> | 2017-10-31 14:19:39 +0000 |
commit | e18a033b921d0d79fa8278f853548e6125b93e0c (patch) | |
tree | a6a55edf6ddceef824561818c9836914c326340d /app/nginx/src/os/unix/ngx_readv_chain.c | |
parent | 7e18fa1bf263822c46d7431a911b41d6377d5f69 (diff) |
Integrate TLDK with NGINX
Created a clone of nginx (from https://github.com/nginx/nginx)
to demonstrate and benchmark TLDK library integrated with real
world application.
A new nginx module is created and and BSD socket-like API is implemented
on top of native TLDK API.
Note, that right now only minimalistic subset of socket-like API is provided:
- accept
- close
- readv
- recv
- writev
so only limited nginx functionality is available for a moment.
Change-Id: Ie1efe9349a0538da4348a48fb8306cbf636b5a92
Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Diffstat (limited to 'app/nginx/src/os/unix/ngx_readv_chain.c')
-rw-r--r-- | app/nginx/src/os/unix/ngx_readv_chain.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/app/nginx/src/os/unix/ngx_readv_chain.c b/app/nginx/src/os/unix/ngx_readv_chain.c new file mode 100644 index 0000000..454cfdc --- /dev/null +++ b/app/nginx/src/os/unix/ngx_readv_chain.c @@ -0,0 +1,214 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_event.h> + + +ssize_t +ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit) +{ + u_char *prev; + ssize_t n, size; + ngx_err_t err; + ngx_array_t vec; + ngx_event_t *rev; + struct iovec *iov, iovs[NGX_IOVS_PREALLOCATE]; + + rev = c->read; + +#if (NGX_HAVE_KQUEUE) + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "readv: eof:%d, avail:%d, err:%d", + rev->pending_eof, rev->available, rev->kq_errno); + + if (rev->available == 0) { + if (rev->pending_eof) { + rev->ready = 0; + rev->eof = 1; + + ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno, + "kevent() reported about an closed connection"); + + if (rev->kq_errno) { + rev->error = 1; + ngx_set_socket_errno(rev->kq_errno); + return NGX_ERROR; + } + + return 0; + + } else { + return NGX_AGAIN; + } + } + } + +#endif + +#if (NGX_HAVE_EPOLLRDHUP) + + if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "readv: eof:%d, avail:%d", + rev->pending_eof, rev->available); + + if (!rev->available && !rev->pending_eof) { + return NGX_AGAIN; + } + } + +#endif + + prev = NULL; + iov = NULL; + size = 0; + + vec.elts = iovs; + vec.nelts = 0; + vec.size = sizeof(struct iovec); + vec.nalloc = NGX_IOVS_PREALLOCATE; + vec.pool = c->pool; + + /* coalesce the neighbouring bufs */ + + while (chain) { + n = chain->buf->end - chain->buf->last; + + if (limit) { + if (size >= limit) { + break; + } + + if (size + n > limit) { + n = (ssize_t) (limit - size); + } + } + + if (prev == chain->buf->last) { + iov->iov_len += n; + + } else { + if (vec.nelts >= IOV_MAX) { + break; + } + + iov = ngx_array_push(&vec); + if (iov == NULL) { + return NGX_ERROR; + } + + iov->iov_base = (void *) chain->buf->last; + iov->iov_len = n; + } + + size += n; + prev = chain->buf->end; + chain = chain->next; + } + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "readv: %ui, last:%uz", vec.nelts, iov->iov_len); + + do { + n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts); + + if (n == 0) { + rev->ready = 0; + rev->eof = 1; + +#if (NGX_HAVE_KQUEUE) + + /* + * on FreeBSD readv() may return 0 on closed socket + * even if kqueue reported about available data + */ + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + rev->available = 0; + } + +#endif + + return 0; + } + + if (n > 0) { + +#if (NGX_HAVE_KQUEUE) + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + rev->available -= n; + + /* + * rev->available may be negative here because some additional + * bytes may be received between kevent() and readv() + */ + + if (rev->available <= 0) { + if (!rev->pending_eof) { + rev->ready = 0; + } + + rev->available = 0; + } + + return n; + } + +#endif + +#if (NGX_HAVE_EPOLLRDHUP) + + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) + && ngx_use_epoll_rdhup) + { + if (n < size) { + if (!rev->pending_eof) { + rev->ready = 0; + } + + rev->available = 0; + } + + return n; + } + +#endif + + if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) { + rev->ready = 0; + } + + return n; + } + + err = ngx_socket_errno; + + if (err == NGX_EAGAIN || err == NGX_EINTR) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "readv() not ready"); + n = NGX_AGAIN; + + } else { + n = ngx_connection_error(c, err, "readv() failed"); + break; + } + + } while (err == NGX_EINTR); + + rev->ready = 0; + + if (n == NGX_ERROR) { + c->read->error = 1; + } + + return n; +} |