272 lines
6.3 KiB
C
272 lines
6.3 KiB
C
/*
|
|
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
|
|
*/
|
|
|
|
|
|
#include "ngx_event_timer_module.h"
|
|
|
|
|
|
static ngx_int_t ngx_event_timer_process_init(ngx_cycle_t *cycle);
|
|
|
|
static void *ngx_event_timer_create_conf(ngx_cycle_t *cycle);
|
|
static char *ngx_event_timer_init_conf(ngx_cycle_t *cycle, void *conf);
|
|
|
|
|
|
typedef struct {
|
|
ngx_uint_t timerid;
|
|
|
|
ngx_event_t event;
|
|
|
|
ngx_timer_handler_pt handler;
|
|
void *data;
|
|
} ngx_event_timer_ctx_t;
|
|
|
|
typedef struct {
|
|
ngx_uint_t timer_n;
|
|
|
|
ngx_event_timer_ctx_t *timer_ctx; /* array to store timers */
|
|
|
|
ngx_event_timer_ctx_t *free_timers; /* timer unused */
|
|
ngx_uint_t free_timer_n;
|
|
} ngx_event_timer_conf_t;
|
|
|
|
|
|
static ngx_str_t event_timer_name = ngx_string("event_timer");
|
|
|
|
|
|
static ngx_command_t ngx_event_timer_commands[] = {
|
|
|
|
{ ngx_string("worker_timers"),
|
|
NGX_EVENT_CONF|NGX_CONF_TAKE1,
|
|
ngx_conf_set_num_slot,
|
|
0,
|
|
offsetof(ngx_event_timer_conf_t, timer_n),
|
|
NULL },
|
|
|
|
ngx_null_command
|
|
};
|
|
|
|
|
|
ngx_event_module_t ngx_event_timer_module_ctx = {
|
|
&event_timer_name,
|
|
ngx_event_timer_create_conf, /* create configuration */
|
|
ngx_event_timer_init_conf, /* init configuration */
|
|
|
|
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
|
|
};
|
|
|
|
|
|
/* this module use ngx_cycle->log */
|
|
ngx_module_t ngx_event_timer_module = {
|
|
NGX_MODULE_V1,
|
|
&ngx_event_timer_module_ctx, /* module context */
|
|
ngx_event_timer_commands, /* module directives */
|
|
NGX_EVENT_MODULE, /* module type */
|
|
NULL, /* init master */
|
|
NULL, /* init module */
|
|
ngx_event_timer_process_init, /* init process */
|
|
NULL, /* init thread */
|
|
NULL, /* exit thread */
|
|
NULL, /* exit process */
|
|
NULL, /* exit master */
|
|
NGX_MODULE_V1_PADDING
|
|
};
|
|
|
|
|
|
static void *
|
|
ngx_event_timer_create_conf(ngx_cycle_t *cycle)
|
|
{
|
|
ngx_event_timer_conf_t *conf;
|
|
|
|
conf = ngx_pcalloc(cycle->pool, sizeof(ngx_event_timer_conf_t));
|
|
if (conf == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
conf->timer_n = NGX_CONF_UNSET_UINT;
|
|
|
|
return conf;
|
|
}
|
|
|
|
static char *
|
|
ngx_event_timer_init_conf(ngx_cycle_t *cycle, void *conf)
|
|
{
|
|
ngx_event_timer_conf_t *etcf = conf;
|
|
|
|
ngx_conf_init_uint_value(etcf->timer_n, 1024);
|
|
|
|
return NGX_CONF_OK;
|
|
}
|
|
|
|
static ngx_int_t
|
|
ngx_event_timer_process_init(ngx_cycle_t *cycle)
|
|
{
|
|
ngx_event_timer_conf_t *etcf;
|
|
ngx_event_timer_ctx_t *t, *next;
|
|
ngx_uint_t i;
|
|
|
|
etcf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_timer_module);
|
|
|
|
if (etcf->timer_n == 0) {
|
|
return NGX_OK;
|
|
}
|
|
|
|
etcf->timer_ctx =
|
|
ngx_alloc(sizeof(ngx_event_timer_ctx_t) * etcf->timer_n, cycle->log);
|
|
if (etcf->timer_ctx == NULL) {
|
|
return NGX_ERROR;
|
|
}
|
|
|
|
t = etcf->timer_ctx;
|
|
|
|
i = etcf->timer_n;
|
|
next = NULL;
|
|
|
|
do {
|
|
--i;
|
|
|
|
t[i].timerid = i;
|
|
t[i].event.timer_set = 0;
|
|
t[i].event.log = NULL;
|
|
t[i].handler = NULL;
|
|
t[i].data = next;
|
|
|
|
next = &t[i];
|
|
} while (i);
|
|
|
|
etcf->free_timers = next;
|
|
etcf->free_timer_n = etcf->timer_n;
|
|
|
|
return NGX_OK;
|
|
}
|
|
|
|
static ngx_event_timer_ctx_t *
|
|
ngx_event_timer_get_timer()
|
|
{
|
|
ngx_event_timer_conf_t *etcf;
|
|
ngx_event_timer_ctx_t *free;
|
|
|
|
etcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_timer_module);
|
|
|
|
free = etcf->free_timers;
|
|
if (etcf->free_timer_n == 0) {
|
|
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
|
|
"nginx event timer module, no free timer");
|
|
return NULL;
|
|
}
|
|
|
|
etcf->free_timers = free->data;
|
|
--etcf->free_timer_n;
|
|
|
|
return free;
|
|
}
|
|
|
|
static void
|
|
ngx_event_timer_free_timer(ngx_event_timer_ctx_t *ctx)
|
|
{
|
|
ngx_event_timer_conf_t *etcf;
|
|
|
|
etcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_timer_module);
|
|
|
|
ctx->data = etcf->free_timers;
|
|
etcf->free_timers = ctx;
|
|
++etcf->free_timer_n;
|
|
}
|
|
|
|
static void
|
|
ngx_event_timer_event_handler(ngx_event_t *e)
|
|
{
|
|
ngx_event_timer_ctx_t *ctx;
|
|
|
|
ctx = e->data;
|
|
|
|
if (ctx->handler) {
|
|
ctx->handler(ctx->data);
|
|
}
|
|
|
|
ngx_event_timer_free_timer(ctx);
|
|
}
|
|
|
|
ngx_int_t
|
|
ngx_event_timer_add_timer(ngx_msec_t tv, ngx_timer_handler_pt h, void *data)
|
|
{
|
|
ngx_event_timer_ctx_t *ctx;
|
|
|
|
if (h == NULL) {
|
|
return NGX_ERROR;
|
|
}
|
|
|
|
ctx = ngx_event_timer_get_timer();
|
|
if (ctx == NULL) {
|
|
return NGX_ERROR;
|
|
}
|
|
|
|
ctx->event.handler = ngx_event_timer_event_handler;
|
|
ctx->event.data = ctx;
|
|
|
|
ctx->handler = h;
|
|
ctx->data = data;
|
|
|
|
if (ctx->event.log == NULL) {
|
|
ctx->event.log = ngx_cycle->log;
|
|
}
|
|
|
|
ngx_event_add_timer(&ctx->event, tv);
|
|
|
|
return ctx->timerid;
|
|
}
|
|
|
|
void
|
|
ngx_event_timer_del_timer(ngx_uint_t timerid)
|
|
{
|
|
ngx_event_timer_ctx_t *ctx;
|
|
ngx_event_timer_conf_t *etcf;
|
|
|
|
etcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_timer_module);
|
|
|
|
ctx = &etcf->timer_ctx[timerid];
|
|
|
|
if (!ctx->event.timer_set) {
|
|
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
|
|
"timer has already deleted");
|
|
return;
|
|
}
|
|
|
|
ngx_event_del_timer(&ctx->event);
|
|
ngx_event_timer_free_timer(ctx);
|
|
}
|
|
|
|
ngx_chain_t *
|
|
ngx_event_timer_state(ngx_http_request_t *r)
|
|
{
|
|
ngx_event_timer_conf_t *etcf;
|
|
ngx_chain_t *cl;
|
|
ngx_buf_t *b;
|
|
size_t len;
|
|
|
|
etcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_timer_module);
|
|
|
|
len = sizeof("##########event timer state##########\n") - 1
|
|
+ sizeof("ngx_event_timer alloc: \n") - 1 + NGX_OFF_T_LEN
|
|
+ sizeof("ngx_event_timer free: \n") - 1 + NGX_OFF_T_LEN;
|
|
|
|
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,
|
|
"##########event timer state##########\n"
|
|
"ngx_event_timer alloc: %ui\nngx_event_timer free: %ui\n",
|
|
etcf->timer_n, etcf->free_timer_n);
|
|
|
|
return cl;
|
|
}
|