Annotation of embedaddon/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: #include <ngx_event.h>
                     11: 
                     12: 
                     13: #if (NGX_TEST_BUILD_SOLARIS_SENDFILEV)
                     14: 
                     15: /* Solaris declarations */
                     16: 
                     17: typedef struct sendfilevec {
                     18:     int     sfv_fd;
                     19:     u_int   sfv_flag;
                     20:     off_t   sfv_off;
                     21:     size_t  sfv_len;
                     22: } sendfilevec_t;
                     23: 
                     24: #define SFV_FD_SELF  -2
                     25: 
                     26: static ssize_t sendfilev(int fd, const struct sendfilevec *vec,
                     27:     int sfvcnt, size_t *xferred)
                     28: {
                     29:     return -1;
                     30: }
                     31: 
                     32: ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in,
                     33:     off_t limit);
                     34: 
                     35: #endif
                     36: 
                     37: 
                     38: #if (IOV_MAX > 64)
                     39: #define NGX_SENDFILEVECS  64
                     40: #else
                     41: #define NGX_SENDFILEVECS  IOV_MAX
                     42: #endif
                     43: 
                     44: 
                     45: 
                     46: ngx_chain_t *
                     47: ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
                     48: {
                     49:     int             fd;
                     50:     u_char         *prev;
                     51:     off_t           size, send, prev_send, aligned, fprev;
                     52:     size_t          sent;
                     53:     ssize_t         n;
                     54:     ngx_int_t       eintr, complete;
                     55:     ngx_err_t       err;
                     56:     sendfilevec_t  *sfv, sfvs[NGX_SENDFILEVECS];
                     57:     ngx_array_t     vec;
                     58:     ngx_event_t    *wev;
                     59:     ngx_chain_t    *cl;
                     60: 
                     61:     wev = c->write;
                     62: 
                     63:     if (!wev->ready) {
                     64:         return in;
                     65:     }
                     66: 
                     67:     if (!c->sendfile) {
                     68:         return ngx_writev_chain(c, in, limit);
                     69:     }
                     70: 
                     71: 
                     72:     /* the maximum limit size is the maximum size_t value - the page size */
                     73: 
                     74:     if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
                     75:         limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize;
                     76:     }
                     77: 
                     78: 
                     79:     send = 0;
                     80: 
                     81:     vec.elts = sfvs;
                     82:     vec.size = sizeof(sendfilevec_t);
                     83:     vec.nalloc = NGX_SENDFILEVECS;
                     84:     vec.pool = c->pool;
                     85: 
                     86:     for ( ;; ) {
                     87:         fd = SFV_FD_SELF;
                     88:         prev = NULL;
                     89:         fprev = 0;
                     90:         sfv = NULL;
                     91:         eintr = 0;
                     92:         complete = 0;
                     93:         sent = 0;
                     94:         prev_send = send;
                     95: 
                     96:         vec.nelts = 0;
                     97: 
                     98:         /* create the sendfilevec and coalesce the neighbouring bufs */
                     99: 
                    100:         for (cl = in; cl && send < limit; cl = cl->next) {
                    101: 
                    102:             if (ngx_buf_special(cl->buf)) {
                    103:                 continue;
                    104:             }
                    105: 
                    106:             if (ngx_buf_in_memory_only(cl->buf)) {
                    107:                 fd = SFV_FD_SELF;
                    108: 
                    109:                 size = cl->buf->last - cl->buf->pos;
                    110: 
                    111:                 if (send + size > limit) {
                    112:                     size = limit - send;
                    113:                 }
                    114: 
                    115:                 if (prev == cl->buf->pos) {
                    116:                     sfv->sfv_len += (size_t) size;
                    117: 
                    118:                 } else {
                    119:                     if (vec.nelts >= IOV_MAX) {
                    120:                         break;
                    121:                     }
                    122: 
                    123:                     sfv = ngx_array_push(&vec);
                    124:                     if (sfv == NULL) {
                    125:                         return NGX_CHAIN_ERROR;
                    126:                     }
                    127: 
                    128:                     sfv->sfv_fd = SFV_FD_SELF;
                    129:                     sfv->sfv_flag = 0;
                    130:                     sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos;
                    131:                     sfv->sfv_len = (size_t) size;
                    132:                 }
                    133: 
                    134:                 prev = cl->buf->pos + (size_t) size;
                    135:                 send += size;
                    136: 
                    137:             } else {
                    138:                 prev = NULL;
                    139: 
                    140:                 size = cl->buf->file_last - cl->buf->file_pos;
                    141: 
                    142:                 if (send + size > limit) {
                    143:                     size = limit - send;
                    144: 
                    145:                     aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
                    146:                                & ~((off_t) ngx_pagesize - 1);
                    147: 
                    148:                     if (aligned <= cl->buf->file_last) {
                    149:                         size = aligned - cl->buf->file_pos;
                    150:                     }
                    151:                 }
                    152: 
                    153:                 if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) {
                    154:                     sfv->sfv_len += (size_t) size;
                    155: 
                    156:                 } else {
                    157:                     if (vec.nelts >= IOV_MAX) {
                    158:                         break;
                    159:                     }
                    160: 
                    161:                     sfv = ngx_array_push(&vec);
                    162:                     if (sfv == NULL) {
                    163:                         return NGX_CHAIN_ERROR;
                    164:                     }
                    165: 
                    166:                     fd = cl->buf->file->fd;
                    167:                     sfv->sfv_fd = fd;
                    168:                     sfv->sfv_flag = 0;
                    169:                     sfv->sfv_off = cl->buf->file_pos;
                    170:                     sfv->sfv_len = (size_t) size;
                    171:                 }
                    172: 
                    173:                 fprev = cl->buf->file_pos + size;
                    174:                 send += size;
                    175:             }
                    176:         }
                    177: 
                    178:         n = sendfilev(c->fd, vec.elts, vec.nelts, &sent);
                    179: 
                    180:         if (n == -1) {
                    181:             err = ngx_errno;
                    182: 
                    183:             switch (err) {
                    184:             case NGX_EAGAIN:
                    185:                 break;
                    186: 
                    187:             case NGX_EINTR:
                    188:                 eintr = 1;
                    189:                 break;
                    190: 
                    191:             default:
                    192:                 wev->error = 1;
                    193:                 ngx_connection_error(c, err, "sendfilev() failed");
                    194:                 return NGX_CHAIN_ERROR;
                    195:             }
                    196: 
                    197:             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
                    198:                           "sendfilev() sent only %uz bytes", sent);
                    199:         }
                    200: 
                    201:         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    202:                        "sendfilev: %z %z", n, sent);
                    203: 
                    204:         if (send - prev_send == (off_t) sent) {
                    205:             complete = 1;
                    206:         }
                    207: 
                    208:         c->sent += sent;
                    209: 
                    210:         for (cl = in; cl; cl = cl->next) {
                    211: 
                    212:             if (ngx_buf_special(cl->buf)) {
                    213:                 continue;
                    214:             }
                    215: 
                    216:             if (sent == 0) {
                    217:                 break;
                    218:             }
                    219: 
                    220:             size = ngx_buf_size(cl->buf);
                    221: 
                    222:             if ((off_t) sent >= size) {
                    223:                 sent = (size_t) ((off_t) sent - size);
                    224: 
                    225:                 if (ngx_buf_in_memory(cl->buf)) {
                    226:                     cl->buf->pos = cl->buf->last;
                    227:                 }
                    228: 
                    229:                 if (cl->buf->in_file) {
                    230:                     cl->buf->file_pos = cl->buf->file_last;
                    231:                 }
                    232: 
                    233:                 continue;
                    234:             }
                    235: 
                    236:             if (ngx_buf_in_memory(cl->buf)) {
                    237:                 cl->buf->pos += sent;
                    238:             }
                    239: 
                    240:             if (cl->buf->in_file) {
                    241:                 cl->buf->file_pos += sent;
                    242:             }
                    243: 
                    244:             break;
                    245:         }
                    246: 
                    247:         if (eintr) {
                    248:             continue;
                    249:         }
                    250: 
                    251:         if (!complete) {
                    252:             wev->ready = 0;
                    253:             return cl;
                    254:         }
                    255: 
                    256:         if (send >= limit || cl == NULL) {
                    257:             return cl;
                    258:         }
                    259: 
                    260:         in = cl;
                    261:     }
                    262: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>