Mercurial > hg > nginx-ranges
comparison src/os/unix/ngx_solaris_sendfilev_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 | cc9f381affaa |
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_SENDFILEVECS 16 | |
13 | |
14 | |
15 ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, | |
16 off_t limit) | |
17 { | |
18 int fd; | |
19 u_char *prev; | |
20 off_t fprev, sprev, send, aligned; | |
21 ssize_t size, sent, n; | |
22 ngx_int_t eintr, complete; | |
23 ngx_err_t err; | |
24 sendfilevec_t *sfv, sfvs[NGX_SENDFILEVECS]; | |
25 ngx_array_t vec; | |
26 ngx_event_t *wev; | |
27 ngx_chain_t *cl, *tail; | |
28 | |
29 wev = c->write; | |
30 | |
31 if (!wev->ready) { | |
32 return in; | |
33 } | |
34 | |
35 send = 0; | |
36 complete = 0; | |
37 | |
38 vec.elts = sfvs; | |
39 vec.size = sizeof(sendfilevec_t); | |
40 vec.nalloc = NGX_SENDFILEVECS; | |
41 vec.pool = c->pool; | |
42 | |
43 for ( ;; ) { | |
44 fd = SFV_FD_SELF; | |
45 prev = NULL; | |
46 fprev = 0; | |
47 sfv = NULL; | |
48 eintr = 0; | |
49 sent = 0; | |
50 sprev = send; | |
51 | |
52 vec.nelts = 0; | |
53 | |
54 /* create the sendfilevec and coalesce the neighbouring bufs */ | |
55 | |
56 for (cl = in; cl && vec.nelts < IOV_MAX && send < limit; cl = cl->next) | |
57 { | |
58 if (ngx_buf_special(cl->buf)) { | |
59 continue; | |
60 } | |
61 | |
62 if (ngx_buf_in_memory_only(cl->buf)) { | |
63 fd = SFV_FD_SELF; | |
64 | |
65 size = cl->buf->last - cl->buf->pos; | |
66 | |
67 if (send + size > limit) { | |
68 size = limit - send; | |
69 } | |
70 | |
71 if (prev == cl->buf->pos) { | |
72 sfv->sfv_len += size; | |
73 | |
74 } else { | |
75 if (!(sfv = ngx_array_push(&vec))) { | |
76 return NGX_CHAIN_ERROR; | |
77 } | |
78 | |
79 sfv->sfv_fd = SFV_FD_SELF; | |
80 sfv->sfv_flag = 0; | |
81 sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos; | |
82 sfv->sfv_len = size; | |
83 } | |
84 | |
85 prev = cl->buf->pos + size; | |
86 send += size; | |
87 | |
88 } else { | |
89 prev = NULL; | |
90 | |
91 size = (size_t) (cl->buf->file_last - cl->buf->file_pos); | |
92 | |
93 if (send + size > limit) { | |
94 size = limit - send; | |
95 | |
96 aligned = (cl->buf->file_pos + size + ngx_pagesize - 1) | |
97 & ~(ngx_pagesize - 1); | |
98 | |
99 if (aligned <= cl->buf->file_last) { | |
100 size = aligned - cl->buf->file_pos; | |
101 } | |
102 } | |
103 | |
104 if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) { | |
105 sfv->sfv_len += size; | |
106 | |
107 } else { | |
108 if (!(sfv = ngx_array_push(&vec))) { | |
109 return NGX_CHAIN_ERROR; | |
110 } | |
111 | |
112 fd = cl->buf->file->fd; | |
113 sfv->sfv_fd = fd; | |
114 sfv->sfv_flag = 0; | |
115 sfv->sfv_off = cl->buf->file_pos; | |
116 sfv->sfv_len = size; | |
117 } | |
118 | |
119 fprev = cl->buf->file_pos + size; | |
120 send += size; | |
121 } | |
122 } | |
123 | |
124 n = sendfilev(c->fd, vec.elts, vec.nelts, &sent); | |
125 | |
126 if (n == -1) { | |
127 err = ngx_errno; | |
128 | |
129 if (err == NGX_EAGAIN || err == NGX_EINTR) { | |
130 if (err == NGX_EINTR) { | |
131 eintr = 1; | |
132 } | |
133 | |
134 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, | |
135 "sendfilev() sent only " SIZE_T_FMT " bytes", | |
136 sent); | |
137 | |
138 } else { | |
139 wev->error = 1; | |
140 ngx_connection_error(c, err, "sendfilev() failed"); | |
141 return NGX_CHAIN_ERROR; | |
142 } | |
143 } | |
144 | |
145 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
146 "sendfilev: %d " SIZE_T_FMT, n, sent); | |
147 | |
148 if (send - sprev == sent) { | |
149 complete = 1; | |
150 } | |
151 | |
152 c->sent += sent; | |
153 | |
154 for (cl = in; cl; cl = cl->next) { | |
155 | |
156 if (ngx_buf_special(cl->buf)) { | |
157 continue; | |
158 } | |
159 | |
160 if (sent == 0) { | |
161 break; | |
162 } | |
163 | |
164 size = ngx_buf_size(cl->buf); | |
165 | |
166 if (sent >= size) { | |
167 sent -= size; | |
168 | |
169 if (ngx_buf_in_memory(cl->buf)) { | |
170 cl->buf->pos = cl->buf->last; | |
171 } | |
172 | |
173 if (cl->buf->in_file) { | |
174 cl->buf->file_pos = cl->buf->file_last; | |
175 } | |
176 | |
177 continue; | |
178 } | |
179 | |
180 if (ngx_buf_in_memory(cl->buf)) { | |
181 cl->buf->pos += sent; | |
182 } | |
183 | |
184 if (cl->buf->in_file) { | |
185 cl->buf->file_pos += sent; | |
186 } | |
187 | |
188 break; | |
189 } | |
190 | |
191 if (eintr) { | |
192 continue; | |
193 } | |
194 | |
195 if (!complete) { | |
196 wev->ready = 0; | |
197 return cl; | |
198 } | |
199 | |
200 if (send >= limit || cl == NULL) { | |
201 return cl; | |
202 } | |
203 | |
204 in = cl; | |
205 } | |
206 } |