@@ -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 , 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,
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 , 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]")
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,225 @@ 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+ 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
295547local 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
635889end
0 commit comments