3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
10 #include <ngx_event.h>
16 #define NGX_IOVS IOV_MAX
21 ngx_writev_chain(ngx_connection_t
*c
, ngx_chain_t
*in
, off_t limit
)
24 ssize_t n
, size
, sent
;
25 off_t send
, prev_send
;
26 ngx_uint_t eintr
, complete
;
31 struct iovec
*iov
, iovs
[NGX_IOVS
];
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");
45 return NGX_CHAIN_ERROR
;
50 /* the maximum limit size is the maximum size_t value - the page size */
52 if (limit
== 0 || limit
> (off_t
) (NGX_MAX_SIZE_T_VALUE
- ngx_pagesize
)) {
53 limit
= NGX_MAX_SIZE_T_VALUE
- ngx_pagesize
;
59 vec
.size
= sizeof(struct iovec
);
60 vec
.nalloc
= NGX_IOVS
;
72 /* create the iovec and coalesce the neighbouring bufs */
74 for (cl
= in
; cl
&& send
< limit
; cl
= cl
->next
) {
76 if (ngx_buf_special(cl
->buf
)) {
81 if (!ngx_buf_in_memory(cl
->buf
)) {
86 size
= cl
->buf
->last
- cl
->buf
->pos
;
88 if (send
+ size
> limit
) {
89 size
= (ssize_t
) (limit
- send
);
92 if (prev
== cl
->buf
->pos
) {
96 if (vec
.nelts
>= IOV_MAX
) {
100 iov
= ngx_array_push(&vec
);
102 return NGX_CHAIN_ERROR
;
105 iov
->iov_base
= (void *) cl
->buf
->pos
;
109 prev
= cl
->buf
->pos
+ size
;
113 n
= writev(c
->fd
, vec
.elts
, vec
.nelts
);
128 (void) ngx_connection_error(c
, err
, "writev() failed");
129 return NGX_CHAIN_ERROR
;
132 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, err
,
133 "writev() not ready");
136 sent
= n
> 0 ? n
: 0;
138 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, c
->log
, 0, "writev: %z", sent
);
140 if (send
- prev_send
== sent
) {
146 for (cl
= in
; cl
; cl
= cl
->next
) {
148 if (ngx_buf_special(cl
->buf
)) {
156 size
= cl
->buf
->last
- cl
->buf
->pos
;
160 cl
->buf
->pos
= cl
->buf
->last
;
165 cl
->buf
->pos
+= sent
;
179 if (send
>= limit
|| cl
== NULL
) {