1*76404edcSAsim Jamshed #include "mod_magnet_cache.h"
2*76404edcSAsim Jamshed #include "stat_cache.h"
3*76404edcSAsim Jamshed
4*76404edcSAsim Jamshed #include <stdlib.h>
5*76404edcSAsim Jamshed #include <time.h>
6*76404edcSAsim Jamshed #include <assert.h>
7*76404edcSAsim Jamshed
8*76404edcSAsim Jamshed #ifdef HAVE_LUA_H
9*76404edcSAsim Jamshed #include <lualib.h>
10*76404edcSAsim Jamshed #include <lauxlib.h>
11*76404edcSAsim Jamshed
script_init()12*76404edcSAsim Jamshed static script *script_init() {
13*76404edcSAsim Jamshed script *sc;
14*76404edcSAsim Jamshed
15*76404edcSAsim Jamshed sc = calloc(1, sizeof(*sc));
16*76404edcSAsim Jamshed sc->name = buffer_init();
17*76404edcSAsim Jamshed sc->etag = buffer_init();
18*76404edcSAsim Jamshed
19*76404edcSAsim Jamshed return sc;
20*76404edcSAsim Jamshed }
21*76404edcSAsim Jamshed
script_free(script * sc)22*76404edcSAsim Jamshed static void script_free(script *sc) {
23*76404edcSAsim Jamshed if (!sc) return;
24*76404edcSAsim Jamshed
25*76404edcSAsim Jamshed lua_pop(sc->L, 1); /* the function copy */
26*76404edcSAsim Jamshed
27*76404edcSAsim Jamshed buffer_free(sc->name);
28*76404edcSAsim Jamshed buffer_free(sc->etag);
29*76404edcSAsim Jamshed
30*76404edcSAsim Jamshed lua_close(sc->L);
31*76404edcSAsim Jamshed
32*76404edcSAsim Jamshed free(sc);
33*76404edcSAsim Jamshed }
34*76404edcSAsim Jamshed
script_cache_init()35*76404edcSAsim Jamshed script_cache *script_cache_init() {
36*76404edcSAsim Jamshed script_cache *p;
37*76404edcSAsim Jamshed
38*76404edcSAsim Jamshed p = calloc(1, sizeof(*p));
39*76404edcSAsim Jamshed
40*76404edcSAsim Jamshed return p;
41*76404edcSAsim Jamshed }
42*76404edcSAsim Jamshed
script_cache_free(script_cache * p)43*76404edcSAsim Jamshed void script_cache_free(script_cache *p) {
44*76404edcSAsim Jamshed size_t i;
45*76404edcSAsim Jamshed
46*76404edcSAsim Jamshed if (!p) return;
47*76404edcSAsim Jamshed
48*76404edcSAsim Jamshed for (i = 0; i < p->used; i++) {
49*76404edcSAsim Jamshed script_free(p->ptr[i]);
50*76404edcSAsim Jamshed }
51*76404edcSAsim Jamshed
52*76404edcSAsim Jamshed free(p->ptr);
53*76404edcSAsim Jamshed
54*76404edcSAsim Jamshed free(p);
55*76404edcSAsim Jamshed }
56*76404edcSAsim Jamshed
script_cache_get_script(server * srv,connection * con,script_cache * cache,buffer * name)57*76404edcSAsim Jamshed lua_State *script_cache_get_script(server *srv, connection *con, script_cache *cache, buffer *name) {
58*76404edcSAsim Jamshed size_t i;
59*76404edcSAsim Jamshed script *sc = NULL;
60*76404edcSAsim Jamshed stat_cache_entry *sce;
61*76404edcSAsim Jamshed
62*76404edcSAsim Jamshed for (i = 0; i < cache->used; i++) {
63*76404edcSAsim Jamshed sc = cache->ptr[i];
64*76404edcSAsim Jamshed
65*76404edcSAsim Jamshed if (buffer_is_equal(name, sc->name)) {
66*76404edcSAsim Jamshed sc->last_used = time(NULL);
67*76404edcSAsim Jamshed
68*76404edcSAsim Jamshed /* oops, the script failed last time */
69*76404edcSAsim Jamshed
70*76404edcSAsim Jamshed if (lua_gettop(sc->L) == 0) break;
71*76404edcSAsim Jamshed
72*76404edcSAsim Jamshed if (HANDLER_ERROR == stat_cache_get_entry(srv, con, sc->name, &sce)) {
73*76404edcSAsim Jamshed lua_pop(sc->L, 1); /* pop the old function */
74*76404edcSAsim Jamshed break;
75*76404edcSAsim Jamshed }
76*76404edcSAsim Jamshed
77*76404edcSAsim Jamshed if (!buffer_is_equal(sce->etag, sc->etag)) {
78*76404edcSAsim Jamshed /* the etag is outdated, reload the function */
79*76404edcSAsim Jamshed lua_pop(sc->L, 1);
80*76404edcSAsim Jamshed break;
81*76404edcSAsim Jamshed }
82*76404edcSAsim Jamshed
83*76404edcSAsim Jamshed assert(lua_isfunction(sc->L, -1));
84*76404edcSAsim Jamshed lua_pushvalue(sc->L, -1); /* copy the function-reference */
85*76404edcSAsim Jamshed
86*76404edcSAsim Jamshed return sc->L;
87*76404edcSAsim Jamshed }
88*76404edcSAsim Jamshed
89*76404edcSAsim Jamshed sc = NULL;
90*76404edcSAsim Jamshed }
91*76404edcSAsim Jamshed
92*76404edcSAsim Jamshed /* if the script was script already loaded but either got changed or
93*76404edcSAsim Jamshed * failed to load last time */
94*76404edcSAsim Jamshed if (sc == NULL) {
95*76404edcSAsim Jamshed sc = script_init();
96*76404edcSAsim Jamshed
97*76404edcSAsim Jamshed if (cache->size == 0) {
98*76404edcSAsim Jamshed cache->size = 16;
99*76404edcSAsim Jamshed cache->ptr = malloc(cache->size * sizeof(*(cache->ptr)));
100*76404edcSAsim Jamshed } else if (cache->used == cache->size) {
101*76404edcSAsim Jamshed cache->size += 16;
102*76404edcSAsim Jamshed cache->ptr = realloc(cache->ptr, cache->size * sizeof(*(cache->ptr)));
103*76404edcSAsim Jamshed }
104*76404edcSAsim Jamshed
105*76404edcSAsim Jamshed cache->ptr[cache->used++] = sc;
106*76404edcSAsim Jamshed
107*76404edcSAsim Jamshed buffer_copy_string_buffer(sc->name, name);
108*76404edcSAsim Jamshed
109*76404edcSAsim Jamshed sc->L = luaL_newstate();
110*76404edcSAsim Jamshed luaL_openlibs(sc->L);
111*76404edcSAsim Jamshed }
112*76404edcSAsim Jamshed
113*76404edcSAsim Jamshed sc->last_used = time(NULL);
114*76404edcSAsim Jamshed
115*76404edcSAsim Jamshed if (0 != luaL_loadfile(sc->L, name->ptr)) {
116*76404edcSAsim Jamshed /* oops, an error, return it */
117*76404edcSAsim Jamshed
118*76404edcSAsim Jamshed return sc->L;
119*76404edcSAsim Jamshed }
120*76404edcSAsim Jamshed
121*76404edcSAsim Jamshed if (HANDLER_GO_ON == stat_cache_get_entry(srv, con, sc->name, &sce)) {
122*76404edcSAsim Jamshed buffer_copy_string_buffer(sc->etag, sce->etag);
123*76404edcSAsim Jamshed }
124*76404edcSAsim Jamshed
125*76404edcSAsim Jamshed /**
126*76404edcSAsim Jamshed * pcall() needs the function on the stack
127*76404edcSAsim Jamshed *
128*76404edcSAsim Jamshed * as pcall() will pop the script from the stack when done, we have to
129*76404edcSAsim Jamshed * duplicate it here
130*76404edcSAsim Jamshed */
131*76404edcSAsim Jamshed assert(lua_isfunction(sc->L, -1));
132*76404edcSAsim Jamshed lua_pushvalue(sc->L, -1); /* copy the function-reference */
133*76404edcSAsim Jamshed
134*76404edcSAsim Jamshed return sc->L;
135*76404edcSAsim Jamshed }
136*76404edcSAsim Jamshed
137*76404edcSAsim Jamshed #endif
138