3 #include "network_backends.h"
5 #if defined(USE_WRITEV)
10 #if defined(HAVE_SYS_UIO_H)
18 #if defined(UIO_MAXIOV)
19 # define SYS_MAX_CHUNKS UIO_MAXIOV
20 #elif defined(IOV_MAX)
21 /* new name for UIO_MAXIOV since IEEE Std 1003.1-2001 */
22 # define SYS_MAX_CHUNKS IOV_MAX
23 #elif defined(_XOPEN_IOV_MAX)
24 /* minimum value for sysconf(_SC_IOV_MAX); posix requires this to be at least 16, which is good enough - no need to call sysconf() */
25 # define SYS_MAX_CHUNKS _XOPEN_IOV_MAX
27 # error neither UIO_MAXIOV nor IOV_MAX nor _XOPEN_IOV_MAX are defined
30 /* allocate iovec[MAX_CHUNKS] on stack, so pick a sane limit:
31 * - each entry will use 1 pointer + 1 size_t
32 * - 32 chunks -> 256 / 512 bytes (32-bit/64-bit pointers)
34 #define STACK_MAX_ALLOC_CHUNKS 32
35 #if SYS_MAX_CHUNKS > STACK_MAX_ALLOC_CHUNKS
36 # define MAX_CHUNKS STACK_MAX_ALLOC_CHUNKS
38 # define MAX_CHUNKS SYS_MAX_CHUNKS
41 int network_writev_mem_chunks(server
*srv
, connection
*con
, int fd
, chunkqueue
*cq
, off_t
*p_max_bytes
) {
42 struct iovec chunks
[MAX_CHUNKS
];
44 off_t max_bytes
= *p_max_bytes
;
49 force_assert(NULL
!= cq
->first
);
50 force_assert(MEM_CHUNK
== cq
->first
->type
);
57 for (c
= cq
->first
; NULL
!= c
&& MEM_CHUNK
== c
->type
&& num_chunks
< MAX_CHUNKS
&& toSend
< max_bytes
; c
= c
->next
) {
60 force_assert(c
->offset
>= 0 && c
->offset
<= (off_t
)buffer_string_length(c
->mem
));
61 c_len
= buffer_string_length(c
->mem
) - c
->offset
;
65 chunks
[num_chunks
].iov_base
= c
->mem
->ptr
+ c
->offset
;
66 chunks
[num_chunks
].iov_len
= c_len
;
73 if (0 == num_chunks
) {
74 chunkqueue_remove_finished_chunks(cq
);
78 r
= writev(fd
, chunks
, num_chunks
);
80 if (r
< 0) switch (errno
) {
88 log_error_write(srv
, __FILE__
, __LINE__
, "ssd",
89 "writev failed:", strerror(errno
), fd
);
95 chunkqueue_mark_written(cq
, r
);
98 return (r
> 0 && r
== toSend
) ? 0 : -3;
101 #endif /* USE_WRITEV */
103 int network_write_chunkqueue_writev(server
*srv
, connection
*con
, int fd
, chunkqueue
*cq
, off_t max_bytes
) {
104 while (max_bytes
> 0 && NULL
!= cq
->first
) {
107 switch (cq
->first
->type
) {
109 r
= network_writev_mem_chunks(srv
, con
, fd
, cq
, &max_bytes
);
112 r
= network_write_file_chunk_mmap(srv
, con
, fd
, cq
, &max_bytes
);
116 if (-3 == r
) return 0;
117 if (0 != r
) return r
;