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>