[njs] Modules: implemented items() method of a shared dictionary.

Dmitry Volyntsev xeioex at nginx.com
Thu Sep 7 23:13:05 UTC 2023


details:   https://hg.nginx.org/njs/rev/f5428bc87159
branches:  
changeset: 2194:f5428bc87159
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Sep 07 16:12:40 2023 -0700
description:
Modules: implemented items() method of a shared dictionary.

diffstat:

 nginx/ngx_js_shared_dict.c |  120 +++++++++++++++++++++++++++++++++++++++++++++
 nginx/t/js_shared_dict.t   |   27 +++++++++-
 2 files changed, 144 insertions(+), 3 deletions(-)

diffs (204 lines):

diff -r 5b52293ad769 -r f5428bc87159 nginx/ngx_js_shared_dict.c
--- a/nginx/ngx_js_shared_dict.c	Thu Sep 07 16:12:31 2023 -0700
+++ b/nginx/ngx_js_shared_dict.c	Thu Sep 07 16:12:40 2023 -0700
@@ -64,6 +64,8 @@ static njs_int_t njs_js_ext_shared_dict_
     njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
 static njs_int_t njs_js_ext_shared_dict_incr(njs_vm_t *vm, njs_value_t *args,
     njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
+static njs_int_t njs_js_ext_shared_dict_items(njs_vm_t *vm, njs_value_t *args,
+    njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
 static njs_int_t njs_js_ext_shared_dict_name(njs_vm_t *vm,
     njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
     njs_value_t *retval);
@@ -186,6 +188,17 @@ static njs_external_t  ngx_js_ext_shared
 
     {
         .flags = NJS_EXTERN_METHOD,
+        .name.string = njs_str("items"),
+        .writable = 1,
+        .configurable = 1,
+        .enumerable = 1,
+        .u.method = {
+            .native = njs_js_ext_shared_dict_items,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_METHOD,
         .name.string = njs_str("get"),
         .writable = 1,
         .configurable = 1,
@@ -739,6 +752,113 @@ njs_js_ext_shared_dict_incr(njs_vm_t *vm
 
 
 static njs_int_t
+njs_js_ext_shared_dict_items(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+    njs_index_t unused, njs_value_t *retval)
+{
+    njs_int_t            rc;
+    ngx_int_t            max_count;
+    ngx_msec_t           now;
+    ngx_time_t          *tp;
+    njs_value_t         *value, *kv;
+    ngx_rbtree_t        *rbtree;
+    ngx_js_dict_t       *dict;
+    ngx_shm_zone_t      *shm_zone;
+    ngx_rbtree_node_t   *rn;
+    ngx_js_dict_node_t  *node;
+
+    shm_zone = njs_vm_external(vm, ngx_js_shared_dict_proto_id,
+                               njs_argument(args, 0));
+    if (shm_zone == NULL) {
+        njs_vm_type_error(vm, "\"this\" is not a shared dict");
+        return NJS_ERROR;
+    }
+
+    dict = shm_zone->data;
+
+    max_count = 1024;
+
+    if (nargs > 1) {
+        if (ngx_js_integer(vm, njs_arg(args, nargs, 1), &max_count) != NGX_OK) {
+            return NJS_ERROR;
+        }
+    }
+
+    rc = njs_vm_array_alloc(vm, retval, 8);
+    if (rc != NJS_OK) {
+        return NJS_ERROR;
+    }
+
+    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) {
+        goto done;
+    }
+
+    for (rn = ngx_rbtree_min(rbtree->root, rbtree->sentinel);
+         rn != NULL;
+         rn = ngx_rbtree_next(rbtree, rn))
+    {
+        if (max_count-- == 0) {
+            break;
+        }
+
+        node = (ngx_js_dict_node_t *) rn;
+
+        kv = njs_vm_array_push(vm, retval);
+        if (kv == NULL) {
+            goto fail;
+        }
+
+        rc = njs_vm_array_alloc(vm, kv, 2);
+        if (rc != NJS_OK) {
+            return NJS_ERROR;
+        }
+
+        value = njs_vm_array_push(vm, kv);
+        if (value == NULL) {
+            goto fail;
+        }
+
+        rc = njs_vm_value_string_set(vm, value, node->sn.str.data,
+                                     node->sn.str.len);
+        if (rc != NJS_OK) {
+            goto fail;
+        }
+
+        value = njs_vm_array_push(vm, kv);
+        if (value == NULL) {
+            goto fail;
+        }
+
+        rc = ngx_js_dict_copy_value_locked(vm, dict, node, value);
+        if (rc != NJS_OK) {
+            goto fail;
+        }
+    }
+
+done:
+
+    ngx_rwlock_unlock(&dict->sh->rwlock);
+
+    return NJS_OK;
+
+fail:
+
+    ngx_rwlock_unlock(&dict->sh->rwlock);
+
+    return NJS_ERROR;
+}
+
+
+static njs_int_t
 njs_js_ext_shared_dict_name(njs_vm_t *vm, njs_object_prop_t *prop,
     njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
 {
diff -r 5b52293ad769 -r f5428bc87159 nginx/t/js_shared_dict.t
--- a/nginx/t/js_shared_dict.t	Thu Sep 07 16:12:31 2023 -0700
+++ b/nginx/t/js_shared_dict.t	Thu Sep 07 16:12:40 2023 -0700
@@ -86,6 +86,10 @@ http {
             js_content test.incr;
         }
 
+        location /items {
+            js_content test.items;
+        }
+
         location /keys {
             js_content test.keys;
         }
@@ -208,6 +212,19 @@ EOF
         r.return(200, `[${ks.toSorted()}]`);
     }
 
+    function items(r) {
+        var kvs;
+
+        if (r.args.max) {
+            kvs = ngx.shared[r.args.dict].items(parseInt(r.args.max));
+
+        } else {
+            kvs = ngx.shared[r.args.dict].items();
+        }
+
+        r.return(200, njs.dump(kvs.toSorted()));
+    }
+
     function name(r) {
         r.return(200, ngx.shared[r.args.dict].name);
     }
@@ -247,11 +264,11 @@ EOF
     }
 
     export default { add, capacity, chain, clear, del, free_space, get, has,
-                     incr, keys, name, njs: test_njs, pop, replace, set, size,
-                     zones };
+                     incr, items, keys, name, njs: test_njs, pop, replace, set,
+                     size, zones };
 EOF
 
-$t->try_run('no js_shared_dict_zone')->plan(41);
+$t->try_run('no js_shared_dict_zone')->plan(43);
 
 ###############################################################################
 
@@ -311,6 +328,10 @@ like(http_get('/keys?dict=foo'), qr/\[]/
 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('/items?dict=bar'), qr/\[\['FOO','zzz'],\['FOO2','aaa']]/,
+	'bar items');
+like(http_get('/items?dict=waka'),
+	qr/\[\['FOO',47],\['FOO2',7779],\['FOO3',3338]]/, 'waka items');
 
 }
 


More information about the nginx-devel mailing list