small-package/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.c

191 lines
4.3 KiB
C

/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include "ngx_poold.h"
#include "ngx_map.h"
typedef struct ngx_poold_node_s ngx_poold_node_t;
static ngx_pool_t *ngx_poold_pool;
static ngx_map_t ngx_poold_map;
static ngx_poold_node_t *ngx_poold_free_node;
static ngx_uint_t ngx_poold_nalloc;
static ngx_uint_t ngx_poold_nfree;
struct ngx_poold_node_s {
ngx_map_node_t m; /* map node */
ngx_poold_node_t *next; /* free node */
ngx_pool_t *pool;
char *file; /* file create pool */
int line; /* line create pool */
};
static ngx_int_t
ngx_poold_init()
{
ngx_poold_pool = ngx_create_pool(4096, ngx_cycle->log);
if (ngx_poold_pool == NULL) {
return NGX_ERROR;
}
ngx_map_init(&ngx_poold_map, ngx_map_hash_uint, ngx_cmp_uint);
ngx_poold_free_node = NULL;
ngx_poold_nalloc = 0;
ngx_poold_nfree = 0;
return NGX_OK;
}
static ngx_poold_node_t *
ngx_poold_get_node()
{
ngx_poold_node_t *n;
n = ngx_poold_free_node;
if (n == NULL) {
n = ngx_pcalloc(ngx_poold_pool, sizeof(ngx_poold_node_t));
if (n == NULL) {
return NULL;
}
++ngx_poold_nalloc;
} else {
ngx_poold_free_node = n->next;
ngx_memzero(n, sizeof(ngx_poold_node_t));
--ngx_poold_nfree;
}
return n;
}
static void
ngx_poold_put_node(ngx_poold_node_t *node)
{
if (ngx_poold_pool == NULL) {
return;
}
if (node == NULL) {
return;
}
node->next = ngx_poold_free_node;
ngx_poold_free_node = node;
++ngx_poold_nfree;
}
ngx_pool_t *
ngx_create_pool_debug(size_t size, ngx_log_t *log, char *file, int line)
{
ngx_poold_node_t *node;
if (ngx_poold_pool == NULL) {
ngx_poold_init();
}
/* construct a poold node */
node = ngx_poold_get_node();
node->pool = ngx_create_pool(size, log);
node->file = file;
node->line = line;
/* record node in poold map */
node->m.raw_key = (intptr_t) node->pool;
ngx_map_insert(&ngx_poold_map, &node->m, 0);
return node->pool;
}
void
ngx_destroy_pool_debug(ngx_pool_t *pool, char *file, int line)
{
ngx_poold_node_t *node;
ngx_map_node_t *m;
/* get node by pool */
m = ngx_map_find(&ngx_poold_map, (intptr_t) pool);
if (m == NULL) {
ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0,
"destroy pool twice: %s:%d", file, line);
return;
}
ngx_map_delete(&ngx_poold_map, (intptr_t) pool);
node = (ngx_poold_node_t *) ((char *) m - offsetof(ngx_poold_node_t, m));
ngx_destroy_pool(pool);
/* put node in poold map */
ngx_poold_put_node(node);
}
ngx_chain_t *
ngx_poold_state(ngx_http_request_t *r, unsigned detail)
{
ngx_chain_t *cl;
ngx_buf_t *b;
ngx_map_node_t *node;
ngx_poold_node_t *pn;
size_t len, len1;
ngx_uint_t n;
len = sizeof("##########ngx debug pool##########\n") - 1
+ sizeof("ngx_poold nalloc node: \n") - 1 + NGX_OFF_T_LEN
+ sizeof("ngx_poold nfree node: \n") - 1 + NGX_OFF_T_LEN;
len1 = 0;
/* node for create pool */
if (detail) {
n = ngx_poold_nalloc - ngx_poold_nfree;
/* " 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 debug pool##########\n"
"ngx_poold nalloc node: %ui\nngx_poold nfree node: %ui\n",
ngx_poold_nalloc, ngx_poold_nfree);
if (detail) {
for (node = ngx_map_begin(&ngx_poold_map); node;
node = ngx_map_next(node))
{
/* m is first element of ngx_poold_node_t */
pn = (ngx_poold_node_t *) node;
b->last = ngx_snprintf(b->last, len1, " %s:%d\n",
pn->file, pn->line);
}
}
return cl;
}