Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: implemented the shdict:lindex method #231

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ install:
- git clone https://github.com/openresty/openresty.git ../openresty
- git clone https://github.com/openresty/openresty-devel-utils.git
- git clone https://github.com/simpl/ngx_devel_kit.git ../ndk-nginx-module
- git clone https://github.com/openresty/lua-nginx-module.git ../lua-nginx-module
- git clone -b feature/shdict-lindex https://github.com/tokers/lua-nginx-module.git ../lua-nginx-module
- git clone https://github.com/openresty/no-pool-nginx.git ../no-pool-nginx
- git clone https://github.com/openresty/echo-nginx-module.git ../echo-nginx-module
- git clone https://github.com/openresty/lua-resty-lrucache.git
Expand Down
78 changes: 78 additions & 0 deletions lib/resty/core/shdict.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ local ngx_lua_ffi_shdict_set_expire
local ngx_lua_ffi_shdict_capacity
local ngx_lua_ffi_shdict_free_space
local ngx_lua_ffi_shdict_udata_to_zone
local ngx_lua_ffi_shdict_lindex


if subsystem == 'http' then
Expand Down Expand Up @@ -60,6 +61,10 @@ int ngx_http_lua_ffi_shdict_set_expire(void *zone,
size_t ngx_http_lua_ffi_shdict_capacity(void *zone);

void *ngx_http_lua_ffi_shdict_udata_to_zone(void *zone_udata);

int ngx_http_lua_ffi_shdict_lindex(void *zone, const unsigned char *key,
size_t key_len, int *value_type, unsigned char **str_value_buf,
size_t *str_value_len, double *num_value, int index, char **errmsg);
]]

ngx_lua_ffi_shdict_get = C.ngx_http_lua_ffi_shdict_get
Expand All @@ -71,6 +76,7 @@ void *ngx_http_lua_ffi_shdict_udata_to_zone(void *zone_udata);
ngx_lua_ffi_shdict_capacity = C.ngx_http_lua_ffi_shdict_capacity
ngx_lua_ffi_shdict_udata_to_zone =
C.ngx_http_lua_ffi_shdict_udata_to_zone
ngx_lua_ffi_shdict_lindex = C.ngx_http_lua_ffi_shdict_lindex

if not pcall(function ()
return C.ngx_http_lua_ffi_shdict_free_space
Expand Down Expand Up @@ -588,6 +594,77 @@ local function shdict_free_space(zone)
end


local function shdict_lindex(zone, key, index)
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

if type(index) ~= "number" then
return nil, "bad index"
end

local size = get_string_buf_size()
local buf = get_string_buf(size)
str_value_buf[0] = buf
local value_len = get_size_ptr()
value_len[0] = size

local rc = ngx_lua_ffi_shdict_lindex(zone, key, key_len, value_type,
str_value_buf, value_len,
num_value, index, errmsg)

if rc ~= 0 then
if errmsg[0] then
return nil, ffi_str(errmsg[0])
end

error("failed to index the key")
end

local typ = value_type[0]

if typ == 0 then -- LUA_TNIL
return nil
end

local val

if typ == 4 then -- LUA_TSTRING
if str_value_buf[0] ~= buf then
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])

else
error("unknown value type: " .. typ)
end

return val
end


if ngx_shared then
local _, dict = next(ngx_shared, nil)
if dict then
Expand All @@ -609,6 +686,7 @@ if ngx_shared then
mt.expire = shdict_expire
mt.capacity = shdict_capacity
mt.free_space = shdict_free_space
mt.lindex = shdict_lindex
end
end
end
Expand Down
189 changes: 189 additions & 0 deletions t/shdict.t
Original file line number Diff line number Diff line change
Expand Up @@ -1620,3 +1620,192 @@ ok
[error]
[alert]
[crit]



=== TEST 51: lindex index argument is not a number
--- config
location = /t {
content_by_lua_block {
local dogs = ngx.shared.dogs
dogs:flush_all()
local ok, err = dogs:lindex("corgi", nil)
ngx.say("ok: ", ok, " err: ", err)
}
}
--- request
GET /t
--- response_body
ok: nil err: bad index
--- no_error_log
[error]
[alert]
[crit]



=== TEST 52: lindex value is not a list
--- config
location = /t {
content_by_lua_block {
local dogs = ngx.shared.dogs
dogs:flush_all()
local ok, err = dogs:set("corgi", "cute")
if not ok then
ngx.say("dogs:set() error: ", err)
return
end

local ok, err = dogs:lindex("corgi", -1)
ngx.say("ok: ", ok, " err: ", err)
}
}
--- request
GET /t
--- response_body
ok: nil err: value not a list
--- no_error_log
[error]
[alert]
[crit]



=== TEST 53: lindex value is nil
--- config
location = /t {
content_by_lua_block {
local dogs = ngx.shared.dogs
dogs:flush_all()
local ok, err = dogs:lindex("corgi", -1)
ngx.say("ok: ", ok, " err: ", err)
}
}
--- request
GET /t
--- response_body
ok: nil err: nil
--- no_error_log
[error]
[alert]
[crit]



=== TEST 54: lindex negative index
--- config
location = /t {
content_by_lua_block {
local dogs = ngx.shared.dogs
dogs:flush_all()
local value = { 2147, 483647, "meat", "bone" }
for i = 1, #value do
local ok, err = dogs:lpush("corgi", value[i])
if not ok then
ngx.say("dogs:lpush() error: ", err)
return
end
end

-- bone meat 483647 2147

for i = -1, -(#value), -1 do
local val, err = dogs:lindex("corgi", i)
if err ~= nil then
ngx.say("index: ", i, " error: ", err)
return
end

ngx.say("index: ", i, " value: ", val)
end
}
}
--- request
GET /t
--- response_body
index: -1 value: 2147
index: -2 value: 483647
index: -3 value: meat
index: -4 value: bone
--- no_error_log
[error]
[alert]
[crit]



=== TEST 55: lindex non-negative index
--- config
location = /t {
content_by_lua_block {
local dogs = ngx.shared.dogs
dogs:flush_all()
local value = { 2147, 483647, "meat", "bone" }
for i = 1, #value do
local ok, err = dogs:lpush("corgi", value[i])
if not ok then
ngx.say("dogs:lpush() error: ", err)
return
end
end

-- bone meat 483647 2147

for i = 0, #value - 1 do
local val, err = dogs:lindex("corgi", i)
if err ~= nil then
ngx.say("index: ", i, " error: ", err)
return
end

ngx.say("index: ", i, " value: ", val)
end
}
}
--- request
GET /t
--- response_body
index: 0 value: bone
index: 1 value: meat
index: 2 value: 483647
index: 3 value: 2147
--- no_error_log
[error]
[alert]
[crit]



=== TEST 56: lindex index out of bound
--- config
location = /t {
content_by_lua_block {
local dogs = ngx.shared.dogs
dogs:flush_all()
local value = { 2147, 483647, "meat", "bone" }
for i = 1, #value do
local ok, err = dogs:lpush("corgi", value[i])
if not ok then
ngx.say("dogs:lpush() error: ", err)
return
end
end

-- bone meat 483647 2147

local val, err = dogs:lindex("corgi", -5)
ngx.say("val: ", val, " err: ", err)

local val, err = dogs:lindex("corgi", 4)
ngx.say("val: ", val, " err: ", err)
}
}
--- request
GET /t
--- response_body
val: nil err: nil
val: nil err: nil
--- no_error_log
[error]
[alert]
[crit]