Skip to content

Commit 8bf3ebe

Browse files
committedOct 4, 2021
Add flags argument to shm:get(_stale)?
Add optional flags argument to shmdict_get(_stale)? that only returns value if flags do not match. And a 3rd (4th for _stale) return value to indicate if it is a flag match.
1 parent 250f31d commit 8bf3ebe

File tree

4 files changed

+342
-5
lines changed

4 files changed

+342
-5
lines changed
 

‎README.markdown

+5-2
Original file line numberDiff line numberDiff line change
@@ -6827,12 +6827,15 @@ This feature was first introduced in the `v0.3.1rc22` release.
68276827
ngx.shared.DICT.get
68286828
-------------------
68296829

6830-
**syntax:** *value, flags = ngx.shared.DICT:get(key)*
6830+
**syntax:** *value, flags, flags_match = ngx.shared.DICT:get(key, flags?)*
68316831

68326832
**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**
68336833

68346834
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.
68356835

6836+
If flags is not `nil`, value will only be returned if flags do not match with shm.
6837+
A 3rd return argument will indicate if flags matched.
6838+
68366839
In case of errors, `nil` and a string describing the error will be returned.
68376840

68386841
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).
68666869
ngx.shared.DICT.get_stale
68676870
-------------------------
68686871

6869-
**syntax:** *value, flags, stale = ngx.shared.DICT:get_stale(key)*
6872+
**syntax:** *value, flags, stale, flags_match = ngx.shared.DICT:get_stale(key, flags?)*
68706873

68716874
**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**
68726875

‎doc/HttpLuaModule.wiki

+5-2
Original file line numberDiff line numberDiff line change
@@ -5778,12 +5778,15 @@ This feature was first introduced in the <code>v0.3.1rc22</code> release.
57785778
57795779
== ngx.shared.DICT.get ==
57805780
5781-
'''syntax:''' ''value, flags = ngx.shared.DICT:get(key)''
5781+
'''syntax:''' ''value, flags, flags_match = ngx.shared.DICT:get(key, flags?)''
57825782
57835783
'''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*''
57845784
57855785
Retrieving the value in the dictionary [[#ngx.shared.DICT|ngx.shared.DICT]] for the key <code>key</code>. If the key does not exist or has expired, then <code>nil</code> will be returned.
57865786
5787+
If flags is not <code>nil</code>, value will only be returned if flags do not match with shm.
5788+
A 3rd return argument will indicate if flags matched.
5789+
57875790
In case of errors, <code>nil</code> and a string describing the error will be returned.
57885791
57895792
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]].
58125815
58135816
== ngx.shared.DICT.get_stale ==
58145817
5815-
'''syntax:''' ''value, flags, stale = ngx.shared.DICT:get_stale(key)''
5818+
'''syntax:''' ''value, flags, stale, flags_match = ngx.shared.DICT:get_stale(key, flags?)''
58165819
58175820
'''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*''
58185821

‎src/ngx_http_lua_shdict.c

+9-1
Original file line numberDiff line numberDiff line change
@@ -1573,7 +1573,7 @@ int
15731573
ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key,
15741574
size_t key_len, int *value_type, u_char **str_value_buf,
15751575
size_t *str_value_len, double *num_value, int *user_flags,
1576-
int get_stale, int *is_stale, char **err)
1576+
int *user_flags_neq, int get_stale, int *is_stale, char **err)
15771577
{
15781578
ngx_str_t name;
15791579
uint32_t hash;
@@ -1613,6 +1613,14 @@ ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key,
16131613
return NGX_OK;
16141614
}
16151615

1616+
if (*user_flags_neq && *user_flags == (int) sd->user_flags) {
1617+
*is_stale = (rc == NGX_DONE);
1618+
*user_flags_neq = 0;
1619+
ngx_shmtx_unlock(&ctx->shpool->mutex);
1620+
*value_type = LUA_TNIL;
1621+
return NGX_OK;
1622+
}
1623+
16161624
/* rc == NGX_OK || (rc == NGX_DONE && get_stale) */
16171625

16181626
*value_type = sd->value_type;

‎t/167-shdict-neq-flags.t

+323
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
# vim:set ft= ts=4 sw=4 et fdm=marker:
2+
use Test::Nginx::Socket::Lua 'no_plan';
3+
4+
run_tests();
5+
6+
__DATA__
7+
8+
=== TEST 1: flag eq
9+
--- http_config
10+
lua_shared_dict dogs 1m;
11+
--- config
12+
location /test {
13+
content_by_lua_block {
14+
local dogs = ngx.shared.dogs
15+
dogs:set("Bernese", 42, 0, 1)
16+
local val = dogs:get("Bernese", 1)
17+
ngx.say(val, " ", type(val))
18+
}
19+
}
20+
--- request
21+
GET /test
22+
--- response_body
23+
nil nil
24+
--- no_error_log
25+
[error]
26+
27+
28+
29+
=== TEST 2: fleq neq
30+
--- http_config
31+
lua_shared_dict dogs 1m;
32+
--- config
33+
location = /test {
34+
content_by_lua_block {
35+
local dogs = ngx.shared.dogs
36+
dogs:set("Bernese", 42, 0, 1)
37+
local val = dogs:get("Bernese", 2)
38+
ngx.say(val, " " , type(val))
39+
}
40+
}
41+
--- request
42+
GET /test
43+
--- response_body
44+
42 number
45+
--- no_error_log
46+
[error]
47+
48+
49+
50+
=== TEST 3: set with no flag
51+
--- http_config
52+
lua_shared_dict dogs 1m;
53+
--- config
54+
location = /test {
55+
content_by_lua_block {
56+
local dogs = ngx.shared.dogs
57+
dogs:set("Bernese", 42, 0)
58+
local val = dogs:get("Bernese", 2)
59+
ngx.say(val, " " , type(val))
60+
}
61+
}
62+
--- request
63+
GET /test
64+
--- response_body
65+
42 number
66+
--- no_error_log
67+
[error]
68+
69+
70+
71+
=== TEST 4: get with no flag
72+
--- http_config
73+
lua_shared_dict dogs 1m;
74+
--- config
75+
location = /test {
76+
content_by_lua_block {
77+
local dogs = ngx.shared.dogs
78+
dogs:set("Bernese", 42, 0, 1)
79+
local val = dogs:get("Bernese")
80+
ngx.say(val, " " , type(val))
81+
}
82+
}
83+
--- request
84+
GET /test
85+
--- response_body
86+
42 number
87+
--- no_error_log
88+
[error]
89+
90+
91+
92+
=== TEST 5: set and get with no flag
93+
--- http_config
94+
lua_shared_dict dogs 1m;
95+
--- config
96+
location = /test {
97+
content_by_lua_block {
98+
local dogs = ngx.shared.dogs
99+
dogs:set("Bernese", 42, 0)
100+
local val = dogs:get("Bernese")
101+
ngx.say(val, " " , type(val))
102+
}
103+
}
104+
--- request
105+
GET /test
106+
--- response_body
107+
42 number
108+
--- no_error_log
109+
[error]
110+
111+
112+
113+
=== TEST 6: set no flag, and read with 0 flag
114+
--- http_config
115+
lua_shared_dict dogs 1m;
116+
--- config
117+
location = /test {
118+
content_by_lua_block {
119+
local dogs = ngx.shared.dogs
120+
dogs:set("Bernese", 42)
121+
local val = dogs:get("Bernese", 0)
122+
ngx.say(val, " " , type(val))
123+
}
124+
}
125+
--- request
126+
GET /test
127+
--- response_body
128+
nil nil
129+
--- no_error_log
130+
[error]
131+
132+
133+
=== TEST 7: flags_match is true
134+
--- http_config
135+
lua_shared_dict dogs 1m;
136+
--- config
137+
location = /test {
138+
content_by_lua_block {
139+
local dogs = ngx.shared.dogs
140+
dogs:set("Bernese", 42, 0, 1)
141+
local val, err, flags_match = dogs:get("Bernese", 1)
142+
143+
ngx.say(val, " ", type(val), " : ",
144+
err, " ", type(err), " : ",
145+
flags_match, " ", type(flags_match))
146+
}
147+
}
148+
--- request
149+
GET /test
150+
--- response_body
151+
nil nil : nil nil : true boolean
152+
--- no_error_log
153+
[error]
154+
155+
156+
157+
=== TEST 8: flags_match is nil
158+
--- http_config
159+
lua_shared_dict dogs 1m;
160+
--- config
161+
location = /test {
162+
content_by_lua_block {
163+
local dogs = ngx.shared.dogs
164+
local val, err, flags_match = dogs:get("Bernese", 3)
165+
ngx.say(flags_match, " ", type(flags_match))
166+
}
167+
}
168+
--- request
169+
GET /test
170+
--- response_body
171+
nil nil
172+
--- no_error_log
173+
[error]
174+
175+
176+
177+
=== TEST 9: get when flag is not number
178+
--- http_config
179+
lua_shared_dict dogs 1m;
180+
--- config
181+
location = /test {
182+
content_by_lua_block {
183+
local dogs = ngx.shared.dogs
184+
dogs:set("Bernese", 42, 0, 1)
185+
local val = dogs:get("Bernese", {})
186+
}
187+
}
188+
--- request
189+
GET /test
190+
--- request_body_like: 500 Internal Server Error
191+
--- error_code: 500
192+
--- error_log
193+
cannot convert 'table' to 'int'
194+
195+
196+
=== TEST 10: flag eq stale
197+
--- http_config
198+
lua_shared_dict dogs 1m;
199+
--- config
200+
location /test {
201+
content_by_lua_block {
202+
local dogs = ngx.shared.dogs
203+
dogs:set("Bernese", 42, 0.01, 1)
204+
ngx.sleep(0.02)
205+
local val = dogs:get_stale("Bernese", 1)
206+
ngx.say(val, " ", type(val))
207+
}
208+
}
209+
--- request
210+
GET /test
211+
--- response_body
212+
nil nil
213+
--- no_error_log
214+
[error]
215+
216+
217+
218+
=== TEST 11: fleq neq stale
219+
--- http_config
220+
lua_shared_dict dogs 1m;
221+
--- config
222+
location = /test {
223+
content_by_lua_block {
224+
local dogs = ngx.shared.dogs
225+
dogs:set("Bernese", 42, 0.01, 1)
226+
ngx.sleep(0.02)
227+
local val = dogs:get_stale("Bernese", 2)
228+
ngx.say(val, " " , type(val))
229+
}
230+
}
231+
--- request
232+
GET /test
233+
--- response_body
234+
42 number
235+
--- no_error_log
236+
[error]
237+
238+
239+
240+
=== TEST 12: get_stale with no flag
241+
--- http_config
242+
lua_shared_dict dogs 1m;
243+
--- config
244+
location = /test {
245+
content_by_lua_block {
246+
local dogs = ngx.shared.dogs
247+
dogs:set("Bernese", 42, 0.01, 1)
248+
ngx.sleep(0.02)
249+
local val = dogs:get_stale("Bernese")
250+
ngx.say(val, " " , type(val))
251+
}
252+
}
253+
--- request
254+
GET /test
255+
--- response_body
256+
42 number
257+
--- no_error_log
258+
[error]
259+
260+
261+
262+
=== TEST 13: flags_match is true
263+
--- http_config
264+
lua_shared_dict dogs 1m;
265+
--- config
266+
location = /test {
267+
content_by_lua_block {
268+
local dogs = ngx.shared.dogs
269+
dogs:set("Bernese", 42, 0.01, 1)
270+
ngx.sleep(0.02)
271+
local val, err, stale, flags_match = dogs:get_stale("Bernese", 1)
272+
273+
ngx.say(val, " ", type(val), " : ",
274+
err, " ", type(err), " : ",
275+
flags_match, " ", type(flags_match))
276+
}
277+
}
278+
--- request
279+
GET /test
280+
--- response_body
281+
nil nil : nil nil : true boolean
282+
--- no_error_log
283+
[error]
284+
285+
286+
287+
=== TEST 14: flags_match is nil
288+
--- http_config
289+
lua_shared_dict dogs 1m;
290+
--- config
291+
location = /test {
292+
content_by_lua_block {
293+
local dogs = ngx.shared.dogs
294+
local val, err, stale, flags_match = dogs:get_stale("Bernese", 3)
295+
ngx.say(flags_match, " ", type(flags_match))
296+
}
297+
}
298+
--- request
299+
GET /test
300+
--- response_body
301+
nil nil
302+
--- no_error_log
303+
[error]
304+
305+
306+
307+
=== TEST 15: get when flag is not number
308+
--- http_config
309+
lua_shared_dict dogs 1m;
310+
--- config
311+
location = /test {
312+
content_by_lua_block {
313+
local dogs = ngx.shared.dogs
314+
dogs:set("Bernese", 42, 0, 1)
315+
local val = dogs:get_stale("Bernese", {})
316+
}
317+
}
318+
--- request
319+
GET /test
320+
--- request_body_like: 500 Internal Server Error
321+
--- error_code: 500
322+
--- error_log
323+
cannot convert 'table' to 'int'

0 commit comments

Comments
 (0)