Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add shdict set_when and safe_set_when #268

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ API Implemented
* [ngx.shared.DICT.incr](https://github.com/openresty/lua-nginx-module#ngxshareddictincr)
* [ngx.shared.DICT.set](https://github.com/openresty/lua-nginx-module#ngxshareddictset)
* [ngx.shared.DICT.safe_set](https://github.com/openresty/lua-nginx-module#ngxshareddictsafe_set)
* [ngx.shared.DICT.set_when](https://github.com/openresty/lua-nginx-module#ngxshareddictset_when)
* [ngx.shared.DICT.safe_set_when](https://github.com/openresty/lua-nginx-module#ngxshareddictsafe_set_when)
* [ngx.shared.DICT.add](https://github.com/openresty/lua-nginx-module#ngxshareddictadd)
* [ngx.shared.DICT.safe_add](https://github.com/openresty/lua-nginx-module#ngxshareddictsafe_add)
* [ngx.shared.DICT.replace](https://github.com/openresty/lua-nginx-module#ngxshareddictreplace)
Expand Down
136 changes: 136 additions & 0 deletions lib/resty/core/shdict.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ local subsystem = ngx.config.subsystem
local ngx_lua_ffi_shdict_get
local ngx_lua_ffi_shdict_incr
local ngx_lua_ffi_shdict_store
local ngx_lua_ffi_shdict_store_when
local ngx_lua_ffi_shdict_flush_all
local ngx_lua_ffi_shdict_get_ttl
local ngx_lua_ffi_shdict_set_expire
Expand All @@ -59,6 +60,14 @@ int ngx_http_lua_ffi_shdict_store(void *zone, int op,
double num_value, long exptime, int user_flags, char **errmsg,
int *forcible);

int ngx_http_lua_ffi_shdict_store_when(void *zone, int op,
const unsigned char *key, size_t key_len, int old_value_type,
const unsigned char *old_str_value_buf, size_t old_str_value_len,
double old_num_value, int value_type,
const unsigned char *str_value_buf, size_t str_value_len,
double num_value, long exptime, int user_flags, char **errmsg,
int *forcible);

int ngx_http_lua_ffi_shdict_flush_all(void *zone);

long ngx_http_lua_ffi_shdict_get_ttl(void *zone,
Expand All @@ -75,6 +84,7 @@ void *ngx_http_lua_ffi_shdict_udata_to_zone(void *zone_udata);
ngx_lua_ffi_shdict_get = C.ngx_http_lua_ffi_shdict_get
ngx_lua_ffi_shdict_incr = C.ngx_http_lua_ffi_shdict_incr
ngx_lua_ffi_shdict_store = C.ngx_http_lua_ffi_shdict_store
ngx_lua_ffi_shdict_store_when = C.ngx_http_lua_ffi_shdict_store_when
ngx_lua_ffi_shdict_flush_all = C.ngx_http_lua_ffi_shdict_flush_all
ngx_lua_ffi_shdict_get_ttl = C.ngx_http_lua_ffi_shdict_get_ttl
ngx_lua_ffi_shdict_set_expire = C.ngx_http_lua_ffi_shdict_set_expire
Expand Down Expand Up @@ -113,6 +123,14 @@ int ngx_stream_lua_ffi_shdict_store(void *zone, int op,
double num_value, long exptime, int user_flags, char **errmsg,
int *forcible);

int ngx_stream_lua_ffi_shdict_store_when(void *zone, int op,
const unsigned char *key, size_t key_len, int old_value_type,
const unsigned char *old_str_value_buf, size_t old_str_value_len,
double old_num_value, int value_type,
const unsigned char *str_value_buf, size_t str_value_len,
double num_value, long exptime, int user_flags, char **errmsg,
int *forcible);

int ngx_stream_lua_ffi_shdict_flush_all(void *zone);

long ngx_stream_lua_ffi_shdict_get_ttl(void *zone,
Expand All @@ -129,6 +147,7 @@ void *ngx_stream_lua_ffi_shdict_udata_to_zone(void *zone_udata);
ngx_lua_ffi_shdict_get = C.ngx_stream_lua_ffi_shdict_get
ngx_lua_ffi_shdict_incr = C.ngx_stream_lua_ffi_shdict_incr
ngx_lua_ffi_shdict_store = C.ngx_stream_lua_ffi_shdict_store
ngx_lua_ffi_shdict_store_when = C.ngx_stream_lua_ffi_shdict_store_when
ngx_lua_ffi_shdict_flush_all = C.ngx_stream_lua_ffi_shdict_flush_all
ngx_lua_ffi_shdict_get_ttl = C.ngx_stream_lua_ffi_shdict_get_ttl
ngx_lua_ffi_shdict_set_expire = C.ngx_stream_lua_ffi_shdict_set_expire
Expand Down Expand Up @@ -262,16 +281,131 @@ local function shdict_store(zone, op, key, value, exptime, flags)
end


local function shdict_store_when(zone, op, key, old_value, value, exptime,
flags)
zone = check_zone(zone)

if not exptime then
exptime = 0
elseif exptime < 0 then
error('bad "exptime" argument', 2)
end

if not flags then
flags = 0
end

if key == nil then
return nil, "nil key"
end

if type(key) ~= "string" then
key = tostring(key)
end

local key_len = #key
if key_len == 0 then
return nil, "empty key"
end
if key_len > 65535 then
return nil, "key too long"
end

local old_str_val_buf
local old_str_val_len = 0
local old_num_val = 0
local old_valtyp = type(old_value)

-- print("value type: ", old_valtyp)

if old_valtyp == "string" then
old_valtyp = 4 -- LUA_TSTRING
old_str_val_buf = old_value
old_str_val_len = #old_value

elseif old_valtyp == "number" then
old_valtyp = 3 -- LUA_TNUMBER
old_num_val = old_value

elseif old_value == nil then
old_valtyp = 0 -- LUA_TNIL

elseif old_valtyp == "boolean" then
old_valtyp = 1 -- LUA_TBOOLEAN
old_num_val = old_value and 1 or 0

else
return nil, "bad old value type"
end

local str_val_buf
local str_val_len = 0
local num_val = 0
local valtyp = type(value)

-- print("value type: ", valtyp)
-- print("exptime: ", exptime)

if valtyp == "string" then
valtyp = 4 -- LUA_TSTRING
str_val_buf = value
str_val_len = #value

elseif valtyp == "number" then
valtyp = 3 -- LUA_TNUMBER
num_val = value

elseif value == nil then
valtyp = 0 -- LUA_TNIL

elseif valtyp == "boolean" then
valtyp = 1 -- LUA_TBOOLEAN
num_val = value and 1 or 0

else
return nil, "bad value type"
end

local rc = ngx_lua_ffi_shdict_store_when(zone, op, key, key_len,
old_valtyp, old_str_val_buf,
old_str_val_len, old_num_val,
valtyp, str_val_buf,
str_val_len, num_val,
exptime * 1000, flags, errmsg,
forcible)

-- print("rc == ", rc)

if rc == 0 then -- NGX_OK
return true, nil, forcible[0] == 1
end

-- NGX_DECLINED or NGX_ERROR
return false, ffi_str(errmsg[0]), forcible[0] == 1
end


local function shdict_set(zone, key, value, exptime, flags)
return shdict_store(zone, 0, key, value, exptime, flags)
end


local function shdict_set_when(zone, key, old_value, value, exptime, flags)
return shdict_store_when(zone, 0, key, old_value, value, exptime, flags)
end


local function shdict_safe_set(zone, key, value, exptime, flags)
return shdict_store(zone, 0x0004, key, value, exptime, flags)
end


local function shdict_safe_set_when(zone, key, old_value, value, exptime, flags)
return shdict_store_when(zone, 0x0004, key, old_value, value, exptime,
flags)
end


local function shdict_add(zone, key, value, exptime, flags)
return shdict_store(zone, 0x0001, key, value, exptime, flags)
end
Expand Down Expand Up @@ -621,6 +755,8 @@ if dict then
mt.incr = shdict_incr
mt.set = shdict_set
mt.safe_set = shdict_safe_set
mt.set_when = shdict_set_when
mt.safe_set_when = shdict_safe_set_when
mt.add = shdict_add
mt.safe_add = shdict_safe_add
mt.replace = shdict_replace
Expand Down
139 changes: 139 additions & 0 deletions t/shdict-set-when.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;

#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');

#repeat_each(2);

plan tests => repeat_each() * (blocks() * 3);

#no_diff();
no_long_string();
#master_on();
#workers(2);

run_tests();

__DATA__

=== TEST 1: set_when success
--- http_config
lua_shared_dict dogs 1m;
--- config
location = /test {
content_by_lua '
local dogs = ngx.shared.dogs
dogs:set("foo", 32)
dogs:set_when("foo", 32, 33)
local val = dogs:get("foo")
ngx.say(val, " ", type(val))
';
}
--- request
GET /test
--- response_body
33 number
--- no_error_log
[error]



=== TEST 2: set_when fail
--- http_config
lua_shared_dict dogs 1m;
--- config
location = /test {
content_by_lua '
local dogs = ngx.shared.dogs
dogs:set("foo", 32)
local ok, err, forcible = dogs:set_when("foo", 32, 33)
ngx.say(ok, " ", err, " ", forcible)
local ok, err, forcible = dogs:set_when("foo", 32, 34)
ngx.say(ok, " ", err, " ", forcible)
local val = dogs:get("foo")
ngx.say(val, " ", type(val))
';
}
--- request
GET /test
--- response_body
true nil false
false already modified false
33 number
--- no_error_log
[error]



=== TEST 3: set_when success for expired value
--- http_config
lua_shared_dict dogs 1m;
--- config
location = /test {
content_by_lua '
local dogs = ngx.shared.dogs
dogs:set("foo", 32, 0.01)
ngx.sleep(0.02)
local ok, err, forcible = dogs:set_when("foo", 32, 33)
ngx.say(ok, " ", err, " ", forcible)
local val = dogs:get("foo")
ngx.say(val, " ", type(val))
';
}
--- request
GET /test
--- response_body
true nil false
33 number
--- no_error_log
[error]



=== TEST 4: set_when success for unmatched expired value
--- http_config
lua_shared_dict dogs 1m;
--- config
location = /test {
content_by_lua '
local dogs = ngx.shared.dogs
dogs:set("foo", 32, 0.01)
ngx.sleep(0.02)
local ok, err, forcible = dogs:set_when("foo", 31, 33)
ngx.say(ok, " ", err, " ", forcible)
local val = dogs:get("foo")
ngx.say(val, " ", type(val))
';
}
--- request
GET /test
--- response_body
true nil false
33 number
--- no_error_log
[error]



=== TEST 5: set_when success when old_value did not exist
--- http_config
lua_shared_dict dogs 1m;
--- config
location = /test {
content_by_lua '
local dogs = ngx.shared.dogs
local ok, err, forcible = dogs:set_when("foo", 32, 33)
ngx.say(ok, " ", err, " ", forcible)
local val = dogs:get("foo")
ngx.say(val, " ", type(val))
';
}
--- request
GET /test
--- response_body
true nil false
33 number
--- no_error_log
[error]
Loading