Mercurial > hg > nginx-vendor-0-8
comparison src/os/unix/ngx_writev_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 #define NGX_IOVS 8 | |
13 | |
14 | |
15 ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) | |
16 { | |
17 u_char *prev; | |
18 ssize_t n, size; | |
19 off_t send, sprev, sent; | |
20 ngx_uint_t eintr, complete; | |
21 ngx_err_t err; | |
22 ngx_array_t vec; | |
23 ngx_chain_t *cl; | |
24 ngx_event_t *wev; | |
25 struct iovec *iov, iovs[NGX_IOVS]; | |
26 | |
27 wev = c->write; | |
28 | |
29 if (!wev->ready) { | |
30 return in; | |
31 } | |
32 | |
33 #if (HAVE_KQUEUE) | |
34 | |
35 if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && wev->pending_eof) { | |
36 ngx_log_error(NGX_LOG_INFO, c->log, wev->kq_errno, | |
37 "kevent() reported about an closed connection"); | |
38 | |
39 wev->error = 1; | |
40 return NGX_CHAIN_ERROR; | |
41 } | |
42 | |
43 #endif | |
44 | |
45 send = 0; | |
46 complete = 0; | |
47 | |
48 vec.elts = iovs; | |
49 vec.size = sizeof(struct iovec); | |
50 vec.nalloc = NGX_IOVS; | |
51 vec.pool = c->pool; | |
52 | |
53 for ( ;; ) { | |
54 prev = NULL; | |
55 iov = NULL; | |
56 eintr = 0; | |
57 sprev = send; | |
58 | |
59 vec.nelts = 0; | |
60 | |
61 /* create the iovec and coalesce the neighbouring bufs */ | |
62 | |
63 for (cl = in; cl && vec.nelts < IOV_MAX && send < limit; cl = cl->next) | |
64 { | |
65 if (ngx_buf_special(cl->buf)) { | |
66 continue; | |
67 } | |
68 | |
69 size = cl->buf->last - cl->buf->pos; | |
70 | |
71 if (send + size > limit) { | |
72 size = limit - send; | |
73 } | |
74 | |
75 if (prev == cl->buf->pos) { | |
76 iov->iov_len += size; | |
77 | |
78 } else { | |
79 if (!(iov = ngx_array_push(&vec))) { | |
80 return NGX_CHAIN_ERROR; | |
81 } | |
82 | |
83 iov->iov_base = (void *) cl->buf->pos; | |
84 iov->iov_len = size; | |
85 } | |
86 | |
87 prev = cl->buf->pos + size; | |
88 send += size; | |
89 } | |
90 | |
91 n = writev(c->fd, vec.elts, vec.nelts); | |
92 | |
93 if (n == -1) { | |
94 err = ngx_errno; | |
95 | |
96 if (err == NGX_EAGAIN || err == NGX_EINTR) { | |
97 if (err == NGX_EINTR) { | |
98 eintr = 1; | |
99 } | |
100 | |
101 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
102 "writev() not ready"); | |
103 | |
104 } else { | |
105 wev->error = 1; | |
106 ngx_connection_error(c, err, "writev() failed"); | |
107 return NGX_CHAIN_ERROR; | |
108 } | |
109 } | |
110 | |
111 sent = n > 0 ? n : 0; | |
112 | |
113 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
114 "writev: " OFF_T_FMT, sent); | |
115 | |
116 if (send - sprev == sent) { | |
117 complete = 1; | |
118 } | |
119 | |
120 c->sent += sent; | |
121 | |
122 for (cl = in; cl && sent > 0; cl = cl->next) { | |
123 if (ngx_buf_special(cl->buf)) { | |
124 continue; | |
125 } | |
126 | |
127 if (sent == 0) { | |
128 break; | |
129 } | |
130 | |
131 size = cl->buf->last - cl->buf->pos; | |
132 | |
133 if (sent >= size) { | |
134 sent -= size; | |
135 cl->buf->pos = cl->buf->last; | |
136 | |
137 continue; | |
138 } | |
139 | |
140 cl->buf->pos += sent; | |
141 | |
142 break; | |
143 } | |
144 | |
145 if (eintr) { | |
146 continue; | |
147 } | |
148 | |
149 if (!complete) { | |
150 wev->ready = 0; | |
151 return cl; | |
152 } | |
153 | |
154 if (send >= limit || cl == NULL) { | |
155 return cl; | |
156 } | |
157 | |
158 in = cl; | |
159 } | |
160 } |