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