ngx_event_pipe.c

来自「Nginx是一个高性能的HTTP和反向代理服务器」· C语言 代码 · 共 979 行 · 第 1/2 页

C
979
字号
            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,                           "pipe write downstream done");            /* TODO: free unused bufs */            p->downstream_done = 1;            break;        }        if (downstream->data != p->output_ctx            || !downstream->write->ready            || downstream->write->delayed)        {            break;        }        /* bsize is the size of the busy recycled bufs */        prev = NULL;        bsize = 0;        for (cl = p->busy; cl; cl = cl->next) {            if (cl->buf->recycled) {                if (prev == cl->buf->start) {                    continue;                }                bsize += cl->buf->end - cl->buf->start;                prev = cl->buf->start;            }        }        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0,                       "pipe write busy: %uz", bsize);        out = NULL;        if (bsize >= (size_t) p->busy_size) {            flush = 1;            goto flush;        }        flush = 0;        ll = NULL;        prev_last_shadow = 1;        for ( ;; ) {            if (p->out) {                cl = p->out;                if (cl->buf->recycled                    && bsize + cl->buf->last - cl->buf->pos > p->busy_size)                {                    flush = 1;                    break;                }                p->out = p->out->next;                ngx_event_pipe_free_shadow_raw_buf(&p->free_raw_bufs, cl->buf);            } else if (!p->cacheable && p->in) {                cl = p->in;                ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0,                               "pipe write buf ls:%d %p %z",                               cl->buf->last_shadow,                               cl->buf->pos,                               cl->buf->last - cl->buf->pos);                if (cl->buf->recycled                    && cl->buf->last_shadow                    && bsize + cl->buf->last - cl->buf->pos > p->busy_size)                {                    if (!prev_last_shadow) {                        p->in = p->in->next;                        cl->next = NULL;                        if (out) {                            *ll = cl;                        } else {                            out = cl;                        }                    }                    flush = 1;                    break;                }                prev_last_shadow = cl->buf->last_shadow;                p->in = p->in->next;            } else {                break;            }            if (cl->buf->recycled) {                bsize += cl->buf->last - cl->buf->pos;            }            cl->next = NULL;            if (out) {                *ll = cl;            } else {                out = cl;            }            ll = &cl->next;        }    flush:        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,                       "pipe write: out:%p, f:%d", out, flush);        if (out == NULL && !flush) {            break;        }        rc = p->output_filter(p->output_ctx, out);        if (downstream->destroyed) {            return NGX_ABORT;        }        if (rc == NGX_ERROR) {            p->downstream_error = 1;            return ngx_event_pipe_drain_chains(p);        }        ngx_chain_update_chains(&p->free, &p->busy, &out, p->tag);        for (cl = p->free; cl; cl = cl->next) {            if (cl->buf->temp_file) {                if (p->cacheable || !p->cyclic_temp_file) {                    continue;                }                /* reset p->temp_offset if all bufs had been sent */                if (cl->buf->file_last == p->temp_file->offset) {                    p->temp_file->offset = 0;                }            }            /* TODO: free buf if p->free_bufs && upstream done */            /* add the free shadow raw buf to p->free_raw_bufs */            if (cl->buf->last_shadow) {                if (ngx_event_pipe_add_free_buf(p, cl->buf->shadow) != NGX_OK) {                    return NGX_ABORT;                }                cl->buf->last_shadow = 0;            }            cl->buf->shadow = NULL;        }    }    return NGX_OK;}static ngx_int_tngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p){    ssize_t       size, bsize;    ngx_buf_t    *b;    ngx_chain_t  *cl, *tl, *next, *out, **ll, **last_free, fl;    if (p->buf_to_file) {        fl.buf = p->buf_to_file;        fl.next = p->in;        out = &fl;    } else {        out = p->in;    }    if (!p->cacheable) {        size = 0;        cl = out;        ll = NULL;        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0,                       "pipe offset: %O", p->temp_file->offset);        do {            bsize = cl->buf->last - cl->buf->pos;            ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0,                           "pipe buf %p, pos %p, size: %z",                           cl->buf->start, cl->buf->pos, bsize);            if ((size + bsize > p->temp_file_write_size)               || (p->temp_file->offset + size + bsize > p->max_temp_file_size))            {                break;            }            size += bsize;            ll = &cl->next;            cl = cl->next;        } while (cl);        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "size: %z", size);        if (ll == NULL) {            return NGX_BUSY;        }        if (cl) {           p->in = cl;           *ll = NULL;        } else {           p->in = NULL;           p->last_in = &p->in;        }    } else {        p->in = NULL;        p->last_in = &p->in;    }    if (ngx_write_chain_to_temp_file(p->temp_file, out) == NGX_ERROR) {        return NGX_ABORT;    }    for (last_free = &p->free_raw_bufs;         *last_free != NULL;         last_free = &(*last_free)->next)    {        /* void */    }    if (p->buf_to_file) {        p->temp_file->offset = p->buf_to_file->last - p->buf_to_file->pos;        p->buf_to_file = NULL;        out = out->next;    }    for (cl = out; cl; cl = next) {        next = cl->next;        cl->next = NULL;        b = cl->buf;        b->file = &p->temp_file->file;        b->file_pos = p->temp_file->offset;        p->temp_file->offset += b->last - b->pos;        b->file_last = p->temp_file->offset;        b->in_file = 1;        b->temp_file = 1;        if (p->out) {            *p->last_out = cl;        } else {            p->out = cl;        }        p->last_out = &cl->next;        if (b->last_shadow) {            tl = ngx_alloc_chain_link(p->pool);            if (tl == NULL) {                return NGX_ABORT;            }            tl->buf = b->shadow;            tl->next = NULL;            *last_free = tl;            last_free = &tl->next;            b->shadow->pos = b->shadow->start;            b->shadow->last = b->shadow->start;            ngx_event_pipe_remove_shadow_links(b->shadow);        }    }    return NGX_OK;}/* the copy input filter */ngx_int_tngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf){    ngx_buf_t    *b;    ngx_chain_t  *cl;    if (buf->pos == buf->last) {        return NGX_OK;    }    if (p->free) {        cl = p->free;        b = cl->buf;        p->free = cl->next;        ngx_free_chain(p->pool, cl);    } else {        b = ngx_alloc_buf(p->pool);        if (b == NULL) {            return NGX_ERROR;        }    }    ngx_memcpy(b, buf, sizeof(ngx_buf_t));    b->shadow = buf;    b->tag = p->tag;    b->last_shadow = 1;    b->recycled = 1;    buf->shadow = b;    cl = ngx_alloc_chain_link(p->pool);    if (cl == NULL) {        return NGX_ERROR;    }    cl->buf = b;    cl->next = NULL;    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);    if (p->in) {        *p->last_in = cl;    } else {        p->in = cl;    }    p->last_in = &cl->next;    return NGX_OK;}static ngx_inline voidngx_event_pipe_remove_shadow_links(ngx_buf_t *buf){    ngx_buf_t  *b, *next;    b = buf->shadow;    if (b == NULL) {        return;    }    while (!b->last_shadow) {        next = b->shadow;        b->temporary = 0;        b->recycled = 0;        b->shadow = NULL;        b = next;    }    b->temporary = 0;    b->recycled = 0;    b->last_shadow = 0;    b->shadow = NULL;    buf->shadow = NULL;}static ngx_inline voidngx_event_pipe_free_shadow_raw_buf(ngx_chain_t **free, ngx_buf_t *buf){    ngx_buf_t    *s;    ngx_chain_t  *cl, **ll;    if (buf->shadow == NULL) {        return;    }    for (s = buf->shadow; !s->last_shadow; s = s->shadow) { /* void */ }    ll = free;    for (cl = *free ; cl; cl = cl->next) {        if (cl->buf == s) {            *ll = cl->next;            break;        }        if (cl->buf->shadow) {            break;        }        ll = &cl->next;    }}ngx_int_tngx_event_pipe_add_free_buf(ngx_event_pipe_t *p, ngx_buf_t *b){    ngx_chain_t  *cl;    cl = ngx_alloc_chain_link(p->pool);    if (cl == NULL) {        return NGX_ERROR;    }    b->pos = b->start;    b->last = b->start;    b->shadow = NULL;    cl->buf = b;    if (p->free_raw_bufs == NULL) {        p->free_raw_bufs = cl;        cl->next = NULL;        return NGX_OK;    }    if (p->free_raw_bufs->buf->pos == p->free_raw_bufs->buf->last) {        /* add the free buf to the list start */        cl->next = p->free_raw_bufs;        p->free_raw_bufs = cl;        return NGX_OK;    }    /* the first free buf is partialy filled, thus add the free buf after it */    cl->next = p->free_raw_bufs->next;    p->free_raw_bufs->next = cl;    return NGX_OK;}static ngx_int_tngx_event_pipe_drain_chains(ngx_event_pipe_t *p){    ngx_chain_t  *cl, *tl;    for ( ;; ) {        if (p->busy) {            cl = p->busy;            p->busy = NULL;        } else if (p->out) {            cl = p->out;            p->out = NULL;        } else if (p->in) {            cl = p->in;            p->in = NULL;        } else {            return NGX_OK;        }        while (cl) {            if (cl->buf->last_shadow) {                if (ngx_event_pipe_add_free_buf(p, cl->buf->shadow) != NGX_OK) {                    return NGX_ABORT;                }                cl->buf->last_shadow = 0;            }            cl->buf->shadow = NULL;            tl = cl->next;            cl->next = p->free;            p->free = cl;            cl = tl;        }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?