#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <poll.h>
#include "shmlog.h"
+#include "heritage.h"
#include "vcl.h"
#include "cache.h"
cnt_done(struct sess *sp)
{
double dh, dp, da;
+ struct pollfd fds[1];
+ int i;
AZ(sp->obj);
AZ(sp->vbc);
sp->xid = 0;
sp->t_open = sp->t_end;
SES_Charge(sp);
- if (sp->fd > 0) {
- VSL(SLT_SessionReuse, sp->fd, "%s %s", sp->addr, sp->port);
-
- /* If we have anything in the input buffer, start over */
- /*
- * XXX: we might even want to do a short timed read (poll)
- * XXX: here to see if something is pending in the kernel
- */
-
- if (http_RecvPrepAgain(sp->http)) {
- sp->step = STP_RECV;
- return (0);
- }
- if (sp->http->t < sp->http->v) {
- sp->step = STP_AGAIN;
- return (0);
- }
+ if (sp->fd < 0) {
+ VSL_stats->sess_closed++;
+ sp->wrk->idle = sp->t_open.tv_sec;
+ vca_return_session(sp);
+ return (1);
}
+ if (http_RecvPrepAgain(sp->http)) {
+ VSL_stats->sess_pipeline++;
+ VSL(SLT_SessionReuse, sp->fd, "%s %s", sp->addr, sp->port);
+ sp->step = STP_RECV;
+ return (0);
+ }
+ if (sp->http->t < sp->http->v) {
+ VSL_stats->sess_readahead++;
+ VSL(SLT_SessionReuse, sp->fd, "%s %s", sp->addr, sp->port);
+ sp->step = STP_AGAIN;
+ return (0);
+ }
+ if (params->session_grace == 0) {
+ VSL_stats->sess_herd++;
+ sp->wrk->idle = sp->t_open.tv_sec;
+ vca_return_session(sp);
+ return (1);
+ }
+ fds[0].fd = sp->fd;
+ fds[0].events = POLLIN;
+ fds[0].revents = 0;
+ i = poll(fds, 1, params->session_grace);
+ if (i == 1 && (fds[0].revents & POLLHUP)) {
+ VSL_stats->sess_EOF++;
+ vca_close_session(sp, "EOF");
+ } else if (i == 1 && (fds[0].revents & POLLIN)) {
+ VSL_stats->sess_ready++;
+ VSL(SLT_SessionReuse, sp->fd, "%s %s",
+ sp->addr, sp->port);
+ sp->step = STP_AGAIN;
+ return (0);
+ } else {
+ VSL_stats->sess_herd++;
+ }
sp->wrk->idle = sp->t_open.tv_sec;
vca_return_session(sp);
return (1);
/* Sendfile object minimum size */
unsigned sendfile_threshold;
+
+ /* Session dispostion grace period */
+ unsigned session_grace;
};
extern struct params *params;
/*--------------------------------------------------------------------*/
+static void
+tweak_session_grace(struct cli *cli, struct parspec *par, const char *arg)
+{
+ unsigned u;
+
+ (void)par;
+ if (arg != NULL) {
+ u = strtoul(arg, NULL, 0);
+ if (u == 0) {
+ cli_out(cli, "Timeout must be greater than zero\n");
+ cli_result(cli, CLIS_PARAM);
+ return;
+ }
+ params->session_grace = u;
+ }
+ if (cli == NULL)
+ return;
+ cli_out(cli, "%u [milliseconds]\n", params->session_grace);
+}
+
+/*--------------------------------------------------------------------*/
+
static void
tweak_auto_restart(struct cli *cli, struct parspec *par, const char *arg)
{
"The minimum size of objects transmitted with sendfile.\n"
"Default is 8192 bytes.", "8192" },
#endif /* HAVE_SENDFILE */
+ { "session_grace", tweak_session_grace,
+ "How long a workerthread waits for a new request to arrive "
+ "before sending the session to the herder.\n"
+ "Default is 10 msec.", "10" },
{ NULL, NULL, NULL }
};
MAC_STAT(s_fetch, uint64_t, "u", "Total fetch")
MAC_STAT(s_hdrbytes, uint64_t, "u", "Total header bytes")
MAC_STAT(s_bodybytes, uint64_t, "u", "Total body bytes")
+
+MAC_STAT(sess_closed, uint64_t, "u", "Session Closed")
+MAC_STAT(sess_pipeline, uint64_t, "u", "Session Pipeline")
+MAC_STAT(sess_readahead, uint64_t, "u", "Session Read Ahead")
+MAC_STAT(sess_EOF, uint64_t, "u", "Session EOF")
+MAC_STAT(sess_ready, uint64_t, "u", "Session Ready")
+MAC_STAT(sess_herd, uint64_t, "u", "Session herd")