ngx.shared.DICT.expire 详解

ngx.shared.DICT.expire

原文链接: ngx.shared.DICT.expire

syntax: success, err = ngx.shared.DICT:expire(key, exptime)

context: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, 
         header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, 
         balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, 
         ssl_session_store_by_lua*

requires: resty.core.shdict or resty.core

设置存储于共享内存 ngx.shared.DICT 中的键值对的过期时间(以秒为单位)。如果操作完成返回布尔值指示成功,否则返回 nil 和错误信息字符串。

如果 key 不存在,则该方法返回 nil 和错误信息字符串 "not found"。

exptime 过期参数的分辨率为 0.001 秒,如果 exptime 为 0,则该项将永不过期。如下:

require "resty.core"

local cats = ngx.shared.cats
local succ, err = cats:set("Marry", "a nice cat", 0.1)

succ, err = cats:expire("Marry", 0.5)

ngx.sleep(0.2)

local val, err = cats:get("Marry")
ngx.say(val)  -- "a nice cat"

expire 源码实现

local function shdict_expire(zone, kye, exptime)
    zone = check_zone(zone)
    
    if not exptime then
        error('bad "exptime" argument', 2)
    end
    
    if key == nil then
        return nil, "nil key"
    end
    
    if (type(key) ~= "string") then
        key = tostring(key)
    end
    
    local key_len = #key
    if key_len == 0 then
        return nil, "empty key"
    end
    
    if key_len > 65535 then
        return nil, "key too long"
    end
    
    local rc = C.ngx_http_lua_ffi_shdict_set_expire(zone, key, key_len, 
                                                    exptime * 1000)
    
    if rc == FFI_ERROR then
        return nil, "bad zone"
    end
    
    if rc == FFI_DECLINED then
        return nil, "not found"
    end
    
    -- NGINX_OK/FFI_OK
    
    return true
end

ngx_http_lua_ffi_shdict_set_expire

int 
ngx_http_lua_ffi_shdict_set_exptire(ngx_shm_zone_t *zone, u_char *key, 
    size_t key_len, long exptime)
{
    uint32_t                     hash;
    ngx_int_t                    rc;
    ngx_time_t                  *tp = NULL;
    ngx_http_lua_shdict_ctx_t   *ctx;
    ngx_http_lua_shdict_node_t  *sd;
    
    if (zone == NULL) {
        return NGX_ERROR;
    }
    
    if (exptime > 0) {
        tp = ngx_timeofday();
    }
    
    ctx = zone->data;
    hash = ngx_crc32_short(key, key_len);
    
    ngx_shmtx_lock(&ctx->shpool->mutex);
    
    rc = ngx_http_lua_shdict_peek(zone, hash, key, key_len, &sd);
    
    if (rc == NGX_DECLINED) {
        ngx_shmtx_unlock(&ctx->shpool->mutex);
        
        return NGX_DECLINED;
    }
    
    /* rc == NGX_OK */
    
    if (exptime > 0) {
        sd->expires = (uint64_t) tp->sec * 1000 + tp->msec
                      + (uint64_t) exptime;
                     
    } else {
        sd->expires = 0;
    }
    
    ngx_shmtx_unlock(&ctx->shpool->mutex);
    
    return NGX_OK;
}

ngx_http_lua_shdict_peek

static ngx_int_t 
ngx_http_lua_shdict_peek(ngx_shm_zone_t *shm_zone, ngx_uint_t hash, 
    u_char *kdata, size_t klen, ngx_http_lua_shdict_node_t **sdp)
{
    ngx_int_t                    rc;
    ngx_rbtree_node_t           *node, *sentinel;
    ngx_http_lua_shdict_ctx_t   *ctx;
    ngx_http_lua_shdict_node_t  *sd;
    
    ctx = shm_zone->data;
    
    node = ctx->sh->rbtree.root;
    sentinel = ctx->sh->rbtree.sentinel;
    
    while (node != sentinel) {
        
        if (hash < node->key) {
            node = node->left;
            continue;
        }
        
        if (hash > node->key) {
            node = node->right;
            continue;
        }
        
        /* hash == node->key */
        
        sd = (ngx_http_lua_shdict_node_t *) &node->color;
        
        rc = ngx_memn2cmp(kdata, sd->data, klen, (size_t) sd->key_len);
        
        if (rc == 0) {
            *sdp = sd;
            
            return NGX_OK;
        }
        
        node = (rc < 0) ? node->left : node->right;
    }
    
    *sdp = NULL;
    
    return NGX_DECLINED;
}
posted @ 2018-08-06 22:53  季末的天堂  阅读(1588)  评论(0编辑  收藏