#if APR_HAVE_LIMITS_H
#include <limits.h>
#endif
+#include <assert.h>
#if defined(HAVE_OPENSSL)
int slot;
int requests;
int concurrency;
+ int polled;
int succeeded_once; /* response header received once */
apr_int64_t started; /* number of requests started, so no excess */
static apr_thread_cond_t *workers_can_start;
#endif
-static APR_INLINE int worker_should_stop(struct worker *worker)
+static APR_INLINE int worker_can_stop(struct worker *worker)
{
return (lasttime >= stoptime
|| (rlimited && worker->metrics.done >= worker->requests));
}
-static APR_INLINE int worker_can_start_connection(struct worker *worker)
+static APR_INLINE int worker_can_connect(struct worker *worker)
{
- return !(worker_should_stop(worker)
+ return !(lasttime >= stoptime
|| (rlimited && worker->started >= worker->requests));
}
graceful_strerror("apr_pollset_remove()", rv);
return 0;
}
- }
+ assert(c->worker->polled > 0);
+ c->worker->polled--;
+ }
c->pollfd.reqevents = new_reqevents;
if (new_reqevents != 0) {
graceful_strerror("apr_pollset_add()", rv);
return 0;
}
+ c->worker->polled++;
}
}
return 1;
for (i=1; i<count; i++) {
cert = (X509 *)SK_VALUE(sk, i);
ssl_print_cert_info(bio_out, cert);
- }
+ }
}
cert = SSL_get_peer_certificate(c->ssl);
if (cert == NULL) {
struct worker *worker = c->worker;
apr_status_t rv;
- if (!worker_can_start_connection(worker)) {
+ if (!worker_can_connect(worker)) {
return;
}
{
struct worker *worker = c->worker;
int good = (c->gotheader && c->bread >= c->length);
+ int final_state = c->state;
/* close before measuring, to account for shutdown time */
if (!reuse || !good) {
*/
worker->metrics.doneka--;
worker->metrics.aborted_ka++;
+ if (final_state > STATE_WRITE) {
+ worker->started--;
+ }
}
else {
/* save out time */
if (tlimit || worker->metrics.done < worker->requests) {
apr_time_t tnow = lasttime = c->end = apr_time_now();
- struct data *s = &worker->stats[worker->metrics.done++ % worker->requests];
+ struct data *s = &worker->stats[worker->metrics.done % worker->requests];
/* Cumulative for when worker->metrics.done > worker->requests (tlimit),
* consolidate_metrics() will do the mean.
}
}
}
+ worker->metrics.done++;
/* update worker's metrics */
if (good) {
}
if (!reuse) {
- start_connection(c); /* nop if !worker_can_start_connection() */
+ start_connection(c); /* nop if !worker_can_connect() */
}
- else if (worker_can_start_connection(worker)) {
+ else if (worker_can_connect(worker)) {
c->keptalive++;
worker->metrics.doneka++;
apr_int32_t n;
const apr_pollfd_t *pollresults, *pollfd;
apr_interval_time_t t = aprtimeout;
- apr_time_t now = apr_time_now();
-
- while (!APR_RING_EMPTY(&worker->delayed_ring, connection, delay_list)) {
- c = APR_RING_FIRST(&worker->delayed_ring);
- if (c->delay <= now) {
- APR_RING_REMOVE(c, delay_list);
- APR_RING_ELEM_INIT(c, delay_list);
- c->delay = 0;
- start_connection(c);
- }
- else {
- t = c->delay - now;
- break;
- }
+
+ if (!APR_RING_EMPTY(&worker->delayed_ring, connection, delay_list)) {
+ apr_time_t now = apr_time_now();
+ do {
+ c = APR_RING_FIRST(&worker->delayed_ring);
+ if (c->delay <= now) {
+ APR_RING_REMOVE(c, delay_list);
+ APR_RING_ELEM_INIT(c, delay_list);
+ c->delay = 0;
+ start_connection(c);
+ }
+ else {
+ t = c->delay - now;
+ break;
+ }
+ } while (!APR_RING_EMPTY(&worker->delayed_ring, connection, delay_list));
}
n = worker->metrics.concurrent;
continue;
}
}
- } while (!worker_should_stop(worker));
+ } while (worker->polled > 0 && stoptime);
+
+ assert(worker_can_stop(worker));
}
#if APR_HAS_THREADS
exit(1);
}
#endif
-
+
if (!(ssl_ctx = SSL_CTX_new(meth))) {
BIO_printf(bio_err, "Could not initialize SSL Context.\n");
ERR_print_errors(bio_err);