[mod_magnet] cache script objects at config time
always check at least mtime and size to trigger script reload
This commit is contained in:
parent
f490078d0f
commit
4e5b822b16
106
src/mod_magnet.c
106
src/mod_magnet.c
|
@ -4,6 +4,7 @@
|
|||
#include "log.h"
|
||||
#include "buffer.h"
|
||||
#include "http_chunk.h"
|
||||
#include "http_etag.h"
|
||||
#include "http_header.h"
|
||||
#include "response.h" /* http_response_send_1xx() */
|
||||
|
||||
|
@ -30,9 +31,9 @@
|
|||
static jmp_buf exceptionjmp;
|
||||
|
||||
typedef struct {
|
||||
const array *url_raw;
|
||||
const array *physical_path;
|
||||
const array *response_start;
|
||||
script * const *url_raw;
|
||||
script * const *physical_path;
|
||||
script * const *response_start;
|
||||
int stage;
|
||||
} plugin_config;
|
||||
|
||||
|
@ -49,20 +50,39 @@ INIT_FUNC(mod_magnet_init) {
|
|||
}
|
||||
|
||||
FREE_FUNC(mod_magnet_free) {
|
||||
plugin_data *p = p_d;
|
||||
plugin_data * const p = p_d;
|
||||
script_cache_free_data(&p->cache);
|
||||
if (NULL == p->cvlist) return;
|
||||
/* (init i to 0 if global context; to 1 to skip empty global context) */
|
||||
for (int i = !p->cvlist[0].v.u2[1], used = p->nconfig; i < used; ++i) {
|
||||
config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0];
|
||||
for (; -1 != cpv->k_id; ++cpv) {
|
||||
if (cpv->vtype != T_CONFIG_LOCAL || NULL == cpv->v.v) continue;
|
||||
switch (cpv->k_id) {
|
||||
case 0: /* magnet.attract-raw-url-to */
|
||||
case 1: /* magnet.attract-physical-path-to */
|
||||
case 2: /* magnet.attract-response-start-to */
|
||||
free(cpv->v.v);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mod_magnet_merge_config_cpv(plugin_config * const pconf, const config_plugin_value_t * const cpv) {
|
||||
if (cpv->vtype != T_CONFIG_LOCAL)
|
||||
return;
|
||||
switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */
|
||||
case 0: /* magnet.attract-raw-url-to */
|
||||
pconf->url_raw = cpv->v.a;
|
||||
pconf->url_raw = cpv->v.v;
|
||||
break;
|
||||
case 1: /* magnet.attract-physical-path-to */
|
||||
pconf->physical_path = cpv->v.a;
|
||||
pconf->physical_path = cpv->v.v;
|
||||
break;
|
||||
case 2: /* magnet.attract-response-start-to */
|
||||
pconf->response_start = cpv->v.a;
|
||||
pconf->response_start = cpv->v.v;
|
||||
break;
|
||||
default:/* should not happen */
|
||||
return;
|
||||
|
@ -107,20 +127,34 @@ SETDEFAULTS_FUNC(mod_magnet_set_defaults) {
|
|||
/* process and validate config directives
|
||||
* (init i to 0 if global context; to 1 to skip empty global context) */
|
||||
for (int i = !p->cvlist[0].v.u2[1]; i < p->nconfig; ++i) {
|
||||
const config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0];
|
||||
config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0];
|
||||
for (; -1 != cpv->k_id; ++cpv) {
|
||||
switch (cpv->k_id) {
|
||||
case 0: /* magnet.attract-raw-url-to */
|
||||
case 1: /* magnet.attract-physical-path-to */
|
||||
case 2: /* magnet.attract-response-start-to */
|
||||
for (uint32_t j = 0; j < cpv->v.a->used; ++j) {
|
||||
data_string *ds = (data_string *)cpv->v.a->data[j];
|
||||
if (buffer_is_blank(&ds->value)) {
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
"unexpected (blank) value for %s; "
|
||||
"expected list of \"scriptpath\"", cpk[cpv->k_id].k);
|
||||
return HANDLER_ERROR;
|
||||
if (0 == cpv->v.a->used) {
|
||||
cpv->v.v = NULL;
|
||||
cpv->vtype = T_CONFIG_LOCAL;
|
||||
}
|
||||
else {
|
||||
script ** const a =
|
||||
malloc(sizeof(script *)*(cpv->v.a->used+1));
|
||||
force_assert(a);
|
||||
for (uint32_t j = 0; j < cpv->v.a->used; ++j) {
|
||||
data_string *ds = (data_string *)cpv->v.a->data[j];
|
||||
if (buffer_is_blank(&ds->value)) {
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
"unexpected (blank) value for %s; "
|
||||
"expected list of \"scriptpath\"", cpk[cpv->k_id].k);
|
||||
free(a);
|
||||
return HANDLER_ERROR;
|
||||
}
|
||||
a[j] = script_cache_get_script(&p->cache, &ds->value);
|
||||
}
|
||||
a[cpv->v.a->used] = NULL;
|
||||
cpv->v.v = a;
|
||||
cpv->vtype = T_CONFIG_LOCAL;
|
||||
}
|
||||
break;
|
||||
default:/* should not happen */
|
||||
|
@ -861,18 +895,17 @@ static int push_traceback(lua_State *L, int narg) {
|
|||
return base;
|
||||
}
|
||||
|
||||
static handler_t magnet_attract(request_st * const r, plugin_data * const p, buffer * const name) {
|
||||
lua_State *L;
|
||||
static handler_t magnet_attract(request_st * const r, plugin_data * const p, script * const sc) {
|
||||
/*(always check at least mtime and size to trigger script reload)*/
|
||||
int etag_flags = r->conf.etag_flags | ETAG_USE_MTIME | ETAG_USE_SIZE;
|
||||
lua_State * const L = script_cache_check_script(sc, etag_flags);
|
||||
int lua_return_value;
|
||||
const int func_ndx = 1;
|
||||
const int lighty_table_ndx = 2;
|
||||
|
||||
/* get the script-context */
|
||||
L = script_cache_get_script(&p->cache, name, r->conf.etag_flags);
|
||||
|
||||
if (NULL == L) {
|
||||
log_perror(r->conf.errh, __FILE__, __LINE__,
|
||||
"loading script %s failed", name->ptr);
|
||||
"loading script %s failed", sc->name.ptr);
|
||||
|
||||
if (p->conf.stage != -1) { /* skip for response-start */
|
||||
r->http_status = 500;
|
||||
|
@ -884,7 +917,7 @@ static handler_t magnet_attract(request_st * const r, plugin_data * const p, buf
|
|||
|
||||
if (lua_isstring(L, -1)) {
|
||||
log_error(r->conf.errh, __FILE__, __LINE__,
|
||||
"loading script %s failed: %s", name->ptr, lua_tostring(L, -1));
|
||||
"loading script %s failed: %s", sc->name.ptr, lua_tostring(L, -1));
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
|
@ -1099,27 +1132,22 @@ static handler_t magnet_attract_array(request_st * const r, plugin_data * const
|
|||
mod_magnet_patch_config(r, p);
|
||||
p->conf.stage = stage;
|
||||
|
||||
const array *files;
|
||||
script * const *scripts;
|
||||
switch (stage) {
|
||||
case 1: files = p->conf.url_raw; break;
|
||||
case 0: files = p->conf.physical_path; break;
|
||||
case -1: files = p->conf.response_start; break;
|
||||
default: files = NULL; break;
|
||||
case 1: scripts = p->conf.url_raw; break;
|
||||
case 0: scripts = p->conf.physical_path; break;
|
||||
case -1: scripts = p->conf.response_start; break;
|
||||
default: scripts = NULL; break;
|
||||
}
|
||||
|
||||
/* no filename set */
|
||||
if (NULL == files || files->used == 0) return HANDLER_GO_ON;
|
||||
if (NULL == scripts) return HANDLER_GO_ON; /* no scripts set */
|
||||
|
||||
r->con->srv->request_env(r);
|
||||
|
||||
/**
|
||||
* execute all files and jump out on the first !HANDLER_GO_ON
|
||||
*/
|
||||
handler_t ret = HANDLER_GO_ON;
|
||||
for (uint32_t i = 0; i < files->used && ret == HANDLER_GO_ON; ++i) {
|
||||
data_string *ds = (data_string *)files->data[i];
|
||||
ret = magnet_attract(r, p, &ds->value);
|
||||
}
|
||||
/* execute scripts sequentially while HANDLER_GO_ON */
|
||||
handler_t rc = HANDLER_GO_ON;
|
||||
do {
|
||||
rc = magnet_attract(r, p, *scripts);
|
||||
} while (rc == HANDLER_GO_ON && *++scripts);
|
||||
|
||||
if (r->error_handler_saved_status) {
|
||||
/* retrieve (possibly modified) REDIRECT_STATUS and store as number */
|
||||
|
@ -1130,7 +1158,7 @@ static handler_t magnet_attract_array(request_st * const r, plugin_data * const
|
|||
r->error_handler_saved_status > 0 ? (int)x : -(int)x;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return rc;
|
||||
}
|
||||
|
||||
URIHANDLER_FUNC(mod_magnet_uri_handler) {
|
||||
|
|
|
@ -92,7 +92,9 @@ static lua_State *script_cache_load_script(script * const sc, int etag_flags)
|
|||
}
|
||||
|
||||
__attribute_cold__
|
||||
static lua_State *script_cache_new_script(script_cache * const cache, const buffer * const name, int etag_flags)
|
||||
__attribute_nonnull__
|
||||
__attribute_returns_nonnull__
|
||||
static script *script_cache_new_script(script_cache * const cache, const buffer * const name)
|
||||
{
|
||||
script * const sc = script_init();
|
||||
|
||||
|
@ -105,10 +107,20 @@ static lua_State *script_cache_new_script(script_cache * const cache, const buff
|
|||
buffer_copy_buffer(&sc->name, name);
|
||||
sc->L = luaL_newstate();
|
||||
luaL_openlibs(sc->L);
|
||||
return script_cache_load_script(sc, etag_flags);
|
||||
return sc;
|
||||
}
|
||||
|
||||
static lua_State *script_cache_check_script(script * const sc, int etag_flags)
|
||||
script *script_cache_get_script(script_cache *cache, const buffer *name)
|
||||
{
|
||||
for (uint32_t i = 0; i < cache->used; ++i) {
|
||||
script * const sc = cache->ptr[i];
|
||||
if (buffer_is_equal(&sc->name, name))
|
||||
return sc;
|
||||
}
|
||||
return script_cache_new_script(cache, name);
|
||||
}
|
||||
|
||||
lua_State *script_cache_check_script(script * const sc, int etag_flags)
|
||||
{
|
||||
if (lua_gettop(sc->L) == 0)
|
||||
return script_cache_load_script(sc, etag_flags);
|
||||
|
@ -133,13 +145,3 @@ static lua_State *script_cache_check_script(script * const sc, int etag_flags)
|
|||
|
||||
return sc->L;
|
||||
}
|
||||
|
||||
lua_State *script_cache_get_script(script_cache *cache, const buffer *name, int etag_flags)
|
||||
{
|
||||
for (uint32_t i = 0; i < cache->used; ++i) {
|
||||
script * const sc = cache->ptr[i];
|
||||
if (buffer_is_equal(&sc->name, name))
|
||||
return script_cache_check_script(sc, etag_flags);
|
||||
}
|
||||
return script_cache_new_script(cache, name, etag_flags);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,12 @@ script_cache *script_cache_init(void);
|
|||
__attribute_cold__
|
||||
void script_cache_free_data(script_cache *cache);
|
||||
|
||||
lua_State *script_cache_get_script(script_cache *cache, const buffer *name, int etag_flags);
|
||||
__attribute_cold__
|
||||
__attribute_nonnull__
|
||||
__attribute_returns_nonnull__
|
||||
script *script_cache_get_script(script_cache *cache, const buffer *name);
|
||||
|
||||
__attribute_nonnull__
|
||||
lua_State *script_cache_check_script(script * const sc, int etag_flags);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue