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