src/os/unix/ngx_solaris_sendfilev_chain.c - nginx-1.7.10

Data types defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>


  8. #if (NGX_TEST_BUILD_SOLARIS_SENDFILEV)

  9. /* Solaris declarations */

  10. typedef struct sendfilevec {
  11.     int     sfv_fd;
  12.     u_int   sfv_flag;
  13.     off_t   sfv_off;
  14.     size_t  sfv_len;
  15. } sendfilevec_t;

  16. #define SFV_FD_SELF  -2

  17. static ssize_t sendfilev(int fd, const struct sendfilevec *vec,
  18.     int sfvcnt, size_t *xferred)
  19. {
  20.     return -1;
  21. }

  22. ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in,
  23.     off_t limit);

  24. #endif


  25. #define NGX_SENDFILEVECS  NGX_IOVS_PREALLOCATE


  26. ngx_chain_t *
  27. ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
  28. {
  29.     int             fd;
  30.     u_char         *prev;
  31.     off_t           size, send, prev_send, aligned, fprev;
  32.     size_t          sent;
  33.     ssize_t         n;
  34.     ngx_int_t       eintr;
  35.     ngx_err_t       err;
  36.     ngx_uint_t      nsfv;
  37.     sendfilevec_t  *sfv, sfvs[NGX_SENDFILEVECS];
  38.     ngx_event_t    *wev;
  39.     ngx_chain_t    *cl;

  40.     wev = c->write;

  41.     if (!wev->ready) {
  42.         return in;
  43.     }

  44.     if (!c->sendfile) {
  45.         return ngx_writev_chain(c, in, limit);
  46.     }


  47.     /* the maximum limit size is the maximum size_t value - the page size */

  48.     if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
  49.         limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize;
  50.     }


  51.     send = 0;

  52.     for ( ;; ) {
  53.         fd = SFV_FD_SELF;
  54.         prev = NULL;
  55.         fprev = 0;
  56.         sfv = NULL;
  57.         eintr = 0;
  58.         sent = 0;
  59.         prev_send = send;

  60.         nsfv = 0;

  61.         /* create the sendfilevec and coalesce the neighbouring bufs */

  62.         for (cl = in; cl && send < limit; cl = cl->next) {

  63.             if (ngx_buf_special(cl->buf)) {
  64.                 continue;
  65.             }

  66.             if (ngx_buf_in_memory_only(cl->buf)) {
  67.                 fd = SFV_FD_SELF;

  68.                 size = cl->buf->last - cl->buf->pos;

  69.                 if (send + size > limit) {
  70.                     size = limit - send;
  71.                 }

  72.                 if (prev == cl->buf->pos) {
  73.                     sfv->sfv_len += (size_t) size;

  74.                 } else {
  75.                     if (nsfv == NGX_SENDFILEVECS) {
  76.                         break;
  77.                     }

  78.                     sfv = &sfvs[nsfv++];

  79.                     sfv->sfv_fd = SFV_FD_SELF;
  80.                     sfv->sfv_flag = 0;
  81.                     sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos;
  82.                     sfv->sfv_len = (size_t) size;
  83.                 }

  84.                 prev = cl->buf->pos + (size_t) size;
  85.                 send += size;

  86.             } else {
  87.                 prev = NULL;

  88.                 size = cl->buf->file_last - cl->buf->file_pos;

  89.                 if (send + size > limit) {
  90.                     size = limit - send;

  91.                     aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
  92.                                & ~((off_t) ngx_pagesize - 1);

  93.                     if (aligned <= cl->buf->file_last) {
  94.                         size = aligned - cl->buf->file_pos;
  95.                     }
  96.                 }

  97.                 if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) {
  98.                     sfv->sfv_len += (size_t) size;

  99.                 } else {
  100.                     if (nsfv == NGX_SENDFILEVECS) {
  101.                         break;
  102.                     }

  103.                     sfv = &sfvs[nsfv++];

  104.                     fd = cl->buf->file->fd;
  105.                     sfv->sfv_fd = fd;
  106.                     sfv->sfv_flag = 0;
  107.                     sfv->sfv_off = cl->buf->file_pos;
  108.                     sfv->sfv_len = (size_t) size;
  109.                 }

  110.                 fprev = cl->buf->file_pos + size;
  111.                 send += size;
  112.             }
  113.         }

  114.         n = sendfilev(c->fd, sfvs, nsfv, &sent);

  115.         if (n == -1) {
  116.             err = ngx_errno;

  117.             switch (err) {
  118.             case NGX_EAGAIN:
  119.                 break;

  120.             case NGX_EINTR:
  121.                 eintr = 1;
  122.                 break;

  123.             default:
  124.                 wev->error = 1;
  125.                 ngx_connection_error(c, err, "sendfilev() failed");
  126.                 return NGX_CHAIN_ERROR;
  127.             }

  128.             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
  129.                           "sendfilev() sent only %uz bytes", sent);
  130.         }

  131.         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
  132.                        "sendfilev: %z %z", n, sent);

  133.         c->sent += sent;

  134.         in = ngx_chain_update_sent(in, sent);

  135.         if (eintr) {
  136.             send = prev_send + sent;
  137.             continue;
  138.         }

  139.         if (send - prev_send != (off_t) sent) {
  140.             wev->ready = 0;
  141.             return in;
  142.         }

  143.         if (send >= limit || in == NULL) {
  144.             return in;
  145.         }
  146.     }
  147. }