feature: implemented new methods "add", "replace", and "delete" for ngx.shared.DICT. also made the "set" method return 3 values: "success", "err", and "forcible".
This commit is contained in:
Родитель
a935e6fdbf
Коммит
24da181717
|
@ -14,6 +14,15 @@ static int ngx_http_lua_shdict_expire(ngx_http_lua_shdict_ctx_t *ctx,
|
|||
static ngx_int_t ngx_http_lua_shdict_lookup(ngx_shm_zone_t *shm_zone,
|
||||
ngx_uint_t hash, u_char *kdata, size_t klen,
|
||||
ngx_http_lua_shdict_node_t **sdp);
|
||||
static int ngx_http_lua_shdict_set_helper(lua_State *L, int flags);
|
||||
static int ngx_http_lua_shdict_add(lua_State *L);
|
||||
static int ngx_http_lua_shdict_replace(lua_State *L);
|
||||
static int ngx_http_lua_shdict_incr(lua_State *L);
|
||||
static int ngx_http_lua_shdict_delete(lua_State *L);
|
||||
|
||||
|
||||
#define NGX_HTTP_LUA_SHDICT_ADD 0x0001
|
||||
#define NGX_HTTP_LUA_SHDICT_REPLACE 0x0002
|
||||
|
||||
|
||||
ngx_int_t
|
||||
|
@ -199,7 +208,7 @@ ngx_http_lua_shdict_expire(ngx_http_lua_shdict_ctx_t *ctx, ngx_uint_t n)
|
|||
* and one or two zero rate entries
|
||||
*/
|
||||
|
||||
while (n < 5) {
|
||||
while (n < 3) {
|
||||
|
||||
if (ngx_queue_empty(&ctx->sh->queue)) {
|
||||
return freed;
|
||||
|
@ -252,8 +261,22 @@ ngx_http_lua_inject_shdict_api(ngx_http_lua_main_conf_t *lmcf, lua_State *L)
|
|||
|
||||
lua_pushcfunction(L, ngx_http_lua_shdict_get);
|
||||
lua_setfield(L, -2, "get");
|
||||
|
||||
lua_pushcfunction(L, ngx_http_lua_shdict_set);
|
||||
lua_setfield(L, -2, "set");
|
||||
|
||||
lua_pushcfunction(L, ngx_http_lua_shdict_add);
|
||||
lua_setfield(L, -2, "add");
|
||||
|
||||
lua_pushcfunction(L, ngx_http_lua_shdict_replace);
|
||||
lua_setfield(L, -2, "replace");
|
||||
|
||||
lua_pushcfunction(L, ngx_http_lua_shdict_incr);
|
||||
lua_setfield(L, -2, "incr");
|
||||
|
||||
lua_pushcfunction(L, ngx_http_lua_shdict_delete);
|
||||
lua_setfield(L, -2, "delete");
|
||||
|
||||
lua_pushvalue(L, -1); /* shared mt mt */
|
||||
lua_setfield(L, -2, "__index"); /* shared mt */
|
||||
|
||||
|
@ -341,6 +364,8 @@ ngx_http_lua_shdict_get(lua_State *L)
|
|||
rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len,
|
||||
&sd);
|
||||
|
||||
dd("shdict lookup returns %d", (int) rc);
|
||||
|
||||
if (rc == NGX_DECLINED || rc == NGX_DONE) {
|
||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||
lua_pushnil(L);
|
||||
|
@ -410,8 +435,47 @@ ngx_http_lua_shdict_get(lua_State *L)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
ngx_http_lua_shdict_delete(lua_State *L)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = lua_gettop(L);
|
||||
|
||||
if (n != 2) {
|
||||
return luaL_error(L, "expecting 2 arguments, "
|
||||
"but only seen %d", n);
|
||||
}
|
||||
|
||||
lua_pushnil(L);
|
||||
|
||||
return ngx_http_lua_shdict_set_helper(L, 0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ngx_http_lua_shdict_add(lua_State *L)
|
||||
{
|
||||
return ngx_http_lua_shdict_set_helper(L, NGX_HTTP_LUA_SHDICT_ADD);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ngx_http_lua_shdict_replace(lua_State *L)
|
||||
{
|
||||
return ngx_http_lua_shdict_set_helper(L, NGX_HTTP_LUA_SHDICT_REPLACE);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ngx_http_lua_shdict_set(lua_State *L)
|
||||
{
|
||||
return ngx_http_lua_shdict_set_helper(L, 0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ngx_http_lua_shdict_set_helper(lua_State *L, int flags)
|
||||
{
|
||||
ngx_http_request_t *r;
|
||||
int i, n;
|
||||
|
@ -430,8 +494,9 @@ ngx_http_lua_shdict_set(lua_State *L)
|
|||
ngx_rbtree_node_t *node;
|
||||
ngx_time_t *tp;
|
||||
ngx_shm_zone_t *zone;
|
||||
int override = 0;
|
||||
/* indicates whether to override other valid entries */
|
||||
int forcible = 0;
|
||||
/* indicates whether to foricibly override other
|
||||
* valid entries */
|
||||
|
||||
n = lua_gettop(L);
|
||||
|
||||
|
@ -458,8 +523,7 @@ ngx_http_lua_shdict_set(lua_State *L)
|
|||
key.data = (u_char *) luaL_checklstring(L, 2, &key.len);
|
||||
|
||||
if (key.len == 0) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
return luaL_error(L, "attemp to use empty keys");
|
||||
}
|
||||
|
||||
if (key.len > 65535) {
|
||||
|
@ -490,6 +554,10 @@ ngx_http_lua_shdict_set(lua_State *L)
|
|||
break;
|
||||
|
||||
case LUA_TNIL:
|
||||
if (flags & (NGX_HTTP_LUA_SHDICT_ADD|NGX_HTTP_LUA_SHDICT_REPLACE)) {
|
||||
return luaL_error(L, "attempt to add or replace nil values");
|
||||
}
|
||||
|
||||
value.len = 0;
|
||||
value.data = NULL;
|
||||
break;
|
||||
|
@ -518,12 +586,55 @@ ngx_http_lua_shdict_set(lua_State *L)
|
|||
rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len,
|
||||
&sd);
|
||||
|
||||
dd("shdict lookup returned %d", (int) rc);
|
||||
|
||||
if (flags & NGX_HTTP_LUA_SHDICT_REPLACE) {
|
||||
|
||||
if (rc == NGX_DECLINED || rc == NGX_DONE) {
|
||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||
|
||||
lua_pushboolean(L, 0);
|
||||
lua_pushliteral(L, "not found");
|
||||
lua_pushboolean(L, forcible);
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* rc == NGX_OK */
|
||||
|
||||
goto replace;
|
||||
}
|
||||
|
||||
if (flags & NGX_HTTP_LUA_SHDICT_ADD) {
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||
|
||||
lua_pushboolean(L, 0);
|
||||
lua_pushliteral(L, "exists");
|
||||
lua_pushboolean(L, forcible);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (rc == NGX_DONE) {
|
||||
/* exists but expired */
|
||||
|
||||
dd("go to replace");
|
||||
goto replace;
|
||||
}
|
||||
|
||||
/* rc == NGX_DECLINED */
|
||||
|
||||
dd("go to insert");
|
||||
goto insert;
|
||||
}
|
||||
|
||||
if (rc == NGX_OK || rc == NGX_DONE) {
|
||||
|
||||
if (value_type == LUA_TNIL) {
|
||||
goto remove;
|
||||
}
|
||||
|
||||
replace:
|
||||
if (value.len == (size_t) sd->value_len) {
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
|
@ -555,8 +666,10 @@ ngx_http_lua_shdict_set(lua_State *L)
|
|||
|
||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||
|
||||
lua_pushboolean(L, override);
|
||||
return 1;
|
||||
lua_pushboolean(L, 1);
|
||||
lua_pushnil(L);
|
||||
lua_pushboolean(L, forcible);
|
||||
return 3;
|
||||
}
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
|
@ -575,12 +688,16 @@ remove:
|
|||
|
||||
}
|
||||
|
||||
insert:
|
||||
/* rc == NGX_DECLINED or value size unmatch */
|
||||
|
||||
if (value_type == LUA_TNIL) {
|
||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||
|
||||
lua_pushboolean(L, 1);
|
||||
lua_pushnil(L);
|
||||
lua_pushboolean(L, 0);
|
||||
return 1;
|
||||
return 3;
|
||||
}
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
|
@ -598,13 +715,13 @@ remove:
|
|||
"lua shared dict set: overriding non-expired items due to memory "
|
||||
"shortage for entry \"%V\"", &name);
|
||||
|
||||
override = 1;
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
if (ngx_http_lua_shdict_expire(ctx, 0) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
forcible = 1;
|
||||
|
||||
node = ngx_slab_alloc_locked(ctx->shpool, n);
|
||||
if (node != NULL) {
|
||||
goto allocated;
|
||||
|
@ -613,9 +730,10 @@ remove:
|
|||
|
||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||
|
||||
return luaL_error(L, "failed to allocate memory for "
|
||||
"shared_dict %s (maybe the total capacity is too "
|
||||
"small?)", name.data);
|
||||
lua_pushboolean(L, 0);
|
||||
lua_pushliteral(L, "no memory");
|
||||
lua_pushboolean(L, forcible);
|
||||
return 3;
|
||||
}
|
||||
|
||||
allocated:
|
||||
|
@ -648,7 +766,121 @@ allocated:
|
|||
|
||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||
|
||||
lua_pushboolean(L, override);
|
||||
return 1;
|
||||
lua_pushboolean(L, 1);
|
||||
lua_pushnil(L);
|
||||
lua_pushboolean(L, forcible);
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ngx_http_lua_shdict_incr(lua_State *L)
|
||||
{
|
||||
ngx_http_request_t *r;
|
||||
int n;
|
||||
ngx_str_t name;
|
||||
ngx_str_t key;
|
||||
uint32_t hash;
|
||||
ngx_int_t rc;
|
||||
ngx_http_lua_shdict_ctx_t *ctx;
|
||||
ngx_http_lua_shdict_node_t *sd;
|
||||
lua_Number num;
|
||||
u_char *p;
|
||||
ngx_shm_zone_t *zone;
|
||||
lua_Number value;
|
||||
|
||||
n = lua_gettop(L);
|
||||
|
||||
if (n != 3) {
|
||||
return luaL_error(L, "expecting 3 arguments, "
|
||||
"but only seen %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");
|
||||
}
|
||||
|
||||
ctx = zone->data;
|
||||
|
||||
name = ctx->name;
|
||||
|
||||
lua_getglobal(L, GLOBALS_SYMBOL_REQUEST);
|
||||
r = lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
key.data = (u_char *) luaL_checklstring(L, 2, &key.len);
|
||||
|
||||
if (key.len == 0) {
|
||||
return luaL_error(L, "attemp to use empty keys");
|
||||
}
|
||||
|
||||
if (key.len > 65535) {
|
||||
return luaL_error(L,
|
||||
"the key argument is more than 65535 bytes: %d",
|
||||
(int) key.len);
|
||||
}
|
||||
|
||||
hash = ngx_crc32_short(key.data, key.len);
|
||||
|
||||
value = luaL_checknumber(L, 3);
|
||||
|
||||
if (value == 0) {
|
||||
lua_pushboolean(L, 1);
|
||||
lua_pushnil(L);
|
||||
return 2;
|
||||
}
|
||||
|
||||
dd("looking up key %s in shared dict %s", key.data, name.data);
|
||||
|
||||
ngx_shmtx_lock(&ctx->shpool->mutex);
|
||||
|
||||
#if 1
|
||||
ngx_http_lua_shdict_expire(ctx, 1);
|
||||
#endif
|
||||
|
||||
rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len,
|
||||
&sd);
|
||||
|
||||
dd("shdict lookup returned %d", (int) rc);
|
||||
|
||||
if (rc == NGX_DECLINED || rc == NGX_DONE) {
|
||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||
|
||||
lua_pushboolean(L, 0);
|
||||
lua_pushliteral(L, "not found");
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* rc == NGX_OK */
|
||||
|
||||
if (sd->value_type != LUA_TNUMBER || sd->value_len != sizeof(lua_Number)) {
|
||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||
|
||||
lua_pushboolean(L, 0);
|
||||
lua_pushliteral(L, "not a number");
|
||||
return 2;
|
||||
}
|
||||
|
||||
ngx_queue_remove(&sd->queue);
|
||||
ngx_queue_insert_head(&ctx->sh->queue, &sd->queue);
|
||||
|
||||
dd("setting value type to %d", value_type);
|
||||
|
||||
p = sd->data + key.len;
|
||||
|
||||
num = *(lua_Number *) p;
|
||||
|
||||
num += value;
|
||||
|
||||
ngx_memcpy(p, (lua_Number *) &num, sizeof(lua_Number));
|
||||
|
||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||
|
||||
lua_pushboolean(L, 1);
|
||||
lua_pushnil(L);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
|
515
t/043-shdict.t
515
t/043-shdict.t
|
@ -107,9 +107,9 @@ false boolean
|
|||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
false
|
||||
false
|
||||
false
|
||||
truenilfalse
|
||||
truenilfalse
|
||||
truenilfalse
|
||||
dog
|
||||
dog
|
||||
bird string
|
||||
|
@ -140,7 +140,7 @@ hello
|
|||
|
||||
|
||||
|
||||
=== TEST 6: expired entries
|
||||
=== TEST 6: expired entries (can be auto-removed by get)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
|
@ -162,7 +162,31 @@ nil
|
|||
|
||||
|
||||
|
||||
=== TEST 7: not yet expired entries
|
||||
=== TEST 7: expired entries (can NOT be auto-removed by get)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("bar", 56, 0.001)
|
||||
dogs:set("baz", 78, 0.001)
|
||||
dogs:set("foo", 32, 0.01)
|
||||
ngx.location.capture("/sleep/0.01")
|
||||
ngx.say(dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
location ~ '^/sleep/(.+)' {
|
||||
echo_sleep $1;
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
nil
|
||||
|
||||
|
||||
|
||||
=== TEST 8: not yet expired entries
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
|
@ -184,7 +208,7 @@ GET /test
|
|||
|
||||
|
||||
|
||||
=== TEST 8: forcibly override other valid entries
|
||||
=== TEST 9: forcibly override other valid entries
|
||||
--- http_config
|
||||
lua_shared_dict dogs 100k;
|
||||
--- config
|
||||
|
@ -195,8 +219,9 @@ GET /test
|
|||
while i < 1000 do
|
||||
i = i + 1
|
||||
local val = string.rep(" hello", 10) .. i
|
||||
local override = dogs:set("key_" .. i, val)
|
||||
if override then
|
||||
local res, err, forcible = dogs:set("key_" .. i, val)
|
||||
if not res or forcible then
|
||||
ngx.say(res, " ", err, " ", forcible)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
@ -213,14 +238,14 @@ GET /test
|
|||
--- pipelined_requests eval
|
||||
["GET /test", "GET /test"]
|
||||
--- response_body eval
|
||||
my $a = "abort at (353|705)\ncur value: " . (" hello" x 10) . "\\1\n1st value: nil\n2nd value: " . (" hello" x 10) . "2\n";
|
||||
my $a = "true nil true\nabort at (353|705)\ncur value: " . (" hello" x 10) . "\\1\n1st value: nil\n2nd value: " . (" hello" x 10) . "2\n";
|
||||
[qr/$a/,
|
||||
"abort at 1\ncur value: " . (" hello" x 10) . "1\n"
|
||||
"true nil true\nabort at 1\ncur value: " . (" hello" x 10) . "1\n"
|
||||
]
|
||||
|
||||
|
||||
|
||||
=== TEST 9: forcibly override other valid entries and test LRU
|
||||
=== TEST 10: forcibly override other valid entries and test LRU
|
||||
--- http_config
|
||||
lua_shared_dict dogs 100k;
|
||||
--- config
|
||||
|
@ -234,8 +259,9 @@ my $a = "abort at (353|705)\ncur value: " . (" hello" x 10) . "\\1\n1st value: n
|
|||
if i == 10 then
|
||||
dogs:get("key_1")
|
||||
end
|
||||
local override = dogs:set("key_" .. i, val)
|
||||
if override then
|
||||
local res, err, forcible = dogs:set("key_" .. i, val)
|
||||
if not res or forcible then
|
||||
ngx.say(res, " ", err, " ", forcible)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
@ -252,14 +278,14 @@ my $a = "abort at (353|705)\ncur value: " . (" hello" x 10) . "\\1\n1st value: n
|
|||
--- pipelined_requests eval
|
||||
["GET /test", "GET /test"]
|
||||
--- response_body eval
|
||||
my $a = "abort at (353|705)\ncur value: " . (" hello" x 10) . "\\1\n1st value: " . (" hello" x 10) . "1\n2nd value: nil\n";
|
||||
my $a = "true nil true\nabort at (353|705)\ncur value: " . (" hello" x 10) . "\\1\n1st value: " . (" hello" x 10) . "1\n2nd value: nil\n";
|
||||
[qr/$a/,
|
||||
"abort at 2\ncur value: " . (" hello" x 10) . "2\n1st value: " . (" hello" x 10) . "1\n"
|
||||
"true nil true\nabort at 2\ncur value: " . (" hello" x 10) . "2\n1st value: " . (" hello" x 10) . "1\n"
|
||||
]
|
||||
|
||||
|
||||
|
||||
=== TEST 10: dogs and cats dicts
|
||||
=== TEST 11: dogs and cats dicts
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
lua_shared_dict cats 1m;
|
||||
|
@ -287,7 +313,7 @@ hello, world
|
|||
|
||||
|
||||
|
||||
=== TEST 11: get non-existent keys
|
||||
=== TEST 12: get non-existent keys
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
|
@ -306,7 +332,7 @@ nil
|
|||
|
||||
|
||||
|
||||
=== TEST 12: not feed the object into the call
|
||||
=== TEST 13: not feed the object into the call
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
|
@ -330,25 +356,25 @@ false expecting exactly two arguments, but only seen 1
|
|||
|
||||
|
||||
|
||||
=== TEST 13: too big value
|
||||
=== TEST 14: too big value
|
||||
--- http_config
|
||||
lua_shared_dict dogs 50k;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
local rc, err = pcall(dogs.set, dogs, "foo", string.rep("helloworld", 10000))
|
||||
ngx.say(rc, " ", err)
|
||||
local res, err, forcible = dogs:set("foo", string.rep("helloworld", 10000))
|
||||
ngx.say(res, " ", err, " ", forcible)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
false failed to allocate memory for shared_dict dogs (maybe the total capacity is too small?)
|
||||
false no memory false
|
||||
|
||||
|
||||
|
||||
=== TEST 14: too big key
|
||||
=== TEST 15: too big key
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
|
@ -356,7 +382,7 @@ false failed to allocate memory for shared_dict dogs (maybe the total capacity i
|
|||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
local key = string.rep("a", 65535)
|
||||
local rc, err = pcall(dogs.set, dogs, key, "hello")
|
||||
local rc, err = dogs:set(key, "hello")
|
||||
ngx.say(rc, " ", err)
|
||||
ngx.say(dogs:get(key))
|
||||
|
||||
|
@ -369,13 +395,13 @@ false failed to allocate memory for shared_dict dogs (maybe the total capacity i
|
|||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
true false
|
||||
true nil
|
||||
hello
|
||||
false the key argument is more than 65535 bytes: 65536
|
||||
|
||||
|
||||
|
||||
=== TEST 15: bad value type
|
||||
=== TEST 16: bad value type
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
|
@ -393,7 +419,52 @@ false unsupported value type for key "foo" in shared_dict "dogs": userdata
|
|||
|
||||
|
||||
|
||||
=== TEST 16: set nil after setting values
|
||||
=== TEST 17: delete after setting values
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("foo", 32)
|
||||
ngx.say(dogs:get("foo"))
|
||||
dogs:delete("foo")
|
||||
ngx.say(dogs:get("foo"))
|
||||
dogs:set("foo", "hello, world")
|
||||
ngx.say(dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
32
|
||||
nil
|
||||
hello, world
|
||||
|
||||
|
||||
|
||||
=== TEST 18: delete at first
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:delete("foo")
|
||||
ngx.say(dogs:get("foo"))
|
||||
dogs:set("foo", "hello, world")
|
||||
ngx.say(dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
nil
|
||||
hello, world
|
||||
|
||||
|
||||
|
||||
=== TEST 19: set nil after setting values
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
|
@ -417,7 +488,7 @@ hello, world
|
|||
|
||||
|
||||
|
||||
=== TEST 17: set nil at first
|
||||
=== TEST 20: set nil at first
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
|
@ -438,7 +509,7 @@ hello, world
|
|||
|
||||
|
||||
|
||||
=== TEST 18: set nil at first
|
||||
=== TEST 21: fail to allocate memory
|
||||
--- http_config
|
||||
lua_shared_dict dogs 100k;
|
||||
--- config
|
||||
|
@ -449,8 +520,9 @@ hello, world
|
|||
while i < 1000 do
|
||||
i = i + 1
|
||||
local val = string.rep("hello", i )
|
||||
local override = dogs:set("key_" .. i, val)
|
||||
if override then
|
||||
local res, err, forcible = dogs:set("key_" .. i, val)
|
||||
if not res or forcible then
|
||||
ngx.say(res, " ", err, " ", forcible)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
@ -460,11 +532,11 @@ hello, world
|
|||
--- request
|
||||
GET /test
|
||||
--- response_body_like
|
||||
^abort at (?:139|142)$
|
||||
^true nil true\nabort at (?:139|142)$
|
||||
|
||||
|
||||
|
||||
=== TEST 19: string key, int value (write_by_lua)
|
||||
=== TEST 22: string key, int value (write_by_lua)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
|
@ -488,7 +560,7 @@ GET /test
|
|||
|
||||
|
||||
|
||||
=== TEST 20: string key, int value (access_by_lua)
|
||||
=== TEST 23: string key, int value (access_by_lua)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
|
@ -512,7 +584,7 @@ GET /test
|
|||
|
||||
|
||||
|
||||
=== TEST 21: string key, int value (set_by_lua)
|
||||
=== TEST 24: string key, int value (set_by_lua)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
|
@ -531,7 +603,7 @@ GET /test
|
|||
|
||||
|
||||
|
||||
=== TEST 21: string key, int value (header_by_lua)
|
||||
=== TEST 25: string key, int value (header_by_lua)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
|
@ -550,3 +622,374 @@ X-Foo: 32
|
|||
--- response_body
|
||||
hello
|
||||
|
||||
|
||||
|
||||
=== TEST 26: too big value (forcible)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 50k;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("bah", "hello")
|
||||
local res, err, forcible = dogs:set("foo", string.rep("helloworld", 10000))
|
||||
ngx.say(res, " ", err, " ", forcible)
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
false no memory true
|
||||
|
||||
|
||||
|
||||
=== TEST 27: add key (key exists)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("foo", 32)
|
||||
local res, err, forcible = dogs:add("foo", 10502)
|
||||
ngx.say("add: ", res, " ", err, " ", forcible)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
add: false exists false
|
||||
foo = 32
|
||||
|
||||
|
||||
|
||||
=== TEST 28: add key (key not exists)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("bah", 32)
|
||||
local res, err, forcible = dogs:add("foo", 10502)
|
||||
ngx.say("add: ", res, " ", err, " ", forcible)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
add: true nil false
|
||||
foo = 10502
|
||||
|
||||
|
||||
|
||||
=== TEST 29: add key (key expired)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("bar", 32, 0.001)
|
||||
dogs:set("baz", 32, 0.001)
|
||||
dogs:set("foo", 32, 0.001)
|
||||
ngx.location.capture("/sleep/0.002")
|
||||
local res, err, forcible = dogs:add("foo", 10502)
|
||||
ngx.say("add: ", res, " ", err, " ", forcible)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
location ~ ^/sleep/(.+) {
|
||||
echo_sleep $1;
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
add: true nil false
|
||||
foo = 10502
|
||||
|
||||
|
||||
|
||||
=== TEST 30: add key (key expired and value size unmatched)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("bar", 32, 0.001)
|
||||
dogs:set("baz", 32, 0.001)
|
||||
dogs:set("foo", "hi", 0.001)
|
||||
ngx.location.capture("/sleep/0.002")
|
||||
local res, err, forcible = dogs:add("foo", "hello")
|
||||
ngx.say("add: ", res, " ", err, " ", forcible)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
location ~ ^/sleep/(.+) {
|
||||
echo_sleep $1;
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
add: true nil false
|
||||
foo = hello
|
||||
|
||||
|
||||
|
||||
=== TEST 31: incr key (key exists)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("foo", 32)
|
||||
local res, err, forcible = dogs:replace("foo", 10502)
|
||||
ngx.say("replace: ", res, " ", err, " ", forcible)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
|
||||
local res, err, forcible = dogs:replace("foo", "hello")
|
||||
ngx.say("replace: ", res, " ", err, " ", forcible)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
replace: true nil false
|
||||
foo = 10502
|
||||
replace: true nil false
|
||||
foo = hello
|
||||
|
||||
|
||||
|
||||
=== TEST 32: replace key (key not exists)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("bah", 32)
|
||||
local res, err, forcible = dogs:replace("foo", 10502)
|
||||
ngx.say("replace: ", res, " ", err, " ", forcible)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
replace: false not found false
|
||||
foo = nil
|
||||
|
||||
|
||||
|
||||
=== TEST 33: replace key (key expired)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("bar", 3, 0.001)
|
||||
dogs:set("baz", 2, 0.001)
|
||||
dogs:set("foo", 32, 0.001)
|
||||
ngx.location.capture("/sleep/0.002")
|
||||
local res, err, forcible = dogs:replace("foo", 10502)
|
||||
ngx.say("replace: ", res, " ", err, " ", forcible)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
location ~ ^/sleep/(.+) {
|
||||
echo_sleep $1;
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
replace: false not found false
|
||||
foo = nil
|
||||
|
||||
|
||||
|
||||
=== TEST 34: replace key (key expired and value size unmatched)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("bar", 32, 0.001)
|
||||
dogs:set("baz", 32, 0.001)
|
||||
dogs:set("foo", "hi", 0.001)
|
||||
ngx.location.capture("/sleep/0.002")
|
||||
local rc, err, forcible = dogs:replace("foo", "hello")
|
||||
ngx.say("replace: ", rc, " ", err, " ", forcible)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
location ~ ^/sleep/(.+) {
|
||||
echo_sleep $1;
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
replace: false not found false
|
||||
foo = nil
|
||||
|
||||
|
||||
|
||||
=== TEST 35: incr key (key exists)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("foo", 32)
|
||||
local res, err = dogs:incr("foo", 10502)
|
||||
ngx.say("replace: ", res, " ", err)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
replace: true nil
|
||||
foo = 10534
|
||||
|
||||
|
||||
|
||||
=== TEST 36: replace key (key not exists)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("bah", 32)
|
||||
local res, err = dogs:incr("foo", 2)
|
||||
ngx.say("replace: ", res, " ", err)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
replace: false not found
|
||||
foo = nil
|
||||
|
||||
|
||||
|
||||
=== TEST 37: replace key (key expired)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("bar", 3, 0.001)
|
||||
dogs:set("baz", 2, 0.001)
|
||||
dogs:set("foo", 32, 0.001)
|
||||
ngx.location.capture("/sleep/0.002")
|
||||
local res, err = dogs:incr("foo", 10502)
|
||||
ngx.say("replace: ", res, " ", err)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
location ~ ^/sleep/(.+) {
|
||||
echo_sleep $1;
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
replace: false not found
|
||||
foo = nil
|
||||
|
||||
|
||||
|
||||
=== TEST 38: incr key (incr by 0)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("foo", 32)
|
||||
local res, err = dogs:incr("foo", 0)
|
||||
ngx.say("replace: ", res, " ", err)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
replace: true nil
|
||||
foo = 32
|
||||
|
||||
|
||||
|
||||
=== TEST 39: incr key (incr by floating point number)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("foo", 32)
|
||||
local res, err = dogs:incr("foo", 0.14)
|
||||
ngx.say("replace: ", res, " ", err)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
replace: true nil
|
||||
foo = 32.14
|
||||
|
||||
|
||||
|
||||
=== TEST 40: incr key (incr by negative numbers)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("foo", 32)
|
||||
local res, err = dogs:incr("foo", -0.14)
|
||||
ngx.say("replace: ", res, " ", err)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
replace: true nil
|
||||
foo = 31.86
|
||||
|
||||
|
||||
|
||||
=== TEST 41: incr key (original value is not number)
|
||||
--- http_config
|
||||
lua_shared_dict dogs 1m;
|
||||
--- config
|
||||
location = /test {
|
||||
content_by_lua '
|
||||
local dogs = ngx.shared.dogs
|
||||
dogs:set("foo", true)
|
||||
local res, err = dogs:incr("foo", -0.14)
|
||||
ngx.say("replace: ", res, " ", err)
|
||||
ngx.say("foo = ", dogs:get("foo"))
|
||||
';
|
||||
}
|
||||
--- request
|
||||
GET /test
|
||||
--- response_body
|
||||
replace: false not a number
|
||||
foo = true
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче