xref: /lighttpd1.4/src/mod_magnet_cache.c (revision 3392e8fb)
1 #include "first.h"
2 
3 #include "mod_magnet_cache.h"
4 #include "log.h"
5 #include "stat_cache.h"
6 
7 #include <stdlib.h>
8 #include <time.h>
9 
10 #include <lualib.h>
11 #include <lauxlib.h>
12 
13 static script *script_init() {
14 	script *sc;
15 
16 	sc = calloc(1, sizeof(*sc));
17 	force_assert(sc);
18 	sc->name = buffer_init();
19 	sc->etag = buffer_init();
20 
21 	return sc;
22 }
23 
24 static void script_free(script *sc) {
25 	if (!sc) return;
26 
27 	lua_pop(sc->L, 1); /* the function copy */
28 
29 	buffer_free(sc->name);
30 	buffer_free(sc->etag);
31 
32 	lua_close(sc->L);
33 
34 	free(sc);
35 }
36 
37 #if 0
38 script_cache *script_cache_init() {
39 	script_cache *p = calloc(1, sizeof(script_cache));
40 	force_assert(p);
41 	return p;
42 }
43 #endif
44 
45 void script_cache_free_data(script_cache *p) {
46 	size_t i;
47 
48 	if (!p) return;
49 
50 	for (i = 0; i < p->used; i++) {
51 		script_free(p->ptr[i]);
52 	}
53 
54 	free(p->ptr);
55 }
56 
57 lua_State *script_cache_get_script(script_cache *cache, buffer *name, int etag_flags) {
58 	script *sc = NULL;
59 	stat_cache_entry *sce;
60 
61 	for (uint32_t i = 0; i < cache->used; ++i, sc = NULL) {
62 		sc = cache->ptr[i];
63 		if (!buffer_is_equal(name, sc->name)) continue;
64 
65 			/* oops, the script failed last time */
66 
67 			if (lua_gettop(sc->L) == 0) break;
68 			force_assert(lua_gettop(sc->L) == 1);
69 
70 			sce = stat_cache_get_entry(sc->name);
71 			if (NULL == sce) {
72 				lua_pop(sc->L, 1); /* pop the old function */
73 				break;
74 			}
75 
76 			const buffer *etag = stat_cache_etag_get(sce, etag_flags);
77 			if (NULL == etag || !buffer_is_equal(sc->etag, etag)) {
78 				/* the etag is outdated, reload the function */
79 				lua_pop(sc->L, 1);
80 				break;
81 			}
82 
83 			force_assert(lua_isfunction(sc->L, -1));
84 
85 			return sc->L;
86 	}
87 
88 	/* if the script was script already loaded but either got changed or
89 	 * failed to load last time */
90 	if (sc == NULL) {
91 		sc = script_init();
92 
93 		if (cache->used == cache->size) {
94 			cache->size += 16;
95 			cache->ptr = realloc(cache->ptr, cache->size * sizeof(*(cache->ptr)));
96 		}
97 
98 		cache->ptr[cache->used++] = sc;
99 
100 		buffer_copy_buffer(sc->name, name);
101 
102 		sc->L = luaL_newstate();
103 		luaL_openlibs(sc->L);
104 	}
105 
106 	if (0 != luaL_loadfile(sc->L, name->ptr)) {
107 		/* oops, an error, return it */
108 		return sc->L;
109 	}
110 
111 	sce = stat_cache_get_entry(sc->name);
112 	if (sce) {
113 		buffer_copy_buffer(sc->etag, stat_cache_etag_get(sce, etag_flags));
114 	}
115 
116 	force_assert(lua_isfunction(sc->L, -1));
117 
118 	return sc->L;
119 }
120