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 详解的更多相关文章

  1. ngx.shared.DICT.expire 详解

    ngx.shared.DICT.expire 原文链接: ngx.shared.DICT.expire syntax: success, err = ngx.shared.DICT:expire(ke ...

  2. ngx.shared.DICT.incr 详解

    ngx.shared.DICT.incr 原文: ngx.shared.DICT.incr syntax: newval, err, forcible? = ngx.shared.DICT:incr( ...

  3. OpenResty之ngx.shared.DICT

    参考链接: resty.core.shdict ngx_shared.DICT 源码正文: dict.lua 部分源码如下: local ffi = require 'ffi' local base ...

  4. ngx.shared.DICT.set

    ngx.shared.DICT.set 原文: ngx.shared.DICT.set syntax: success, err, forcible = ngx.shared.DICT:set(key ...

  5. Python 中的字符串(str)、字典(dict)详解及操作方法

    一.字符串 在python中字符串是一种重要数据类型.其他数据类型分别为: 数字-number -------- int.long.float.complex这几种 字符串-string ------ ...

  6. Python之dict字典详解

    Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,字典是另 一种可变容器模型,且可存储任意类型对象.具有极快的查找速度. 字典是一种通过名字或者关键字 ...

  7. 【精选】Nginx模块Lua-Nginx-Module学习笔记(二)Lua指令详解(Directives)

    源码地址:https://github.com/Tinywan/Lua-Nginx-Redis Nginx与Lua编写脚本的基本构建块是指令. 指令用于指定何时运行用户Lua代码以及如何使用结果. 下 ...

  8. Nginx模块Lua-Nginx-Module学习笔记(二)Lua指令详解(Directives)

    源码地址:https://github.com/Tinywan/Lua-Nginx-Redis Nginx与Lua编写脚本的基本构建块是指令. 指令用于指定何时运行用户Lua代码以及如何使用结果. 下 ...

  9. Python中dict详解

    from:http://www.cnblogs.com/yangyongzhi/archive/2012/09/17/2688326.html Python中dict详解 python3.0以上,pr ...

随机推荐

  1. 如何把SAP Kyma和SAP Cloud for Customer连接起来

    首先进入SAP Cloud for Customer的Administration的工作中心,打开General Settings视图,进入Event Notification配置UI: 新建一个C4 ...

  2. docker linux下配置加速器

    [root@foundation83 ~]# cd /etc/docker/[root@foundation83 docker]# vim daemon.json{ "registry-mi ...

  3. py网络编程学习笔记

    一.异常处理 异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止),在python中,错误触发的异常如下 而错误分为两种: 1 ...

  4. 直接插入排序算法(java)

    直接插入排序是将未排序的数据插入至已排好序序列的合适位置. 具体流程如下: 1.首先比较数组的前两个数据,并排序: 2.比较第三个元素与前两个排好序的数据,并将第三个元素放入适当的位置: 3.比较第四 ...

  5. poi 生成word 表格,并向表格单元格中插入多个图片

    接这上一篇,导入数据,也要完整导出来.话不多说,直接上代码. 效果图 //根据实体对象 ,生成XWPFDocument public static XWPFDocument exportDataInf ...

  6. pytorch版yolov3训练自己数据集

    目录 1. 环境搭建 2. 数据集构建 3. 训练模型 4. 测试模型 5. 评估模型 6. 可视化 7. 高级进阶-网络结构更改 1. 环境搭建 将github库download下来. git cl ...

  7. jupyter notebook new Python3报错:Permission denied: Untitled.ipynb,修改workspace

    点击新建Python文件即弹出弹窗显示 Permission denied: Untitled.ipynb 看到Permission denied 尝试是权限问题进行解决,各种百度结果都是对文件进行权 ...

  8. Log parser工具使用

    Windows日志存放于目录“C:\Windows\System32\winevt\Logs”中, 在目录中可以找到“System”.“Setup”.“Application”.“Security” ...

  9. JDK环境变量配置window

    下面开始配置环境变量,右击[我的电脑]---[属性]-----[高级]---[环境变量],如图: ​选择[新建系统变量]--弹出“新建系统变量”对话框,在“变量名”文本框输入“JAVA_HOME”,在 ...

  10. Java枚举的小例子

    有一次工作中,要根据多个参数确定一个值(车辆事件),确定一个值需要的参数大部分的属性名称是相同的,少部分是独有的,但是参数的值几乎都是不同的: 因为参数太多,if-else写起来就太不优雅了,可以参考 ...