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:
agentzh (章亦春) 2011-10-27 17:20:22 +08:00
Родитель a935e6fdbf
Коммит 24da181717
2 изменённых файлов: 726 добавлений и 51 удалений

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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