src/core/ngx_buf.c - nginx source code

Functions 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. ngx_buf_t *
  8. ngx_create_temp_buf(ngx_pool_t *pool, size_t size)
  9. {
  10.     ngx_buf_t *b;

  11.     b = ngx_calloc_buf(pool);
  12.     if (b == NULL) {
  13.         return NULL;
  14.     }

  15.     b->start = ngx_palloc(pool, size);
  16.     if (b->start == NULL) {
  17.         return NULL;
  18.     }

  19.     /*
  20.      * set by ngx_calloc_buf():
  21.      *
  22.      *     b->file_pos = 0;
  23.      *     b->file_last = 0;
  24.      *     b->file = NULL;
  25.      *     b->shadow = NULL;
  26.      *     b->tag = 0;
  27.      *     and flags
  28.      */

  29.     b->pos = b->start;
  30.     b->last = b->start;
  31.     b->end = b->last + size;
  32.     b->temporary = 1;

  33.     return b;
  34. }


  35. ngx_chain_t *
  36. ngx_alloc_chain_link(ngx_pool_t *pool)
  37. {
  38.     ngx_chain_t  *cl;

  39.     cl = pool->chain;

  40.     if (cl) {
  41.         pool->chain = cl->next;
  42.         return cl;
  43.     }

  44.     cl = ngx_palloc(pool, sizeof(ngx_chain_t));
  45.     if (cl == NULL) {
  46.         return NULL;
  47.     }

  48.     return cl;
  49. }


  50. ngx_chain_t *
  51. ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs)
  52. {
  53.     u_char       *p;
  54.     ngx_int_t     i;
  55.     ngx_buf_t    *b;
  56.     ngx_chain_t  *chain, *cl, **ll;

  57.     p = ngx_palloc(pool, bufs->num * bufs->size);
  58.     if (p == NULL) {
  59.         return NULL;
  60.     }

  61.     ll = &chain;

  62.     for (i = 0; i < bufs->num; i++) {

  63.         b = ngx_calloc_buf(pool);
  64.         if (b == NULL) {
  65.             return NULL;
  66.         }

  67.         /*
  68.          * set by ngx_calloc_buf():
  69.          *
  70.          *     b->file_pos = 0;
  71.          *     b->file_last = 0;
  72.          *     b->file = NULL;
  73.          *     b->shadow = NULL;
  74.          *     b->tag = 0;
  75.          *     and flags
  76.          *
  77.          */

  78.         b->pos = p;
  79.         b->last = p;
  80.         b->temporary = 1;

  81.         b->start = p;
  82.         p += bufs->size;
  83.         b->end = p;

  84.         cl = ngx_alloc_chain_link(pool);
  85.         if (cl == NULL) {
  86.             return NULL;
  87.         }

  88.         cl->buf = b;
  89.         *ll = cl;
  90.         ll = &cl->next;
  91.     }

  92.     *ll = NULL;

  93.     return chain;
  94. }


  95. ngx_int_t
  96. ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain, ngx_chain_t *in)
  97. {
  98.     ngx_chain_t  *cl, **ll;

  99.     ll = chain;

  100.     for (cl = *chain; cl; cl = cl->next) {
  101.         ll = &cl->next;
  102.     }

  103.     while (in) {
  104.         cl = ngx_alloc_chain_link(pool);
  105.         if (cl == NULL) {
  106.             *ll = NULL;
  107.             return NGX_ERROR;
  108.         }

  109.         cl->buf = in->buf;
  110.         *ll = cl;
  111.         ll = &cl->next;
  112.         in = in->next;
  113.     }

  114.     *ll = NULL;

  115.     return NGX_OK;
  116. }


  117. ngx_chain_t *
  118. ngx_chain_get_free_buf(ngx_pool_t *p, ngx_chain_t **free)
  119. {
  120.     ngx_chain_t  *cl;

  121.     if (*free) {
  122.         cl = *free;
  123.         *free = cl->next;
  124.         cl->next = NULL;
  125.         return cl;
  126.     }

  127.     cl = ngx_alloc_chain_link(p);
  128.     if (cl == NULL) {
  129.         return NULL;
  130.     }

  131.     cl->buf = ngx_calloc_buf(p);
  132.     if (cl->buf == NULL) {
  133.         return NULL;
  134.     }

  135.     cl->next = NULL;

  136.     return cl;
  137. }


  138. void
  139. ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free, ngx_chain_t **busy,
  140.     ngx_chain_t **out, ngx_buf_tag_t tag)
  141. {
  142.     ngx_chain_t  *cl;

  143.     if (*out) {
  144.         if (*busy == NULL) {
  145.             *busy = *out;

  146.         } else {
  147.             for (cl = *busy; cl->next; cl = cl->next) { /* void */ }

  148.             cl->next = *out;
  149.         }

  150.         *out = NULL;
  151.     }

  152.     while (*busy) {
  153.         cl = *busy;

  154.         if (cl->buf->tag != tag) {
  155.             *busy = cl->next;
  156.             ngx_free_chain(p, cl);
  157.             continue;
  158.         }

  159.         if (ngx_buf_size(cl->buf) != 0) {
  160.             break;
  161.         }

  162.         cl->buf->pos = cl->buf->start;
  163.         cl->buf->last = cl->buf->start;

  164.         *busy = cl->next;
  165.         cl->next = *free;
  166.         *free = cl;
  167.     }
  168. }


  169. off_t
  170. ngx_chain_coalesce_file(ngx_chain_t **in, off_t limit)
  171. {
  172.     off_t         total, size, aligned, fprev;
  173.     ngx_fd_t      fd;
  174.     ngx_chain_t  *cl;

  175.     total = 0;

  176.     cl = *in;
  177.     fd = cl->buf->file->fd;

  178.     do {
  179.         size = cl->buf->file_last - cl->buf->file_pos;

  180.         if (size > limit - total) {
  181.             size = limit - total;

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

  184.             if (aligned <= cl->buf->file_last) {
  185.                 size = aligned - cl->buf->file_pos;
  186.             }

  187.             total += size;
  188.             break;
  189.         }

  190.         total += size;
  191.         fprev = cl->buf->file_pos + size;
  192.         cl = cl->next;

  193.     } while (cl
  194.              && cl->buf->in_file
  195.              && total < limit
  196.              && fd == cl->buf->file->fd
  197.              && fprev == cl->buf->file_pos);

  198.     *in = cl;

  199.     return total;
  200. }


  201. ngx_chain_t *
  202. ngx_chain_update_sent(ngx_chain_t *in, off_t sent)
  203. {
  204.     off_t  size;

  205.     for ( /* void */ ; in; in = in->next) {

  206.         if (ngx_buf_special(in->buf)) {
  207.             continue;
  208.         }

  209.         if (sent == 0) {
  210.             break;
  211.         }

  212.         size = ngx_buf_size(in->buf);

  213.         if (sent >= size) {
  214.             sent -= size;

  215.             if (ngx_buf_in_memory(in->buf)) {
  216.                 in->buf->pos = in->buf->last;
  217.             }

  218.             if (in->buf->in_file) {
  219.                 in->buf->file_pos = in->buf->file_last;
  220.             }

  221.             continue;
  222.         }

  223.         if (ngx_buf_in_memory(in->buf)) {
  224.             in->buf->pos += (size_t) sent;
  225.         }

  226.         if (in->buf->in_file) {
  227.             in->buf->file_pos += sent;
  228.         }

  229.         break;
  230.     }

  231.     return in;
  232. }