Annotation of embedaddon/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c, revision 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>