diff --git a/.travis.yml b/.travis.yml index b4082f30a2..08dd91c622 100644 --- a/.travis.yml +++ b/.travis.yml @@ -85,11 +85,11 @@ install: - git clone https://github.com/openresty/rds-json-nginx-module.git ../rds-json-nginx-module - git clone https://github.com/openresty/srcache-nginx-module.git ../srcache-nginx-module - git clone https://github.com/openresty/redis2-nginx-module.git ../redis2-nginx-module - - git clone https://github.com/openresty/lua-resty-core.git ../lua-resty-core + - git clone https://github.com/webcore-no/lua-resty-core.git ../lua-resty-core - git clone https://github.com/openresty/lua-resty-lrucache.git ../lua-resty-lrucache - git clone https://github.com/openresty/lua-resty-mysql.git ../lua-resty-mysql - git clone https://github.com/openresty/lua-resty-string.git ../lua-resty-string - - git clone https://github.com/openresty/stream-lua-nginx-module.git ../stream-lua-nginx-module + - git clone https://github.com/webcore-no/stream-lua-nginx-module.git ../stream-lua-nginx-module - git clone -b v2.1-agentzh https://github.com/openresty/luajit2.git luajit2 before_script: diff --git a/README.markdown b/README.markdown index 28717882b7..bdc7d1204a 100644 --- a/README.markdown +++ b/README.markdown @@ -6827,12 +6827,15 @@ This feature was first introduced in the `v0.3.1rc22` release. ngx.shared.DICT.get ------------------- -**syntax:** *value, flags = ngx.shared.DICT:get(key)* +**syntax:** *value, flags, flags_match = ngx.shared.DICT:get(key, flags?)* **context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*, ssl_client_hello_by_lua** Retrieving the value in the dictionary [ngx.shared.DICT](#ngxshareddict) for the key `key`. If the key does not exist or has expired, then `nil` will be returned. +If flags is not `nil`, value will only be returned if flags do not match with shm. +A 3rd return argument will indicate if flags matched. + In case of errors, `nil` and a string describing the error will be returned. The value returned will have the original data type when they were inserted into the dictionary, for example, Lua booleans, numbers, or strings. @@ -6866,7 +6869,7 @@ See also [ngx.shared.DICT](#ngxshareddict). ngx.shared.DICT.get_stale ------------------------- -**syntax:** *value, flags, stale = ngx.shared.DICT:get_stale(key)* +**syntax:** *value, flags, stale, flags_match = ngx.shared.DICT:get_stale(key, flags?)* **context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*, ssl_client_hello_by_lua** diff --git a/doc/HttpLuaModule.wiki b/doc/HttpLuaModule.wiki index 2a647e879e..0ef7088373 100644 --- a/doc/HttpLuaModule.wiki +++ b/doc/HttpLuaModule.wiki @@ -5778,12 +5778,15 @@ This feature was first introduced in the v0.3.1rc22 release. == ngx.shared.DICT.get == -'''syntax:''' ''value, flags = ngx.shared.DICT:get(key)'' +'''syntax:''' ''value, flags, flags_match = ngx.shared.DICT:get(key, flags?)'' '''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*, ssl_client_hello_by_lua*'' Retrieving the value in the dictionary [[#ngx.shared.DICT|ngx.shared.DICT]] for the key key. If the key does not exist or has expired, then nil will be returned. +If flags is not nil, value will only be returned if flags do not match with shm. +A 3rd return argument will indicate if flags matched. + In case of errors, nil and a string describing the error will be returned. The value returned will have the original data type when they were inserted into the dictionary, for example, Lua booleans, numbers, or strings. @@ -5812,7 +5815,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.get_stale == -'''syntax:''' ''value, flags, stale = ngx.shared.DICT:get_stale(key)'' +'''syntax:''' ''value, flags, stale, flags_match = ngx.shared.DICT:get_stale(key, flags?)'' '''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*, ssl_client_hello_by_lua*'' diff --git a/src/ngx_http_lua_shdict.c b/src/ngx_http_lua_shdict.c index 8421ac1714..3ba2445b24 100644 --- a/src/ngx_http_lua_shdict.c +++ b/src/ngx_http_lua_shdict.c @@ -1573,7 +1573,7 @@ int ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key, size_t key_len, int *value_type, u_char **str_value_buf, size_t *str_value_len, double *num_value, int *user_flags, - int get_stale, int *is_stale, char **err) + int *user_flags_neq, int get_stale, int *is_stale, char **err) { ngx_str_t name; uint32_t hash; @@ -1613,6 +1613,14 @@ ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key, return NGX_OK; } + if (*user_flags_neq && *user_flags == (int) sd->user_flags) { + *is_stale = (rc == NGX_DONE); + *user_flags_neq = 0; + ngx_shmtx_unlock(&ctx->shpool->mutex); + *value_type = LUA_TNIL; + return NGX_OK; + } + /* rc == NGX_OK || (rc == NGX_DONE && get_stale) */ *value_type = sd->value_type; diff --git a/t/167-shdict-neq-flags.t b/t/167-shdict-neq-flags.t new file mode 100644 index 0000000000..be7bd6e623 --- /dev/null +++ b/t/167-shdict-neq-flags.t @@ -0,0 +1,323 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: +use Test::Nginx::Socket::Lua 'no_plan'; + +run_tests(); + +__DATA__ + +=== TEST 1: flag eq +--- http_config + lua_shared_dict dogs 1m; +--- config + location /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42, 0, 1) + local val = dogs:get("Bernese", 1) + ngx.say(val, " ", type(val)) + } + } +--- request +GET /test +--- response_body +nil nil +--- no_error_log +[error] + + + +=== TEST 2: fleq neq +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42, 0, 1) + local val = dogs:get("Bernese", 2) + ngx.say(val, " " , type(val)) + } + } +--- request +GET /test +--- response_body +42 number +--- no_error_log +[error] + + + +=== TEST 3: set with no flag +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42, 0) + local val = dogs:get("Bernese", 2) + ngx.say(val, " " , type(val)) + } + } +--- request +GET /test +--- response_body +42 number +--- no_error_log +[error] + + + +=== TEST 4: get with no flag +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42, 0, 1) + local val = dogs:get("Bernese") + ngx.say(val, " " , type(val)) + } + } +--- request +GET /test +--- response_body +42 number +--- no_error_log +[error] + + + +=== TEST 5: set and get with no flag +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42, 0) + local val = dogs:get("Bernese") + ngx.say(val, " " , type(val)) + } + } +--- request +GET /test +--- response_body +42 number +--- no_error_log +[error] + + + +=== TEST 6: set no flag, and read with 0 flag +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42) + local val = dogs:get("Bernese", 0) + ngx.say(val, " " , type(val)) + } + } +--- request +GET /test +--- response_body +nil nil +--- no_error_log +[error] + + +=== TEST 7: flags_match is true +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42, 0, 1) + local val, err, flags_match = dogs:get("Bernese", 1) + + ngx.say(val, " ", type(val), " : ", + err, " ", type(err), " : ", + flags_match, " ", type(flags_match)) + } + } +--- request +GET /test +--- response_body +nil nil : nil nil : true boolean +--- no_error_log +[error] + + + +=== TEST 8: flags_match is nil +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + local val, err, flags_match = dogs:get("Bernese", 3) + ngx.say(flags_match, " ", type(flags_match)) + } + } +--- request +GET /test +--- response_body +nil nil +--- no_error_log +[error] + + + +=== TEST 9: get when flag is not number +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42, 0, 1) + local val = dogs:get("Bernese", {}) + } + } +--- request +GET /test +--- request_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log +cannot convert 'table' to 'int' + + +=== TEST 10: flag eq stale +--- http_config + lua_shared_dict dogs 1m; +--- config + location /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42, 0.01, 1) + ngx.sleep(0.02) + local val = dogs:get_stale("Bernese", 1) + ngx.say(val, " ", type(val)) + } + } +--- request +GET /test +--- response_body +nil nil +--- no_error_log +[error] + + + +=== TEST 11: fleq neq stale +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42, 0.01, 1) + ngx.sleep(0.02) + local val = dogs:get_stale("Bernese", 2) + ngx.say(val, " " , type(val)) + } + } +--- request +GET /test +--- response_body +42 number +--- no_error_log +[error] + + + +=== TEST 12: get_stale with no flag +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42, 0.01, 1) + ngx.sleep(0.02) + local val = dogs:get_stale("Bernese") + ngx.say(val, " " , type(val)) + } + } +--- request +GET /test +--- response_body +42 number +--- no_error_log +[error] + + + +=== TEST 13: flags_match is true +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42, 0.01, 1) + ngx.sleep(0.02) + local val, err, stale, flags_match = dogs:get_stale("Bernese", 1) + + ngx.say(val, " ", type(val), " : ", + err, " ", type(err), " : ", + flags_match, " ", type(flags_match)) + } + } +--- request +GET /test +--- response_body +nil nil : nil nil : true boolean +--- no_error_log +[error] + + + +=== TEST 14: flags_match is nil +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + local val, err, stale, flags_match = dogs:get_stale("Bernese", 3) + ngx.say(flags_match, " ", type(flags_match)) + } + } +--- request +GET /test +--- response_body +nil nil +--- no_error_log +[error] + + + +=== TEST 15: get when flag is not number +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("Bernese", 42, 0, 1) + local val = dogs:get_stale("Bernese", {}) + } + } +--- request +GET /test +--- request_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log +cannot convert 'table' to 'int'