Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_writev_chain.c
Go to the documentation of this file.
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 
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 
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)) {
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)) {
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 
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 }