varnish-cache/bin/varnishd/http1/cache_http1_pipe.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2011 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 *
8
 * SPDX-License-Identifier: BSD-2-Clause
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 *
31
 * XXX: charge bytes to srcaddr
32
 */
33
34
#include "config.h"
35
36
#include "cache/cache_varnishd.h"
37
38
#include <poll.h>
39
#include <stdio.h>
40
41
#include "cache_http1.h"
42
43
#include "VSC_vbe.h"
44
45
static struct lock pipestat_mtx;
46
47
static int
48 44
rdf(int fd0, int fd1, uint64_t *pcnt)
49
{
50
        int i, j;
51
        char buf[BUFSIZ], *p;
52
53 44
        i = read(fd0, buf, sizeof buf);
54 44
        if (i <= 0)
55 28
                return (1);
56 32
        for (p = buf; i > 0; i -= j, p += j) {
57 16
                j = write(fd1, p, i);
58 16
                if (j <= 0)
59 0
                        return (1);
60 16
                *pcnt += j;
61 16
                if (i != j)
62 0
                        (void)usleep(100000);           /* XXX hack */
63 16
        }
64 16
        return (0);
65 44
}
66
67
int
68 16
V1P_Enter(void)
69
{
70 16
        int retval = 0;
71
72 16
        Lck_Lock(&pipestat_mtx);
73 16
        if (cache_param->pipe_sess_max == 0 ||
74 1
            VSC_C_main->n_pipe < cache_param->pipe_sess_max)
75 15
                VSC_C_main->n_pipe++;
76
        else
77 1
                retval = -1;
78 16
        Lck_Unlock(&pipestat_mtx);
79 16
        return (retval);
80
}
81
82
void
83 15
V1P_Leave(void)
84
{
85
86 15
        Lck_Lock(&pipestat_mtx);
87 15
        assert(VSC_C_main->n_pipe > 0);
88 15
        VSC_C_main->n_pipe--;
89 15
        Lck_Unlock(&pipestat_mtx);
90 15
}
91
92
void
93 15
V1P_Charge(struct req *req, const struct v1p_acct *a, struct VSC_vbe *b)
94
{
95
96 15
        AN(b);
97 30
        VSLb(req->vsl, SLT_PipeAcct, "%ju %ju %ju %ju",
98 15
            (uintmax_t)a->req,
99 15
            (uintmax_t)a->bereq,
100 15
            (uintmax_t)a->in,
101 15
            (uintmax_t)a->out);
102
103 15
        Lck_Lock(&pipestat_mtx);
104 15
        VSC_C_main->s_pipe_hdrbytes += a->req;
105 15
        VSC_C_main->s_pipe_in += a->in;
106 15
        VSC_C_main->s_pipe_out += a->out;
107 15
        b->pipe_hdrbytes += a->bereq;
108 15
        b->pipe_out += a->in;
109 15
        b->pipe_in += a->out;
110 15
        Lck_Unlock(&pipestat_mtx);
111 15
}
112
113
void
114 14
V1P_Process(const struct req *req, int fd, struct v1p_acct *v1a)
115
{
116
        struct pollfd fds[2];
117
        int i, j;
118
119 14
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
120 14
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
121 14
        assert(fd > 0);
122
123 14
        if (req->htc->pipeline_b != NULL) {
124 6
                j = write(fd,  req->htc->pipeline_b,
125 3
                    req->htc->pipeline_e - req->htc->pipeline_b);
126 3
                if (j < 0)
127 0
                        return;
128 3
                req->htc->pipeline_b = NULL;
129 3
                req->htc->pipeline_e = NULL;
130 3
                v1a->in += j;
131 3
        }
132 14
        memset(fds, 0, sizeof fds);
133 14
        fds[0].fd = fd;
134 14
        fds[0].events = POLLIN;
135 14
        fds[1].fd = req->sp->fd;
136 14
        fds[1].events = POLLIN;
137
138 44
        while (fds[0].fd > -1 || fds[1].fd > -1) {
139 44
                fds[0].revents = 0;
140 44
                fds[1].revents = 0;
141 88
                i = poll(fds, 2,
142 44
                    (int)(cache_param->pipe_timeout * 1e3));
143 44
                if (i < 1)
144 0
                        break;
145 44
                if (fds[0].revents &&
146 29
                    rdf(fd, req->sp->fd, &v1a->out)) {
147 14
                        if (fds[1].fd == -1)
148 1
                                break;
149 13
                        (void)shutdown(fd, SHUT_RD);
150 13
                        (void)shutdown(req->sp->fd, SHUT_WR);
151 13
                        fds[0].events = 0;
152 13
                        fds[0].fd = -1;
153 13
                }
154 43
                if (fds[1].revents &&
155 15
                    rdf(req->sp->fd, fd, &v1a->in)) {
156 14
                        if (fds[0].fd == -1)
157 13
                                break;
158 1
                        (void)shutdown(req->sp->fd, SHUT_RD);
159 1
                        (void)shutdown(fd, SHUT_WR);
160 1
                        fds[1].events = 0;
161 1
                        fds[1].fd = -1;
162 1
                }
163
        }
164 14
}
165
166
/*--------------------------------------------------------------------*/
167
168
void
169 769
V1P_Init(void)
170
{
171
172 769
        Lck_New(&pipestat_mtx, lck_pipestat);
173 769
}