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; |
-} |