Skip to content

Commit 8780ceb

Browse files
committed
Added atomic type opperations to shmdict
- Added cas(compare and swap) to shdict - Added cog(compare or get) to shdict
1 parent a9f85fd commit 8780ceb

File tree

1 file changed

+256
-2
lines changed

1 file changed

+256
-2
lines changed

lib/resty/core/shdict.lua

Lines changed: 256 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ local ngx_lua_ffi_shdict_set_expire
4040
local ngx_lua_ffi_shdict_capacity
4141
local ngx_lua_ffi_shdict_free_space
4242
local ngx_lua_ffi_shdict_udata_to_zone
43-
43+
local ngx_lua_ffi_shdict_cas
44+
local ngx_lua_ffi_shdict_cog
4445

4546
if subsystem == 'http' then
4647
ffi.cdef[[
@@ -70,6 +71,20 @@ int ngx_http_lua_ffi_shdict_set_expire(void *zone,
7071
size_t ngx_http_lua_ffi_shdict_capacity(void *zone);
7172

7273
void *ngx_http_lua_ffi_shdict_udata_to_zone(void *zone_udata);
74+
75+
int ngx_http_lua_ffi_shdict_cas(void *zone, const unsigned char *key,
76+
size_t key_len, int old_value_type, const unsigned char *old_str_value_buf,
77+
size_t old_str_value_len, double old_num_value, int old_user_flags,
78+
int value_type, const unsigned char *str_value_buf, size_t str_value_len,
79+
double num_value, int user_flags, long exptime,int match_flags,
80+
int *match, char **errmsg, int *forcible);
81+
int
82+
ngx_http_lua_ffi_shdict_cog(void *zone,
83+
const unsigned char *key, size_t key_len, int old_value_type,
84+
const unsigned char *old_str_value_buf, size_t old_str_value_len,
85+
double old_num_value, int old_user_flags, int *value_type,
86+
unsigned char **str_value_buf, size_t *str_value_len, double *num_value,
87+
int *user_flags, int match_flags, int *match, char **errmsg);
7388
]]
7489

7590
ngx_lua_ffi_shdict_get = C.ngx_http_lua_ffi_shdict_get
@@ -81,7 +96,8 @@ void *ngx_http_lua_ffi_shdict_udata_to_zone(void *zone_udata);
8196
ngx_lua_ffi_shdict_capacity = C.ngx_http_lua_ffi_shdict_capacity
8297
ngx_lua_ffi_shdict_udata_to_zone =
8398
C.ngx_http_lua_ffi_shdict_udata_to_zone
84-
99+
ngx_lua_ffi_shdict_cas = C.ngx_http_lua_ffi_shdict_cas
100+
ngx_lua_ffi_shdict_cog = C.ngx_http_lua_ffi_shdict_cog
85101
if not pcall(function ()
86102
return C.ngx_http_lua_ffi_shdict_free_space
87103
end)
@@ -124,6 +140,20 @@ int ngx_stream_lua_ffi_shdict_set_expire(void *zone,
124140
size_t ngx_stream_lua_ffi_shdict_capacity(void *zone);
125141

126142
void *ngx_stream_lua_ffi_shdict_udata_to_zone(void *zone_udata);
143+
144+
int ngx_stream_lua_ffi_shdict_cas(void *zone, const unsigned char *key,
145+
size_t key_len, int old_value_type, const unsigned char *old_str_value_buf,
146+
size_t old_str_value_len, double old_num_value, int old_user_flags,
147+
int value_type, const unsigned char *str_value_buf, size_t str_value_len,
148+
double num_value, int user_flags, long exptime,int match_flags,
149+
int *match, char **errmsg, int *forcible);
150+
int
151+
ngx_stream_lua_ffi_shdict_cog(void *zone,
152+
const unsigned char *key, size_t key_len, int old_value_type,
153+
const unsigned char *old_str_value_buf, size_t old_str_value_len,
154+
double old_num_value, int old_user_flags, int *value_type,
155+
unsigned char **str_value_buf, size_t *str_value_len, double *num_value,
156+
int *user_flags, int match_flags, int *match, char **errmsg);
127157
]]
128158

129159
ngx_lua_ffi_shdict_get = C.ngx_stream_lua_ffi_shdict_get
@@ -135,6 +165,8 @@ void *ngx_stream_lua_ffi_shdict_udata_to_zone(void *zone_udata);
135165
ngx_lua_ffi_shdict_capacity = C.ngx_stream_lua_ffi_shdict_capacity
136166
ngx_lua_ffi_shdict_udata_to_zone =
137167
C.ngx_stream_lua_ffi_shdict_udata_to_zone
168+
ngx_lua_ffi_shdict_cas = C.ngx_stream_lua_ffi_shdict_cas
169+
ngx_lua_ffi_shdict_cog = C.ngx_stream_lua_ffi_shdict_cog
138170

139171
if not pcall(function ()
140172
return C.ngx_stream_lua_ffi_shdict_free_space
@@ -164,6 +196,7 @@ local value_type = ffi_new("int[1]")
164196
local user_flags = ffi_new("int[1]")
165197
local num_value = ffi_new("double[1]")
166198
local is_stale = ffi_new("int[1]")
199+
local match = ffi_new("int[1]")
167200
local forcible = ffi_new("int[1]")
168201
local str_value_buf = ffi_new("unsigned char *[1]")
169202
local errmsg = base.get_errmsg_ptr()
@@ -291,6 +324,225 @@ local function shdict_delete(zone, key)
291324
return shdict_set(zone, key, nil)
292325
end
293326

327+
local function shdict_cas(zone, key, old_value, old_flags,
328+
value, flags, exptime)
329+
zone = check_zone(zone)
330+
331+
if not exptime then
332+
exptime = 0
333+
elseif exptime < 0 then
334+
error('bad "exptime" argument',2)
335+
end
336+
337+
if key == nil then
338+
return nil, "nil key"
339+
end
340+
341+
if type(key) ~= "string" then
342+
key = tostring(key)
343+
end
344+
345+
local key_len = #key
346+
if key_len == 0 then
347+
return nil, "empty key"
348+
end
349+
if key_len > 65535 then
350+
return nil, "key to long"
351+
end
352+
353+
if not flags then
354+
flags = 0
355+
end
356+
357+
local match_flags = 1
358+
if not old_flags then
359+
old_flags = 0
360+
match_flags = 0
361+
end
362+
363+
local str_val_buf
364+
local str_val_len = 0
365+
local num_val = 0
366+
local valtyp = type(value)
367+
368+
if valtyp == "string" then
369+
valtyp = 4 -- LUA_TSTRING
370+
str_val_buf = value
371+
str_val_len = #value
372+
373+
elseif valtyp == "number" then
374+
valtyp = 3 -- LUA_TNUMBER
375+
num_val = value
376+
377+
elseif value == nil then
378+
valtyp = 0 -- LUA_TNIL
379+
380+
elseif valtyp == "boolean" then
381+
valtyp = 1 -- LUA_TBOOLEAN
382+
num_val = value and 1 or 0
383+
384+
else
385+
return nil, "bad value type"
386+
end
387+
388+
local old_str_val_buf
389+
local old_str_val_len = 0
390+
local old_num_val = 0
391+
local old_valtyp = type(old_value)
392+
393+
if old_valtyp == "string" then
394+
old_valtyp = 4 -- LUA_TSTRING
395+
old_str_val_buf = old_value
396+
old_str_val_len = #old_value
397+
398+
elseif old_valtyp == "number" then
399+
old_valtyp = 3 -- LUA_TNUMBER
400+
old_num_val = old_value
401+
402+
elseif old_value == nil then
403+
old_valtyp = 0 -- LUA_TNIL
404+
405+
elseif old_valtyp == "boolean" then
406+
old_valtyp = 1 -- LUA_TBOOLEAN
407+
old_num_val = old_value and 1 or 0
408+
409+
else
410+
return nil, "bad old_value type"
411+
end
412+
local rc = ngx_lua_ffi_shdict_cas(zone, key, key_len,
413+
old_valtyp, old_str_val_buf,
414+
old_str_val_len, old_num_val,
415+
old_flags,
416+
valtyp, str_val_buf,
417+
str_val_len, num_val, flags,
418+
exptime * 1000,
419+
match_flags, match,
420+
errmsg, forcible)
421+
if rc == 0 then -- NGX_OK
422+
return true, nil, forcible[0] == 1
423+
end
424+
425+
-- NGX_DECLINED or NGX_ERROR
426+
if match[0] == 1 then
427+
return false, false, forcible[0] == 1
428+
end
429+
if errmsg[0] ~= nil then
430+
return false, ffi_str(errmsg[0]), forcible[0] == 1
431+
end
432+
error("errmsg not specified")
433+
434+
end
435+
local function shdict_cog(zone, key, old_value, old_flags)
436+
zone = check_zone(zone)
437+
438+
if key == nil then
439+
return nil, "nil key"
440+
end
441+
442+
if type(key) ~= "string" then
443+
key = tostring(key)
444+
end
445+
446+
local match_flags = 1
447+
if not old_flags then
448+
old_flags = 0
449+
match_flags = 0
450+
end
451+
452+
local key_len = #key
453+
if key_len == 0 then
454+
return nil, "empty key"
455+
end
456+
if key_len > 65535 then
457+
return nil, "key too long"
458+
end
459+
460+
local old_str_val_buf
461+
local old_str_val_len = 0
462+
local old_num_val = 0
463+
local old_valtyp = type(old_value)
464+
465+
if old_valtyp == "string" then
466+
old_valtyp = 4 -- LUA_TSTRING
467+
old_str_val_buf = old_value
468+
old_str_val_len = #old_value
469+
470+
elseif old_valtyp == "number" then
471+
old_valtyp = 3 -- LUA_TNUMBER
472+
old_num_val = old_value
473+
474+
elseif old_value == nil then
475+
old_valtyp = 0 -- LUA_TNIL
476+
477+
elseif old_valtyp == "boolean" then
478+
old_valtyp = 1 -- LUA_TBOOLEAN
479+
old_num_val = old_value and 1 or 0
480+
481+
else
482+
return nil, "bad old_value type"
483+
end
484+
485+
local size = get_string_buf_size()
486+
local buf = get_string_buf(size)
487+
str_value_buf[0] = buf
488+
local value_len = get_size_ptr()
489+
value_len[0] = size
490+
491+
local rc = ngx_lua_ffi_shdict_cog(zone, key, key_len,
492+
old_valtyp, old_str_val_buf,
493+
old_str_val_len,
494+
old_num_val, old_flags,
495+
value_type,
496+
str_value_buf, value_len,
497+
num_value, user_flags,
498+
match_flags, match, errmsg)
499+
if rc ~= 0 then
500+
if match[0] == 1 then
501+
return nil, false
502+
elseif errmsg[0] ~= nil then
503+
return nil, ffi_str(errmsg[0])
504+
end
505+
506+
error("failed to get the key")
507+
end
508+
509+
local typ = value_type[0]
510+
511+
if typ == 0 then -- LUA_TNIL
512+
return nil
513+
end
514+
515+
local flags = tonumber(user_flags[0])
516+
517+
local val
518+
519+
if typ == 4 then -- LUA_TSTRING
520+
if str_value_buf[0] ~= buf then
521+
-- ngx.say("len: ", tonumber(value_len[0]))
522+
buf = str_value_buf[0]
523+
val = ffi_str(buf, value_len[0])
524+
C.free(buf)
525+
else
526+
val = ffi_str(buf, value_len[0])
527+
end
528+
529+
elseif typ == 3 then -- LUA_TNUMBER
530+
val = tonumber(num_value[0])
531+
532+
elseif typ == 1 then -- LUA_TBOOLEAN
533+
val = (tonumber(buf[0]) ~= 0)
534+
535+
else
536+
error("unknown value type: " .. typ)
537+
end
538+
539+
if flags ~= 0 then
540+
return val, flags
541+
end
542+
543+
return val
544+
end
545+
294546

295547
local function shdict_get(zone, key)
296548
zone = check_zone(zone)
@@ -630,6 +882,8 @@ if dict then
630882
mt.expire = shdict_expire
631883
mt.capacity = shdict_capacity
632884
mt.free_space = shdict_free_space
885+
mt.cas = shdict_cas
886+
mt.cog = shdict_cog
633887
end
634888
end
635889
end

0 commit comments

Comments
 (0)