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