Mercurial > hg > nginx
comparison src/os/unix/ngx_writev_chain.c @ 362:7650aea1816f
nginx-0.0.7-2004-06-21-19:59:32 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 21 Jun 2004 15:59:32 +0000 |
parents | 6bdf858bff8c |
children | 744ccb59062d |
comparison
equal
deleted
inserted
replaced
361:446782c909b3 | 362:7650aea1816f |
---|---|
2 #include <ngx_config.h> | 2 #include <ngx_config.h> |
3 #include <ngx_core.h> | 3 #include <ngx_core.h> |
4 #include <ngx_event.h> | 4 #include <ngx_event.h> |
5 | 5 |
6 | 6 |
7 ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in) | 7 ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) |
8 { | 8 { |
9 u_char *prev; | 9 u_char *prev; |
10 ssize_t n, size; | 10 ssize_t n, size; |
11 off_t sent; | 11 off_t send, sprev, sent; |
12 struct iovec *iov; | 12 struct iovec *iov; |
13 ngx_int_t eintr; | 13 ngx_uint_t eintr, complete; |
14 ngx_err_t err; | 14 ngx_err_t err; |
15 ngx_array_t io; | 15 ngx_array_t vec; |
16 ngx_chain_t *cl; | 16 ngx_chain_t *cl; |
17 ngx_event_t *wev; | 17 ngx_event_t *wev; |
18 | 18 |
19 wev = c->write; | 19 wev = c->write; |
20 | 20 |
32 return NGX_CHAIN_ERROR; | 32 return NGX_CHAIN_ERROR; |
33 } | 33 } |
34 | 34 |
35 #endif | 35 #endif |
36 | 36 |
37 ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR); | 37 ngx_init_array(vec, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR); |
38 | 38 |
39 do { | 39 send = 0; |
40 complete = 0; | |
41 | |
42 for ( ;; ) { | |
40 prev = NULL; | 43 prev = NULL; |
41 iov = NULL; | 44 iov = NULL; |
42 eintr = 0; | 45 eintr = 0; |
46 sprev = send; | |
43 | 47 |
44 /* create the iovec and coalesce the neighbouring bufs */ | 48 /* create the iovec and coalesce the neighbouring bufs */ |
45 | 49 |
46 for (cl = in; cl; cl = cl->next) { | 50 for (cl = in; cl && vec.nelts < IOV_MAX && send < limit; cl = cl->next) |
51 { | |
52 if (ngx_buf_special(cl->buf)) { | |
53 continue; | |
54 } | |
55 | |
56 size = cl->buf->last - cl->buf->pos; | |
57 | |
58 if (send + size > limit) { | |
59 size = limit - send; | |
60 } | |
47 | 61 |
48 if (prev == cl->buf->pos) { | 62 if (prev == cl->buf->pos) { |
49 iov->iov_len += cl->buf->last - cl->buf->pos; | 63 iov->iov_len += size; |
50 prev = cl->buf->last; | |
51 | 64 |
52 } else { | 65 } else { |
53 ngx_test_null(iov, ngx_push_array(&io), NGX_CHAIN_ERROR); | 66 ngx_test_null(iov, ngx_push_array(&vec), NGX_CHAIN_ERROR); |
54 iov->iov_base = (void *) cl->buf->pos; | 67 iov->iov_base = (void *) cl->buf->pos; |
55 iov->iov_len = cl->buf->last - cl->buf->pos; | 68 iov->iov_len = size; |
56 prev = cl->buf->last; | |
57 } | 69 } |
70 | |
71 prev = cl->buf->pos + size; | |
72 send += size; | |
58 } | 73 } |
59 | 74 |
60 n = writev(c->fd, io.elts, io.nelts); | 75 n = writev(c->fd, vec.elts, vec.nelts); |
61 | 76 |
62 if (n == -1) { | 77 if (n == -1) { |
63 err = ngx_errno; | 78 err = ngx_errno; |
64 | 79 |
65 if (err == NGX_EAGAIN || err == NGX_EINTR) { | 80 if (err == NGX_EAGAIN || err == NGX_EINTR) { |
80 sent = n > 0 ? n : 0; | 95 sent = n > 0 ? n : 0; |
81 | 96 |
82 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 97 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
83 "writev: " OFF_T_FMT, sent); | 98 "writev: " OFF_T_FMT, sent); |
84 | 99 |
100 if (send - sprev == sent) { | |
101 complete = 1; | |
102 } | |
103 | |
85 c->sent += sent; | 104 c->sent += sent; |
86 | 105 |
87 for (cl = in; cl && sent > 0; cl = cl->next) { | 106 for (cl = in; cl && sent > 0; cl = cl->next) { |
107 if (ngx_buf_special(cl->buf)) { | |
108 continue; | |
109 } | |
110 | |
111 if (sent == 0) { | |
112 break; | |
113 } | |
88 | 114 |
89 size = cl->buf->last - cl->buf->pos; | 115 size = cl->buf->last - cl->buf->pos; |
90 | 116 |
91 if (sent >= size) { | 117 if (sent >= size) { |
92 sent -= size; | 118 sent -= size; |
93 | 119 cl->buf->pos = cl->buf->last; |
94 if (ngx_buf_in_memory(cl->buf)) { | |
95 cl->buf->pos = cl->buf->last; | |
96 } | |
97 | 120 |
98 continue; | 121 continue; |
99 } | 122 } |
100 | 123 |
101 if (ngx_buf_in_memory(cl->buf)) { | 124 cl->buf->pos += sent; |
102 cl->buf->pos += sent; | |
103 } | |
104 | 125 |
105 break; | 126 break; |
106 } | 127 } |
107 | 128 |
108 } while (eintr); | 129 if (eintr) { |
130 continue; | |
131 } | |
109 | 132 |
110 if (cl) { | 133 if (!complete) { |
111 wev->ready = 0; | 134 wev->ready = 0; |
135 return cl; | |
136 } | |
137 | |
138 if (send >= limit || cl == NULL) { | |
139 return cl; | |
140 } | |
141 | |
142 in = cl; | |
112 } | 143 } |
113 | |
114 return cl; | |
115 } | 144 } |