Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_solaris_sendfilev_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 (NGX_TEST_BUILD_SOLARIS_SENDFILEV)
14 
15 /* Solaris declarations */
16 
17 typedef struct sendfilevec {
18  int sfv_fd;
19  u_int sfv_flag;
20  off_t sfv_off;
21  size_t sfv_len;
22 } sendfilevec_t;
23 
24 #define SFV_FD_SELF -2
25 
26 static ssize_t sendfilev(int fd, const struct sendfilevec *vec,
27  int sfvcnt, size_t *xferred)
28 {
29  return -1;
30 }
31 
33  off_t limit);
34 
35 #endif
36 
37 
38 #if (IOV_MAX > 64)
39 #define NGX_SENDFILEVECS 64
40 #else
41 #define NGX_SENDFILEVECS IOV_MAX
42 #endif
43 
44 
45 
48 {
49  int fd;
50  u_char *prev;
51  off_t size, send, prev_send, aligned, fprev;
52  size_t sent;
53  ssize_t n;
54  ngx_int_t eintr, complete;
55  ngx_err_t err;
56  sendfilevec_t *sfv, sfvs[NGX_SENDFILEVECS];
57  ngx_array_t vec;
58  ngx_event_t *wev;
59  ngx_chain_t *cl;
60 
61  wev = c->write;
62 
63  if (!wev->ready) {
64  return in;
65  }
66 
67  if (!c->sendfile) {
68  return ngx_writev_chain(c, in, limit);
69  }
70 
71 
72  /* the maximum limit size is the maximum size_t value - the page size */
73 
74  if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
76  }
77 
78 
79  send = 0;
80 
81  vec.elts = sfvs;
82  vec.size = sizeof(sendfilevec_t);
84  vec.pool = c->pool;
85 
86  for ( ;; ) {
87  fd = SFV_FD_SELF;
88  prev = NULL;
89  fprev = 0;
90  sfv = NULL;
91  eintr = 0;
92  complete = 0;
93  sent = 0;
94  prev_send = send;
95 
96  vec.nelts = 0;
97 
98  /* create the sendfilevec and coalesce the neighbouring bufs */
99 
100  for (cl = in; cl && send < limit; cl = cl->next) {
101 
102  if (ngx_buf_special(cl->buf)) {
103  continue;
104  }
105 
106  if (ngx_buf_in_memory_only(cl->buf)) {
107  fd = SFV_FD_SELF;
108 
109  size = cl->buf->last - cl->buf->pos;
110 
111  if (send + size > limit) {
112  size = limit - send;
113  }
114 
115  if (prev == cl->buf->pos) {
116  sfv->sfv_len += (size_t) size;
117 
118  } else {
119  if (vec.nelts >= IOV_MAX) {
120  break;
121  }
122 
123  sfv = ngx_array_push(&vec);
124  if (sfv == NULL) {
125  return NGX_CHAIN_ERROR;
126  }
127 
128  sfv->sfv_fd = SFV_FD_SELF;
129  sfv->sfv_flag = 0;
130  sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos;
131  sfv->sfv_len = (size_t) size;
132  }
133 
134  prev = cl->buf->pos + (size_t) size;
135  send += size;
136 
137  } else {
138  prev = NULL;
139 
140  size = cl->buf->file_last - cl->buf->file_pos;
141 
142  if (send + size > limit) {
143  size = limit - send;
144 
145  aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
146  & ~((off_t) ngx_pagesize - 1);
147 
148  if (aligned <= cl->buf->file_last) {
149  size = aligned - cl->buf->file_pos;
150  }
151  }
152 
153  if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) {
154  sfv->sfv_len += (size_t) size;
155 
156  } else {
157  if (vec.nelts >= IOV_MAX) {
158  break;
159  }
160 
161  sfv = ngx_array_push(&vec);
162  if (sfv == NULL) {
163  return NGX_CHAIN_ERROR;
164  }
165 
166  fd = cl->buf->file->fd;
167  sfv->sfv_fd = fd;
168  sfv->sfv_flag = 0;
169  sfv->sfv_off = cl->buf->file_pos;
170  sfv->sfv_len = (size_t) size;
171  }
172 
173  fprev = cl->buf->file_pos + size;
174  send += size;
175  }
176  }
177 
178  n = sendfilev(c->fd, vec.elts, vec.nelts, &sent);
179 
180  if (n == -1) {
181  err = ngx_errno;
182 
183  switch (err) {
184  case NGX_EAGAIN:
185  break;
186 
187  case NGX_EINTR:
188  eintr = 1;
189  break;
190 
191  default:
192  wev->error = 1;
193  ngx_connection_error(c, err, "sendfilev() failed");
194  return NGX_CHAIN_ERROR;
195  }
196 
198  "sendfilev() sent only %uz bytes", sent);
199  }
200 
202  "sendfilev: %z %z", n, sent);
203 
204  if (send - prev_send == (off_t) sent) {
205  complete = 1;
206  }
207 
208  c->sent += sent;
209 
210  for (cl = in; cl; cl = cl->next) {
211 
212  if (ngx_buf_special(cl->buf)) {
213  continue;
214  }
215 
216  if (sent == 0) {
217  break;
218  }
219 
220  size = ngx_buf_size(cl->buf);
221 
222  if ((off_t) sent >= size) {
223  sent = (size_t) ((off_t) sent - size);
224 
225  if (ngx_buf_in_memory(cl->buf)) {
226  cl->buf->pos = cl->buf->last;
227  }
228 
229  if (cl->buf->in_file) {
230  cl->buf->file_pos = cl->buf->file_last;
231  }
232 
233  continue;
234  }
235 
236  if (ngx_buf_in_memory(cl->buf)) {
237  cl->buf->pos += sent;
238  }
239 
240  if (cl->buf->in_file) {
241  cl->buf->file_pos += sent;
242  }
243 
244  break;
245  }
246 
247  if (eintr) {
248  continue;
249  }
250 
251  if (!complete) {
252  wev->ready = 0;
253  return cl;
254  }
255 
256  if (send >= limit || cl == NULL) {
257  return cl;
258  }
259 
260  in = cl;
261  }
262 }