@@ -40,7 +40,8 @@ local ngx_lua_ffi_shdict_set_expire
40
40
local ngx_lua_ffi_shdict_capacity
41
41
local ngx_lua_ffi_shdict_free_space
42
42
local ngx_lua_ffi_shdict_udata_to_zone
43
-
43
+ local ngx_lua_ffi_shdict_cas
44
+ local ngx_lua_ffi_shdict_get_if_not_eq
44
45
45
46
if subsystem == ' http' then
46
47
ffi .cdef [[
@@ -70,6 +71,20 @@ int ngx_http_lua_ffi_shdict_set_expire(void *zone,
70
71
size_t ngx_http_lua_ffi_shdict_capacity (void * zone );
71
72
72
73
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 , int set_user_flags ,
80
+ long exptime , int match_flags , int * match , char ** errmsg , int * forcible );
81
+ int
82
+ ngx_http_lua_ffi_shdict_get_if_not_eq (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 );
73
88
]]
74
89
75
90
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);
81
96
ngx_lua_ffi_shdict_capacity = C .ngx_http_lua_ffi_shdict_capacity
82
97
ngx_lua_ffi_shdict_udata_to_zone =
83
98
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_get_if_not_eq = C .ngx_http_lua_ffi_shdict_get_if_not_eq
85
101
if not pcall (function ()
86
102
return C .ngx_http_lua_ffi_shdict_free_space
87
103
end )
@@ -124,6 +140,20 @@ int ngx_stream_lua_ffi_shdict_set_expire(void *zone,
124
140
size_t ngx_stream_lua_ffi_shdict_capacity (void * zone );
125
141
126
142
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 , int set_user_flags ,
149
+ long exptime , int match_flags , int * match , char ** errmsg , int * forcible );
150
+ int
151
+ ngx_stream_lua_ffi_shdict_get_if_not_eq (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 );
127
157
]]
128
158
129
159
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);
135
165
ngx_lua_ffi_shdict_capacity = C .ngx_stream_lua_ffi_shdict_capacity
136
166
ngx_lua_ffi_shdict_udata_to_zone =
137
167
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_get_if_not_eq = C .ngx_stream_lua_ffi_shdict_get_if_not_eq
138
170
139
171
if not pcall (function ()
140
172
return C .ngx_stream_lua_ffi_shdict_free_space
@@ -164,6 +196,7 @@ local value_type = ffi_new("int[1]")
164
196
local user_flags = ffi_new (" int[1]" )
165
197
local num_value = ffi_new (" double[1]" )
166
198
local is_stale = ffi_new (" int[1]" )
199
+ local match = ffi_new (" int[1]" )
167
200
local forcible = ffi_new (" int[1]" )
168
201
local str_value_buf = ffi_new (" unsigned char *[1]" )
169
202
local errmsg = base .get_errmsg_ptr ()
@@ -291,6 +324,228 @@ local function shdict_delete(zone, key)
291
324
return shdict_set (zone , key , nil )
292
325
end
293
326
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_get_if_not_eq (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_get_if_not_eq (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
+
294
549
295
550
local function shdict_get (zone , key )
296
551
zone = check_zone (zone )
@@ -630,6 +885,8 @@ if dict then
630
885
mt .expire = shdict_expire
631
886
mt .capacity = shdict_capacity
632
887
mt .free_space = shdict_free_space
888
+ mt .cas = shdict_cas
889
+ mt .get_if_not_eq = shdict_get_if_not_eq
633
890
end
634
891
end
635
892
end
0 commit comments