upstream nginx-0.7.31
[nginx.git] / nginx / src / os / unix / ngx_aio_write_chain.c
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 #include <ngx_aio.h>
11
12
13 ngx_chain_t *
14 ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
15 {
16     u_char       *buf, *prev;
17     off_t         send, sent;
18     size_t        len;
19     ssize_t       n, size;
20     ngx_chain_t  *cl;
21
22     /* the maximum limit size is the maximum size_t value - the page size */
23
24     if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
25         limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize;
26     }
27
28     send = 0;
29     sent = 0;
30     cl = in;
31
32     while (cl) {
33
34         if (cl->buf->pos == cl->buf->last) {
35             cl = cl->next;
36             continue;
37         }
38
39         /* we can post the single aio operation only */
40
41         if (!c->write->ready) {
42             return cl;
43         }
44
45         buf = cl->buf->pos;
46         prev = buf;
47         len = 0;
48
49         /* coalesce the neighbouring bufs */
50
51         while (cl && prev == cl->buf->pos && send < limit) {
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             }
61
62             len += size;
63             prev = cl->buf->pos + size;
64             send += size;
65             cl = cl->next;
66         }
67
68         n = ngx_aio_write(c, buf, len);
69
70         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "aio_write: %z", n);
71
72         if (n == NGX_ERROR) {
73             return NGX_CHAIN_ERROR;
74         }
75
76         if (n > 0) {
77             sent += n;
78             c->sent += n;
79         }
80
81         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
82                        "aio_write sent: %O", c->sent);
83
84         for (cl = in; cl; cl = cl->next) {
85
86             if (sent >= cl->buf->last - cl->buf->pos) {
87                 sent -= cl->buf->last - cl->buf->pos;
88                 cl->buf->pos = cl->buf->last;
89
90                 continue;
91             }
92
93             cl->buf->pos += sent;
94
95             break;
96         }
97     }
98
99     return cl;
100 }