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 }