Mercurial > hg > nginx
comparison src/os/unix/ngx_writev_chain.c @ 5917:2c64b69daec5
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.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Wed, 13 Aug 2014 15:11:45 +0400 |
parents | 8e903522c17a |
children |
comparison
equal
deleted
inserted
replaced
5916:e044893b4587 | 5917:2c64b69daec5 |
---|---|
13 ngx_chain_t * | 13 ngx_chain_t * |
14 ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) | 14 ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) |
15 { | 15 { |
16 ssize_t n, sent; | 16 ssize_t n, sent; |
17 off_t send, prev_send; | 17 off_t send, prev_send; |
18 ngx_uint_t eintr; | |
19 ngx_err_t err; | |
20 ngx_chain_t *cl; | 18 ngx_chain_t *cl; |
21 ngx_event_t *wev; | 19 ngx_event_t *wev; |
22 ngx_iovec_t vec; | 20 ngx_iovec_t vec; |
23 struct iovec iovs[NGX_IOVS_PREALLOCATE]; | 21 struct iovec iovs[NGX_IOVS_PREALLOCATE]; |
24 | 22 |
49 | 47 |
50 vec.iovs = iovs; | 48 vec.iovs = iovs; |
51 vec.nalloc = NGX_IOVS_PREALLOCATE; | 49 vec.nalloc = NGX_IOVS_PREALLOCATE; |
52 | 50 |
53 for ( ;; ) { | 51 for ( ;; ) { |
54 eintr = 0; | |
55 prev_send = send; | 52 prev_send = send; |
56 | 53 |
57 /* create the iovec and coalesce the neighbouring bufs */ | 54 /* create the iovec and coalesce the neighbouring bufs */ |
58 | 55 |
59 cl = ngx_output_chain_to_iovec(&vec, in, limit - send, c->log); | 56 cl = ngx_output_chain_to_iovec(&vec, in, limit - send, c->log); |
81 return NGX_CHAIN_ERROR; | 78 return NGX_CHAIN_ERROR; |
82 } | 79 } |
83 | 80 |
84 send += vec.size; | 81 send += vec.size; |
85 | 82 |
86 n = writev(c->fd, vec.iovs, vec.count); | 83 n = ngx_writev(c, &vec); |
87 | 84 |
88 if (n == -1) { | 85 if (n == NGX_ERROR) { |
89 err = ngx_errno; | 86 return NGX_CHAIN_ERROR; |
90 | 87 } |
91 switch (err) { | 88 |
92 case NGX_EAGAIN: | 89 sent = (n == NGX_AGAIN) ? 0 : n; |
93 break; | |
94 | |
95 case NGX_EINTR: | |
96 eintr = 1; | |
97 break; | |
98 | |
99 default: | |
100 wev->error = 1; | |
101 (void) ngx_connection_error(c, err, "writev() failed"); | |
102 return NGX_CHAIN_ERROR; | |
103 } | |
104 | |
105 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
106 "writev() not ready"); | |
107 } | |
108 | |
109 sent = n > 0 ? n : 0; | |
110 | |
111 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent); | |
112 | 90 |
113 c->sent += sent; | 91 c->sent += sent; |
114 | 92 |
115 in = ngx_chain_update_sent(in, sent); | 93 in = ngx_chain_update_sent(in, sent); |
116 | |
117 if (eintr) { | |
118 send = prev_send; | |
119 continue; | |
120 } | |
121 | 94 |
122 if (send - prev_send != sent) { | 95 if (send - prev_send != sent) { |
123 wev->ready = 0; | 96 wev->ready = 0; |
124 return in; | 97 return in; |
125 } | 98 } |
201 vec->count = n; | 174 vec->count = n; |
202 vec->size = total; | 175 vec->size = total; |
203 | 176 |
204 return in; | 177 return in; |
205 } | 178 } |
179 | |
180 | |
181 ssize_t | |
182 ngx_writev(ngx_connection_t *c, ngx_iovec_t *vec) | |
183 { | |
184 ssize_t n; | |
185 ngx_err_t err; | |
186 | |
187 eintr: | |
188 | |
189 n = writev(c->fd, vec->iovs, vec->count); | |
190 | |
191 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
192 "writev: %z of %uz", n, vec->size); | |
193 | |
194 if (n == -1) { | |
195 err = ngx_errno; | |
196 | |
197 switch (err) { | |
198 case NGX_EAGAIN: | |
199 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
200 "writev() not ready"); | |
201 return NGX_AGAIN; | |
202 | |
203 case NGX_EINTR: | |
204 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
205 "writev() was interrupted"); | |
206 goto eintr; | |
207 | |
208 default: | |
209 c->write->error = 1; | |
210 ngx_connection_error(c, err, "writev() failed"); | |
211 return NGX_ERROR; | |
212 } | |
213 } | |
214 | |
215 return n; | |
216 } |