Skip to content

Commit

Permalink
feature: implemented the shdict:lindex method
Browse files Browse the repository at this point in the history
  • Loading branch information
tokers committed Feb 23, 2019
1 parent d36c977 commit a9eb9ff
Show file tree
Hide file tree
Showing 2 changed files with 267 additions and 0 deletions.
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]

0 comments on commit a9eb9ff

Please sign in to comment.