comparison src/os/unix/ngx_linux_sendfile_chain.c @ 97:70d2345a903f

nginx-0.0.1-2003-05-29-17:02:09 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 29 May 2003 13:02:09 +0000
parents
children 8dee38ea9117
comparison
equal deleted inserted replaced
96:a23d010f356d 97:70d2345a903f
1
2 #include <ngx_config.h>
3 #include <ngx_core.h>
4 #include <ngx_linux_init.h>
5
6
7 ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
8 {
9 int rc, on, off;
10 char *prev;
11 size_t hsize, size;
12 ssize_t sent;
13 struct iovec *iov;
14 struct sf_hdtr hdtr;
15 ngx_err_t err;
16 ngx_array_t header, trailer;
17 ngx_hunk_t *file;
18 ngx_chain_t *ce;
19
20 ce = in;
21 file = NULL;
22 hsize = 0;
23
24 on = 1;
25 off = 0;
26
27 ngx_init_array(header, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
28 ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
29
30 /* create the header iovec */
31 if (ngx_hunk_in_memory_only(ce->hunk)) {
32 prev = NULL;
33 iov = NULL;
34
35 /* create the iovec and coalesce the neighbouring chain entries */
36 while (ce && ngx_hunk_in_memory_only(ce->hunk)) {
37
38 if (prev == ce->hunk->pos) {
39 iov->iov_len += ce->hunk->last - ce->hunk->pos;
40 prev = ce->hunk->last;
41
42 } else {
43 ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
44 iov->iov_base = ce->hunk->pos;
45 iov->iov_len = ce->hunk->last - ce->hunk->pos;
46 prev = ce->hunk->last;
47 }
48
49 if (ngx_freebsd_sendfile_nbytes_bug) {
50 hsize += ce->hunk->last - ce->hunk->pos;
51 }
52
53 ce = ce->next;
54 }
55 }
56
57 /* TODO: coalesce the neighbouring file hunks */
58 if (ce && (ce->hunk->type & NGX_HUNK_FILE)) {
59 file = ce->hunk;
60 ce = ce->next;
61 }
62
63 /* create the trailer iovec */
64 if (ce && ngx_hunk_in_memory_only(ce->hunk)) {
65 prev = NULL;
66 iov = NULL;
67
68 /* create the iovec and coalesce the neighbouring chain entries */
69 while (ce && ngx_hunk_in_memory_only(ce->hunk)) {
70
71 if (prev == ce->hunk->pos) {
72 iov->iov_len += ce->hunk->last - ce->hunk->pos;
73 prev = ce->hunk->last;
74
75 } else {
76 ngx_test_null(iov, ngx_push_array(&trailer), NGX_CHAIN_ERROR);
77 iov->iov_base = ce->hunk->pos;
78 iov->iov_len = ce->hunk->last - ce->hunk->pos;
79 prev = ce->hunk->last;
80 }
81
82 ce = ce->next;
83 }
84 }
85
86 if (file) {
87 if (setsockopt(c->fd, IPPROTO_TCP, TCP_CORK,
88 (const void *) &on, sizeof(int)) == -1) {
89 ngx_log_error(NGX_LOG_CRIT, c->log, err,
90 "setsockopt(TCP_CORK, 1) failed");
91 return NGX_CHAIN_ERROR;
92 }
93
94
95 rc = sendfile(c->fd, file->file->fd, file->file_pos,
96 (size_t) (file->file_last - file->file_pos));
97
98 if (rc == -1) {
99 err = ngx_errno;
100 if (err == NGX_EAGAIN) {
101 ngx_log_error(NGX_LOG_INFO, c->log, err, "senfile() EAGAIN");
102
103 } else if (err == NGX_EINTR) {
104 ngx_log_error(NGX_LOG_INFO, c->log, err, "senfile() EINTR");
105
106 } else {
107 ngx_log_error(NGX_LOG_CRIT, c->log, err, "sendfile() failed");
108 return NGX_CHAIN_ERROR;
109 }
110 }
111
112 sent = rc > 0 ? rc : 0;
113
114 #if (NGX_DEBUG_WRITE_CHAIN)
115 ngx_log_debug(c->log, "sendfile: %d, @%qd %d:%d" _
116 rc _ file->file_pos _ sent _
117 (size_t) (file->file_last - file->file_pos));
118 #endif
119
120 } else {
121 rc = writev(c->fd, (struct iovec *) header.elts, header.nelts);
122
123 if (rc == -1) {
124 err = ngx_errno;
125 if (err == NGX_EAGAIN) {
126 ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN");
127
128 } else if (err == NGX_EINTR) {
129 ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR");
130
131 } else {
132 ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed");
133 return NGX_CHAIN_ERROR;
134 }
135 }
136
137 sent = rc > 0 ? rc : 0;
138
139 #if (NGX_DEBUG_WRITE_CHAIN)
140 ngx_log_debug(c->log, "writev: %d" _ sent);
141 #endif
142 }
143
144 c->sent += sent;
145
146 for (ce = in; ce && sent > 0; ce = ce->next) {
147
148 if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
149 size = ce->hunk->last - ce->hunk->pos;
150 } else {
151 size = ce->hunk->file_last - ce->hunk->file_pos;
152 }
153
154 if (sent >= size) {
155 sent -= size;
156
157 if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
158 ce->hunk->pos = ce->hunk->last;
159 }
160
161 if (ce->hunk->type & NGX_HUNK_FILE) {
162 ce->hunk->file_pos = ce->hunk->file_last;
163 }
164
165 continue;
166 }
167
168 if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
169 ce->hunk->pos += sent;
170 }
171
172 if (ce->hunk->type & NGX_HUNK_FILE) {
173 ce->hunk->file_pos += sent;
174 }
175
176 break;
177 }
178
179 ngx_destroy_array(&trailer);
180 ngx_destroy_array(&header);
181
182 return ce;
183 }