| Index: c/poll.c
|
| diff --git a/c/poll.c b/c/poll.c
|
| deleted file mode 100644
|
| index 1df8b63039639cb978bde247fb7b8a8251f8d80a..0000000000000000000000000000000000000000
|
| --- a/c/poll.c
|
| +++ /dev/null
|
| @@ -1,489 +0,0 @@
|
| -/* Licensed to the Apache Software Foundation (ASF) under one or more
|
| - * contributor license agreements. See the NOTICE file distributed with
|
| - * this work for additional information regarding copyright ownership.
|
| - * The ASF licenses this file to You under the Apache License, Version 2.0
|
| - * (the "License"); you may not use this file except in compliance with
|
| - * the License. You may obtain a copy of the License at
|
| - *
|
| - * http://www.apache.org/licenses/LICENSE-2.0
|
| - *
|
| - * Unless required by applicable law or agreed to in writing, software
|
| - * distributed under the License is distributed on an "AS IS" BASIS,
|
| - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| - * See the License for the specific language governing permissions and
|
| - * limitations under the License.
|
| - */
|
| -
|
| -/*
|
| - *
|
| - * @author Mladen Turk
|
| - * @version $Id: poll.c 1667243 2015-03-17 10:28:05Z markt $
|
| - */
|
| -
|
| -#include "tcn.h"
|
| -
|
| -#ifdef TCN_DO_STATISTICS
|
| -static int sp_created = 0;
|
| -static int sp_destroyed = 0;
|
| -static int sp_cleared = 0;
|
| -#endif
|
| -
|
| -/* Internal poll structure for queryset
|
| - */
|
| -typedef struct tcn_pollset {
|
| - apr_pool_t *pool;
|
| - apr_int32_t nelts;
|
| - apr_int32_t nalloc;
|
| - apr_pollset_t *pollset;
|
| - jlong *set;
|
| - apr_interval_time_t default_timeout;
|
| - /* A ring containing all of the pollfd_t that are active
|
| - */
|
| - APR_RING_HEAD(pfd_poll_ring_t, tcn_pfde_t) poll_ring;
|
| - /* A ring of pollfd_t that have been used, and then _remove()'d
|
| - */
|
| - APR_RING_HEAD(pfd_free_ring_t, tcn_pfde_t) free_ring;
|
| - /* A ring of pollfd_t where rings that have been _remove()`ed but
|
| - * might still be inside a _poll()
|
| - */
|
| - APR_RING_HEAD(pfd_dead_ring_t, tcn_pfde_t) dead_ring;
|
| -#ifdef TCN_DO_STATISTICS
|
| - int sp_added;
|
| - int sp_max_count;
|
| - int sp_poll;
|
| - int sp_polled;
|
| - int sp_max_polled;
|
| - int sp_remove;
|
| - int sp_removed;
|
| - int sp_maintained;
|
| - int sp_max_maintained;
|
| - int sp_err_poll;
|
| - int sp_poll_timeout;
|
| - int sp_overflow;
|
| - int sp_equals;
|
| - int sp_eintr;
|
| -#endif
|
| -} tcn_pollset_t;
|
| -
|
| -#ifdef TCN_DO_STATISTICS
|
| -static void sp_poll_statistics(tcn_pollset_t *p)
|
| -{
|
| - fprintf(stderr, "Pollset Statistics ......\n");
|
| - fprintf(stderr, "Number of added sockets : %d\n", p->sp_added);
|
| - fprintf(stderr, "Max. number of sockets : %d\n", p->sp_max_count);
|
| - fprintf(stderr, "Poll calls : %d\n", p->sp_poll);
|
| - fprintf(stderr, "Poll timeouts : %d\n", p->sp_poll_timeout);
|
| - fprintf(stderr, "Poll errors : %d\n", p->sp_err_poll);
|
| - fprintf(stderr, "Poll overflows : %d\n", p->sp_overflow);
|
| - fprintf(stderr, "Polled sockets : %d\n", p->sp_polled);
|
| - fprintf(stderr, "Max. Polled sockets : %d\n", p->sp_max_polled);
|
| - fprintf(stderr, "Poll remove : %d\n", p->sp_remove);
|
| - fprintf(stderr, "Total removed : %d\n", p->sp_removed);
|
| - fprintf(stderr, "Maintained : %d\n", p->sp_maintained);
|
| - fprintf(stderr, "Max. maintained : %d\n", p->sp_max_maintained);
|
| - fprintf(stderr, "Number of duplicates : %d\n", p->sp_equals);
|
| - fprintf(stderr, "Number of interrupts : %d\n", p->sp_eintr);
|
| -
|
| -}
|
| -
|
| -static apr_status_t sp_poll_cleanup(void *data)
|
| -{
|
| - sp_cleared++;
|
| - sp_poll_statistics(data);
|
| - return APR_SUCCESS;
|
| -}
|
| -
|
| -void sp_poll_dump_statistics()
|
| -{
|
| - fprintf(stderr, "Poll Statistics .........\n");
|
| - fprintf(stderr, "Polls created : %d\n", sp_created);
|
| - fprintf(stderr, "Polls destroyed : %d\n", sp_destroyed);
|
| - fprintf(stderr, "Polls cleared : %d\n", sp_cleared);
|
| -}
|
| -#endif
|
| -
|
| -TCN_IMPLEMENT_CALL(jlong, Poll, create)(TCN_STDARGS, jint size,
|
| - jlong pool, jint flags,
|
| - jlong default_timeout)
|
| -{
|
| - apr_pool_t *p = J2P(pool, apr_pool_t *);
|
| - apr_pollset_t *pollset = NULL;
|
| - tcn_pollset_t *tps = NULL;
|
| - apr_uint32_t f = (apr_uint32_t)flags | APR_POLLSET_NOCOPY;
|
| - UNREFERENCED(o);
|
| - TCN_ASSERT(pool != 0);
|
| -
|
| - if (f & APR_POLLSET_THREADSAFE) {
|
| - apr_status_t rv = apr_pollset_create(&pollset, (apr_uint32_t)size, p, f);
|
| - if (rv == APR_ENOTIMPL)
|
| - f &= ~APR_POLLSET_THREADSAFE;
|
| - else if (rv != APR_SUCCESS) {
|
| - tcn_ThrowAPRException(e, rv);
|
| - goto cleanup;
|
| - }
|
| - }
|
| - if (pollset == NULL) {
|
| - TCN_THROW_IF_ERR(apr_pollset_create(&pollset,
|
| - (apr_uint32_t)size, p, f), pollset);
|
| - }
|
| - tps = apr_pcalloc(p, sizeof(tcn_pollset_t));
|
| - TCN_CHECK_ALLOCATED(tps);
|
| - tps->pollset = pollset;
|
| - tps->set = apr_pcalloc(p, size * sizeof(jlong) * 2);
|
| - TCN_CHECK_ALLOCATED(tps->set);
|
| - APR_RING_INIT(&tps->poll_ring, tcn_pfde_t, link);
|
| - APR_RING_INIT(&tps->free_ring, tcn_pfde_t, link);
|
| - APR_RING_INIT(&tps->dead_ring, tcn_pfde_t, link);
|
| -
|
| - tps->nelts = 0;
|
| - tps->nalloc = size;
|
| - tps->pool = p;
|
| - tps->default_timeout = J2T(default_timeout);
|
| -#ifdef TCN_DO_STATISTICS
|
| - sp_created++;
|
| - apr_pool_cleanup_register(p, (const void *)tps,
|
| - sp_poll_cleanup,
|
| - apr_pool_cleanup_null);
|
| -#endif
|
| -cleanup:
|
| - return P2J(tps);
|
| -}
|
| -
|
| -TCN_IMPLEMENT_CALL(jint, Poll, destroy)(TCN_STDARGS, jlong pollset)
|
| -{
|
| - tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
|
| -
|
| - UNREFERENCED_STDARGS;
|
| - TCN_ASSERT(pollset != 0);
|
| -#ifdef TCN_DO_STATISTICS
|
| - sp_destroyed++;
|
| - apr_pool_cleanup_kill(p->pool, p, sp_poll_cleanup);
|
| - sp_poll_statistics(p);
|
| -#endif
|
| - return (jint)apr_pollset_destroy(p->pollset);
|
| -}
|
| -
|
| -static apr_status_t do_add(tcn_pollset_t *p, tcn_socket_t *s,
|
| - apr_int16_t reqevents,
|
| - apr_interval_time_t socket_timeout)
|
| -{
|
| -
|
| - apr_status_t rv;
|
| - apr_interval_time_t timeout = socket_timeout;
|
| - tcn_pfde_t *elem = NULL;
|
| -
|
| - if (p->nelts == p->nalloc) {
|
| -#ifdef TCN_DO_STATISTICS
|
| - p->sp_overflow++;
|
| -#endif
|
| - return APR_ENOMEM;
|
| - }
|
| - if (s->pe != NULL) {
|
| - /* Socket is already added to the pollset.
|
| - */
|
| -#ifdef TCN_DO_STATISTICS
|
| - p->sp_equals++;
|
| -#endif
|
| - return APR_EEXIST;
|
| - }
|
| - if (timeout == TCN_NO_SOCKET_TIMEOUT) {
|
| - timeout = p->default_timeout;
|
| - }
|
| - if (timeout > 0)
|
| - s->last_active = apr_time_now();
|
| - else
|
| - s->last_active = 0;
|
| - s->timeout = socket_timeout;
|
| - if (!APR_RING_EMPTY(&p->free_ring, tcn_pfde_t, link)) {
|
| - elem = APR_RING_FIRST(&p->free_ring);
|
| - APR_RING_REMOVE(elem, link);
|
| - }
|
| - else {
|
| - elem = (tcn_pfde_t *)apr_palloc(p->pool, sizeof(tcn_pfde_t));
|
| - APR_RING_ELEM_INIT(elem, link);
|
| - }
|
| - elem->fd.reqevents = reqevents;
|
| - elem->fd.desc_type = APR_POLL_SOCKET;
|
| - elem->fd.desc.s = s->sock;
|
| - elem->fd.client_data = s;
|
| -#ifdef TCN_DO_STATISTICS
|
| - p->sp_added++;
|
| - p->sp_max_count = TCN_MAX(p->sp_max_count, p->sp_added);
|
| -#endif
|
| - rv = apr_pollset_add(p->pollset, &elem->fd);
|
| - if (rv != APR_SUCCESS) {
|
| - APR_RING_INSERT_TAIL(&p->free_ring, elem, tcn_pfde_t, link);
|
| - }
|
| - else {
|
| - APR_RING_INSERT_TAIL(&p->poll_ring, elem, tcn_pfde_t, link);
|
| - s->pe = elem;
|
| - }
|
| - return rv;
|
| -}
|
| -
|
| -TCN_IMPLEMENT_CALL(jint, Poll, add)(TCN_STDARGS, jlong pollset,
|
| - jlong socket, jint reqevents)
|
| -{
|
| - tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
|
| - tcn_socket_t *s = J2P(socket, tcn_socket_t *);
|
| -
|
| - UNREFERENCED_STDARGS;
|
| - TCN_ASSERT(socket != 0);
|
| -
|
| - return (jint) do_add(p, s, (apr_int16_t)reqevents, TCN_NO_SOCKET_TIMEOUT);
|
| -}
|
| -
|
| -TCN_IMPLEMENT_CALL(jint, Poll, addWithTimeout)(TCN_STDARGS, jlong pollset,
|
| - jlong socket, jint reqevents,
|
| - jlong socket_timeout)
|
| -{
|
| - tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
|
| - tcn_socket_t *s = J2P(socket, tcn_socket_t *);
|
| -
|
| - UNREFERENCED_STDARGS;
|
| - TCN_ASSERT(socket != 0);
|
| -
|
| - return (jint) do_add(p, s, (apr_int16_t)reqevents, J2T(socket_timeout));
|
| -}
|
| -
|
| -TCN_IMPLEMENT_CALL(jint, Poll, remove)(TCN_STDARGS, jlong pollset,
|
| - jlong socket)
|
| -{
|
| - apr_pollfd_t fd;
|
| - apr_status_t rv;
|
| - tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
|
| - tcn_socket_t *s = J2P(socket, tcn_socket_t *);
|
| -
|
| - UNREFERENCED_STDARGS;
|
| - TCN_ASSERT(socket != 0);
|
| -
|
| - if (s->pe == NULL) {
|
| - /* Already removed */
|
| - return APR_NOTFOUND;
|
| - }
|
| - fd.desc_type = APR_POLL_SOCKET;
|
| - fd.desc.s = s->sock;
|
| - fd.client_data = s;
|
| - fd.reqevents = APR_POLLIN | APR_POLLOUT;
|
| -#ifdef TCN_DO_STATISTICS
|
| - p->sp_remove++;
|
| -#endif
|
| -
|
| - rv = apr_pollset_remove(p->pollset, &fd);
|
| - APR_RING_REMOVE(s->pe, link);
|
| - APR_RING_INSERT_TAIL(&p->dead_ring, s->pe, tcn_pfde_t, link);
|
| - s->pe = NULL;
|
| - p->nelts--;
|
| -#ifdef TCN_DO_STATISTICS
|
| - p->sp_removed++;
|
| -#endif
|
| - return rv;
|
| -}
|
| -
|
| -
|
| -TCN_IMPLEMENT_CALL(jint, Poll, poll)(TCN_STDARGS, jlong pollset,
|
| - jlong timeout, jlongArray set,
|
| - jboolean remove)
|
| -{
|
| - const apr_pollfd_t *fd = NULL;
|
| - tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
|
| - apr_int32_t i, num = 0;
|
| - apr_status_t rv = APR_SUCCESS;
|
| - apr_time_t now = 0;
|
| - apr_interval_time_t ptime = J2T(timeout);
|
| - UNREFERENCED(o);
|
| - TCN_ASSERT(pollset != 0);
|
| -
|
| -#ifdef TCN_DO_STATISTICS
|
| - p->sp_poll++;
|
| -#endif
|
| -
|
| - if (ptime > 0) {
|
| - tcn_pfde_t *ep;
|
| -
|
| - now = apr_time_now();
|
| - /* Find the minimum timeout */
|
| - APR_RING_FOREACH(ep, &p->poll_ring, tcn_pfde_t, link)
|
| - {
|
| - apr_interval_time_t socket_timeout = 0;
|
| - tcn_socket_t *s = (tcn_socket_t *)ep->fd.client_data;
|
| - if (s->timeout == TCN_NO_SOCKET_TIMEOUT) {
|
| - socket_timeout = p->default_timeout;
|
| - }
|
| - else {
|
| - socket_timeout = s->timeout;
|
| - }
|
| - if (socket_timeout >= 0) {
|
| - apr_interval_time_t t = now - s->last_active;
|
| - if (t >= socket_timeout) {
|
| - ptime = 0;
|
| - break;
|
| - }
|
| - else {
|
| - ptime = TCN_MIN(socket_timeout - t, ptime);
|
| - }
|
| - }
|
| - }
|
| - }
|
| - else if (ptime < 0)
|
| - ptime = 0;
|
| - for (;;) {
|
| - rv = apr_pollset_poll(p->pollset, ptime, &num, &fd);
|
| - if (rv != APR_SUCCESS) {
|
| - if (APR_STATUS_IS_EINTR(rv)) {
|
| -#ifdef TCN_DO_STATISTICS
|
| - p->sp_eintr++;
|
| -#endif
|
| - continue;
|
| - }
|
| - TCN_ERROR_WRAP(rv);
|
| -#ifdef TCN_DO_STATISTICS
|
| - if (rv == TCN_TIMEUP)
|
| - p->sp_poll_timeout++;
|
| - else
|
| - p->sp_err_poll++;
|
| -#endif
|
| - num = (apr_int32_t)(-rv);
|
| - }
|
| - break;
|
| - }
|
| - /* Shift all PFDs in the Dead Ring to the Free Ring */
|
| - APR_RING_CONCAT(&p->free_ring, &p->dead_ring, tcn_pfde_t, link);
|
| - if (num > 0) {
|
| -#ifdef TCN_DO_STATISTICS
|
| - p->sp_polled += num;
|
| - p->sp_max_polled = TCN_MAX(p->sp_max_polled, num);
|
| -#endif
|
| - if (!remove)
|
| - now = apr_time_now();
|
| - for (i = 0; i < num; i++) {
|
| - tcn_socket_t *s = (tcn_socket_t *)fd->client_data;
|
| - p->set[i*2+0] = (jlong)(fd->rtnevents);
|
| - p->set[i*2+1] = P2J(s);
|
| - /* If a socket is registered for multiple events and the poller has
|
| - multiple events to return it may do as a single pair in this
|
| - array or as multiple pairs depending on implementation. On OSX at
|
| - least, multiple pairs have been observed. In this case do not try
|
| - and remove socket from the pollset for a second time else a crash
|
| - will result. */
|
| - if (remove) {
|
| - if (s->pe) {
|
| - apr_pollset_remove(p->pollset, fd);
|
| - APR_RING_REMOVE(s->pe, link);
|
| - APR_RING_INSERT_TAIL(&p->dead_ring, s->pe, tcn_pfde_t, link);
|
| - s->pe = NULL;
|
| - p->nelts--;
|
| -#ifdef TCN_DO_STATISTICS
|
| - p->sp_removed++;
|
| -#endif
|
| - }
|
| - }
|
| - else {
|
| - /* Update last active with the current time
|
| - * after the poll call.
|
| - */
|
| - s->last_active = now;
|
| - }
|
| - fd ++;
|
| - }
|
| - (*e)->SetLongArrayRegion(e, set, 0, num * 2, p->set);
|
| - }
|
| -
|
| - return (jint)num;
|
| -}
|
| -
|
| -TCN_IMPLEMENT_CALL(jint, Poll, maintain)(TCN_STDARGS, jlong pollset,
|
| - jlongArray set, jboolean remove)
|
| -{
|
| - tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
|
| - apr_int32_t i = 0, num = 0;
|
| - apr_time_t now = apr_time_now();
|
| - tcn_pfde_t *ep, *ip;
|
| -
|
| - UNREFERENCED(o);
|
| - TCN_ASSERT(pollset != 0);
|
| -
|
| - /* Check for timeout sockets */
|
| - APR_RING_FOREACH_SAFE(ep, ip, &p->poll_ring, tcn_pfde_t, link)
|
| - {
|
| - apr_interval_time_t timeout = 0;
|
| - tcn_socket_t *s = (tcn_socket_t *)ep->fd.client_data;
|
| - if (s->timeout == TCN_NO_SOCKET_TIMEOUT) {
|
| - timeout = p->default_timeout;
|
| - }
|
| - else {
|
| - timeout = s->timeout;
|
| - }
|
| - if (timeout == -1) {
|
| - continue;
|
| - }
|
| - if ((now - s->last_active) >= timeout) {
|
| - p->set[num++] = P2J(s);
|
| - if (remove) {
|
| - APR_RING_REMOVE(ep, link);
|
| - APR_RING_INSERT_TAIL(&p->dead_ring, ep, tcn_pfde_t, link);
|
| - s->pe = NULL;
|
| - p->nelts--;
|
| -#ifdef TCN_DO_STATISTICS
|
| - p->sp_removed++;
|
| -#endif
|
| - }
|
| - }
|
| - }
|
| - if (num) {
|
| -#ifdef TCN_DO_STATISTICS
|
| - p->sp_maintained += num;
|
| - p->sp_max_maintained = TCN_MAX(p->sp_max_maintained, num);
|
| -#endif
|
| - if (remove) {
|
| - for (i = 0; i < num; i++) {
|
| - apr_pollfd_t fd;
|
| - tcn_socket_t *s = J2P(p->set[i], tcn_socket_t *);
|
| - fd.desc_type = APR_POLL_SOCKET;
|
| - fd.desc.s = s->sock;
|
| - fd.client_data = s;
|
| - fd.reqevents = APR_POLLIN | APR_POLLOUT;
|
| - apr_pollset_remove(p->pollset, &fd);
|
| - }
|
| - }
|
| - (*e)->SetLongArrayRegion(e, set, 0, num, p->set);
|
| - }
|
| - return (jint)num;
|
| -}
|
| -
|
| -TCN_IMPLEMENT_CALL(void, Poll, setTtl)(TCN_STDARGS, jlong pollset,
|
| - jlong default_timeout)
|
| -{
|
| - tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
|
| - UNREFERENCED_STDARGS;
|
| - p->default_timeout = J2T(default_timeout);
|
| -}
|
| -
|
| -TCN_IMPLEMENT_CALL(jlong, Poll, getTtl)(TCN_STDARGS, jlong pollset)
|
| -{
|
| - tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
|
| - UNREFERENCED_STDARGS;
|
| - return (jlong)p->default_timeout;
|
| -}
|
| -
|
| -TCN_IMPLEMENT_CALL(jint, Poll, pollset)(TCN_STDARGS, jlong pollset,
|
| - jlongArray set)
|
| -{
|
| - tcn_pollset_t *p = J2P(pollset, tcn_pollset_t *);
|
| - apr_int32_t n = 0;
|
| - tcn_pfde_t *ep;
|
| -
|
| - UNREFERENCED(o);
|
| - TCN_ASSERT(pollset != 0);
|
| -
|
| - APR_RING_FOREACH(ep, &p->poll_ring, tcn_pfde_t, link)
|
| - {
|
| - apr_pollfd_t *fd = &ep->fd;
|
| - fd->rtnevents = APR_POLLHUP | APR_POLLIN;
|
| - p->set[n++] = (jlong)(fd->rtnevents);
|
| - p->set[n++] = P2J(fd->client_data);
|
| - }
|
| - if (n > 0)
|
| - (*e)->SetLongArrayRegion(e, set, 0, n, p->set);
|
| - return n / 2;
|
| -}
|
|
|