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);
}
},
+ {
+ .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"),
}
+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)
js_content test.incr;
}
+ location /items {
+ js_content test.items;
+ }
+
location /keys {
js_content test.keys;
}
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);
}
}
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);
###############################################################################
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');
}