[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