src/ngx_stream_lua_shdict.c
/*
 * This trades CPU for memory. This is potentially slow. O(2n)
 */
This trades CPU for memory. This is potentially slow.
This trades CPU for memory . This is potentially slow .
static int
ngx_stream_lua_shdict_get_keys(lua_State *L)
{
    ngx_queue_t                 *q, *prev;
    ngx_shm_zone_t              *zone;
    ngx_time_t                  *tp;
    int                          total = 0;
    int                          attempts = 1024;
    uint64_t                     now;
    int                          n;
    ngx_stream_lua_shdict_node_t        *sd;
    ngx_stream_lua_shdict_ctx_t         *ctx;
    n = lua_gettop(L);
    if (n != 1 && n != 2) {
        return luaL_error(L, "expecting 1 or 2 argument(s), "
                          "but saw %d", n);
    }
    luaL_checktype(L, 1, LUA_TTABLE);
    zone = ngx_stream_lua_shdict_get_zone(L, 1);
    if (zone == NULL) {
        return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer");
    }
    if (n == 2) {
        attempts = luaL_checkint(L, 2);
    }
    ctx = zone->data;
    ngx_shmtx_lock(&ctx->shpool->mutex);
    if (ngx_queue_empty(&ctx->sh->lru_queue)) {
        ngx_shmtx_unlock(&ctx->shpool->mutex);
        lua_createtable(L, 0, 0);
        return 1;
    }
    tp = ngx_timeofday();
    now = (uint64_t) tp->sec * 1000 + tp->msec;
    q = ngx_queue_last(&ctx->sh->lru_queue);
    while (q != ngx_queue_sentinel(&ctx->sh->lru_queue)) {
        prev = ngx_queue_prev(q);
        sd = ngx_queue_data(q, ngx_stream_lua_shdict_node_t, queue);
        if (sd->expires == 0 || sd->expires > now) {
            total++;
            if (attempts && total == attempts) {
                break;
            }
        }
        q = prev;
    }
    lua_createtable(L, total, 0);
    total = 0;
    q = ngx_queue_last(&ctx->sh->lru_queue);
    while (q != ngx_queue_sentinel(&ctx->sh->lru_queue)) {
        prev = ngx_queue_prev(q);
        sd = ngx_queue_data(q, ngx_stream_lua_shdict_node_t, queue);
        if (sd->expires == 0 || sd->expires > now) {
            lua_pushlstring(L, (char *) sd->data, sd->key_len);
            lua_rawseti(L, -2, ++total);
            if (attempts && total == attempts) {
                break;
            }
        }
        q = prev;
    }
    ngx_shmtx_unlock(&ctx->shpool->mutex);
    return 1;
}
static int ngx_stream_lua_shdict_get_keys ( lua_State * L ) { ngx_queue_t * q , * prev ; ngx_shm_zone_t * zone ; ngx_time_t * tp ; int total = 0 ; int attempts = 1024 ; uint64_t now ; int n ; ngx_stream_lua_shdict_node_t * sd ; ngx_stream_lua_shdict_ctx_t * ctx ; n = lua_gettop ( L ) ; if ( n != 1 && n != 2 ) { return luaL_error ( L , " " " " , n ) ; } luaL_checktype ( L , 1 , LUA_TTABLE ) ; zone = ngx_stream_lua_shdict_get_zone ( L , 1 ) ; if ( zone == NULL ) { return luaL_error ( L , " " ) ; } if ( n == 2 ) { attempts = luaL_checkint ( L , 2 ) ; } ctx = zone -> data ; ngx_shmtx_lock ( & ctx -> shpool -> mutex ) ; if ( ngx_queue_empty ( & ctx -> sh -> lru_queue ) ) { ngx_shmtx_unlock ( & ctx -> shpool -> mutex ) ; lua_createtable ( L , 0 , 0 ) ; return 1 ; } tp = ngx_timeofday ( ) ; now = ( uint64_t ) tp -> sec * 1000 + tp -> msec ; q = ngx_queue_last ( & ctx -> sh -> lru_queue ) ; while ( q != ngx_queue_sentinel ( & ctx -> sh -> lru_queue ) ) { prev = ngx_queue_prev ( q ) ; sd = ngx_queue_data ( q , ngx_stream_lua_shdict_node_t , queue ) ; if ( sd -> expires == 0 || sd -> expires > now ) { total ++ ; if ( attempts && total == attempts ) { break ; } } q = prev ; } lua_createtable ( L , total , 0 ) ; total = 0 ; q = ngx_queue_last ( & ctx -> sh -> lru_queue ) ; while ( q != ngx_queue_sentinel ( & ctx -> sh -> lru_queue ) ) { prev = ngx_queue_prev ( q ) ; sd = ngx_queue_data ( q , ngx_stream_lua_shdict_node_t , queue ) ; if ( sd -> expires == 0 || sd -> expires > now ) { lua_pushlstring ( L , ( char * ) sd -> data , sd -> key_len ) ; lua_rawseti ( L , -2 , ++ total ) ; if ( attempts && total == attempts ) { break ; } } q = prev ; } ngx_shmtx_unlock ( & ctx -> shpool -> mutex ) ; return 1 ; }
This trades CPU for memory.
This trades CPU for memory .
/* first run through: get total number of elements we need to allocate */ /* second run through: add keys to table */ /* table is at top of stack */