Moved writev() handling code to a separate function.
This reduces code duplication and unifies debug logging of the writev() syscall
among various send chain functions.
Valentin Bartenev
7 years ago
32 | 32 | int rc; |
33 | 33 | off_t send, prev_send, sent; |
34 | 34 | off_t file_size; |
35 | ssize_t n; | |
35 | 36 | ngx_uint_t eintr; |
36 | 37 | ngx_err_t err; |
37 | 38 | ngx_buf_t *file; |
171 | 172 | rc, file->file_pos, sent, file_size + header.size); |
172 | 173 | |
173 | 174 | } else { |
174 | rc = writev(c->fd, header.iovs, header.count); | |
175 | ||
176 | ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
177 | "writev: %d of %uz", rc, header.size); | |
178 | ||
179 | if (rc == -1) { | |
180 | err = ngx_errno; | |
181 | ||
182 | switch (err) { | |
183 | case NGX_EAGAIN: | |
184 | break; | |
185 | ||
186 | case NGX_EINTR: | |
187 | eintr = 1; | |
188 | break; | |
189 | ||
190 | default: | |
191 | wev->error = 1; | |
192 | ngx_connection_error(c, err, "writev() failed"); | |
193 | return NGX_CHAIN_ERROR; | |
194 | } | |
195 | ||
196 | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
197 | "writev() not ready"); | |
198 | } | |
199 | ||
200 | sent = rc > 0 ? rc : 0; | |
175 | n = ngx_writev(c, &header); | |
176 | ||
177 | if (n == NGX_ERROR) { | |
178 | return NGX_CHAIN_ERROR; | |
179 | } | |
180 | ||
181 | sent = (n == NGX_AGAIN) ? 0 : n; | |
201 | 182 | } |
202 | 183 | |
203 | 184 | c->sent += sent; |
34 | 34 | int rc, flags; |
35 | 35 | off_t send, prev_send, sent; |
36 | 36 | size_t file_size; |
37 | ssize_t n; | |
37 | 38 | ngx_uint_t eintr, eagain; |
38 | 39 | ngx_err_t err; |
39 | 40 | ngx_buf_t *file; |
216 | 217 | rc, file->file_pos, sent, file_size + header.size); |
217 | 218 | |
218 | 219 | } else { |
219 | rc = writev(c->fd, header.iovs, header.count); | |
220 | ||
221 | ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
222 | "writev: %d of %uz", rc, header.size); | |
223 | ||
224 | if (rc == -1) { | |
225 | err = ngx_errno; | |
226 | ||
227 | switch (err) { | |
228 | case NGX_EAGAIN: | |
229 | break; | |
230 | ||
231 | case NGX_EINTR: | |
232 | eintr = 1; | |
233 | break; | |
234 | ||
235 | default: | |
236 | wev->error = 1; | |
237 | ngx_connection_error(c, err, "writev() failed"); | |
238 | return NGX_CHAIN_ERROR; | |
239 | } | |
240 | ||
241 | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
242 | "writev() not ready"); | |
243 | } | |
244 | ||
245 | sent = rc > 0 ? rc : 0; | |
220 | n = ngx_writev(c, &header); | |
221 | ||
222 | if (n == NGX_ERROR) { | |
223 | return NGX_CHAIN_ERROR; | |
224 | } | |
225 | ||
226 | sent = (n == NGX_AGAIN) ? 0 : n; | |
246 | 227 | } |
247 | 228 | |
248 | 229 | c->sent += sent; |
32 | 32 | int rc, tcp_nodelay; |
33 | 33 | off_t send, prev_send, sent; |
34 | 34 | size_t file_size; |
35 | ssize_t n; | |
35 | 36 | ngx_err_t err; |
36 | 37 | ngx_buf_t *file; |
37 | 38 | ngx_uint_t eintr; |
198 | 199 | rc, file->file_pos, sent, file_size); |
199 | 200 | |
200 | 201 | } else { |
201 | rc = writev(c->fd, header.iovs, header.count); | |
202 | ||
203 | if (rc == -1) { | |
204 | err = ngx_errno; | |
205 | ||
206 | switch (err) { | |
207 | case NGX_EAGAIN: | |
208 | break; | |
209 | ||
210 | case NGX_EINTR: | |
211 | eintr = 1; | |
212 | break; | |
213 | ||
214 | default: | |
215 | wev->error = 1; | |
216 | ngx_connection_error(c, err, "writev() failed"); | |
217 | return NGX_CHAIN_ERROR; | |
218 | } | |
219 | ||
220 | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
221 | "writev() not ready"); | |
222 | } | |
223 | ||
224 | sent = rc > 0 ? rc : 0; | |
225 | ||
226 | ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %O", sent); | |
202 | n = ngx_writev(c, &header); | |
203 | ||
204 | if (n == NGX_ERROR) { | |
205 | return NGX_CHAIN_ERROR; | |
206 | } | |
207 | ||
208 | sent = (n == NGX_AGAIN) ? 0 : n; | |
227 | 209 | } |
228 | 210 | |
229 | 211 | c->sent += sent; |
74 | 74 | size_t limit, ngx_log_t *log); |
75 | 75 | |
76 | 76 | |
77 | ssize_t ngx_writev(ngx_connection_t *c, ngx_iovec_t *vec); | |
78 | ||
79 | ||
77 | 80 | extern ngx_os_io_t ngx_os_io; |
78 | 81 | extern ngx_int_t ngx_ncpu; |
79 | 82 | extern ngx_int_t ngx_max_sockets; |
14 | 14 | { |
15 | 15 | ssize_t n, sent; |
16 | 16 | off_t send, prev_send; |
17 | ngx_uint_t eintr; | |
18 | ngx_err_t err; | |
19 | 17 | ngx_chain_t *cl; |
20 | 18 | ngx_event_t *wev; |
21 | 19 | ngx_iovec_t vec; |
50 | 48 | vec.nalloc = NGX_IOVS_PREALLOCATE; |
51 | 49 | |
52 | 50 | for ( ;; ) { |
53 | eintr = 0; | |
54 | 51 | prev_send = send; |
55 | 52 | |
56 | 53 | /* create the iovec and coalesce the neighbouring bufs */ |
82 | 79 | |
83 | 80 | send += vec.size; |
84 | 81 | |
85 | n = writev(c->fd, vec.iovs, vec.count); | |
86 | ||
87 | if (n == -1) { | |
88 | err = ngx_errno; | |
89 | ||
90 | switch (err) { | |
91 | case NGX_EAGAIN: | |
92 | break; | |
93 | ||
94 | case NGX_EINTR: | |
95 | eintr = 1; | |
96 | break; | |
97 | ||
98 | default: | |
99 | wev->error = 1; | |
100 | (void) ngx_connection_error(c, err, "writev() failed"); | |
101 | return NGX_CHAIN_ERROR; | |
102 | } | |
103 | ||
104 | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
105 | "writev() not ready"); | |
106 | } | |
107 | ||
108 | sent = n > 0 ? n : 0; | |
109 | ||
110 | ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent); | |
82 | n = ngx_writev(c, &vec); | |
83 | ||
84 | if (n == NGX_ERROR) { | |
85 | return NGX_CHAIN_ERROR; | |
86 | } | |
87 | ||
88 | sent = (n == NGX_AGAIN) ? 0 : n; | |
111 | 89 | |
112 | 90 | c->sent += sent; |
113 | 91 | |
114 | 92 | in = ngx_chain_update_sent(in, sent); |
115 | ||
116 | if (eintr) { | |
117 | send = prev_send; | |
118 | continue; | |
119 | } | |
120 | 93 | |
121 | 94 | if (send - prev_send != sent) { |
122 | 95 | wev->ready = 0; |
202 | 175 | |
203 | 176 | return in; |
204 | 177 | } |
178 | ||
179 | ||
180 | ssize_t | |
181 | ngx_writev(ngx_connection_t *c, ngx_iovec_t *vec) | |
182 | { | |
183 | ssize_t n; | |
184 | ngx_err_t err; | |
185 | ||
186 | eintr: | |
187 | ||
188 | n = writev(c->fd, vec->iovs, vec->count); | |
189 | ||
190 | ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
191 | "writev: %z of %uz", n, vec->size); | |
192 | ||
193 | if (n == -1) { | |
194 | err = ngx_errno; | |
195 | ||
196 | switch (err) { | |
197 | case NGX_EAGAIN: | |
198 | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
199 | "writev() not ready"); | |
200 | return NGX_AGAIN; | |
201 | ||
202 | case NGX_EINTR: | |
203 | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
204 | "writev() was interrupted"); | |
205 | goto eintr; | |
206 | ||
207 | default: | |
208 | c->write->error = 1; | |
209 | ngx_connection_error(c, err, "writev() failed"); | |
210 | return NGX_ERROR; | |
211 | } | |
212 | } | |
213 | ||
214 | return n; | |
215 | } |