Annotation of embedaddon/lighttpd/src/network_writev.c, revision 1.1.1.3
1.1.1.3 ! misho 1: #include "first.h"
! 2:
1.1 misho 3: #include "network_backends.h"
4:
1.1.1.3 ! misho 5: #if defined(USE_WRITEV)
1.1 misho 6:
7: #include "network.h"
8: #include "log.h"
9:
1.1.1.3 ! misho 10: #if defined(HAVE_SYS_UIO_H)
! 11: # include <sys/uio.h>
! 12: #endif
1.1 misho 13:
14: #include <errno.h>
15: #include <string.h>
16: #include <stdlib.h>
17:
18: #if defined(UIO_MAXIOV)
1.1.1.3 ! misho 19: # define SYS_MAX_CHUNKS UIO_MAXIOV
1.1 misho 20: #elif defined(IOV_MAX)
21: /* new name for UIO_MAXIOV since IEEE Std 1003.1-2001 */
1.1.1.3 ! misho 22: # define SYS_MAX_CHUNKS IOV_MAX
1.1 misho 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() */
1.1.1.3 ! misho 25: # define SYS_MAX_CHUNKS _XOPEN_IOV_MAX
1.1 misho 26: #else
27: # error neither UIO_MAXIOV nor IOV_MAX nor _XOPEN_IOV_MAX are defined
28: #endif
29:
1.1.1.3 ! misho 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)
! 33: */
! 34: #define STACK_MAX_ALLOC_CHUNKS 32
! 35: #if SYS_MAX_CHUNKS > STACK_MAX_ALLOC_CHUNKS
! 36: # define MAX_CHUNKS STACK_MAX_ALLOC_CHUNKS
! 37: #else
! 38: # define MAX_CHUNKS SYS_MAX_CHUNKS
! 39: #endif
1.1 misho 40:
1.1.1.3 ! misho 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];
! 43: size_t num_chunks;
! 44: off_t max_bytes = *p_max_bytes;
! 45: off_t toSend;
! 46: ssize_t r;
! 47: UNUSED(con);
1.1 misho 48:
1.1.1.3 ! misho 49: force_assert(NULL != cq->first);
! 50: force_assert(MEM_CHUNK == cq->first->type);
1.1 misho 51:
1.1.1.3 ! misho 52: {
! 53: chunk const *c;
1.1 misho 54:
1.1.1.3 ! misho 55: toSend = 0;
! 56: num_chunks = 0;
! 57: for (c = cq->first; NULL != c && MEM_CHUNK == c->type && num_chunks < MAX_CHUNKS && toSend < max_bytes; c = c->next) {
! 58: size_t c_len;
1.1 misho 59:
1.1.1.3 ! misho 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;
! 62: if (c_len > 0) {
! 63: toSend += c_len;
1.1 misho 64:
1.1.1.3 ! misho 65: chunks[num_chunks].iov_base = c->mem->ptr + c->offset;
! 66: chunks[num_chunks].iov_len = c_len;
1.1 misho 67:
1.1.1.3 ! misho 68: ++num_chunks;
1.1 misho 69: }
70: }
1.1.1.3 ! misho 71: }
1.1 misho 72:
1.1.1.3 ! misho 73: if (0 == num_chunks) {
! 74: chunkqueue_remove_finished_chunks(cq);
! 75: return 0;
! 76: }
1.1 misho 77:
1.1.1.3 ! misho 78: r = writev(fd, chunks, num_chunks);
1.1 misho 79:
1.1.1.3 ! misho 80: if (r < 0) switch (errno) {
! 81: case EAGAIN:
! 82: case EINTR:
! 83: break;
! 84: case EPIPE:
! 85: case ECONNRESET:
! 86: return -2;
! 87: default:
! 88: log_error_write(srv, __FILE__, __LINE__, "ssd",
! 89: "writev failed:", strerror(errno), fd);
! 90: return -1;
! 91: }
1.1 misho 92:
1.1.1.3 ! misho 93: if (r >= 0) {
! 94: *p_max_bytes -= r;
! 95: chunkqueue_mark_written(cq, r);
! 96: }
1.1 misho 97:
1.1.1.3 ! misho 98: return (r > 0 && r == toSend) ? 0 : -3;
! 99: }
1.1 misho 100:
1.1.1.3 ! misho 101: #endif /* USE_WRITEV */
1.1 misho 102:
1.1.1.3 ! misho 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) {
! 105: int r = -1;
1.1 misho 106:
1.1.1.3 ! misho 107: switch (cq->first->type) {
! 108: case MEM_CHUNK:
! 109: r = network_writev_mem_chunks(srv, con, fd, cq, &max_bytes);
1.1 misho 110: break;
1.1.1.3 ! misho 111: case FILE_CHUNK:
! 112: r = network_write_file_chunk_mmap(srv, con, fd, cq, &max_bytes);
1.1 misho 113: break;
114: }
1.1.1.3 ! misho 115:
! 116: if (-3 == r) return 0;
! 117: if (0 != r) return r;
1.1 misho 118: }
119:
120: return 0;
121: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>