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 }