293 lines
6.9 KiB
C
293 lines
6.9 KiB
C
/*
|
|
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
|
|
*/
|
|
|
|
|
|
#include <ngx_config.h>
|
|
#include <ngx_core.h>
|
|
#include <ngx_http.h>
|
|
#include "ngx_map.h"
|
|
|
|
|
|
static ngx_pool_t *ngx_rbuf_pool;
|
|
|
|
static ngx_map_t ngx_rbuf_map;
|
|
static ngx_chain_t *ngx_rbuf_free_chain;
|
|
|
|
static ngx_uint_t ngx_rbuf_nalloc_node;
|
|
|
|
static ngx_uint_t ngx_rbuf_nalloc_buf;
|
|
static ngx_uint_t ngx_rbuf_nfree_buf;
|
|
|
|
static ngx_uint_t ngx_rbuf_nalloc_chain;
|
|
static ngx_uint_t ngx_rbuf_nfree_chain;
|
|
|
|
static ngx_map_t ngx_rbuf_using;
|
|
|
|
#define ngx_rbuf_buf(b) \
|
|
(ngx_rbuf_t *) ((u_char *) (b) - offsetof(ngx_rbuf_t, buf))
|
|
|
|
typedef struct ngx_rbuf_s ngx_rbuf_t;
|
|
|
|
struct ngx_rbuf_s {
|
|
size_t size;
|
|
ngx_rbuf_t *next;
|
|
u_char buf[];
|
|
};
|
|
|
|
typedef struct {
|
|
ngx_map_node_t node;
|
|
ngx_rbuf_t *rbuf;
|
|
} ngx_rbuf_node_t;
|
|
|
|
typedef struct {
|
|
ngx_chain_t cl;
|
|
ngx_buf_t buf;
|
|
unsigned alloc;
|
|
|
|
ngx_map_node_t node;
|
|
char *file;
|
|
int line;
|
|
} ngx_chainbuf_t;
|
|
|
|
|
|
static ngx_int_t
|
|
ngx_rbuf_init()
|
|
{
|
|
ngx_rbuf_pool = ngx_create_pool(4096, ngx_cycle->log);
|
|
if (ngx_rbuf_pool == NULL) {
|
|
return NGX_ERROR;
|
|
}
|
|
|
|
ngx_map_init(&ngx_rbuf_map, ngx_map_hash_uint, ngx_cmp_uint);
|
|
ngx_map_init(&ngx_rbuf_using, ngx_map_hash_uint, ngx_cmp_uint);
|
|
|
|
ngx_rbuf_nalloc_node = 0;
|
|
ngx_rbuf_nalloc_buf = 0;
|
|
ngx_rbuf_nfree_buf = 0;
|
|
ngx_rbuf_nalloc_chain = 0;
|
|
ngx_rbuf_nfree_chain = 0;
|
|
|
|
return NGX_OK;
|
|
}
|
|
|
|
|
|
static ngx_rbuf_t *
|
|
ngx_rbuf_get_buf(size_t key)
|
|
{
|
|
ngx_rbuf_node_t *rn;
|
|
ngx_map_node_t *node;
|
|
ngx_rbuf_t *rb;
|
|
|
|
node = ngx_map_find(&ngx_rbuf_map, key);
|
|
if (node == NULL) { /* new key */
|
|
rn = ngx_pcalloc(ngx_rbuf_pool, sizeof(ngx_rbuf_node_t));
|
|
if (rn == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
node = &rn->node;
|
|
node->raw_key = key;
|
|
ngx_map_insert(&ngx_rbuf_map, node, 0);
|
|
|
|
++ngx_rbuf_nalloc_node;
|
|
} else {
|
|
rn = (ngx_rbuf_node_t *) node;
|
|
}
|
|
|
|
rb = rn->rbuf;
|
|
if (rb == NULL) {
|
|
rb = ngx_pcalloc(ngx_rbuf_pool, sizeof(ngx_rbuf_t) + key);
|
|
if (rb == NULL) {
|
|
return NULL;
|
|
}
|
|
rb->size = key;
|
|
|
|
++ngx_rbuf_nalloc_buf;
|
|
} else {
|
|
rn->rbuf = rb->next;
|
|
rb->next = NULL;
|
|
|
|
--ngx_rbuf_nfree_buf;
|
|
}
|
|
|
|
return rb;
|
|
}
|
|
|
|
static void
|
|
ngx_rbuf_put_buf(ngx_rbuf_t *rb)
|
|
{
|
|
ngx_rbuf_node_t *rn;
|
|
ngx_map_node_t *node;
|
|
|
|
node = ngx_map_find(&ngx_rbuf_map, rb->size);
|
|
if (node == NULL) {
|
|
return;
|
|
}
|
|
|
|
rn = (ngx_rbuf_node_t *) node;
|
|
rb->next = rn->rbuf;
|
|
rn->rbuf = rb;
|
|
|
|
++ngx_rbuf_nfree_buf;
|
|
}
|
|
|
|
|
|
static u_char *
|
|
ngx_rbuf_alloc(size_t size)
|
|
{
|
|
ngx_rbuf_t *rb;
|
|
|
|
rb = ngx_rbuf_get_buf(size);
|
|
|
|
return rb->buf;
|
|
}
|
|
|
|
static void
|
|
ngx_rbuf_free(u_char *rb)
|
|
{
|
|
ngx_rbuf_t *rbuf;
|
|
|
|
rbuf = ngx_rbuf_buf(rb);
|
|
ngx_rbuf_put_buf(rbuf);
|
|
}
|
|
|
|
|
|
ngx_chain_t *
|
|
ngx_get_chainbuf_debug(size_t size, ngx_flag_t alloc_rbuf, char *file, int line)
|
|
{
|
|
ngx_chainbuf_t *cb;
|
|
ngx_chain_t *cl;
|
|
|
|
if (ngx_rbuf_pool == NULL) {
|
|
ngx_rbuf_init();
|
|
}
|
|
|
|
cl = ngx_rbuf_free_chain;
|
|
if (cl) {
|
|
ngx_rbuf_free_chain = cl->next;
|
|
cl->next = NULL;
|
|
cb = (ngx_chainbuf_t *) cl;
|
|
|
|
--ngx_rbuf_nfree_chain;
|
|
} else {
|
|
cb = ngx_pcalloc(ngx_rbuf_pool, sizeof(ngx_chainbuf_t));
|
|
if (cb == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
cl = &cb->cl;
|
|
cl->buf = &cb->buf;
|
|
|
|
++ngx_rbuf_nalloc_chain;
|
|
}
|
|
|
|
if (alloc_rbuf) {
|
|
cl->buf->last = cl->buf->pos = cl->buf->start = ngx_rbuf_alloc(size);
|
|
cl->buf->end = cl->buf->start + size;
|
|
cb->alloc = 1;
|
|
} else {
|
|
cl->buf->pos = cl->buf->last = cl->buf->start = cl->buf->end = NULL;
|
|
cb->alloc = 0;
|
|
}
|
|
cl->buf->memory = 1;
|
|
|
|
// record chainbuf in using map
|
|
cb->file = file;
|
|
cb->line = line;
|
|
cb->node.raw_key = (intptr_t) cl;
|
|
ngx_map_insert(&ngx_rbuf_using, &cb->node, 0);
|
|
|
|
return cl;
|
|
}
|
|
|
|
void
|
|
ngx_put_chainbuf_debug(ngx_chain_t *cl, char *file, int line)
|
|
{
|
|
ngx_chainbuf_t *cb;
|
|
|
|
if (ngx_rbuf_pool == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (cl == NULL) {
|
|
return;
|
|
}
|
|
|
|
cb = (ngx_chainbuf_t *) cl;
|
|
|
|
if (cb->alloc) {
|
|
ngx_rbuf_free(cl->buf->start);
|
|
}
|
|
cl->next = ngx_rbuf_free_chain;
|
|
ngx_rbuf_free_chain = cl;
|
|
++ngx_rbuf_nfree_chain;
|
|
|
|
// delete chainbuf from using map
|
|
if (ngx_map_find(&ngx_rbuf_using, (intptr_t) cl) == NULL) {
|
|
ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0,
|
|
"destroy chainbuf twice: %s:%d", file, line);
|
|
return;
|
|
}
|
|
ngx_map_delete(&ngx_rbuf_using, (intptr_t) cl);
|
|
}
|
|
|
|
ngx_chain_t *
|
|
ngx_rbuf_state(ngx_http_request_t *r, unsigned detail)
|
|
{
|
|
ngx_chain_t *cl;
|
|
ngx_buf_t *b;
|
|
size_t len, len1;
|
|
ngx_uint_t n;
|
|
ngx_chainbuf_t *cb;
|
|
ngx_map_node_t *node;
|
|
|
|
len = sizeof("##########ngx rbuf state##########\n") - 1
|
|
+ sizeof("ngx_rbuf nalloc node: \n") - 1 + NGX_OFF_T_LEN
|
|
+ sizeof("ngx_rbuf nalloc buf: \n") - 1 + NGX_OFF_T_LEN
|
|
+ sizeof("ngx_rbuf nfree buf: \n") - 1 + NGX_OFF_T_LEN
|
|
+ sizeof("ngx_rbuf nalloc chain: \n") - 1 + NGX_OFF_T_LEN
|
|
+ sizeof("ngx_rbuf nfree chain: \n") - 1 + NGX_OFF_T_LEN;
|
|
|
|
len1 = 0;
|
|
|
|
if (detail) {
|
|
n = ngx_rbuf_nalloc_chain - ngx_rbuf_nfree_chain;
|
|
/* " file:line\n" */
|
|
len1 = 4 + 256 + 1 + NGX_OFF_T_LEN + 1;
|
|
len += len1 * n;
|
|
}
|
|
|
|
cl = ngx_alloc_chain_link(r->pool);
|
|
if (cl == NULL) {
|
|
return NULL;
|
|
}
|
|
cl->next = NULL;
|
|
|
|
b = ngx_create_temp_buf(r->pool, len);
|
|
if (b == NULL) {
|
|
return NULL;
|
|
}
|
|
cl->buf = b;
|
|
|
|
b->last = ngx_snprintf(b->last, len,
|
|
"##########ngx rbuf state##########\nngx_rbuf nalloc node: %ui\n"
|
|
"ngx_rbuf nalloc buf: %ui\nngx_rbuf nfree buf: %ui\n"
|
|
"ngx_rbuf nalloc chain: %ui\nngx_rbuf nfree chain: %ui\n",
|
|
ngx_rbuf_nalloc_node, ngx_rbuf_nalloc_buf, ngx_rbuf_nfree_buf,
|
|
ngx_rbuf_nalloc_chain, ngx_rbuf_nfree_chain);
|
|
|
|
if (detail) {
|
|
for (node = ngx_map_begin(&ngx_rbuf_using); node;
|
|
node = ngx_map_next(node))
|
|
{
|
|
cb = (ngx_chainbuf_t *) ((char *) node
|
|
- offsetof(ngx_chainbuf_t, node));
|
|
b->last = ngx_snprintf(b->last, len1, " %s:%d\n",
|
|
cb->file, cb->line);
|
|
}
|
|
}
|
|
|
|
return cl;
|
|
}
|