comparison src/os/unix/ngx_readv_chain.c @ 0:f0b350454894 NGINX_0_1_0

nginx 0.1.0 *) The first public version.
author Igor Sysoev <http://sysoev.ru>
date Mon, 04 Oct 2004 00:00:00 +0400
parents
children 4b2dafa26fe2
comparison
equal deleted inserted replaced
-1:000000000000 0:f0b350454894
1
2 /*
3 * Copyright (C) Igor Sysoev
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_event.h>
10
11
12 #if (HAVE_KQUEUE)
13
14 ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
15 {
16 u_char *prev;
17 ssize_t n, size;
18 ngx_err_t err;
19 ngx_array_t io;
20 ngx_event_t *rev;
21 struct iovec *iov;
22
23 rev = c->read;
24
25 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
26 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
27 "readv: eof:%d, avail:%d, err:%d",
28 rev->pending_eof, rev->available, rev->kq_errno);
29
30 if (rev->available == 0) {
31 if (rev->pending_eof) {
32 rev->ready = 0;
33 rev->eof = 1;
34
35 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
36 "kevent() reported about an closed connection");
37
38 if (rev->kq_errno) {
39 rev->error = 1;
40 ngx_set_socket_errno(rev->kq_errno);
41 return NGX_ERROR;
42 }
43
44 return 0;
45
46 } else {
47 return NGX_AGAIN;
48 }
49 }
50 }
51
52 prev = NULL;
53 iov = NULL;
54 size = 0;
55
56 ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_ERROR);
57
58 /* coalesce the neighbouring bufs */
59
60 while (chain) {
61 if (prev == chain->buf->last) {
62 iov->iov_len += chain->buf->end - chain->buf->last;
63
64 } else {
65 ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR);
66 iov->iov_base = (void *) chain->buf->last;
67 iov->iov_len = chain->buf->end - chain->buf->last;
68 }
69
70 size += chain->buf->end - chain->buf->last;
71 prev = chain->buf->end;
72 chain = chain->next;
73 }
74
75 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
76 "readv: %d, last:%d", io.nelts, iov->iov_len);
77
78 rev = c->read;
79
80 do {
81 n = readv(c->fd, (struct iovec *) io.elts, io.nelts);
82
83 if (n >= 0) {
84 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
85 rev->available -= n;
86
87 /*
88 * rev->available can be negative here because some additional
89 * bytes can be received between kevent() and recv()
90 */
91
92 if (rev->available <= 0) {
93 if (!rev->pending_eof) {
94 rev->ready = 0;
95 }
96
97 if (rev->available < 0) {
98 rev->available = 0;
99 }
100 }
101
102 return n;
103 }
104
105 if (n < size) {
106 rev->ready = 0;
107 }
108
109 if (n == 0) {
110 rev->eof = 1;
111 }
112
113 return n;
114 }
115
116 err = ngx_socket_errno;
117
118 if (err == NGX_EAGAIN || err == NGX_EINTR) {
119 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
120 "readv() not ready");
121 n = NGX_AGAIN;
122
123 } else {
124 n = ngx_connection_error(c, err, "readv() failed");
125 break;
126 }
127
128 } while (err == NGX_EINTR);
129
130 rev->ready = 0;
131
132 if (n == NGX_ERROR){
133 c->read->error = 1;
134 }
135
136 return n;
137 }
138
139 #else /* ! NAVE_KQUEUE */
140
141 ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
142 {
143 u_char *prev;
144 ssize_t n, size;
145 ngx_err_t err;
146 ngx_array_t io;
147 ngx_event_t *rev;
148 struct iovec *iov;
149
150 prev = NULL;
151 iov = NULL;
152 size = 0;
153
154 ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_ERROR);
155
156 /* coalesce the neighbouring bufs */
157
158 while (chain) {
159 if (prev == chain->buf->last) {
160 iov->iov_len += chain->buf->end - chain->buf->last;
161
162 } else {
163 ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR);
164 iov->iov_base = chain->buf->last;
165 iov->iov_len = chain->buf->end - chain->buf->last;
166 }
167
168 size += chain->buf->end - chain->buf->last;
169 prev = chain->buf->end;
170 chain = chain->next;
171 }
172
173 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
174 "readv: %d:%d", io.nelts, iov->iov_len);
175
176 rev = c->read;
177
178 do {
179 n = readv(c->fd, (struct iovec *) io.elts, io.nelts);
180
181 if (n == 0) {
182 rev->ready = 0;
183 rev->eof = 1;
184
185 return n;
186
187 } else if (n > 0) {
188
189 if (n < size && !(ngx_event_flags & NGX_HAVE_GREEDY_EVENT)) {
190 rev->ready = 0;
191 }
192
193 return n;
194 }
195
196 err = ngx_socket_errno;
197
198 if (err == NGX_EAGAIN || err == NGX_EINTR) {
199 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
200 "readv() not ready");
201 n = NGX_AGAIN;
202
203 } else {
204 n = ngx_connection_error(c, err, "readv() failed");
205 break;
206 }
207
208 } while (err == NGX_EINTR);
209
210 rev->ready = 0;
211
212 if (n == NGX_ERROR){
213 c->read->error = 1;
214 }
215
216 return n;
217 }
218
219 #endif /* NAVE_KQUEUE */