[njs] Refactored working with external prototypes.
Dmitry Volyntsev
xeioex at nginx.com
Thu Dec 24 18:36:52 UTC 2020
details: https://hg.nginx.org/njs/rev/40dc1818a485
branches:
changeset: 1586:40dc1818a485
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Thu Dec 24 18:35:18 2020 +0000
description:
Refactored working with external prototypes.
Previously, njs_vm_external_prototype() returned the pointer to a
created prototype structure. Which were expected to be passed to
njs_vm_external_create() as is. The returned pointer is needed to be
stored somewhere by user code which complicates user code in cases when
many prototypes are created.
Instead, an index in the VM internal table is returned.
njs_vm_external_create() is changed accordingly. This simplifies
user code because the index is known at static time for most cases.
diffstat:
nginx/ngx_http_js_module.c | 26 ++++++------------
nginx/ngx_js.c | 15 +++++------
nginx/ngx_js.h | 2 +
nginx/ngx_stream_js_module.c | 15 +++-------
src/njs.h | 5 +--
src/njs_extern.c | 34 +++++++++++++++++++------
src/njs_shell.c | 11 +++----
src/njs_vm.h | 1 +
src/test/njs_benchmark.c | 7 ++---
src/test/njs_externals_test.c | 57 +++++++++++++++++++++---------------------
src/test/njs_externals_test.h | 4 +-
src/test/njs_unit_test.c | 27 +++++++++----------
12 files changed, 104 insertions(+), 100 deletions(-)
diffs (584 lines):
diff -r 1e5f3455d2d1 -r 40dc1818a485 nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.c Wed Dec 23 11:27:50 2020 +0000
+++ b/nginx/ngx_http_js_module.c Thu Dec 24 18:35:18 2020 +0000
@@ -19,7 +19,6 @@ typedef struct {
ngx_uint_t line;
ngx_array_t *imports;
ngx_array_t *paths;
- njs_external_proto_t req_proto;
} ngx_http_js_main_conf_t;
@@ -836,7 +835,7 @@ ngx_http_js_init_vm(ngx_http_request_t *
}
rc = njs_vm_external_create(ctx->vm, njs_value_arg(&ctx->request),
- jmcf->req_proto, r, 0);
+ NGX_JS_PROTO_MAIN, r, 0);
if (rc != NJS_OK) {
return NGX_ERROR;
}
@@ -2708,10 +2707,9 @@ ngx_http_js_subrequest_done(ngx_http_req
{
njs_vm_event_t vm_event = data;
- njs_int_t ret;
- ngx_http_js_ctx_t *ctx;
- njs_opaque_value_t reply;
- ngx_http_js_main_conf_t *jmcf;
+ njs_int_t ret;
+ ngx_http_js_ctx_t *ctx;
+ njs_opaque_value_t reply;
if (rc != NGX_OK || r->connection->error || r->buffered) {
return rc;
@@ -2734,8 +2732,6 @@ ngx_http_js_subrequest_done(ngx_http_req
ctx->done = 1;
- jmcf = ngx_http_get_module_main_conf(r, ngx_http_js_module);
-
ctx = ngx_http_get_module_ctx(r->parent, ngx_http_js_module);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -2750,7 +2746,7 @@ ngx_http_js_subrequest_done(ngx_http_req
}
ret = njs_vm_external_create(ctx->vm, njs_value_arg(&reply),
- jmcf->req_proto, r, 0);
+ NGX_JS_PROTO_MAIN, r, 0);
if (ret != NJS_OK) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"js subrequest reply creation failed");
@@ -2954,7 +2950,7 @@ ngx_http_js_init_main_conf(ngx_conf_t *c
ssize_t n;
ngx_fd_t fd;
ngx_str_t *m, file;
- njs_int_t rc;
+ njs_int_t rc, proto_id;
njs_str_t text, path;
ngx_uint_t i;
njs_value_t *value;
@@ -2962,7 +2958,6 @@ ngx_http_js_init_main_conf(ngx_conf_t *c
ngx_file_info_t fi;
ngx_pool_cleanup_t *cln;
njs_opaque_value_t lvalue, exception;
- njs_external_proto_t proto;
ngx_http_js_import_t *import;
static const njs_str_t line_number_key = njs_str("lineNumber");
@@ -3114,16 +3109,14 @@ ngx_http_js_init_main_conf(ngx_conf_t *c
}
}
- proto = njs_vm_external_prototype(jmcf->vm, ngx_http_js_ext_request,
- njs_nitems(ngx_http_js_ext_request));
- if (proto == NULL) {
+ proto_id = njs_vm_external_prototype(jmcf->vm, ngx_http_js_ext_request,
+ njs_nitems(ngx_http_js_ext_request));
+ if (proto_id < 0) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"failed to add js request proto");
return NGX_CONF_ERROR;
}
- jmcf->req_proto = proto;
-
rc = ngx_js_core_init(jmcf->vm, cf->log);
if (njs_slow_path(rc != NJS_OK)) {
return NGX_CONF_ERROR;
@@ -3379,7 +3372,6 @@ ngx_http_js_create_main_conf(ngx_conf_t
* conf->include = { 0, NULL };
* conf->file = NULL;
* conf->line = 0;
- * conf->req_proto = NULL;
*/
conf->paths = NGX_CONF_UNSET_PTR;
diff -r 1e5f3455d2d1 -r 40dc1818a485 nginx/ngx_js.c
--- a/nginx/ngx_js.c Wed Dec 23 11:27:50 2020 +0000
+++ b/nginx/ngx_js.c Thu Dec 24 18:35:18 2020 +0000
@@ -117,19 +117,18 @@ ngx_js_string(njs_vm_t *vm, njs_value_t
ngx_int_t
ngx_js_core_init(njs_vm_t *vm, ngx_log_t *log)
{
- njs_int_t ret;
- njs_str_t name;
- njs_opaque_value_t value;
- njs_external_proto_t proto;
+ njs_int_t ret, proto_id;
+ njs_str_t name;
+ njs_opaque_value_t value;
- proto = njs_vm_external_prototype(vm, ngx_js_ext_core,
- njs_nitems(ngx_js_ext_core));
- if (proto == NULL) {
+ proto_id = njs_vm_external_prototype(vm, ngx_js_ext_core,
+ njs_nitems(ngx_js_ext_core));
+ if (proto_id < 0) {
ngx_log_error(NGX_LOG_EMERG, log, 0, "failed to add js core proto");
return NGX_ERROR;
}
- ret = njs_vm_external_create(vm, njs_value_arg(&value), proto, NULL, 1);
+ ret = njs_vm_external_create(vm, njs_value_arg(&value), proto_id, NULL, 1);
if (njs_slow_path(ret != NJS_OK)) {
ngx_log_error(NGX_LOG_EMERG, log, 0,
"njs_vm_external_create() failed\n");
diff -r 1e5f3455d2d1 -r 40dc1818a485 nginx/ngx_js.h
--- a/nginx/ngx_js.h Wed Dec 23 11:27:50 2020 +0000
+++ b/nginx/ngx_js.h Thu Dec 24 18:35:18 2020 +0000
@@ -19,6 +19,8 @@
#define NGX_JS_STRING 1
#define NGX_JS_BUFFER 2
+#define NGX_JS_PROTO_MAIN 0
+
#define ngx_external_connection(vm, ext) \
(*((ngx_connection_t **) ((u_char *) ext + njs_vm_meta(vm, 0))))
diff -r 1e5f3455d2d1 -r 40dc1818a485 nginx/ngx_stream_js_module.c
--- a/nginx/ngx_stream_js_module.c Wed Dec 23 11:27:50 2020 +0000
+++ b/nginx/ngx_stream_js_module.c Thu Dec 24 18:35:18 2020 +0000
@@ -19,7 +19,6 @@ typedef struct {
ngx_uint_t line;
ngx_array_t *imports;
ngx_array_t *paths;
- njs_external_proto_t proto;
} ngx_stream_js_main_conf_t;
@@ -696,7 +695,7 @@ ngx_stream_js_init_vm(ngx_stream_session
}
rc = njs_vm_external_create(ctx->vm, njs_value_arg(&ctx->args[0]),
- jmcf->proto, s, 0);
+ NGX_JS_PROTO_MAIN, s, 0);
if (rc != NJS_OK) {
return NGX_ERROR;
}
@@ -1306,7 +1305,7 @@ ngx_stream_js_init_main_conf(ngx_conf_t
ssize_t n;
ngx_fd_t fd;
ngx_str_t *m, file;
- njs_int_t rc;
+ njs_int_t rc, proto_id;
njs_str_t text, path;
ngx_uint_t i;
njs_value_t *value;
@@ -1314,7 +1313,6 @@ ngx_stream_js_init_main_conf(ngx_conf_t
ngx_file_info_t fi;
ngx_pool_cleanup_t *cln;
njs_opaque_value_t lvalue, exception;
- njs_external_proto_t proto;
ngx_stream_js_import_t *import;
static const njs_str_t line_number_key = njs_str("lineNumber");
@@ -1466,16 +1464,14 @@ ngx_stream_js_init_main_conf(ngx_conf_t
}
}
- proto = njs_vm_external_prototype(jmcf->vm, ngx_stream_js_ext_session,
- njs_nitems(ngx_stream_js_ext_session));
- if (proto == NULL) {
+ proto_id = njs_vm_external_prototype(jmcf->vm, ngx_stream_js_ext_session,
+ njs_nitems(ngx_stream_js_ext_session));
+ if (proto_id < 0) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"failed to add js request proto");
return NGX_CONF_ERROR;
}
- jmcf->proto = proto;
-
rc = ngx_js_core_init(jmcf->vm, cf->log);
if (njs_slow_path(rc != NJS_OK)) {
return NGX_CONF_ERROR;
@@ -1708,7 +1704,6 @@ ngx_stream_js_create_main_conf(ngx_conf_
* conf->include = { 0, NULL };
* conf->file = NULL;
* conf->line = 0;
- * conf->proto = NULL;
*/
conf->paths = NGX_CONF_UNSET_PTR;
diff -r 1e5f3455d2d1 -r 40dc1818a485 src/njs.h
--- a/src/njs.h Wed Dec 23 11:27:50 2020 +0000
+++ b/src/njs.h Thu Dec 24 18:35:18 2020 +0000
@@ -29,7 +29,6 @@ typedef struct njs_function_s njs_
typedef struct njs_vm_shared_s njs_vm_shared_t;
typedef struct njs_object_prop_s njs_object_prop_t;
typedef struct njs_external_s njs_external_t;
-typedef void * njs_external_proto_t;
/*
* njs_opaque_value_t is the external storage type for native njs_value_t type.
@@ -297,10 +296,10 @@ NJS_EXPORT njs_int_t njs_vm_start(njs_vm
NJS_EXPORT njs_int_t njs_vm_add_path(njs_vm_t *vm, const njs_str_t *path);
-NJS_EXPORT njs_external_proto_t njs_vm_external_prototype(njs_vm_t *vm,
+NJS_EXPORT njs_int_t njs_vm_external_prototype(njs_vm_t *vm,
const njs_external_t *definition, njs_uint_t n);
NJS_EXPORT njs_int_t njs_vm_external_create(njs_vm_t *vm, njs_value_t *value,
- njs_external_proto_t proto, njs_external_ptr_t external, njs_bool_t shared);
+ njs_int_t proto_id, njs_external_ptr_t external, njs_bool_t shared);
NJS_EXPORT njs_external_ptr_t njs_vm_external(njs_vm_t *vm,
const njs_value_t *value);
NJS_EXPORT uintptr_t njs_vm_meta(njs_vm_t *vm, njs_uint_t index);
diff -r 1e5f3455d2d1 -r 40dc1818a485 src/njs_extern.c
--- a/src/njs_extern.c Wed Dec 23 11:27:50 2020 +0000
+++ b/src/njs_extern.c Thu Dec 24 18:35:18 2020 +0000
@@ -256,12 +256,13 @@ njs_external_protos(const njs_external_t
}
-njs_external_proto_t
+njs_int_t
njs_vm_external_prototype(njs_vm_t *vm, const njs_external_t *definition,
njs_uint_t n)
{
njs_arr_t *protos;
njs_int_t ret;
+ uintptr_t *pr;
njs_uint_t size;
size = njs_external_protos(definition, n) + 1;
@@ -269,38 +270,55 @@ njs_vm_external_prototype(njs_vm_t *vm,
protos = njs_arr_create(vm->mem_pool, size, sizeof(njs_exotic_slots_t));
if (njs_slow_path(protos == NULL)) {
njs_memory_error(vm);
- return NULL;
+ return -1;
}
ret = njs_external_add(vm, protos, definition, n);
if (njs_slow_path(ret != NJS_OK)) {
njs_internal_error(vm, "njs_vm_external_add() failed");
- return NULL;
+ return -1;
}
- return protos;
+ if (vm->protos == NULL) {
+ vm->protos = njs_arr_create(vm->mem_pool, 4, sizeof(uintptr_t));
+ if (njs_slow_path(vm->protos == NULL)) {
+ return -1;
+ }
+ }
+
+ pr = njs_arr_add(vm->protos);
+ if (njs_slow_path(pr == NULL)) {
+ return -1;
+ }
+
+ *pr = (uintptr_t) protos;
+
+ return vm->protos->items - 1;
}
njs_int_t
-njs_vm_external_create(njs_vm_t *vm, njs_value_t *value,
- njs_external_proto_t proto, njs_external_ptr_t external, njs_bool_t shared)
+njs_vm_external_create(njs_vm_t *vm, njs_value_t *value, njs_int_t proto_id,
+ njs_external_ptr_t external, njs_bool_t shared)
{
njs_arr_t *protos;
+ uintptr_t proto;
njs_object_value_t *ov;
njs_exotic_slots_t *slots;
- if (njs_slow_path(proto == NULL)) {
+ if (vm->protos == NULL || (njs_int_t) vm->protos->items <= proto_id) {
return NJS_ERROR;
}
+ proto = ((uintptr_t *) vm->protos->start)[proto_id];
+
ov = njs_mp_alloc(vm->mem_pool, sizeof(njs_object_value_t));
if (njs_slow_path(ov == NULL)) {
njs_memory_error(vm);
return NJS_ERROR;
}
- protos = proto;
+ protos = (njs_arr_t *) proto;
slots = protos->start;
njs_lvlhsh_init(&ov->object.hash);
diff -r 1e5f3455d2d1 -r 40dc1818a485 src/njs_shell.c
--- a/src/njs_shell.c Wed Dec 23 11:27:50 2020 +0000
+++ b/src/njs_shell.c Thu Dec 24 18:35:18 2020 +0000
@@ -653,12 +653,11 @@ static njs_value_t *
njs_external_add(njs_vm_t *vm, njs_external_t *definition,
njs_uint_t n, const njs_str_t *name, njs_external_ptr_t external)
{
- njs_int_t ret;
- njs_value_t *value;
- njs_external_proto_t proto;
+ njs_int_t ret, proto_id;
+ njs_value_t *value;
- proto = njs_vm_external_prototype(vm, definition, n);
- if (njs_slow_path(proto == NULL)) {
+ proto_id = njs_vm_external_prototype(vm, definition, n);
+ if (njs_slow_path(proto_id < 0)) {
njs_stderror("failed to add \"%V\" proto\n", name);
return NULL;
}
@@ -668,7 +667,7 @@ njs_external_add(njs_vm_t *vm, njs_exter
return NULL;
}
- ret = njs_vm_external_create(vm, value, proto, external, 0);
+ ret = njs_vm_external_create(vm, value, proto_id, external, 0);
if (njs_slow_path(ret != NJS_OK)) {
return NULL;
}
diff -r 1e5f3455d2d1 -r 40dc1818a485 src/njs_vm.h
--- a/src/njs_vm.h Wed Dec 23 11:27:50 2020 +0000
+++ b/src/njs_vm.h Thu Dec 24 18:35:18 2020 +0000
@@ -180,6 +180,7 @@ struct njs_vm_s {
njs_value_t retval;
njs_arr_t *paths;
+ njs_arr_t *protos;
njs_value_t *scopes[NJS_SCOPES];
diff -r 1e5f3455d2d1 -r 40dc1818a485 src/test/njs_benchmark.c
--- a/src/test/njs_benchmark.c Wed Dec 23 11:27:50 2020 +0000
+++ b/src/test/njs_benchmark.c Thu Dec 24 18:35:18 2020 +0000
@@ -36,13 +36,12 @@ njs_benchmark_test(njs_vm_t *parent, njs
u_char *start;
njs_vm_t *vm, *nvm;
uint64_t us;
- njs_int_t ret;
+ njs_int_t ret, proto_id;
njs_str_t s, *expected;
njs_uint_t i, n;
njs_bool_t success;
njs_value_t *result, name, usec, times;
njs_vm_opt_t options;
- njs_external_proto_t proto;
static const njs_value_t name_key = njs_string("name");
static const njs_value_t usec_key = njs_string("usec");
@@ -68,8 +67,8 @@ njs_benchmark_test(njs_vm_t *parent, njs
goto done;
}
- proto = njs_externals_shared_init(vm);
- if (proto == NULL) {
+ proto_id = njs_externals_shared_init(vm);
+ if (proto_id < 0) {
goto done;
}
diff -r 1e5f3455d2d1 -r 40dc1818a485 src/test/njs_externals_test.c
--- a/src/test/njs_externals_test.c Wed Dec 23 11:27:50 2020 +0000
+++ b/src/test/njs_externals_test.c Thu Dec 24 18:35:18 2020 +0000
@@ -11,7 +11,7 @@
typedef struct {
njs_lvlhsh_t hash;
- njs_external_proto_t proto;
+ njs_int_t proto_id;
uint32_t a;
uint32_t d;
@@ -394,9 +394,9 @@ njs_unit_test_r_create(njs_vm_t *vm, njs
return NJS_ERROR;
}
- sr->proto = r->proto;
+ sr->proto_id = r->proto_id;
- ret = njs_vm_external_create(vm, &vm->retval, sr->proto, sr, 0);
+ ret = njs_vm_external_create(vm, &vm->retval, sr->proto_id, sr, 0);
if (ret != NJS_OK) {
return NJS_ERROR;
}
@@ -678,8 +678,8 @@ static njs_unit_test_req_init_t njs_test
};
-static njs_external_proto_t
-njs_externals_init_internal(njs_vm_t *vm, njs_external_proto_t proto,
+static njs_int_t
+njs_externals_init_internal(njs_vm_t *vm, njs_int_t proto_id,
njs_unit_test_req_init_t *init, njs_uint_t n, njs_bool_t shared)
{
njs_int_t ret;
@@ -687,37 +687,37 @@ njs_externals_init_internal(njs_vm_t *vm
njs_unit_test_req_t *requests;
njs_unit_test_prop_t *prop;
- if (proto == NULL) {
- proto = njs_vm_external_prototype(vm, njs_unit_test_r_external,
- njs_nitems(njs_unit_test_r_external));
- if (njs_slow_path(proto == NULL)) {
+ if (proto_id == -1) {
+ proto_id = njs_vm_external_prototype(vm, njs_unit_test_r_external,
+ njs_nitems(njs_unit_test_r_external));
+ if (njs_slow_path(proto_id < 0)) {
njs_printf("njs_vm_external_prototype() failed\n");
- return NULL;
+ return -1;
}
}
requests = njs_mp_zalloc(vm->mem_pool, n * sizeof(njs_unit_test_req_t));
if (njs_slow_path(requests == NULL)) {
- return NULL;
+ return -1;
}
for (i = 0; i < n; i++) {
requests[i] = init[i].request;
- requests[i].proto = proto;
+ requests[i].proto_id = proto_id;
ret = njs_vm_external_create(vm, njs_value_arg(&requests[i].value),
- proto, &requests[i], shared);
+ proto_id, &requests[i], shared);
if (njs_slow_path(ret != NJS_OK)) {
njs_printf("njs_vm_external_create() failed\n");
- return NULL;
+ return -1;
}
ret = njs_vm_bind(vm, &init[i].name, njs_value_arg(&requests[i].value),
shared);
if (njs_slow_path(ret != NJS_OK)) {
njs_printf("njs_vm_bind() failed\n");
- return NULL;
+ return -1;
}
for (j = 0; j < njs_nitems(init[i].props); j++) {
@@ -726,33 +726,34 @@ njs_externals_init_internal(njs_vm_t *vm
if (njs_slow_path(prop == NULL)) {
njs_printf("lvlhsh_unit_test_alloc() failed\n");
- return NULL;
+ return -1;
}
ret = lvlhsh_unit_test_add(vm->mem_pool, &requests[i], prop);
if (njs_slow_path(ret != NJS_OK)) {
njs_printf("lvlhsh_unit_test_add() failed\n");
- return NULL;
+ return -1;
}
}
}
- return proto;
-}
-
-
-njs_external_proto_t
-njs_externals_shared_init(njs_vm_t *vm)
-{
- return njs_externals_init_internal(vm, NULL, njs_test_requests, 1, 1);
+ return proto_id;
}
njs_int_t
-njs_externals_init(njs_vm_t *vm, njs_external_proto_t proto)
+njs_externals_shared_init(njs_vm_t *vm)
{
- proto = njs_externals_init_internal(vm, proto, &njs_test_requests[1], 3, 0);
- if (proto == NULL) {
+ return njs_externals_init_internal(vm, -1, njs_test_requests, 1, 1);
+}
+
+
+njs_int_t
+njs_externals_init(njs_vm_t *vm, njs_int_t proto_id)
+{
+ proto_id = njs_externals_init_internal(vm, proto_id, &njs_test_requests[1],
+ 3, 0);
+ if (proto_id < 0) {
return NJS_ERROR;
}
diff -r 1e5f3455d2d1 -r 40dc1818a485 src/test/njs_externals_test.h
--- a/src/test/njs_externals_test.h Wed Dec 23 11:27:50 2020 +0000
+++ b/src/test/njs_externals_test.h Thu Dec 24 18:35:18 2020 +0000
@@ -8,8 +8,8 @@
#define _NJS_EXTERNALS_TEST_H_INCLUDED_
-njs_external_proto_t njs_externals_shared_init(njs_vm_t *vm);
-njs_int_t njs_externals_init(njs_vm_t *vm, njs_external_proto_t proto);
+njs_int_t njs_externals_shared_init(njs_vm_t *vm);
+njs_int_t njs_externals_init(njs_vm_t *vm, njs_int_t proto_id);
#endif /* _NJS_EXTERNALS_TEST_H_INCLUDED_ */
diff -r 1e5f3455d2d1 -r 40dc1818a485 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Wed Dec 23 11:27:50 2020 +0000
+++ b/src/test/njs_unit_test.c Thu Dec 24 18:35:18 2020 +0000
@@ -20483,19 +20483,18 @@ static njs_int_t
njs_unit_test(njs_unit_test_t tests[], size_t num, njs_str_t *name,
njs_opts_t *opts, njs_stat_t *stat)
{
- u_char *start, *end;
- njs_vm_t *vm, *nvm;
- njs_int_t ret;
- njs_str_t s;
- njs_uint_t i, repeat;
- njs_stat_t prev;
- njs_bool_t success;
- njs_vm_opt_t options;
- njs_external_proto_t proto;
+ u_char *start, *end;
+ njs_vm_t *vm, *nvm;
+ njs_int_t ret, proto_id;
+ njs_str_t s;
+ njs_uint_t i, repeat;
+ njs_stat_t prev;
+ njs_bool_t success;
+ njs_vm_opt_t options;
vm = NULL;
nvm = NULL;
- proto = NULL;
+ proto_id = -1;
prev = *stat;
@@ -20519,8 +20518,8 @@ njs_unit_test(njs_unit_test_t tests[], s
}
if (opts->externals) {
- proto = njs_externals_shared_init(vm);
- if (proto == NULL) {
+ proto_id = njs_externals_shared_init(vm);
+ if (proto_id < 0) {
goto done;
}
}
@@ -20549,7 +20548,7 @@ njs_unit_test(njs_unit_test_t tests[], s
}
if (opts->externals) {
- ret = njs_externals_init(nvm, proto);
+ ret = njs_externals_init(nvm, proto_id);
if (ret != NJS_OK) {
goto done;
}
@@ -20653,7 +20652,7 @@ njs_interactive_test(njs_unit_test_t tes
}
if (opts->externals) {
- ret = njs_externals_init(vm, NULL);
+ ret = njs_externals_init(vm, -1);
if (ret != NJS_OK) {
goto done;
}
More information about the nginx-devel
mailing list