Annotation of embedaddon/nginx/src/os/unix/ngx_writev_chain.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (C) Igor Sysoev
4: * Copyright (C) Nginx, Inc.
5: */
6:
7:
8: #include <ngx_config.h>
9: #include <ngx_core.h>
10: #include <ngx_event.h>
11:
12:
13: #if (IOV_MAX > 64)
14: #define NGX_IOVS 64
15: #else
16: #define NGX_IOVS IOV_MAX
17: #endif
18:
19:
20: ngx_chain_t *
21: ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
22: {
23: u_char *prev;
24: ssize_t n, size, sent;
25: off_t send, prev_send;
26: ngx_uint_t eintr, complete;
27: ngx_err_t err;
28: ngx_array_t vec;
29: ngx_chain_t *cl;
30: ngx_event_t *wev;
31: struct iovec *iov, iovs[NGX_IOVS];
32:
33: wev = c->write;
34:
35: if (!wev->ready) {
36: return in;
37: }
38:
39: #if (NGX_HAVE_KQUEUE)
40:
41: if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) {
42: (void) ngx_connection_error(c, wev->kq_errno,
43: "kevent() reported about an closed connection");
44: wev->error = 1;
45: return NGX_CHAIN_ERROR;
46: }
47:
48: #endif
49:
50: /* the maximum limit size is the maximum size_t value - the page size */
51:
52: if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
53: limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize;
54: }
55:
56: send = 0;
57:
58: vec.elts = iovs;
59: vec.size = sizeof(struct iovec);
60: vec.nalloc = NGX_IOVS;
61: vec.pool = c->pool;
62:
63: for ( ;; ) {
64: prev = NULL;
65: iov = NULL;
66: eintr = 0;
67: complete = 0;
68: prev_send = send;
69:
70: vec.nelts = 0;
71:
72: /* create the iovec and coalesce the neighbouring bufs */
73:
74: for (cl = in; cl && send < limit; cl = cl->next) {
75:
76: if (ngx_buf_special(cl->buf)) {
77: continue;
78: }
79:
80: #if 1
81: if (!ngx_buf_in_memory(cl->buf)) {
82: ngx_debug_point();
83: }
84: #endif
85:
86: size = cl->buf->last - cl->buf->pos;
87:
88: if (send + size > limit) {
89: size = (ssize_t) (limit - send);
90: }
91:
92: if (prev == cl->buf->pos) {
93: iov->iov_len += size;
94:
95: } else {
96: if (vec.nelts >= IOV_MAX) {
97: break;
98: }
99:
100: iov = ngx_array_push(&vec);
101: if (iov == NULL) {
102: return NGX_CHAIN_ERROR;
103: }
104:
105: iov->iov_base = (void *) cl->buf->pos;
106: iov->iov_len = size;
107: }
108:
109: prev = cl->buf->pos + size;
110: send += size;
111: }
112:
113: n = writev(c->fd, vec.elts, vec.nelts);
114:
115: if (n == -1) {
116: err = ngx_errno;
117:
118: switch (err) {
119: case NGX_EAGAIN:
120: break;
121:
122: case NGX_EINTR:
123: eintr = 1;
124: break;
125:
126: default:
127: wev->error = 1;
128: (void) ngx_connection_error(c, err, "writev() failed");
129: return NGX_CHAIN_ERROR;
130: }
131:
132: ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
133: "writev() not ready");
134: }
135:
136: sent = n > 0 ? n : 0;
137:
138: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent);
139:
140: if (send - prev_send == sent) {
141: complete = 1;
142: }
143:
144: c->sent += sent;
145:
146: for (cl = in; cl; cl = cl->next) {
147:
148: if (ngx_buf_special(cl->buf)) {
149: continue;
150: }
151:
152: if (sent == 0) {
153: break;
154: }
155:
156: size = cl->buf->last - cl->buf->pos;
157:
158: if (sent >= size) {
159: sent -= size;
160: cl->buf->pos = cl->buf->last;
161:
162: continue;
163: }
164:
165: cl->buf->pos += sent;
166:
167: break;
168: }
169:
170: if (eintr) {
171: continue;
172: }
173:
174: if (!complete) {
175: wev->ready = 0;
176: return cl;
177: }
178:
179: if (send >= limit || cl == NULL) {
180: return cl;
181: }
182:
183: in = cl;
184: }
185: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>