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>