diff options
author | kaiwu <kaiwu2004@gmail.com> | 2025-03-01 12:42:23 +0800 |
---|---|---|
committer | kaiwu <kaiwu2004@gmail.com> | 2025-03-01 12:42:23 +0800 |
commit | 3f33461e4948bf05e60bdff35ec6c57a649c7860 (patch) | |
tree | 284c2ba95a41536ae1bff6bea710db0709a64739 /ngx_stream_lua-0.0.16/src/ngx_stream_lua_cache.c | |
download | openresty-3f33461e4948bf05e60bdff35ec6c57a649c7860.tar.gz openresty-3f33461e4948bf05e60bdff35ec6c57a649c7860.zip |
openresty bundle
Diffstat (limited to 'ngx_stream_lua-0.0.16/src/ngx_stream_lua_cache.c')
-rw-r--r-- | ngx_stream_lua-0.0.16/src/ngx_stream_lua_cache.c | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/ngx_stream_lua-0.0.16/src/ngx_stream_lua_cache.c b/ngx_stream_lua-0.0.16/src/ngx_stream_lua_cache.c new file mode 100644 index 0000000..4c57137 --- /dev/null +++ b/ngx_stream_lua-0.0.16/src/ngx_stream_lua_cache.c @@ -0,0 +1,319 @@ + +/* + * !!! DO NOT EDIT DIRECTLY !!! + * This file was automatically generated from the following template: + * + * src/subsys/ngx_subsys_lua_cache.c.tt2 + */ + + +/* + * Copyright (C) Xiaozhe Wang (chaoslawful) + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef DDEBUG +#define DDEBUG 0 +#endif +#include "ddebug.h" + + +#include <nginx.h> +#include <ngx_md5.h> +#include "ngx_stream_lua_common.h" +#include "ngx_stream_lua_cache.h" +#include "ngx_stream_lua_clfactory.h" +#include "ngx_stream_lua_util.h" + + +/** + * Find code chunk associated with the given key in code cache, + * and push it to the top of Lua stack if found. + * + * Stack layout before call: + * | ... | <- top + * + * Stack layout after call: + * | code chunk | <- top + * | ... | + * + * */ +static ngx_int_t +ngx_stream_lua_cache_load_code(ngx_log_t *log, lua_State *L, + const char *key) +{ +#ifndef OPENRESTY_LUAJIT + int rc; + u_char *err; +#endif + + /* get code cache table */ + lua_pushlightuserdata(L, ngx_stream_lua_lightudata_mask( + code_cache_key)); + lua_rawget(L, LUA_REGISTRYINDEX); /* sp++ */ + + dd("Code cache table to load: %p", lua_topointer(L, -1)); + + if (!lua_istable(L, -1)) { + dd("Error: code cache table to load did not exist!!"); + return NGX_ERROR; + } + + lua_getfield(L, -1, key); /* sp++ */ + + if (lua_isfunction(L, -1)) { +#ifdef OPENRESTY_LUAJIT + lua_remove(L, -2); /* sp-- */ + return NGX_OK; +#else + /* call closure factory to gen new closure */ + rc = lua_pcall(L, 0, 1, 0); + if (rc == 0) { + /* remove cache table from stack, leave code chunk at + * top of stack */ + lua_remove(L, -2); /* sp-- */ + return NGX_OK; + } + + if (lua_isstring(L, -1)) { + err = (u_char *) lua_tostring(L, -1); + + } else { + err = (u_char *) "unknown error"; + } + + ngx_log_error(NGX_LOG_ERR, log, 0, + "lua: failed to run factory at key \"%s\": %s", + key, err); + lua_pop(L, 2); + return NGX_ERROR; +#endif /* OPENRESTY_LUAJIT */ + } + + dd("Value associated with given key in code cache table is not code " + "chunk: stack top=%d, top value type=%s\n", + lua_gettop(L), luaL_typename(L, -1)); + + /* remove cache table and value from stack */ + lua_pop(L, 2); /* sp-=2 */ + + return NGX_DECLINED; +} + + +/** + * Store the closure factory at the top of Lua stack to code cache, and + * associate it with the given key. Then generate new closure. + * + * Stack layout before call: + * | code factory | <- top + * | ... | + * + * Stack layout after call: + * | code chunk | <- top + * | ... | + * + * */ +static ngx_int_t +ngx_stream_lua_cache_store_code(lua_State *L, const char *key) +{ +#ifndef OPENRESTY_LUAJIT + int rc; +#endif + + /* get code cache table */ + lua_pushlightuserdata(L, ngx_stream_lua_lightudata_mask( + code_cache_key)); + lua_rawget(L, LUA_REGISTRYINDEX); + + dd("Code cache table to store: %p", lua_topointer(L, -1)); + + if (!lua_istable(L, -1)) { + dd("Error: code cache table to load did not exist!!"); + return NGX_ERROR; + } + + lua_pushvalue(L, -2); /* closure cache closure */ + lua_setfield(L, -2, key); /* closure cache */ + + /* remove cache table, leave closure factory at top of stack */ + lua_pop(L, 1); /* closure */ + +#ifndef OPENRESTY_LUAJIT + /* call closure factory to generate new closure */ + rc = lua_pcall(L, 0, 1, 0); + if (rc != 0) { + dd("Error: failed to call closure factory!!"); + return NGX_ERROR; + } +#endif + + return NGX_OK; +} + + +ngx_int_t +ngx_stream_lua_cache_loadbuffer(ngx_log_t *log, lua_State *L, + const u_char *src, size_t src_len, const u_char *cache_key, + const char *name) +{ + int n; + ngx_int_t rc; + const char *err = NULL; + + n = lua_gettop(L); + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, log, 0, + "looking up Lua code cache with key '%s'", cache_key); + + rc = ngx_stream_lua_cache_load_code(log, L, (char *) cache_key); + if (rc == NGX_OK) { + /* code chunk loaded from cache, sp++ */ + dd("Code cache hit! cache key='%s', stack top=%d, script='%.*s'", + cache_key, lua_gettop(L), (int) src_len, src); + return NGX_OK; + } + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + /* rc == NGX_DECLINED */ + + dd("Code cache missed! cache key='%s', stack top=%d, script='%.*s'", + cache_key, lua_gettop(L), (int) src_len, src); + + /* load closure factory of inline script to the top of lua stack, sp++ */ + rc = ngx_stream_lua_clfactory_loadbuffer(L, (char *) src, src_len, name); + + if (rc != 0) { + /* Oops! error occurred when loading Lua script */ + if (rc == LUA_ERRMEM) { + err = "memory allocation error"; + + } else { + if (lua_isstring(L, -1)) { + err = lua_tostring(L, -1); + + } else { + err = "unknown error"; + } + } + + goto error; + } + + /* store closure factory and gen new closure at the top of lua stack to + * code cache */ + rc = ngx_stream_lua_cache_store_code(L, (char *) cache_key); + if (rc != NGX_OK) { + err = "fail to generate new closure from the closure factory"; + goto error; + } + + return NGX_OK; + +error: + + ngx_log_error(NGX_LOG_ERR, log, 0, + "failed to load inlined Lua code: %s", err); + lua_settop(L, n); + return NGX_ERROR; +} + + +ngx_int_t +ngx_stream_lua_cache_loadfile(ngx_log_t *log, lua_State *L, + const u_char *script, const u_char *cache_key) +{ + int n; + ngx_int_t rc, errcode = NGX_ERROR; + u_char *p; + u_char buf[NGX_STREAM_LUA_FILE_KEY_LEN + 1]; + const char *err = NULL; + + n = lua_gettop(L); + + /* calculate digest of script file path */ + if (cache_key == NULL) { + dd("CACHE file key not pre-calculated...calculating"); + p = ngx_copy(buf, NGX_STREAM_LUA_FILE_TAG, NGX_STREAM_LUA_FILE_TAG_LEN); + + p = ngx_stream_lua_digest_hex(p, script, ngx_strlen(script)); + + *p = '\0'; + cache_key = buf; + + } else { + dd("CACHE file key already pre-calculated"); + } + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, log, 0, + "looking up Lua code cache with key '%s'", cache_key); + + rc = ngx_stream_lua_cache_load_code(log, L, (char *) cache_key); + if (rc == NGX_OK) { + /* code chunk loaded from cache, sp++ */ + dd("Code cache hit! cache key='%s', stack top=%d, file path='%s'", + cache_key, lua_gettop(L), script); + return NGX_OK; + } + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + /* rc == NGX_DECLINED */ + + dd("Code cache missed! cache key='%s', stack top=%d, file path='%s'", + cache_key, lua_gettop(L), script); + + /* load closure factory of script file to the top of lua stack, sp++ */ + rc = ngx_stream_lua_clfactory_loadfile(L, (char *) script); + + dd("loadfile returns %d (%d)", (int) rc, LUA_ERRFILE); + + if (rc != 0) { + /* Oops! error occurred when loading Lua script */ + switch (rc) { + case LUA_ERRMEM: + err = "memory allocation error"; + break; + + case LUA_ERRFILE: + errcode = NGX_STREAM_INTERNAL_SERVER_ERROR; + /* fall through */ + + default: + if (lua_isstring(L, -1)) { + err = lua_tostring(L, -1); + + } else { + err = "unknown error"; + } + } + + goto error; + } + + /* store closure factory and gen new closure at the top of lua stack + * to code cache */ + rc = ngx_stream_lua_cache_store_code(L, (char *) cache_key); + if (rc != NGX_OK) { + err = "fail to generate new closure from the closure factory"; + goto error; + } + + return NGX_OK; + +error: + + ngx_log_error(NGX_LOG_ERR, log, 0, + "failed to load external Lua file \"%s\": %s", script, err); + + lua_settop(L, n); + return errcode; +} + +/* vi:set ft=c ts=4 sw=4 et fdm=marker: */ |