Mercurial > hg > nginx-vendor-0-5
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 */ |