From 25fedb319cfc318ecceb457524ed3ea57f903c27 Mon Sep 17 00:00:00 2001 From: Vadim Zhestikov Date: Tue, 19 Dec 2023 12:37:05 -0800 Subject: [PATCH] Modules: fixed clear() method of a shared dictionary without timeout. This fixes #690 issue on Github. --- nginx/ngx_js_shared_dict.c | 30 +++++++++++++++++++++++++++--- nginx/t/js_shared_dict.t | 21 +++++++++++++++++++-- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/nginx/ngx_js_shared_dict.c b/nginx/ngx_js_shared_dict.c index e9acd9f7..66227428 100644 --- a/nginx/ngx_js_shared_dict.c +++ b/nginx/ngx_js_shared_dict.c @@ -109,6 +109,8 @@ static njs_int_t ngx_js_dict_shared_error_name(njs_vm_t *vm, static ngx_int_t ngx_js_dict_init_zone(ngx_shm_zone_t *shm_zone, void *data); static njs_int_t ngx_js_shared_dict_preinit(njs_vm_t *vm); static njs_int_t ngx_js_shared_dict_init(njs_vm_t *vm); +static void ngx_js_dict_node_free(ngx_js_dict_t *dict, + ngx_js_dict_node_t *node); static njs_external_t ngx_js_ext_shared_dict[] = { @@ -454,8 +456,10 @@ static njs_int_t njs_js_ext_shared_dict_clear(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - ngx_js_dict_t *dict; - ngx_shm_zone_t *shm_zone; + ngx_rbtree_t *rbtree; + ngx_js_dict_t *dict; + ngx_shm_zone_t *shm_zone; + ngx_rbtree_node_t *rn, *next; shm_zone = njs_vm_external(vm, ngx_js_shared_dict_proto_id, njs_argument(args, 0)); @@ -468,7 +472,27 @@ njs_js_ext_shared_dict_clear(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, ngx_rwlock_wlock(&dict->sh->rwlock); - ngx_js_dict_evict(dict, 0x7fffffff /* INT_MAX */); + if (dict->timeout) { + ngx_js_dict_evict(dict, 0x7fffffff /* INT_MAX */); + + } else { + rbtree = &dict->sh->rbtree; + + if (rbtree->root == rbtree->sentinel) { + return NJS_OK; + } + + for (rn = ngx_rbtree_min(rbtree->root, rbtree->sentinel); + rn != NULL; + rn = next) + { + next = ngx_rbtree_next(rbtree, rn); + + ngx_rbtree_delete(rbtree, rn); + + ngx_js_dict_node_free(dict, (ngx_js_dict_node_t *) rn); + } + } ngx_rwlock_unlock(&dict->sh->rwlock); diff --git a/nginx/t/js_shared_dict.t b/nginx/t/js_shared_dict.t index 1cf794ce..bfa45c60 100644 --- a/nginx/t/js_shared_dict.t +++ b/nginx/t/js_shared_dict.t @@ -41,6 +41,7 @@ http { js_shared_dict_zone zone=foo:32k timeout=2s evict; js_shared_dict_zone zone=bar:64k type=string; js_shared_dict_zone zone=waka:32k type=number; + js_shared_dict_zone zone=no_timeout:32k; server { listen 127.0.0.1:8080; @@ -110,6 +111,10 @@ http { js_content test.set; } + location /set_clear { + js_content test.set_clear; + } + location /size { js_content test.size; } @@ -259,16 +264,25 @@ $t->write_file('test.js', <<'EOF'); r.return(200, `size: ${dict.size()}`); } + function set_clear(r) { + var dict = ngx.shared.no_timeout; + dict.set("test", "test value"); + dict.set("test1", "test1 value"); + dict.clear(); + r.return(200, `size: ${dict.size()}`); + } + + function zones(r) { r.return(200, Object.keys(ngx.shared).sort()); } export default { add, capacity, chain, clear, del, free_space, get, has, incr, items, keys, name, njs: test_njs, pop, replace, set, - size, zones }; + set_clear, size, zones }; EOF -$t->try_run('no js_shared_dict_zone')->plan(43); +$t->try_run('no js_shared_dict_zone')->plan(44); ############################################################################### @@ -339,7 +353,10 @@ like(http_get('/pop?dict=bar&key=FOO'), qr/zzz/, 'pop bar.FOO'); like(http_get('/pop?dict=bar&key=FOO'), qr/undefined/, 'pop deleted bar.FOO'); http_get('/set?dict=foo&key=BAR&value=xxx'); like(http_get('/clear?dict=foo'), qr/undefined/, 'clear foo'); + like(http_get('/size?dict=foo'), qr/size: 0/, 'no of items in foo after clear'); +like(http_get('/set_clear'), qr/size: 0/, + 'no of items in no_timeout after clear'); ############################################################################### -- 2.47.3