xref: /unit/src/nxt_solaris_sendfilev.c (revision 13:3a52b2c3d3f1)
10Sigor@sysoev.ru 
20Sigor@sysoev.ru /*
30Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
40Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
50Sigor@sysoev.ru  */
60Sigor@sysoev.ru 
70Sigor@sysoev.ru #include <nxt_main.h>
80Sigor@sysoev.ru 
90Sigor@sysoev.ru 
100Sigor@sysoev.ru /*
110Sigor@sysoev.ru  * sendfilev() has been introduced in Solaris 8 (7/01).
120Sigor@sysoev.ru  * According to sendfilev(3EXT) it can write to:
130Sigor@sysoev.ru  *
140Sigor@sysoev.ru  *   a file descriptor to a regular file or to a AF_NCA, AF_INET, or
150Sigor@sysoev.ru  *   AF_INET6 family type SOCK_STREAM socket that is open for writing.
160Sigor@sysoev.ru  */
170Sigor@sysoev.ru 
180Sigor@sysoev.ru ssize_t nxt_solaris_event_conn_io_sendfilev(nxt_event_conn_t *c, nxt_buf_t *b,
190Sigor@sysoev.ru     size_t limit);
200Sigor@sysoev.ru static size_t nxt_solaris_buf_coalesce(nxt_buf_t *b, sendfilevec_t *sfv,
210Sigor@sysoev.ru     int32_t *nsfv, nxt_bool_t *sync, size_t limit);
220Sigor@sysoev.ru 
230Sigor@sysoev.ru 
240Sigor@sysoev.ru ssize_t
nxt_solaris_event_conn_io_sendfilev(nxt_event_conn_t * c,nxt_buf_t * b,size_t limit)250Sigor@sysoev.ru nxt_solaris_event_conn_io_sendfilev(nxt_event_conn_t *c, nxt_buf_t *b,
260Sigor@sysoev.ru     size_t limit)
270Sigor@sysoev.ru {
280Sigor@sysoev.ru     size_t         sent;
290Sigor@sysoev.ru     ssize_t        n;
300Sigor@sysoev.ru     int32_t        nsfv;
310Sigor@sysoev.ru     nxt_err_t      err;
320Sigor@sysoev.ru     nxt_off_t      size;
330Sigor@sysoev.ru     nxt_bool_t     sync;
340Sigor@sysoev.ru     sendfilevec_t  sfv[NXT_IOBUF_MAX];
350Sigor@sysoev.ru 
360Sigor@sysoev.ru     if (c->sendfile == 0) {
370Sigor@sysoev.ru         /* AF_UNIX does not support sendfilev(). */
380Sigor@sysoev.ru         return nxt_event_conn_io_sendbuf(c, b, limit);
390Sigor@sysoev.ru     }
400Sigor@sysoev.ru 
410Sigor@sysoev.ru     sync = 0;
420Sigor@sysoev.ru 
430Sigor@sysoev.ru     size = nxt_solaris_buf_coalesce(b, sfv, &nsfv, &sync, limit);
440Sigor@sysoev.ru 
45*13Sigor@sysoev.ru     nxt_debug(c->socket.task, "sendfilev(%d, %D)", c->socket.fd, nsfv);
460Sigor@sysoev.ru 
470Sigor@sysoev.ru     if (nsfv == 0 && sync) {
480Sigor@sysoev.ru         return 0;
490Sigor@sysoev.ru     }
500Sigor@sysoev.ru 
510Sigor@sysoev.ru     sent = 0;
520Sigor@sysoev.ru     n = sendfilev(c->socket.fd, sfv, nsfv, &sent);
530Sigor@sysoev.ru 
540Sigor@sysoev.ru     err = (n == -1) ? nxt_errno : 0;
550Sigor@sysoev.ru 
56*13Sigor@sysoev.ru     nxt_debug(c->socket.task, "sendfilev(): %d sent:%uz", n, sent);
570Sigor@sysoev.ru 
580Sigor@sysoev.ru     if (n == -1) {
590Sigor@sysoev.ru         switch (err) {
600Sigor@sysoev.ru 
610Sigor@sysoev.ru         case NXT_EAGAIN:
620Sigor@sysoev.ru             c->socket.write_ready = 0;
630Sigor@sysoev.ru             break;
640Sigor@sysoev.ru 
650Sigor@sysoev.ru         case NXT_EINTR:
660Sigor@sysoev.ru             break;
670Sigor@sysoev.ru 
680Sigor@sysoev.ru         default:
690Sigor@sysoev.ru             c->socket.error = err;
70*13Sigor@sysoev.ru             nxt_log(c->socket.task, nxt_socket_error_level(err),
71*13Sigor@sysoev.ru                     "sendfilev(%d, %D) failed %E", c->socket.fd, nsfv, err);
720Sigor@sysoev.ru 
730Sigor@sysoev.ru             return NXT_ERROR;
740Sigor@sysoev.ru         }
750Sigor@sysoev.ru 
76*13Sigor@sysoev.ru         nxt_debug(c->socket.task, "sendfilev() %E", err);
770Sigor@sysoev.ru 
780Sigor@sysoev.ru         return sent;
790Sigor@sysoev.ru     }
800Sigor@sysoev.ru 
810Sigor@sysoev.ru     if ((nxt_off_t) sent < size) {
820Sigor@sysoev.ru         c->socket.write_ready = 0;
830Sigor@sysoev.ru     }
840Sigor@sysoev.ru 
850Sigor@sysoev.ru     return sent;
860Sigor@sysoev.ru }
870Sigor@sysoev.ru 
880Sigor@sysoev.ru 
890Sigor@sysoev.ru static size_t
nxt_solaris_buf_coalesce(nxt_buf_t * b,sendfilevec_t * sfv,int32_t * nsfv,nxt_bool_t * sync,size_t limit)900Sigor@sysoev.ru nxt_solaris_buf_coalesce(nxt_buf_t *b, sendfilevec_t *sfv, int32_t *nsfv,
910Sigor@sysoev.ru     nxt_bool_t *sync, size_t limit)
920Sigor@sysoev.ru {
930Sigor@sysoev.ru     size_t     size, total;
940Sigor@sysoev.ru     nxt_fd_t   fd, last_fd;
950Sigor@sysoev.ru     nxt_int_t  i;
960Sigor@sysoev.ru     nxt_off_t  pos, last_pos;
970Sigor@sysoev.ru 
980Sigor@sysoev.ru     i = -1;
990Sigor@sysoev.ru     last_fd = -1;
1000Sigor@sysoev.ru     last_pos = 0;
1010Sigor@sysoev.ru     total = 0;
1020Sigor@sysoev.ru 
1030Sigor@sysoev.ru     for (total = 0; b != NULL && total < limit; b = b->next) {
1040Sigor@sysoev.ru 
1050Sigor@sysoev.ru         if (nxt_buf_is_file(b)) {
1060Sigor@sysoev.ru 
1070Sigor@sysoev.ru             fd = b->file->fd;
1080Sigor@sysoev.ru             pos = b->file_pos;
1090Sigor@sysoev.ru             size = b->file_end - pos;
1100Sigor@sysoev.ru 
1110Sigor@sysoev.ru             if (size == 0) {
1120Sigor@sysoev.ru                 continue;
1130Sigor@sysoev.ru             }
1140Sigor@sysoev.ru 
1150Sigor@sysoev.ru             if (total + size > limit) {
1160Sigor@sysoev.ru                 size = limit - total;
1170Sigor@sysoev.ru             }
1180Sigor@sysoev.ru 
1190Sigor@sysoev.ru         } else if (nxt_buf_is_mem(b)) {
1200Sigor@sysoev.ru 
1210Sigor@sysoev.ru             fd = SFV_FD_SELF;
1220Sigor@sysoev.ru             pos = (uintptr_t) b->mem.pos;
1230Sigor@sysoev.ru             size = b->mem.free - b->mem.pos;
1240Sigor@sysoev.ru 
1250Sigor@sysoev.ru             if (size == 0) {
1260Sigor@sysoev.ru                 continue;
1270Sigor@sysoev.ru             }
1280Sigor@sysoev.ru 
1290Sigor@sysoev.ru             if (total + size > limit) {
1300Sigor@sysoev.ru                 size = limit - total;
1310Sigor@sysoev.ru             }
1320Sigor@sysoev.ru 
1330Sigor@sysoev.ru         } else {
1340Sigor@sysoev.ru             *sync = 1;
1350Sigor@sysoev.ru             continue;
1360Sigor@sysoev.ru         }
1370Sigor@sysoev.ru 
1380Sigor@sysoev.ru         if (size == 0) {
1390Sigor@sysoev.ru             break;
1400Sigor@sysoev.ru         }
1410Sigor@sysoev.ru 
1420Sigor@sysoev.ru         if (fd != last_fd || pos != last_pos) {
1430Sigor@sysoev.ru 
1440Sigor@sysoev.ru             if (++i >= NXT_IOBUF_MAX) {
1450Sigor@sysoev.ru                 goto done;
1460Sigor@sysoev.ru             }
1470Sigor@sysoev.ru 
1480Sigor@sysoev.ru             sfv[i].sfv_fd = fd;
1490Sigor@sysoev.ru             sfv[i].sfv_flag = 0;
1500Sigor@sysoev.ru             sfv[i].sfv_off = pos;
1510Sigor@sysoev.ru             sfv[i].sfv_len = size;
1520Sigor@sysoev.ru 
1530Sigor@sysoev.ru         } else {
1540Sigor@sysoev.ru             sfv[i].sfv_len += size;
1550Sigor@sysoev.ru         }
1560Sigor@sysoev.ru 
1570Sigor@sysoev.ru         total += size;
1580Sigor@sysoev.ru         last_pos = pos + size;
1590Sigor@sysoev.ru         last_fd = fd;
1600Sigor@sysoev.ru     }
1610Sigor@sysoev.ru 
1620Sigor@sysoev.ru     i++;
1630Sigor@sysoev.ru 
1640Sigor@sysoev.ru done:
1650Sigor@sysoev.ru 
1660Sigor@sysoev.ru     *nsfv = i;
1670Sigor@sysoev.ru 
1680Sigor@sysoev.ru     return total;
1690Sigor@sysoev.ru }
170