ngx.shared.DICT.get 详解
ngx.shared.DICT.get
syntax: value, flags = ngx.shared.DICT:get(key)
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 共享内存中 key 对应的值。如果 key 不存在或者超时,则返回 nil。
如果发生错误,返回 nil 和错误描述字符串。
在插入字典后,返回的值具有原始数据类型,如 Lua boolean,number,或者 string。
该方法的第一个参数是字典自身,如下:
local cats = ngx.shared.cats
local value, flags = cats.get(cats, "Mary")
或者用如下方法调用:
local cats = ngx.shared.cats
local value, flags = cats:get("Marry")
如果用户标志 flag 为 0(默认),则不返回任何标志值。
get 源码实现如下
local value_type = ffi_new("int[1]")
local user_flags = ffi_new("int[1]")
local num_value = ffi_new("double[1]")
local is_stale = ffi_new("int[1]")
local str_value_buf = ffi_new("unsigned char *[1]")
local errmsg = base.get_errmsg_ptr()
local function shdict_get(zone, key)
    zone = check_zone(zone)
    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 size = get_string_buf_size() -- 4096
    local buf = get_string_buf(size)
    str_value_buf[0] = buf      -- str_value_buf = ffi_new("unsigned char *[1]")
    local value_len = get_size_ptr()
    value_len[0] = size
    local rc = C.ngx_http_lua_ffi_shdict_get(zone, key, key_len, value_type,
                                             str_value_buf, value_len,
                                             num_value, user_flags, 0,
                                             is_stale, errmsg)
    if rc ~= 0 then
        if errmsg[0] then
            return nil, ffi_str(errmsg[0])
        end
        error("failed to get the key")
    end
    local typ = value_type[0]
    if typ == 0 then -- LUA_TNIL
        return nil
    end
    local flags = tonumber(user_flags[0])
    local val
    if typ == 4 then -- LUA_TSTRING
        if str_value_buf[0] ~= buf then
            -- ngx.say("len: ", tonumber(value_len[0]))
            buf = str_value_buf[0]
            val = ffi_str(buf, value_len[0])
            C.free(buf)
        else
            val = ffi_str(buf, value_len[0])
        end
    elseif typ == 3 then -- LUA_TNUMBER
        val = tonumber(num_value[0])
    elseif typ == 1 then -- LUA_TBOOLEAN
        val = (tonumber(buf[0]) ~= 0)
    else
        error("unknown value type: " .. typ)
    end
    if flags ~= 0 then
        return val, flags
    end
    return val
end
get_string_buf_size 和 get_string_buf
这两个函数位于 resty.core.base.lua 文件中:
local ffi = require = 'ffi'
local ffi_new = ffi.new
local str_buf_size = 4096
local str_buf
local size_ptr
local FREE_LIST_REF = 0
local c_buf_type = ffi.typeof("char[?]")
local errmsg 
function _M.get_errmsg_ptr()
    if not errmsg then
        errmsg = ffi_new("char *[1]")
    end
    return errmsg
end
function _M.get_string_buf_size()
    return str_buf_size
end
function _M.get_string_buf(size, must_alloc)
    -- ngx.log(ngx.ERR, "str buf size: ", str_buf_size)
    if size > str_buf_size or must_alloc then
        return ffi_new(c_buf_type, size)
    end
    if not str_buf then
        str_buf = ffi_new(c_buf_type, str_buf_size)
    end
    return str_buf
end
function _M.get_size_ptr()
    if not size_ptr then
        size_ptr = ffi_new("size_t[1]")
    end
    return size_ptr
end
ngx_http_lua_ffi_shdict_get
int
ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key,
    size_t key_len, int *value_type, u_char **str_value_buf,
    size_t *str_value_len, double *num_value, int *user_flags,
    int get_stale, int *is_stale, char **err)
{
    ngx_str_t                    name;
    uint32_t                     hash;
    ngx_int_t                    rc;
    ngx_http_lua_shdict_ctx_t   *ctx;
    ngx_http_lua_shdict_node_t  *sd;
    ngx_str_t                    value;
    if (zone == NULL) {
        return NGX_ERROR;
    }
    *err = NULL;
    ctx = zone->data;
    name = ctx->name;
    hash = ngx_crc32_short(key, key_len);
#if (NGX_DEBUG)
    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
                   "fetching key \"%*s\" in shared dict \"%V\"", key_len,
                   key, &name);
end
    ngx_shmtx_lock(&ctx->shpool->mutex);
#if 1
    if (!get_stale) {
        /* 删除共享内存中过期的 1~2 个项 */
        ngx_http_lua_shdict_expire(ctx, 1);
    }
end
    rc = ngx_http_lua_shdict_lookup(zone, hash, key, key_len, &sd);
    dd("shdict lookup returns %d", (int) rc);
    if (rc == NGX_DECLINED || (rc == NGX_DONE && !get_stale)) {
        ngx_shmtx_unlock(&ctx->shpool->mutex);
        *value_type = LUA_TNIL;
        return NGX_OK;
    }
    /* rc == NGX_OK || (rc == NGX_DONE && get_stale) */
    *value_type = sd->value_type;
    dd("data: ", sd->data);
    dd("key len: %d", (int) sd->key_len);
    value.data = sd->data + sd->key_len;
    value.len = (size_t) sd->value_len;
    if (*str_value_len < (size_t) value.len) {
        if (*value_type == SHDICT_TBOOLEAN) {
            ngx_shmtx_unlock(&ctx->shpool->mutex);
            return NGX_ERROR;
        }
        if (*value_type == SHDICT_TSTRING) {
            *str_value_buf = malloc(value.len);
            if (*str_value_buf == NULL) {
                ngx_shmtx_unlock(&ctx->shpool->mutex);
                return NGX_ERROR;
            }
        }
    }
    switch (*value_type) {
    case SHDICT_TSTRING:
        *str_value_len = value.len;
        ngx_memcpy(*str_value_buf, value.data, value.len);
        break;
    case SHDCIT_TNUMBER:
        if (value.len != sizeof(double)) {
            ngx_shmtx_unlock(&ctx->shpool->mutex);
            ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
                          "bad lua number value size found for key %*s "
                          "in shared_dict %V: %z", key_len, key,
                          &name, value.len);
            return NGX_ERROR;
        }
        *str_value_len = value.len;
        ngx_memcpy(num_value, value.data, sizeof(double));
        break;
    case SHDICT_TBOOLEAN:
        if (value.len != sizeof(u_char)) {
            ngx_shmtx_unlock(&ctx->shpool->mutex);
            ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
                          "bad lua boolean value size found for key %*s "
                          "in shared_dict %V: %z", key_len, key, &name,
                          value.len);
            return NGX_ERROR;
        }
        ngx_memcpy(*str_value_buf, value.data, value.len);
        break;
    case SHDICT_TLIST:
        ngx_shmtx_unlock(&ctx->shpool->mutex);
        *err = "value is a list";
        return NGX_ERROR;
    default:
        ngx_shmtx_unlock(&ctx->shpool->mutex);
        ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
                      "bad value type found for key %*s in "
                      "shared_dict %V: %d", key_len, key, &name,
                      *value_type);
        return NGX_ERROR;
    }
    *user_flags = sd->user_flags;
    dd("user flags: %d", *user_flags);
    ngx_shmtx_unlock(&ctx->shpool->mutex);
    if (get_stale) {
        /* always return value, flags, stale */
        /* 为 true 表示已经过期了 */
        *is_stale = (rc == NGX_DONE);
        return NGX_OK;
    }
    return NGX_OK;
}
												
											ngx.shared.DICT.get 详解的更多相关文章
- ngx.shared.DICT.expire 详解
		
ngx.shared.DICT.expire 原文链接: ngx.shared.DICT.expire syntax: success, err = ngx.shared.DICT:expire(ke ...
 - ngx.shared.DICT.incr 详解
		
ngx.shared.DICT.incr 原文: ngx.shared.DICT.incr syntax: newval, err, forcible? = ngx.shared.DICT:incr( ...
 - OpenResty之ngx.shared.DICT
		
参考链接: resty.core.shdict ngx_shared.DICT 源码正文: dict.lua 部分源码如下: local ffi = require 'ffi' local base ...
 - ngx.shared.DICT.set
		
ngx.shared.DICT.set 原文: ngx.shared.DICT.set syntax: success, err, forcible = ngx.shared.DICT:set(key ...
 - Python 中的字符串(str)、字典(dict)详解及操作方法
		
一.字符串 在python中字符串是一种重要数据类型.其他数据类型分别为: 数字-number -------- int.long.float.complex这几种 字符串-string ------ ...
 - Python之dict字典详解
		
Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,字典是另 一种可变容器模型,且可存储任意类型对象.具有极快的查找速度. 字典是一种通过名字或者关键字 ...
 - 【精选】Nginx模块Lua-Nginx-Module学习笔记(二)Lua指令详解(Directives)
		
源码地址:https://github.com/Tinywan/Lua-Nginx-Redis Nginx与Lua编写脚本的基本构建块是指令. 指令用于指定何时运行用户Lua代码以及如何使用结果. 下 ...
 - Nginx模块Lua-Nginx-Module学习笔记(二)Lua指令详解(Directives)
		
源码地址:https://github.com/Tinywan/Lua-Nginx-Redis Nginx与Lua编写脚本的基本构建块是指令. 指令用于指定何时运行用户Lua代码以及如何使用结果. 下 ...
 - Python中dict详解
		
from:http://www.cnblogs.com/yangyongzhi/archive/2012/09/17/2688326.html Python中dict详解 python3.0以上,pr ...
 
随机推荐
- springboot学习入门简易版二---springboot2.0项目创建
			
2 springboot项目创建(5) 环境要求:jdk1.8+ 项目结构: 2.1创建maven工程 Group id :com.springbootdemo Artifact id: spring ...
 - MySQL主从复制(Centos6.3&MySQL5.6)
			
环境: Master:Centos 6.3 192.168.1.4 Slave:Centos 6.3 192.168.1.5 MySQL: MySQL-5.6.2 ...
 - JAVA笔记整理(二),下载安装JDK
			
Windows平台 1.登录Oracle官方网站(http://www.oracle.com/index.html),找到下载 2.选择要下载的版本,点击JDK DOWNLOAD 3.下载文件,先勾选 ...
 - linux个人常用命令【持续更新】
			
netstat -tnl 查看网络相关的端口情况 ps -A 查看所有进程的情况 cat /proc/cpuinfo| grep "physical id"| sort| uniq ...
 - 【胡搞的不能AC的题解,暴力搜索一发博弈问题】1995 三子棋 - 51Nod
			
1995 三子棋 题目来源: syu校赛 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 原题链接: https://www.51nod.com/onlineJudge/ ...
 - Vue实现一个图片懒加载插件(转载)
			
Vue是可以自定义指令的,最近学习过程中遇见了一个需要图片懒加载的功能,最后参考了别人的代码和思路自己重新写了一遍.以下将详细介绍如何实现自定义指令v-lazyload. 先看如何使用这个指令: &l ...
 - webpack中配置babel时遇到的问题
			
1.Error: Cannot find module '@babel/core' babel-loader@8 requires Babel 7.x (the package '@babel/cor ...
 - postgresql学习笔记--基础篇
			
1. 客户端程序和服务器端程序 1.1 客户端程序 Command Example Describe clusterdb clusterdb -h pghost1 -p 1921 -d mydb Cl ...
 - [Sdoi2013] [bzoj 3198] spring (hash+容斥原理)
			
题目描述 给出nnn个666维坐标,求有多少对点对满足恰好mmm个位置相等 1<=n<=1051<=n<=10^51<=n<=105 0<=k<=60& ...
 - div 水平垂直居中
			
css <style> .main{ background: #999999; width: 600px; height: 400px; position: absolute; top: ...