feature: added the "get_keys" method for the shared dictionaries for fetching all the (or the specified number of) keys (default to 1024 keys). thanks Brian Akins for the patch in pull \#170.
This commit is contained in:
Родитель
e607b639be
Коммит
f928feae8d
|
@ -24,6 +24,7 @@ static int ngx_http_lua_shdict_incr(lua_State *L);
|
|||
static int ngx_http_lua_shdict_delete(lua_State *L);
|
||||
static int ngx_http_lua_shdict_flush_all(lua_State *L);
|
||||
static int ngx_http_lua_shdict_flush_expired(lua_State *L);
|
||||
static int ngx_http_lua_shdict_get_keys(lua_State *L);
|
||||
|
||||
|
||||
#define NGX_HTTP_LUA_SHDICT_ADD 0x0001
|
||||
|
@ -282,7 +283,7 @@ ngx_http_lua_inject_shdict_api(ngx_http_lua_main_conf_t *lmcf, lua_State *L)
|
|||
lua_createtable(L, 0, lmcf->shm_zones->nelts /* nrec */);
|
||||
/* ngx.shared */
|
||||
|
||||
lua_createtable(L, 0 /* narr */, 9 /* nrec */); /* shared mt */
|
||||
lua_createtable(L, 0 /* narr */, 10 /* nrec */); /* shared mt */
|
||||
|
||||
lua_pushcfunction(L, ngx_http_lua_shdict_get);
|
||||
lua_setfield(L, -2, "get");
|
||||
|
@ -308,6 +309,9 @@ ngx_http_lua_inject_shdict_api(ngx_http_lua_main_conf_t *lmcf, lua_State *L)
|
|||
lua_pushcfunction(L, ngx_http_lua_shdict_flush_expired);
|
||||
lua_setfield(L, -2, "flush_expired");
|
||||
|
||||
lua_pushcfunction(L, ngx_http_lua_shdict_get_keys);
|
||||
lua_setfield(L, -2, "get_keys");
|
||||
|
||||
lua_pushvalue(L, -1); /* shared mt mt */
|
||||
lua_setfield(L, -2, "__index"); /* shared mt */
|
||||
|
||||
|
@ -617,6 +621,104 @@ ngx_http_lua_shdict_flush_expired(lua_State *L)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* This trades CPU for memory. This is potentially slow. O(2n)
|
||||
*/
|
||||
|
||||
static int
|
||||
ngx_http_lua_shdict_get_keys(lua_State *L)
|
||||
{
|
||||
ngx_queue_t *q, *prev;
|
||||
ngx_http_lua_shdict_node_t *sd;
|
||||
ngx_http_lua_shdict_ctx_t *ctx;
|
||||
ngx_shm_zone_t *zone;
|
||||
ngx_time_t *tp;
|
||||
int total = 0;
|
||||
int attempts = 1024;
|
||||
uint64_t now;
|
||||
int n;
|
||||
|
||||
n = lua_gettop(L);
|
||||
|
||||
if (n != 1 && n != 2) {
|
||||
return luaL_error(L, "expecting 1 or 2 argument(s), "
|
||||
"but saw %d", n);
|
||||
}
|
||||
|
||||
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
|
||||
|
||||
zone = lua_touserdata(L, 1);
|
||||
if (zone == NULL) {
|
||||
return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer");
|
||||
}
|
||||
|
||||
if (n == 2) {
|
||||
attempts = luaL_checknumber(L, 2);
|
||||
}
|
||||
|
||||
ctx = zone->data;
|
||||
|
||||
ngx_shmtx_lock(&ctx->shpool->mutex);
|
||||
|
||||
if (ngx_queue_empty(&ctx->sh->queue)) {
|
||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||
lua_createtable(L, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
tp = ngx_timeofday();
|
||||
|
||||
now = (uint64_t) tp->sec * 1000 + tp->msec;
|
||||
|
||||
/* first run through: get total number of elements we need to allocate */
|
||||
|
||||
q = ngx_queue_last(&ctx->sh->queue);
|
||||
|
||||
while (q != ngx_queue_sentinel(&ctx->sh->queue)) {
|
||||
prev = ngx_queue_prev(q);
|
||||
|
||||
sd = ngx_queue_data(q, ngx_http_lua_shdict_node_t, queue);
|
||||
|
||||
if (sd->expires == 0 || sd->expires > now) {
|
||||
total++;
|
||||
if (attempts && total == attempts) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
q = prev;
|
||||
}
|
||||
|
||||
lua_createtable(L, total, 0);
|
||||
|
||||
/* second run through: add keys to table */
|
||||
|
||||
total = 0;
|
||||
q = ngx_queue_last(&ctx->sh->queue);
|
||||
|
||||
while (q != ngx_queue_sentinel(&ctx->sh->queue)) {
|
||||
prev = ngx_queue_prev(q);
|
||||
|
||||
sd = ngx_queue_data(q, ngx_http_lua_shdict_node_t, queue);
|
||||
|
||||
if (sd->expires == 0 || sd->expires > now) {
|
||||
lua_pushlstring(L, (char *) sd->data, sd->key_len);
|
||||
lua_rawseti(L, -2, ++total);
|
||||
if (attempts && total == attempts) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
q = prev;
|
||||
}
|
||||
|
||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||
|
||||
/* table is at top of stack */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ngx_http_lua_shdict_add(lua_State *L)
|
||||
{
|
||||
|
|
195
t/043-shdict.t
195
t/043-shdict.t
|
@ -1172,3 +1172,198 @@ GET /t
|
|||
--- response_body
|
||||
0
|
||||
|
||||
|
||||
|
||||
=== TEST 49: list all keys in a shdict
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /t {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
|
||||
dogs:set("bah", "y", 0)
|
||||
dogs:set("bar", "z", 0)
|
||||
local keys = dogs:get_keys()
|
||||
ngx.say(#keys)
|
||||
table.sort(keys)
|
||||
for _,k in ipairs(keys) do
|
||||
ngx.say(k)
|
||||
end
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
2
|
||||
bah
|
||||
bar
|
||||
|
||||
|
||||
|
||||
=== TEST 50: list keys in a shdict with limit
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /t {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
|
||||
dogs:set("bah", "y", 0)
|
||||
dogs:set("bar", "z", 0)
|
||||
local keys = dogs:get_keys(1)
|
||||
ngx.say(#keys)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
1
|
||||
|
||||
|
||||
|
||||
=== TEST 51: list all keys in a shdict with expires
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /t {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("foo", "x", 1)
|
||||
dogs:set("bah", "y", 0)
|
||||
dogs:set("bar", "z", 100)
|
||||
|
||||
ngx.sleep(1.5)
|
||||
|
||||
local keys = dogs:get_keys()
|
||||
ngx.say(#keys)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
2
|
||||
|
||||
|
||||
|
||||
=== TEST 52: list keys in a shdict with limit larger than number of keys
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /t {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
|
||||
dogs:set("bah", "y", 0)
|
||||
dogs:set("bar", "z", 0)
|
||||
local keys = dogs:get_keys(3)
|
||||
ngx.say(#keys)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
2
|
||||
|
||||
|
||||
|
||||
=== TEST 53: list keys in an empty shdict
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /t {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
local keys = dogs:get_keys()
|
||||
ngx.say(#keys)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
0
|
||||
|
||||
|
||||
|
||||
=== TEST 54: list keys in an empty shdict with a limit
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /t {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
local keys = dogs:get_keys(4)
|
||||
ngx.say(#keys)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
0
|
||||
|
||||
|
||||
|
||||
=== TEST 55: list all keys in a shdict with all keys expired
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /t {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("foo", "x", 1)
|
||||
dogs:set("bah", "y", 1)
|
||||
dogs:set("bar", "z", 1)
|
||||
|
||||
ngx.sleep(1.5)
|
||||
|
||||
local keys = dogs:get_keys()
|
||||
ngx.say(#keys)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
0
|
||||
|
||||
|
||||
|
||||
=== TEST 56: list all keys in a shdict with more than 1024 keys with no limit set
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /t {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
for i=1,2048 do
|
||||
dogs:set(tostring(i), i)
|
||||
end
|
||||
local keys = dogs:get_keys()
|
||||
ngx.say(#keys)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
1024
|
||||
|
||||
|
||||
|
||||
=== TEST 57: list all keys in a shdict with more than 1024 keys with 0 limit set
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /t {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
for i=1,2048 do
|
||||
dogs:set(tostring(i), i)
|
||||
end
|
||||
local keys = dogs:get_keys(0)
|
||||
ngx.say(#keys)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
2048
|
||||
|
||||
|
|
|
@ -279,7 +279,7 @@ n = 4
|
|||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
n = 9
|
||||
n = 10
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче