comparison src/os/unix/ngx_freebsd_sendfile_chain.c @ 143:5526213be452

nginx-0.0.1-2003-10-10-19:10:50 import
author Igor Sysoev <igor@sysoev.ru>
date Fri, 10 Oct 2003 15:10:50 +0000
parents cb77c084acdb
children ef8c87afcfc5
comparison
equal deleted inserted replaced
142:cb77c084acdb 143:5526213be452
12 * with the part of the file in one packet. So we use TCP_NOPUSH (similar 12 * with the part of the file in one packet. So we use TCP_NOPUSH (similar
13 * to Linux's TCP_CORK) to postpone the sending - it not only sends the header 13 * to Linux's TCP_CORK) to postpone the sending - it not only sends the header
14 * and the first part of the file in one packet but also sends 4K pages 14 * and the first part of the file in one packet but also sends 4K pages
15 * in the full packets. 15 * in the full packets.
16 * 16 *
17 * Until FreeBSD 4.5 the turning TCP_NOPUSH off does not not flush 17 * Until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush
18 * the pending data that less than MSS and the data sent with 5 second delay. 18 * the pending data that less than MSS so the data is sent with 5 second delay.
19 * So we use TCP_NOPUSH on FreeBSD prior to 4.5 only if the connection 19 * We do not use TCP_NOPUSH on FreeBSD prior to 4.5 although it can be used
20 * is not needed to be keepalive. 20 * for non-keepalive HTTP connections.
21 */ 21 */
22 22
23 23
24 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) 24 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
25 { 25 {
26 int rc, eintr, tcp_nopush; 26 int rc, eintr;
27 char *prev; 27 char *prev;
28 ssize_t hsize, size; 28 ssize_t hsize, size;
29 off_t sent; 29 off_t sent;
30 struct iovec *iov; 30 struct iovec *iov;
31 struct sf_hdtr hdtr; 31 struct sf_hdtr hdtr;
32 ngx_err_t err; 32 ngx_err_t err;
33 ngx_array_t header, trailer; 33 ngx_array_t header, trailer;
34 ngx_hunk_t *file; 34 ngx_hunk_t *file;
35 ngx_chain_t *ce, *tail; 35 ngx_chain_t *ce, *tail;
36 36
37 tcp_nopush = 0;
38
39 do { 37 do {
40 ce = in; 38 ce = in;
41 file = NULL; 39 file = NULL;
42 hsize = 0; 40 hsize = 0;
43 eintr = 0; 41 eintr = 0;
45 ngx_init_array(header, c->pool, 10, sizeof(struct iovec), 43 ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
46 NGX_CHAIN_ERROR); 44 NGX_CHAIN_ERROR);
47 ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), 45 ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec),
48 NGX_CHAIN_ERROR); 46 NGX_CHAIN_ERROR);
49 47
50 /* create the header iovec */ 48 /* create the iovec and coalesce the neighbouring chain entries */
51 49
52 #if 0 50 prev = NULL;
53 if (ngx_hunk_in_memory_only(ce->hunk) || ngx_hunk_special(ce->hunk)) { 51 iov = NULL;
54 #endif 52
55 prev = NULL; 53 for (ce = in; ce; ce = ce->next) {
56 iov = NULL; 54 if (ngx_hunk_special(ce->hunk)) {
57 55 continue;
58 /* create the iovec and coalesce the neighbouring chain entries */ 56 }
59 57
60 for ( /* void */; ce; ce = ce->next) { 58 if (!ngx_hunk_in_memory_only(ce->hunk)) {
61 if (ngx_hunk_special(ce->hunk)) { 59 break;
62 continue; 60 }
63 } 61
64 62 if (prev == ce->hunk->pos) {
65 if (!ngx_hunk_in_memory_only(ce->hunk)) { 63 iov->iov_len += ce->hunk->last - ce->hunk->pos;
66 break; 64 prev = ce->hunk->last;
67 } 65
68 66 } else {
69 if (prev == ce->hunk->pos) { 67 ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
70 iov->iov_len += ce->hunk->last - ce->hunk->pos; 68 iov->iov_base = ce->hunk->pos;
71 prev = ce->hunk->last; 69 iov->iov_len = ce->hunk->last - ce->hunk->pos;
72 70 prev = ce->hunk->last;
73 } else { 71 }
74 ngx_test_null(iov, ngx_push_array(&header), 72
75 NGX_CHAIN_ERROR); 73 hsize += ce->hunk->last - ce->hunk->pos;
76 iov->iov_base = ce->hunk->pos; 74 }
77 iov->iov_len = ce->hunk->last - ce->hunk->pos;
78 prev = ce->hunk->last;
79 }
80
81 hsize += ce->hunk->last - ce->hunk->pos;
82 }
83 #if 0
84 }
85 #endif
86 75
87 /* TODO: coalesce the neighbouring file hunks */ 76 /* TODO: coalesce the neighbouring file hunks */
88 77
89 if (ce && (ce->hunk->type & NGX_HUNK_FILE)) { 78 if (ce && (ce->hunk->type & NGX_HUNK_FILE)) {
90 file = ce->hunk; 79 file = ce->hunk;
91 ce = ce->next; 80 ce = ce->next;
92 } 81 }
93 82
94 /* create the trailer iovec */ 83 /* create the iovec and coalesce the neighbouring chain entries */
95 84
96 #if 0 85 prev = NULL;
97 if (ce 86 iov = NULL;
98 && (ngx_hunk_in_memory_only(ce->hunk) 87
99 || ngx_hunk_special(ce->hunk))) 88 for ( /* void */; ce; ce = ce->next) {
100 { 89 if (ngx_hunk_special(ce->hunk)) {
101 #endif 90 continue;
102 prev = NULL; 91 }
103 iov = NULL; 92
104 93 if (!ngx_hunk_in_memory_only(ce->hunk)) {
105 /* create the iovec and coalesce the neighbouring chain entries */ 94 break;
106 95 }
107 for ( /* void */; ce; ce = ce->next) { 96
108 if (ngx_hunk_special(ce->hunk)) { 97 if (prev == ce->hunk->pos) {
109 continue; 98 iov->iov_len += ce->hunk->last - ce->hunk->pos;
110 } 99 prev = ce->hunk->last;
111 100
112 if (!ngx_hunk_in_memory_only(ce->hunk)) { 101 } else {
113 break; 102 ngx_test_null(iov, ngx_push_array(&trailer), NGX_CHAIN_ERROR);
114 } 103 iov->iov_base = ce->hunk->pos;
115 104 iov->iov_len = ce->hunk->last - ce->hunk->pos;
116 if (prev == ce->hunk->pos) { 105 prev = ce->hunk->last;
117 iov->iov_len += ce->hunk->last - ce->hunk->pos; 106 }
118 prev = ce->hunk->last; 107 }
119
120 } else {
121 ngx_test_null(iov, ngx_push_array(&trailer),
122 NGX_CHAIN_ERROR);
123 iov->iov_base = ce->hunk->pos;
124 iov->iov_len = ce->hunk->last - ce->hunk->pos;
125 prev = ce->hunk->last;
126 }
127 }
128 #if 0
129 }
130 #endif
131 108
132 tail = ce; 109 tail = ce;
133 110
134 if (file) { 111 if (file) {
135 112
136 if (!c->tcp_nopush && c->tcp_nopush_enabled) { 113 if (ngx_freebsd_use_tcp_nopush && !c->tcp_nopush) {
137 c->tcp_nopush = 1; 114 c->tcp_nopush = 1;
138 tcp_nopush = 1; 115
116 ngx_log_debug(c->log, "NOPUSH");
117
139 if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { 118 if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
140 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno, 119 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
141 ngx_tcp_nopush_n " failed"); 120 ngx_tcp_nopush_n " failed");
142 return NGX_CHAIN_ERROR; 121 return NGX_CHAIN_ERROR;
143 } 122 }
144 ngx_log_debug(c->log, "NOPUSH");
145 } 123 }
146 124
147 hdtr.headers = (struct iovec *) header.elts; 125 hdtr.headers = (struct iovec *) header.elts;
148 hdtr.hdr_cnt = header.nelts; 126 hdtr.hdr_cnt = header.nelts;
149 hdtr.trailers = (struct iovec *) trailer.elts; 127 hdtr.trailers = (struct iovec *) trailer.elts;
180 rc _ file->file_pos _ sent _ 158 rc _ file->file_pos _ sent _
181 (size_t) (file->file_last - file->file_pos) + hsize); 159 (size_t) (file->file_last - file->file_pos) + hsize);
182 #endif 160 #endif
183 161
184 } else { 162 } else {
185 if (hsize) { 163 rc = writev(c->fd, (struct iovec *) header.elts, header.nelts);
186 rc = writev(c->fd, (struct iovec *) header.elts, header.nelts); 164
187 165 if (rc == -1) {
188 if (rc == -1) { 166 err = ngx_errno;
189 err = ngx_errno; 167 if (err == NGX_EAGAIN) {
190 if (err == NGX_EAGAIN) { 168 ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN");
191 ngx_log_error(NGX_LOG_INFO, c->log, err, 169
192 "writev() EAGAIN"); 170 } else if (err == NGX_EINTR) {
193 171 eintr = 1;
194 } else if (err == NGX_EINTR) { 172 ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR");
195 eintr = 1; 173
196 ngx_log_error(NGX_LOG_INFO, c->log, err, 174 } else {
197 "writev() EINTR"); 175 ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed");
198 176 return NGX_CHAIN_ERROR;
199 } else { 177 }
200 ngx_log_error(NGX_LOG_CRIT, c->log, err, 178 }
201 "writev() failed"); 179
202 return NGX_CHAIN_ERROR; 180 sent = rc > 0 ? rc : 0;
203 }
204 }
205
206 sent = rc > 0 ? rc : 0;
207 181
208 #if (NGX_DEBUG_WRITE_CHAIN) 182 #if (NGX_DEBUG_WRITE_CHAIN)
209 ngx_log_debug(c->log, "writev: %qd" _ sent); 183 ngx_log_debug(c->log, "writev: %qd" _ sent);
210 #endif 184 #endif
211
212 } else {
213 sent = 0;
214 }
215 } 185 }
216 186
217 c->sent += sent; 187 c->sent += sent;
218 188
219 for (ce = in; ce && sent > 0; ce = ce->next) { 189 for (ce = in; ce && sent > 0; ce = ce->next) {