Welcome! Log In Create A New Profile

Advanced

[njs] Modules: fixed size() and keys() methods of a shared dictionary.

Dmitry Volyntsev
August 31, 2023 12:02AM
details: https://hg.nginx.org/njs/rev/3fe16507f80a
branches:
changeset: 2187:3fe16507f80a
user: Dmitry Volyntsev <xeioex@nginx.com>
date: Wed Aug 30 18:59:28 2023 -0700
description:
Modules: fixed size() and keys() methods of a shared dictionary.

Previously, these methods did not take into the account exprired
entries. The expired entries appear in js_shared_dict_zone when timeout
directive is specified as the expired elements are not removed at the
moment they become stale right away.

This closes #665 issue on Github.

diffstat:

nginx/ngx_js_shared_dict.c | 16 +++++++++++++
nginx/t/js_shared_dict.t | 54 ++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 64 insertions(+), 6 deletions(-)

diffs (149 lines):

diff -r c7d2a7846b0b -r 3fe16507f80a nginx/ngx_js_shared_dict.c
--- a/nginx/ngx_js_shared_dict.c Wed Aug 30 12:06:12 2023 -0700
+++ b/nginx/ngx_js_shared_dict.c Wed Aug 30 18:59:28 2023 -0700
@@ -599,6 +599,8 @@ njs_js_ext_shared_dict_keys(njs_vm_t *vm
{
njs_int_t rc;
ngx_int_t max_count;
+ ngx_msec_t now;
+ ngx_time_t *tp;
njs_value_t *value;
ngx_rbtree_t *rbtree;
ngx_js_dict_t *dict;
@@ -630,6 +632,12 @@ njs_js_ext_shared_dict_keys(njs_vm_t *vm

ngx_rwlock_rlock(&dict->sh->rwlock);

+ if (dict->timeout) {
+ tp = ngx_timeofday();
+ now = tp->sec * 1000 + tp->msec;
+ ngx_js_dict_expire(dict, now);
+ }
+
rbtree = &dict->sh->rbtree;

if (rbtree->root == rbtree->sentinel) {
@@ -835,6 +843,8 @@ njs_js_ext_shared_dict_size(njs_vm_t *vm
njs_index_t unused, njs_value_t *retval)
{
njs_int_t items;
+ ngx_msec_t now;
+ ngx_time_t *tp;
ngx_rbtree_t *rbtree;
ngx_js_dict_t *dict;
ngx_shm_zone_t *shm_zone;
@@ -851,6 +861,12 @@ njs_js_ext_shared_dict_size(njs_vm_t *vm

ngx_rwlock_rlock(&dict->sh->rwlock);

+ if (dict->timeout) {
+ tp = ngx_timeofday();
+ now = tp->sec * 1000 + tp->msec;
+ ngx_js_dict_expire(dict, now);
+ }
+
rbtree = &dict->sh->rbtree;

if (rbtree->root == rbtree->sentinel) {
diff -r c7d2a7846b0b -r 3fe16507f80a nginx/t/js_shared_dict.t
--- a/nginx/t/js_shared_dict.t Wed Aug 30 12:06:12 2023 -0700
+++ b/nginx/t/js_shared_dict.t Wed Aug 30 18:59:28 2023 -0700
@@ -46,6 +46,10 @@ http {
listen 127.0.0.1:8080;
server_name localhost;

+ location /njs {
+ js_content test.njs;
+ }
+
location /add {
js_content test.add;
}
@@ -115,6 +119,10 @@ http {
EOF

$t->write_file('test.js', <<'EOF');
+ function test_njs(r) {
+ r.return(200, njs.version);
+ }
+
function convertToValue(dict, v) {
if (dict.type == 'number') {
return parseInt(v);
@@ -197,7 +205,7 @@ EOF
ks = ngx.shared[r.args.dict].keys();
}

- r.return(200, ks.toSorted());
+ r.return(200, `[${ks.toSorted()}]`);
}

function name(r) {
@@ -239,10 +247,11 @@ EOF
}

export default { add, capacity, chain, clear, del, free_space, get, has,
- incr, keys, name, pop, replace, set, size, zones };
+ incr, keys, name, njs: test_njs, pop, replace, set, size,
+ zones };
EOF

-$t->try_run('no js_shared_dict_zone')->plan(38);
+$t->try_run('no js_shared_dict_zone')->plan(41);

###############################################################################

@@ -274,8 +283,9 @@ like(http_get('/has?dict=waka&key=FOO'),

$t->reload();

-like(http_get('/keys?dict=foo'), qr/FOO\,FOO2\,FOO3/, 'foo keys');
-like(http_get('/keys?dict=foo&max=2'), qr/FOO\,FOO3/, 'foo keys max 2');
+like(http_get('/keys?dict=foo'), qr/\[FOO\,FOO2\,FOO3]/, 'foo keys');
+like(http_get('/keys?dict=foo&max=2'), qr/\[FOO\,FOO3]/, 'foo keys max 2');
+like(http_get('/size?dict=foo'), qr/size: 3/, 'no of items in foo');
like(http_get('/get?dict=foo&key=FOO2'), qr/yyy/, 'get foo.FOO2');
like(http_get('/get?dict=bar&key=FOO'), qr/zzz/, 'get bar.FOO');
like(http_get('/get?dict=foo&key=FOO'), qr/xxx/, 'get foo.FOO');
@@ -292,8 +302,40 @@ select undef, undef, undef, 2.1;

like(http_get('/get?dict=foo&key=FOO'), qr/undefined/, 'get expired foo.FOO');
like(http_get('/pop?dict=foo&key=FOO'), qr/undefined/, 'pop expired foo.FOO');
-like(http_get('/size?dict=foo'), qr/size: 2/, 'no of items in foo');
+
+TODO: {
+local $TODO = 'not yet' unless has_version('0.8.1');
+
+like(http_get('/keys?dict=foo'), qr/\[]/, 'foo keys after expire');
+like(http_get('/keys?dict=bar'), qr/\[FOO\,FOO2]/, 'bar keys after a delay');
+like(http_get('/size?dict=foo'), qr/size: 0/,
+ 'no of items in foo after expire');
+
+}
+
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');
+
+###############################################################################
+
+sub has_version {
+ my $need = shift;
+
+ http_get('/njs') =~ /^([.0-9]+)$/m;
+
+ my @v = split(/\./, $1);
+ my ($n, $v);
+
+ for $n (split(/\./, $need)) {
+ $v = shift @v || 0;
+ return 0 if $n > $v;
+ return 1 if $v > $n;
+ }
+
+ return 1;
+}
+
+###############################################################################
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[njs] Modules: fixed size() and keys() methods of a shared dictionary.

Dmitry Volyntsev 319 August 31, 2023 12:02AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 250
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready