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