1*0Sigor@sysoev.ru 2*0Sigor@sysoev.ru /* 3*0Sigor@sysoev.ru * Copyright (C) Igor Sysoev 4*0Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 5*0Sigor@sysoev.ru */ 6*0Sigor@sysoev.ru 7*0Sigor@sysoev.ru #include <nxt_main.h> 8*0Sigor@sysoev.ru 9*0Sigor@sysoev.ru 10*0Sigor@sysoev.ru /* 11*0Sigor@sysoev.ru * sendfilev() has been introduced in Solaris 8 (7/01). 12*0Sigor@sysoev.ru * According to sendfilev(3EXT) it can write to: 13*0Sigor@sysoev.ru * 14*0Sigor@sysoev.ru * a file descriptor to a regular file or to a AF_NCA, AF_INET, or 15*0Sigor@sysoev.ru * AF_INET6 family type SOCK_STREAM socket that is open for writing. 16*0Sigor@sysoev.ru */ 17*0Sigor@sysoev.ru 18*0Sigor@sysoev.ru ssize_t nxt_solaris_event_conn_io_sendfilev(nxt_event_conn_t *c, nxt_buf_t *b, 19*0Sigor@sysoev.ru size_t limit); 20*0Sigor@sysoev.ru static size_t nxt_solaris_buf_coalesce(nxt_buf_t *b, sendfilevec_t *sfv, 21*0Sigor@sysoev.ru int32_t *nsfv, nxt_bool_t *sync, size_t limit); 22*0Sigor@sysoev.ru 23*0Sigor@sysoev.ru 24*0Sigor@sysoev.ru ssize_t 25*0Sigor@sysoev.ru nxt_solaris_event_conn_io_sendfilev(nxt_event_conn_t *c, nxt_buf_t *b, 26*0Sigor@sysoev.ru size_t limit) 27*0Sigor@sysoev.ru { 28*0Sigor@sysoev.ru size_t sent; 29*0Sigor@sysoev.ru ssize_t n; 30*0Sigor@sysoev.ru int32_t nsfv; 31*0Sigor@sysoev.ru nxt_err_t err; 32*0Sigor@sysoev.ru nxt_off_t size; 33*0Sigor@sysoev.ru nxt_bool_t sync; 34*0Sigor@sysoev.ru sendfilevec_t sfv[NXT_IOBUF_MAX]; 35*0Sigor@sysoev.ru 36*0Sigor@sysoev.ru if (c->sendfile == 0) { 37*0Sigor@sysoev.ru /* AF_UNIX does not support sendfilev(). */ 38*0Sigor@sysoev.ru return nxt_event_conn_io_sendbuf(c, b, limit); 39*0Sigor@sysoev.ru } 40*0Sigor@sysoev.ru 41*0Sigor@sysoev.ru sync = 0; 42*0Sigor@sysoev.ru 43*0Sigor@sysoev.ru size = nxt_solaris_buf_coalesce(b, sfv, &nsfv, &sync, limit); 44*0Sigor@sysoev.ru 45*0Sigor@sysoev.ru nxt_log_debug(c->socket.log, "sendfilev(%d, %D)", c->socket.fd, nsfv); 46*0Sigor@sysoev.ru 47*0Sigor@sysoev.ru if (nsfv == 0 && sync) { 48*0Sigor@sysoev.ru return 0; 49*0Sigor@sysoev.ru } 50*0Sigor@sysoev.ru 51*0Sigor@sysoev.ru sent = 0; 52*0Sigor@sysoev.ru n = sendfilev(c->socket.fd, sfv, nsfv, &sent); 53*0Sigor@sysoev.ru 54*0Sigor@sysoev.ru err = (n == -1) ? nxt_errno : 0; 55*0Sigor@sysoev.ru 56*0Sigor@sysoev.ru nxt_log_debug(c->socket.log, "sendfilev(): %d sent:%uz", n, sent); 57*0Sigor@sysoev.ru 58*0Sigor@sysoev.ru if (n == -1) { 59*0Sigor@sysoev.ru switch (err) { 60*0Sigor@sysoev.ru 61*0Sigor@sysoev.ru case NXT_EAGAIN: 62*0Sigor@sysoev.ru c->socket.write_ready = 0; 63*0Sigor@sysoev.ru break; 64*0Sigor@sysoev.ru 65*0Sigor@sysoev.ru case NXT_EINTR: 66*0Sigor@sysoev.ru break; 67*0Sigor@sysoev.ru 68*0Sigor@sysoev.ru default: 69*0Sigor@sysoev.ru c->socket.error = err; 70*0Sigor@sysoev.ru nxt_log_error(nxt_socket_error_level(err, c->socket.log_error), 71*0Sigor@sysoev.ru c->socket.log, "sendfilev(%d, %D) failed %E", 72*0Sigor@sysoev.ru c->socket.fd, nsfv, err); 73*0Sigor@sysoev.ru 74*0Sigor@sysoev.ru return NXT_ERROR; 75*0Sigor@sysoev.ru } 76*0Sigor@sysoev.ru 77*0Sigor@sysoev.ru nxt_log_debug(c->socket.log, "sendfilev() %E", err); 78*0Sigor@sysoev.ru 79*0Sigor@sysoev.ru return sent; 80*0Sigor@sysoev.ru } 81*0Sigor@sysoev.ru 82*0Sigor@sysoev.ru if ((nxt_off_t) sent < size) { 83*0Sigor@sysoev.ru c->socket.write_ready = 0; 84*0Sigor@sysoev.ru } 85*0Sigor@sysoev.ru 86*0Sigor@sysoev.ru return sent; 87*0Sigor@sysoev.ru } 88*0Sigor@sysoev.ru 89*0Sigor@sysoev.ru 90*0Sigor@sysoev.ru static size_t 91*0Sigor@sysoev.ru nxt_solaris_buf_coalesce(nxt_buf_t *b, sendfilevec_t *sfv, int32_t *nsfv, 92*0Sigor@sysoev.ru nxt_bool_t *sync, size_t limit) 93*0Sigor@sysoev.ru { 94*0Sigor@sysoev.ru size_t size, total; 95*0Sigor@sysoev.ru nxt_fd_t fd, last_fd; 96*0Sigor@sysoev.ru nxt_int_t i; 97*0Sigor@sysoev.ru nxt_off_t pos, last_pos; 98*0Sigor@sysoev.ru 99*0Sigor@sysoev.ru i = -1; 100*0Sigor@sysoev.ru last_fd = -1; 101*0Sigor@sysoev.ru last_pos = 0; 102*0Sigor@sysoev.ru total = 0; 103*0Sigor@sysoev.ru 104*0Sigor@sysoev.ru for (total = 0; b != NULL && total < limit; b = b->next) { 105*0Sigor@sysoev.ru 106*0Sigor@sysoev.ru if (nxt_buf_is_file(b)) { 107*0Sigor@sysoev.ru 108*0Sigor@sysoev.ru fd = b->file->fd; 109*0Sigor@sysoev.ru pos = b->file_pos; 110*0Sigor@sysoev.ru size = b->file_end - pos; 111*0Sigor@sysoev.ru 112*0Sigor@sysoev.ru if (size == 0) { 113*0Sigor@sysoev.ru continue; 114*0Sigor@sysoev.ru } 115*0Sigor@sysoev.ru 116*0Sigor@sysoev.ru if (total + size > limit) { 117*0Sigor@sysoev.ru size = limit - total; 118*0Sigor@sysoev.ru } 119*0Sigor@sysoev.ru 120*0Sigor@sysoev.ru } else if (nxt_buf_is_mem(b)) { 121*0Sigor@sysoev.ru 122*0Sigor@sysoev.ru fd = SFV_FD_SELF; 123*0Sigor@sysoev.ru pos = (uintptr_t) b->mem.pos; 124*0Sigor@sysoev.ru size = b->mem.free - b->mem.pos; 125*0Sigor@sysoev.ru 126*0Sigor@sysoev.ru if (size == 0) { 127*0Sigor@sysoev.ru continue; 128*0Sigor@sysoev.ru } 129*0Sigor@sysoev.ru 130*0Sigor@sysoev.ru if (total + size > limit) { 131*0Sigor@sysoev.ru size = limit - total; 132*0Sigor@sysoev.ru } 133*0Sigor@sysoev.ru 134*0Sigor@sysoev.ru } else { 135*0Sigor@sysoev.ru *sync = 1; 136*0Sigor@sysoev.ru continue; 137*0Sigor@sysoev.ru } 138*0Sigor@sysoev.ru 139*0Sigor@sysoev.ru if (size == 0) { 140*0Sigor@sysoev.ru break; 141*0Sigor@sysoev.ru } 142*0Sigor@sysoev.ru 143*0Sigor@sysoev.ru if (fd != last_fd || pos != last_pos) { 144*0Sigor@sysoev.ru 145*0Sigor@sysoev.ru if (++i >= NXT_IOBUF_MAX) { 146*0Sigor@sysoev.ru goto done; 147*0Sigor@sysoev.ru } 148*0Sigor@sysoev.ru 149*0Sigor@sysoev.ru sfv[i].sfv_fd = fd; 150*0Sigor@sysoev.ru sfv[i].sfv_flag = 0; 151*0Sigor@sysoev.ru sfv[i].sfv_off = pos; 152*0Sigor@sysoev.ru sfv[i].sfv_len = size; 153*0Sigor@sysoev.ru 154*0Sigor@sysoev.ru } else { 155*0Sigor@sysoev.ru sfv[i].sfv_len += size; 156*0Sigor@sysoev.ru } 157*0Sigor@sysoev.ru 158*0Sigor@sysoev.ru total += size; 159*0Sigor@sysoev.ru last_pos = pos + size; 160*0Sigor@sysoev.ru last_fd = fd; 161*0Sigor@sysoev.ru } 162*0Sigor@sysoev.ru 163*0Sigor@sysoev.ru i++; 164*0Sigor@sysoev.ru 165*0Sigor@sysoev.ru done: 166*0Sigor@sysoev.ru 167*0Sigor@sysoev.ru *nsfv = i; 168*0Sigor@sysoev.ru 169*0Sigor@sysoev.ru return total; 170*0Sigor@sysoev.ru } 171