@@ -40,7 +40,8 @@ local ngx_lua_ffi_shdict_set_expire
4040local ngx_lua_ffi_shdict_capacity
4141local ngx_lua_ffi_shdict_free_space
4242local ngx_lua_ffi_shdict_udata_to_zone
43-
43+ local ngx_lua_ffi_shdict_cas
44+ local ngx_lua_ffi_shdict_cog
4445
4546if subsystem == ' http' then
4647 ffi .cdef [[
@@ -70,6 +71,20 @@ int ngx_http_lua_ffi_shdict_set_expire(void *zone,
7071size_t ngx_http_lua_ffi_shdict_capacity (void * zone );
7172
7273void *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 , int set_user_flags ,
80+ long exptime , int match_flags , 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,
124140size_t ngx_stream_lua_ffi_shdict_capacity (void * zone );
125141
126142void *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 , int set_user_flags ,
149+ long exptime , int match_flags , 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]")
164196local user_flags = ffi_new (" int[1]" )
165197local num_value = ffi_new (" double[1]" )
166198local is_stale = ffi_new (" int[1]" )
199+ local match = ffi_new (" int[1]" )
167200local forcible = ffi_new (" int[1]" )
168201local str_value_buf = ffi_new (" unsigned char *[1]" )
169202local errmsg = base .get_errmsg_ptr ()
@@ -291,6 +324,228 @@ local function shdict_delete(zone, key)
291324 return shdict_set (zone , key , nil )
292325end
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+ local set_user_flags = 1
354+ if not flags then
355+ set_user_flags = 0
356+ flags = 0
357+ end
358+
359+ local match_flags = 1
360+ if not old_flags then
361+ old_flags = 0
362+ match_flags = 0
363+ end
364+
365+ local str_val_buf
366+ local str_val_len = 0
367+ local num_val = 0
368+ local valtyp = type (value )
369+
370+ if valtyp == " string" then
371+ valtyp = 4 -- LUA_TSTRING
372+ str_val_buf = value
373+ str_val_len = # value
374+
375+ elseif valtyp == " number" then
376+ valtyp = 3 -- LUA_TNUMBER
377+ num_val = value
378+
379+ elseif value == nil then
380+ valtyp = 0 -- LUA_TNIL
381+
382+ elseif valtyp == " boolean" then
383+ valtyp = 1 -- LUA_TBOOLEAN
384+ num_val = value and 1 or 0
385+
386+ else
387+ return nil , " bad value type"
388+ end
389+
390+ local old_str_val_buf
391+ local old_str_val_len = 0
392+ local old_num_val = 0
393+ local old_valtyp = type (old_value )
394+
395+ if old_valtyp == " string" then
396+ old_valtyp = 4 -- LUA_TSTRING
397+ old_str_val_buf = old_value
398+ old_str_val_len = # old_value
399+
400+ elseif old_valtyp == " number" then
401+ old_valtyp = 3 -- LUA_TNUMBER
402+ old_num_val = old_value
403+
404+ elseif old_value == nil then
405+ old_valtyp = 0 -- LUA_TNIL
406+
407+ elseif old_valtyp == " boolean" then
408+ old_valtyp = 1 -- LUA_TBOOLEAN
409+ old_num_val = old_value and 1 or 0
410+
411+ else
412+ return nil , " bad old_value type"
413+ end
414+ local rc = ngx_lua_ffi_shdict_cas (zone , key , key_len ,
415+ old_valtyp , old_str_val_buf ,
416+ old_str_val_len , old_num_val ,
417+ old_flags ,
418+ valtyp , str_val_buf ,
419+ str_val_len , num_val , flags ,
420+ set_user_flags ,
421+ exptime * 1000 ,
422+ match_flags , match ,
423+ errmsg , forcible )
424+ if rc == 0 then -- NGX_OK
425+ return true , nil , forcible [0 ] == 1
426+ end
427+
428+ -- NGX_DECLINED or NGX_ERROR
429+ if match [0 ] == 1 then
430+ return false , false , forcible [0 ] == 1
431+ end
432+ if errmsg [0 ] ~= nil then
433+ return false , ffi_str (errmsg [0 ]), forcible [0 ] == 1
434+ end
435+ error (" errmsg not specified" )
436+
437+ end
438+ local function shdict_cog (zone , key , old_value , old_flags )
439+ zone = check_zone (zone )
440+
441+ if key == nil then
442+ return nil , " nil key"
443+ end
444+
445+ if type (key ) ~= " string" then
446+ key = tostring (key )
447+ end
448+
449+ local match_flags = 1
450+ if not old_flags then
451+ old_flags = 0
452+ match_flags = 0
453+ end
454+
455+ local key_len = # key
456+ if key_len == 0 then
457+ return nil , " empty key"
458+ end
459+ if key_len > 65535 then
460+ return nil , " key too long"
461+ end
462+
463+ local old_str_val_buf
464+ local old_str_val_len = 0
465+ local old_num_val = 0
466+ local old_valtyp = type (old_value )
467+
468+ if old_valtyp == " string" then
469+ old_valtyp = 4 -- LUA_TSTRING
470+ old_str_val_buf = old_value
471+ old_str_val_len = # old_value
472+
473+ elseif old_valtyp == " number" then
474+ old_valtyp = 3 -- LUA_TNUMBER
475+ old_num_val = old_value
476+
477+ elseif old_value == nil then
478+ old_valtyp = 0 -- LUA_TNIL
479+
480+ elseif old_valtyp == " boolean" then
481+ old_valtyp = 1 -- LUA_TBOOLEAN
482+ old_num_val = old_value and 1 or 0
483+
484+ else
485+ return nil , " bad old_value type"
486+ end
487+
488+ local size = get_string_buf_size ()
489+ local buf = get_string_buf (size )
490+ str_value_buf [0 ] = buf
491+ local value_len = get_size_ptr ()
492+ value_len [0 ] = size
493+
494+ local rc = ngx_lua_ffi_shdict_cog (zone , key , key_len ,
495+ old_valtyp , old_str_val_buf ,
496+ old_str_val_len ,
497+ old_num_val , old_flags ,
498+ value_type ,
499+ str_value_buf , value_len ,
500+ num_value , user_flags ,
501+ match_flags , match , errmsg )
502+ if rc ~= 0 then
503+ if match [0 ] == 1 then
504+ return nil , false
505+ elseif errmsg [0 ] ~= nil then
506+ return nil , ffi_str (errmsg [0 ])
507+ end
508+
509+ error (" failed to get the key" )
510+ end
511+
512+ local typ = value_type [0 ]
513+
514+ if typ == 0 then -- LUA_TNIL
515+ return nil
516+ end
517+
518+ local flags = tonumber (user_flags [0 ])
519+
520+ local val
521+
522+ if typ == 4 then -- LUA_TSTRING
523+ if str_value_buf [0 ] ~= buf then
524+ -- ngx.say("len: ", tonumber(value_len[0]))
525+ buf = str_value_buf [0 ]
526+ val = ffi_str (buf , value_len [0 ])
527+ C .free (buf )
528+ else
529+ val = ffi_str (buf , value_len [0 ])
530+ end
531+
532+ elseif typ == 3 then -- LUA_TNUMBER
533+ val = tonumber (num_value [0 ])
534+
535+ elseif typ == 1 then -- LUA_TBOOLEAN
536+ val = (tonumber (buf [0 ]) ~= 0 )
537+
538+ else
539+ error (" unknown value type: " .. typ )
540+ end
541+
542+ if flags ~= 0 then
543+ return val , flags
544+ end
545+
546+ return val
547+ end
548+
294549
295550local function shdict_get (zone , key )
296551 zone = check_zone (zone )
@@ -630,6 +885,8 @@ if dict then
630885 mt .expire = shdict_expire
631886 mt .capacity = shdict_capacity
632887 mt .free_space = shdict_free_space
888+ mt .cas = shdict_cas
889+ mt .cog = shdict_cog
633890 end
634891 end
635892end
0 commit comments