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'