LCOV - code coverage report
Current view: top level - home/build/openresty-1.13.6.1/build/ngx_lua-0.10.11/src - ngx_http_lua_cache.c (source / functions) Hit Total Coverage
Test: coverage ngix Lines: 29 92 31.5 %
Date: 2020-03-03 04:25:50 Functions: 3 4 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : 
       2             : /*
       3             :  * Copyright (C) Xiaozhe Wang (chaoslawful)
       4             :  * Copyright (C) Yichun Zhang (agentzh)
       5             :  */
       6             : 
       7             : 
       8             : #ifndef DDEBUG
       9             : #define DDEBUG 0
      10             : #endif
      11             : #include "ddebug.h"
      12             : 
      13             : 
      14             : #include <nginx.h>
      15             : #include <ngx_md5.h>
      16             : #include "ngx_http_lua_common.h"
      17             : #include "ngx_http_lua_cache.h"
      18             : #include "ngx_http_lua_clfactory.h"
      19             : #include "ngx_http_lua_util.h"
      20             : 
      21             : 
      22             : /**
      23             :  * Find code chunk associated with the given key in code cache,
      24             :  * and push it to the top of Lua stack if found.
      25             :  *
      26             :  * Stack layout before call:
      27             :  *         |     ...    | <- top
      28             :  *
      29             :  * Stack layout after call:
      30             :  *         | code chunk | <- top
      31             :  *         |     ...    |
      32             :  *
      33             :  * */
      34             : static ngx_int_t
      35           1 : ngx_http_lua_cache_load_code(ngx_log_t *log, lua_State *L,
      36             :     const char *key)
      37             : {
      38             :     int          rc;
      39             :     u_char      *err;
      40             : 
      41             :     /*  get code cache table */
      42           1 :     lua_pushlightuserdata(L, &ngx_http_lua_code_cache_key);
      43           1 :     lua_rawget(L, LUA_REGISTRYINDEX);    /*  sp++ */
      44             : 
      45             :     dd("Code cache table to load: %p", lua_topointer(L, -1));
      46             : 
      47           1 :     if (!lua_istable(L, -1)) {
      48             :         dd("Error: code cache table to load did not exist!!");
      49           0 :         return NGX_ERROR;
      50             :     }
      51             : 
      52           1 :     lua_getfield(L, -1, key);    /*  sp++ */
      53             : 
      54           1 :     if (lua_isfunction(L, -1)) {
      55             :         /*  call closure factory to gen new closure */
      56           0 :         rc = lua_pcall(L, 0, 1, 0);
      57           0 :         if (rc == 0) {
      58             :             /*  remove cache table from stack, leave code chunk at
      59             :              *  top of stack */
      60           0 :             lua_remove(L, -2);   /*  sp-- */
      61           0 :             return NGX_OK;
      62             :         }
      63             : 
      64           0 :         if (lua_isstring(L, -1)) {
      65           0 :             err = (u_char *) lua_tostring(L, -1);
      66             : 
      67             :         } else {
      68           0 :             err = (u_char *) "unknown error";
      69             :         }
      70             : 
      71           0 :         ngx_log_error(NGX_LOG_ERR, log, 0,
      72             :                       "lua: failed to run factory at key \"%s\": %s",
      73             :                       key, err);
      74           0 :         lua_pop(L, 2);
      75           0 :         return NGX_ERROR;
      76             :     }
      77             : 
      78             :     dd("Value associated with given key in code cache table is not code "
      79             :        "chunk: stack top=%d, top value type=%s\n",
      80             :        lua_gettop(L), lua_typename(L, -1));
      81             : 
      82             :     /*  remove cache table and value from stack */
      83           1 :     lua_pop(L, 2);                                /*  sp-=2 */
      84             : 
      85           1 :     return NGX_DECLINED;
      86             : }
      87             : 
      88             : 
      89             : /**
      90             :  * Store the closure factory at the top of Lua stack to code cache, and
      91             :  * associate it with the given key. Then generate new closure.
      92             :  *
      93             :  * Stack layout before call:
      94             :  *         | code factory | <- top
      95             :  *         |     ...      |
      96             :  *
      97             :  * Stack layout after call:
      98             :  *         | code chunk | <- top
      99             :  *         |     ...    |
     100             :  *
     101             :  * */
     102             : static ngx_int_t
     103           1 : ngx_http_lua_cache_store_code(lua_State *L, const char *key)
     104             : {
     105             :     int rc;
     106             : 
     107             :     /*  get code cache table */
     108           1 :     lua_pushlightuserdata(L, &ngx_http_lua_code_cache_key);
     109           1 :     lua_rawget(L, LUA_REGISTRYINDEX);
     110             : 
     111             :     dd("Code cache table to store: %p", lua_topointer(L, -1));
     112             : 
     113           1 :     if (!lua_istable(L, -1)) {
     114             :         dd("Error: code cache table to load did not exist!!");
     115           0 :         return NGX_ERROR;
     116             :     }
     117             : 
     118           1 :     lua_pushvalue(L, -2); /* closure cache closure */
     119           1 :     lua_setfield(L, -2, key); /* closure cache */
     120             : 
     121             :     /*  remove cache table, leave closure factory at top of stack */
     122           1 :     lua_pop(L, 1); /* closure */
     123             : 
     124             :     /*  call closure factory to generate new closure */
     125           1 :     rc = lua_pcall(L, 0, 1, 0);
     126           1 :     if (rc != 0) {
     127             :         dd("Error: failed to call closure factory!!");
     128           0 :         return NGX_ERROR;
     129             :     }
     130             : 
     131           1 :     return NGX_OK;
     132             : }
     133             : 
     134             : 
     135             : ngx_int_t
     136           1 : ngx_http_lua_cache_loadbuffer(ngx_log_t *log, lua_State *L,
     137             :     const u_char *src, size_t src_len, const u_char *cache_key,
     138             :     const char *name)
     139             : {
     140             :     int          n;
     141             :     ngx_int_t    rc;
     142           1 :     const char  *err = NULL;
     143             : 
     144           1 :     n = lua_gettop(L);
     145             : 
     146             :     dd("XXX cache key: [%s]", cache_key);
     147             : 
     148           1 :     rc = ngx_http_lua_cache_load_code(log, L, (char *) cache_key);
     149           1 :     if (rc == NGX_OK) {
     150             :         /*  code chunk loaded from cache, sp++ */
     151             :         dd("Code cache hit! cache key='%s', stack top=%d, script='%.*s'",
     152             :            cache_key, lua_gettop(L), (int) src_len, src);
     153           0 :         return NGX_OK;
     154             :     }
     155             : 
     156           1 :     if (rc == NGX_ERROR) {
     157           0 :         return NGX_ERROR;
     158             :     }
     159             : 
     160             :     /* rc == NGX_DECLINED */
     161             : 
     162             :     dd("Code cache missed! cache key='%s', stack top=%d, script='%.*s'",
     163             :        cache_key, lua_gettop(L), (int) src_len, src);
     164             : 
     165             :     /* load closure factory of inline script to the top of lua stack, sp++ */
     166           1 :     rc = ngx_http_lua_clfactory_loadbuffer(L, (char *) src, src_len, name);
     167             : 
     168           1 :     if (rc != 0) {
     169             :         /*  Oops! error occurred when loading Lua script */
     170           0 :         if (rc == LUA_ERRMEM) {
     171           0 :             err = "memory allocation error";
     172             : 
     173             :         } else {
     174           0 :             if (lua_isstring(L, -1)) {
     175           0 :                 err = lua_tostring(L, -1);
     176             : 
     177             :             } else {
     178           0 :                 err = "unknown error";
     179             :             }
     180             :         }
     181             : 
     182           0 :         goto error;
     183             :     }
     184             : 
     185             :     /*  store closure factory and gen new closure at the top of lua stack to
     186             :      *  code cache */
     187           1 :     rc = ngx_http_lua_cache_store_code(L, (char *) cache_key);
     188           1 :     if (rc != NGX_OK) {
     189           0 :         err = "fail to generate new closure from the closure factory";
     190           0 :         goto error;
     191             :     }
     192             : 
     193           1 :     return NGX_OK;
     194             : 
     195           0 : error:
     196             : 
     197           0 :     ngx_log_error(NGX_LOG_ERR, log, 0,
     198             :                   "failed to load inlined Lua code: %s", err);
     199           0 :     lua_settop(L, n);
     200           0 :     return NGX_ERROR;
     201             : }
     202             : 
     203             : 
     204             : ngx_int_t
     205           0 : ngx_http_lua_cache_loadfile(ngx_log_t *log, lua_State *L,
     206             :     const u_char *script, const u_char *cache_key)
     207             : {
     208             :     int              n;
     209           0 :     ngx_int_t        rc, errcode = NGX_ERROR;
     210             :     u_char          *p;
     211             :     u_char           buf[NGX_HTTP_LUA_FILE_KEY_LEN + 1];
     212           0 :     const char      *err = NULL;
     213             : 
     214           0 :     n = lua_gettop(L);
     215             : 
     216             :     /*  calculate digest of script file path */
     217           0 :     if (cache_key == NULL) {
     218             :         dd("CACHE file key not pre-calculated...calculating");
     219           0 :         p = ngx_copy(buf, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN);
     220             : 
     221           0 :         p = ngx_http_lua_digest_hex(p, script, ngx_strlen(script));
     222             : 
     223           0 :         *p = '\0';
     224           0 :         cache_key = buf;
     225             : 
     226             :     } else {
     227             :         dd("CACHE file key already pre-calculated");
     228             :     }
     229             : 
     230             :     dd("XXX cache key for file: [%s]", cache_key);
     231             : 
     232           0 :     rc = ngx_http_lua_cache_load_code(log, L, (char *) cache_key);
     233           0 :     if (rc == NGX_OK) {
     234             :         /*  code chunk loaded from cache, sp++ */
     235             :         dd("Code cache hit! cache key='%s', stack top=%d, file path='%s'",
     236             :            cache_key, lua_gettop(L), script);
     237           0 :         return NGX_OK;
     238             :     }
     239             : 
     240           0 :     if (rc == NGX_ERROR) {
     241           0 :         return NGX_ERROR;
     242             :     }
     243             : 
     244             :     /* rc == NGX_DECLINED */
     245             : 
     246             :     dd("Code cache missed! cache key='%s', stack top=%d, file path='%s'",
     247             :        cache_key, lua_gettop(L), script);
     248             : 
     249             :     /*  load closure factory of script file to the top of lua stack, sp++ */
     250           0 :     rc = ngx_http_lua_clfactory_loadfile(L, (char *) script);
     251             : 
     252             :     dd("loadfile returns %d (%d)", (int) rc, LUA_ERRFILE);
     253             : 
     254           0 :     if (rc != 0) {
     255             :         /*  Oops! error occurred when loading Lua script */
     256           0 :         switch (rc) {
     257           0 :         case LUA_ERRMEM:
     258           0 :             err = "memory allocation error";
     259           0 :             break;
     260             : 
     261           0 :         case LUA_ERRFILE:
     262           0 :             errcode = NGX_HTTP_NOT_FOUND;
     263             :             /* fall through */
     264             : 
     265           0 :         default:
     266           0 :             if (lua_isstring(L, -1)) {
     267           0 :                 err = lua_tostring(L, -1);
     268             : 
     269             :             } else {
     270           0 :                 err = "unknown error";
     271             :             }
     272             :         }
     273             : 
     274           0 :         goto error;
     275             :     }
     276             : 
     277             :     /*  store closure factory and gen new closure at the top of lua stack
     278             :      *  to code cache */
     279           0 :     rc = ngx_http_lua_cache_store_code(L, (char *) cache_key);
     280           0 :     if (rc != NGX_OK) {
     281           0 :         err = "fail to generate new closure from the closure factory";
     282           0 :         goto error;
     283             :     }
     284             : 
     285           0 :     return NGX_OK;
     286             : 
     287           0 : error:
     288             : 
     289           0 :     ngx_log_error(NGX_LOG_ERR, log, 0,
     290             :                   "failed to load external Lua file \"%s\": %s", script, err);
     291             : 
     292           0 :     lua_settop(L, n);
     293           0 :     return errcode;
     294             : }
     295             : 
     296             : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */

Generated by: LCOV version 1.13