Skip to content

Commit 307596b

Browse files
doujiang24agentzh
authored andcommitted
feature: shdict:incr(): added the optional "init" argument to allow intializing nonexistent keys with an initial value.
Signed-off-by: Yichun Zhang (agentzh) <agentzh@gmail.com>
1 parent e3ef58d commit 307596b

File tree

2 files changed

+114
-6
lines changed

2 files changed

+114
-6
lines changed

lib/resty/core/shdict.lua

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ ffi.cdef[[
2626
int get_stale, int *is_stale);
2727

2828
int ngx_http_lua_ffi_shdict_incr(void *zone, const unsigned char *key,
29-
size_t key_len, double *value, char **err);
29+
size_t key_len, double *value, char **err, int has_init, double init,
30+
int *forcible);
3031

3132
int ngx_http_lua_ffi_shdict_store(void *zone, int op,
3233
const unsigned char *key, size_t key_len, int value_type,
@@ -313,7 +314,7 @@ local function shdict_get_stale(zone, key)
313314
end
314315

315316

316-
local function shdict_incr(zone, key, value)
317+
local function shdict_incr(zone, key, value, init)
317318
zone = check_zone(zone)
318319

319320
if key == nil then
@@ -337,13 +338,36 @@ local function shdict_incr(zone, key, value)
337338
end
338339
num_value[0] = value
339340

341+
local has_init
342+
343+
if init then
344+
if type(init) ~= "number" then
345+
init = tonumber(init)
346+
347+
if not init then
348+
return error("init should be a number")
349+
end
350+
end
351+
352+
has_init = 1
353+
354+
else
355+
has_init = 0
356+
init = 0
357+
end
358+
340359
local rc = C.ngx_http_lua_ffi_shdict_incr(zone, key, key_len, num_value,
341-
errmsg)
360+
errmsg, has_init, init,
361+
forcible)
342362
if rc ~= 0 then -- ~= NGX_OK
343363
return nil, ffi_str(errmsg[0])
344364
end
345365

346-
return tonumber(num_value[0])
366+
if has_init == 0 then
367+
return tonumber(num_value[0])
368+
end
369+
370+
return tonumber(num_value[0]), nil, forcible[0] == 1
347371
end
348372

349373

t/shdict.t

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):12 loop\]/
349349
local val
350350
local dogs = ngx.shared.dogs
351351
-- local cd = ffi.cast("void *", dogs)
352-
local ok, err, foricible = dogs:set("foo", 56)
352+
local ok, err, forcible = dogs:set("foo", 56)
353353
if not ok then
354354
ngx.say("failed to set: ", err)
355355
return
@@ -867,7 +867,7 @@ failed to get stale: nil key
867867
local val, flags
868868
local dogs = ngx.shared.dogs
869869
local value, err = dogs:incr(nil, 32)
870-
if not ok then
870+
if not value then
871871
ngx.say("failed to incr: ", err)
872872
end
873873
';
@@ -915,3 +915,87 @@ qr/\[TRACE \d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/
915915
-- NYI:
916916
stitch
917917
918+
919+
920+
=== TEST 28: incr, value is not number
921+
--- http_config eval: $::HttpConfig
922+
--- config
923+
location = /t {
924+
content_by_lua_block {
925+
local val, flags
926+
local dogs = ngx.shared.dogs
927+
local value, err = dogs:incr("foo", "bar")
928+
if not value then
929+
ngx.say("failed to incr: ", err)
930+
end
931+
}
932+
}
933+
--- request
934+
GET /t
935+
--- error_code: 500
936+
--- response_body_like: 500
937+
--- error_log
938+
cannot convert 'nil' to 'double'
939+
--- no_error_log
940+
[alert]
941+
[crit]
942+
943+
944+
945+
=== TEST 29: incr with init
946+
--- http_config eval: $::HttpConfig
947+
--- config
948+
location = /t {
949+
content_by_lua_block {
950+
local val, flags
951+
local dogs = ngx.shared.dogs
952+
dogs:flush_all()
953+
954+
local value, err = dogs:incr("foo", 10)
955+
if not value then
956+
ngx.say("failed to incr: ", err)
957+
end
958+
959+
local value, err, forcible = dogs:incr("foo", 10, 10)
960+
if not value then
961+
ngx.say("failed to incr: ", err)
962+
return
963+
end
964+
965+
ngx.say("incr ok, value: ", value, ", forcible: ", forcible)
966+
}
967+
}
968+
--- request
969+
GET /t
970+
--- response_body
971+
failed to incr: not found
972+
incr ok, value: 20, forcible: false
973+
--- no_error_log
974+
[error]
975+
[alert]
976+
[crit]
977+
978+
979+
980+
=== TEST 30: incr, init is not number
981+
--- http_config eval: $::HttpConfig
982+
--- config
983+
location = /t {
984+
content_by_lua_block {
985+
local val, flags
986+
local dogs = ngx.shared.dogs
987+
local value, err = dogs:incr("foo", 10, "bar")
988+
if not ok then
989+
ngx.say("failed to incr: ", err)
990+
end
991+
}
992+
}
993+
--- request
994+
GET /t
995+
--- error_code: 500
996+
--- response_body_like: 500
997+
--- error_log
998+
init should be a number
999+
--- no_error_log
1000+
[alert]
1001+
[crit]

0 commit comments

Comments
 (0)