Skip to content

Commit cf03ee6

Browse files
committed
feature: implemented the shdict:lindex method
1 parent d36c977 commit cf03ee6

File tree

3 files changed

+268
-1
lines changed

3 files changed

+268
-1
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ install:
6060
- git clone https://github.com/openresty/openresty.git ../openresty
6161
- git clone https://github.com/openresty/openresty-devel-utils.git
6262
- git clone https://github.com/simpl/ngx_devel_kit.git ../ndk-nginx-module
63-
- git clone https://github.com/openresty/lua-nginx-module.git ../lua-nginx-module
63+
- git clone -b feature/shdict-lindex https://github.com/tokers/lua-nginx-module.git ../lua-nginx-module
6464
- git clone https://github.com/openresty/no-pool-nginx.git ../no-pool-nginx
6565
- git clone https://github.com/openresty/echo-nginx-module.git ../echo-nginx-module
6666
- git clone https://github.com/openresty/lua-resty-lrucache.git

lib/resty/core/shdict.lua

+78
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ local ngx_lua_ffi_shdict_set_expire
3030
local ngx_lua_ffi_shdict_capacity
3131
local ngx_lua_ffi_shdict_free_space
3232
local ngx_lua_ffi_shdict_udata_to_zone
33+
local ngx_lua_ffi_shdict_lindex
3334

3435

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

6263
void *ngx_http_lua_ffi_shdict_udata_to_zone(void *zone_udata);
64+
65+
int ngx_http_lua_ffi_shdict_lindex(void *zone, const unsigned char *key,
66+
size_t key_len, int *value_type, unsigned char **str_value_buf,
67+
size_t *str_value_len, double *num_value, int index, char **errmsg);
6368
]]
6469

6570
ngx_lua_ffi_shdict_get = C.ngx_http_lua_ffi_shdict_get
@@ -71,6 +76,7 @@ void *ngx_http_lua_ffi_shdict_udata_to_zone(void *zone_udata);
7176
ngx_lua_ffi_shdict_capacity = C.ngx_http_lua_ffi_shdict_capacity
7277
ngx_lua_ffi_shdict_udata_to_zone =
7378
C.ngx_http_lua_ffi_shdict_udata_to_zone
79+
ngx_lua_ffi_shdict_lindex = C.ngx_http_lua_ffi_shdict_lindex
7480

7581
if not pcall(function ()
7682
return C.ngx_http_lua_ffi_shdict_free_space
@@ -588,6 +594,77 @@ local function shdict_free_space(zone)
588594
end
589595

590596

597+
local function shdict_lindex(zone, key, index)
598+
zone = check_zone(zone)
599+
600+
if key == nil then
601+
return nil, "nil key"
602+
end
603+
604+
if type(key) ~= "string" then
605+
key = tostring(key)
606+
end
607+
608+
local key_len = #key
609+
if key_len == 0 then
610+
return nil, "empty key"
611+
end
612+
613+
if key_len > 65535 then
614+
return nil, "key too long"
615+
end
616+
617+
if type(index) ~= "number" then
618+
return nil, "bad index"
619+
end
620+
621+
local size = get_string_buf_size()
622+
local buf = get_string_buf(size)
623+
str_value_buf[0] = buf
624+
local value_len = get_size_ptr()
625+
value_len[0] = size
626+
627+
local rc = ngx_lua_ffi_shdict_lindex(zone, key, key_len, value_type,
628+
str_value_buf, value_len,
629+
num_value, index, errmsg)
630+
631+
if rc ~= 0 then
632+
if errmsg[0] then
633+
return nil, ffi_str(errmsg[0])
634+
end
635+
636+
error("failed to index the key")
637+
end
638+
639+
local typ = value_type[0]
640+
641+
if typ == 0 then -- LUA_TNIL
642+
return nil
643+
end
644+
645+
local val
646+
647+
if typ == 4 then -- LUA_TSTRING
648+
if str_value_buf[0] ~= buf then
649+
buf = str_value_buf[0]
650+
val = ffi_str(buf, value_len[0])
651+
C.free(buf)
652+
653+
else
654+
val = ffi_str(buf, value_len[0])
655+
end
656+
657+
elseif typ == 3 then -- LUA_TNUMBER
658+
val = tonumber(num_value[0])
659+
660+
else
661+
error("unknown value type: " .. typ)
662+
end
663+
664+
return val
665+
end
666+
667+
591668
if ngx_shared then
592669
local _, dict = next(ngx_shared, nil)
593670
if dict then
@@ -609,6 +686,7 @@ if ngx_shared then
609686
mt.expire = shdict_expire
610687
mt.capacity = shdict_capacity
611688
mt.free_space = shdict_free_space
689+
mt.lindex = shdict_lindex
612690
end
613691
end
614692
end

t/shdict.t

+189
Original file line numberDiff line numberDiff line change
@@ -1620,3 +1620,192 @@ ok
16201620
[error]
16211621
[alert]
16221622
[crit]
1623+
1624+
1625+
1626+
=== TEST 51: lindex index argument is not a number
1627+
--- config
1628+
location = /t {
1629+
content_by_lua_block {
1630+
local dogs = ngx.shared.dogs
1631+
dogs:flush_all()
1632+
local ok, err = dogs:lindex("corgi", nil)
1633+
ngx.say("ok: ", ok, " err: ", err)
1634+
}
1635+
}
1636+
--- request
1637+
GET /t
1638+
--- response_body
1639+
ok: nil err: bad index
1640+
--- no_error_log
1641+
[error]
1642+
[alert]
1643+
[crit]
1644+
1645+
1646+
1647+
=== TEST 52: lindex value is not a list
1648+
--- config
1649+
location = /t {
1650+
content_by_lua_block {
1651+
local dogs = ngx.shared.dogs
1652+
dogs:flush_all()
1653+
local ok, err = dogs:set("corgi", "cute")
1654+
if not ok then
1655+
ngx.say("dogs:set() error: ", err)
1656+
return
1657+
end
1658+
1659+
local ok, err = dogs:lindex("corgi", -1)
1660+
ngx.say("ok: ", ok, " err: ", err)
1661+
}
1662+
}
1663+
--- request
1664+
GET /t
1665+
--- response_body
1666+
ok: nil err: value not a list
1667+
--- no_error_log
1668+
[error]
1669+
[alert]
1670+
[crit]
1671+
1672+
1673+
1674+
=== TEST 53: lindex value is nil
1675+
--- config
1676+
location = /t {
1677+
content_by_lua_block {
1678+
local dogs = ngx.shared.dogs
1679+
dogs:flush_all()
1680+
local ok, err = dogs:lindex("corgi", -1)
1681+
ngx.say("ok: ", ok, " err: ", err)
1682+
}
1683+
}
1684+
--- request
1685+
GET /t
1686+
--- response_body
1687+
ok: nil err: nil
1688+
--- no_error_log
1689+
[error]
1690+
[alert]
1691+
[crit]
1692+
1693+
1694+
1695+
=== TEST 54: lindex negative index
1696+
--- config
1697+
location = /t {
1698+
content_by_lua_block {
1699+
local dogs = ngx.shared.dogs
1700+
dogs:flush_all()
1701+
local value = { 2147, 483647, "meat", "bone" }
1702+
for i = 1, #value do
1703+
local ok, err = dogs:lpush("corgi", value[i])
1704+
if not ok then
1705+
ngx.say("dogs:lpush() error: ", err)
1706+
return
1707+
end
1708+
end
1709+
1710+
-- bone meat 483647 2147
1711+
1712+
for i = -1, -(#value), -1 do
1713+
local val, err = dogs:lindex("corgi", i)
1714+
if err ~= nil then
1715+
ngx.say("index: ", i, " error: ", err)
1716+
return
1717+
end
1718+
1719+
ngx.say("index: ", i, " value: ", val)
1720+
end
1721+
}
1722+
}
1723+
--- request
1724+
GET /t
1725+
--- response_body
1726+
index: -1 value: 2147
1727+
index: -2 value: 483647
1728+
index: -3 value: meat
1729+
index: -4 value: bone
1730+
--- no_error_log
1731+
[error]
1732+
[alert]
1733+
[crit]
1734+
1735+
1736+
1737+
=== TEST 55: lindex non-negative index
1738+
--- config
1739+
location = /t {
1740+
content_by_lua_block {
1741+
local dogs = ngx.shared.dogs
1742+
dogs:flush_all()
1743+
local value = { 2147, 483647, "meat", "bone" }
1744+
for i = 1, #value do
1745+
local ok, err = dogs:lpush("corgi", value[i])
1746+
if not ok then
1747+
ngx.say("dogs:lpush() error: ", err)
1748+
return
1749+
end
1750+
end
1751+
1752+
-- bone meat 483647 2147
1753+
1754+
for i = 0, #value - 1 do
1755+
local val, err = dogs:lindex("corgi", i)
1756+
if err ~= nil then
1757+
ngx.say("index: ", i, " error: ", err)
1758+
return
1759+
end
1760+
1761+
ngx.say("index: ", i, " value: ", val)
1762+
end
1763+
}
1764+
}
1765+
--- request
1766+
GET /t
1767+
--- response_body
1768+
index: 0 value: bone
1769+
index: 1 value: meat
1770+
index: 2 value: 483647
1771+
index: 3 value: 2147
1772+
--- no_error_log
1773+
[error]
1774+
[alert]
1775+
[crit]
1776+
1777+
1778+
1779+
=== TEST 56: lindex index out of bound
1780+
--- config
1781+
location = /t {
1782+
content_by_lua_block {
1783+
local dogs = ngx.shared.dogs
1784+
dogs:flush_all()
1785+
local value = { 2147, 483647, "meat", "bone" }
1786+
for i = 1, #value do
1787+
local ok, err = dogs:lpush("corgi", value[i])
1788+
if not ok then
1789+
ngx.say("dogs:lpush() error: ", err)
1790+
return
1791+
end
1792+
end
1793+
1794+
-- bone meat 483647 2147
1795+
1796+
local val, err = dogs:lindex("corgi", -5)
1797+
ngx.say("val: ", val, " err: ", err)
1798+
1799+
local val, err = dogs:lindex("corgi", 4)
1800+
ngx.say("val: ", val, " err: ", err)
1801+
}
1802+
}
1803+
--- request
1804+
GET /t
1805+
--- response_body
1806+
val: nil err: nil
1807+
val: nil err: nil
1808+
--- no_error_log
1809+
[error]
1810+
[alert]
1811+
[crit]

0 commit comments

Comments
 (0)