/*
* Copyright (C) Yichun Zhang (agentzh)
*/
#ifndef DDEBUG
#define DDEBUG 0
#endif
#include "ddebug.h"
#include "ngx_http_lua_util.h"
#include "ngx_http_lua_ctx.h"
typedef struct {
int ref;
lua_State *vm;
} ngx_http_lua_ngx_ctx_cleanup_data_t;
static ngx_int_t ngx_http_lua_ngx_ctx_add_cleanup(ngx_http_request_t *r,
int ref);
static void ngx_http_lua_ngx_ctx_cleanup(void *data);
int
ngx_http_lua_ngx_get_ctx(lua_State *L)
{
ngx_http_request_t *r;
ngx_http_lua_ctx_t *ctx;
r = ngx_http_lua_get_req(L);
if (r == NULL) {
return luaL_error(L, "no request found");
}
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
return luaL_error(L, "no request ctx found");
}
if (ctx->ctx_ref == LUA_NOREF) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua create ngx.ctx table for the current request");
lua_pushliteral(L, ngx_http_lua_ctx_tables_key);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_createtable(L, 0 /* narr */, 4 /* nrec */);
lua_pushvalue(L, -1);
ctx->ctx_ref = luaL_ref(L, -3);
if (ngx_http_lua_ngx_ctx_add_cleanup(r, ctx->ctx_ref) != NGX_OK) {
return luaL_error(L, "no memory");
}
return 1;
}
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua fetching existing ngx.ctx table for the current "
"request");
lua_pushliteral(L, ngx_http_lua_ctx_tables_key);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_rawgeti(L, -1, ctx->ctx_ref);
return 1;
}
int
ngx_http_lua_ngx_set_ctx(lua_State *L)
{
ngx_http_request_t *r;
ngx_http_lua_ctx_t *ctx;
r = ngx_http_lua_get_req(L);
if (r == NULL) {
return luaL_error(L, "no request found");
}
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
return luaL_error(L, "no request ctx found");
}
return ngx_http_lua_ngx_set_ctx_helper(L, r, ctx, 3);
}
int
ngx_http_lua_ngx_set_ctx_helper(lua_State *L, ngx_http_request_t *r,
ngx_http_lua_ctx_t *ctx, int index)
{
if (index < 0) {
index = lua_gettop(L) + index + 1;
}
if (ctx->ctx_ref == LUA_NOREF) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua create ngx.ctx table for the current request");
lua_pushliteral(L, ngx_http_lua_ctx_tables_key);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushvalue(L, index);
ctx->ctx_ref = luaL_ref(L, -2);
lua_pop(L, 1);
if (ngx_http_lua_ngx_ctx_add_cleanup(r, ctx->ctx_ref) != NGX_OK) {
return luaL_error(L, "no memory");
}
return 0;
}
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua fetching existing ngx.ctx table for the current "
"request");
lua_pushliteral(L, ngx_http_lua_ctx_tables_key);
lua_rawget(L, LUA_REGISTRYINDEX);
luaL_unref(L, -1, ctx->ctx_ref);
lua_pushvalue(L, index);
ctx->ctx_ref = luaL_ref(L, -2);
lua_pop(L, 1);
return 0;
}
#ifndef NGX_LUA_NO_FFI_API
int
ngx_http_lua_ffi_get_ctx_ref(ngx_http_request_t *r)
{
ngx_http_lua_ctx_t *ctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
return NGX_HTTP_LUA_FFI_NO_REQ_CTX;
}
return ctx->ctx_ref;
}
int
ngx_http_lua_ffi_set_ctx_ref(ngx_http_request_t *r, int ref)
{
ngx_http_lua_ctx_t *ctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
return NGX_HTTP_LUA_FFI_NO_REQ_CTX;
}
ctx->ctx_ref = ref;
if (ngx_http_lua_ngx_ctx_add_cleanup(r, ref) != NGX_OK) {
return NGX_ERROR;
}
return NGX_OK;
}
#endif /* NGX_LUA_NO_FFI_API */
static ngx_int_t
ngx_http_lua_ngx_ctx_add_cleanup(ngx_http_request_t *r, int ref)
{
lua_State *L;
ngx_pool_cleanup_t *cln;
ngx_http_lua_ctx_t *ctx;
ngx_http_lua_ngx_ctx_cleanup_data_t *data;
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
L = ngx_http_lua_get_lua_vm(r, ctx);
cln = ngx_pool_cleanup_add(r->pool,
sizeof(ngx_http_lua_ngx_ctx_cleanup_data_t));
if (cln == NULL) {
return NGX_ERROR;
}
cln->handler = ngx_http_lua_ngx_ctx_cleanup;
data = cln->data;
data->vm = L;
data->ref = ref;
return NGX_OK;
}
static void
ngx_http_lua_ngx_ctx_cleanup(void *data)
{
lua_State *L;
ngx_http_lua_ngx_ctx_cleanup_data_t *clndata = data;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"lua release ngx.ctx at ref %d", clndata->ref);
L = clndata->vm;
lua_pushliteral(L, ngx_http_lua_ctx_tables_key);
lua_rawget(L, LUA_REGISTRYINDEX);
luaL_unref(L, -1, clndata->ref);
lua_pop(L, 1);
}
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */