diff --git a/docs/DIRECTIVES.md b/docs/DIRECTIVES.md index d328e74ec..950d17f56 100644 --- a/docs/DIRECTIVES.md +++ b/docs/DIRECTIVES.md @@ -3,6 +3,7 @@ By alphabetical order: - [backtraces](#backtraces) +- [cache_config](#cache-config) - [compiler](#compiler) - [flag](#flag) - [module](#module) @@ -57,6 +58,7 @@ By context: - [tls_verify_cert](#tls_verify_cert) - [tls_verify_host](#tls_verify_host) - `wasmtime{}` + - [cache_config](#cache-config) - [flag](#flag) - `wasmer{}` - [flag](#flag) @@ -131,6 +133,23 @@ Different runtimes support different compilers: [Back to TOC](#directives) +cache_config +------------ + +**usage** | `cache_config ;` +------------:|:---------------------------------------------------------------- +**contexts** | `wasmtime{}` +**default** | +**example** | `cache_config /path/to/wasmtime_config.toml;` + +Enables Wasmtime's compilation cache and loads the specified configuration file. + +By default the Wasmtime compilation cache is disabled. If specified, the path +must point to a file on the filesystem with TOML configuration; see +https://bytecodealliance.github.io/wasmtime/cli-cache.html. + +[Back to TOC](#directives) + flag ---- diff --git a/src/wasm/ngx_wasm_core_module.c b/src/wasm/ngx_wasm_core_module.c index d68c00e27..cd7f8d80b 100644 --- a/src/wasm/ngx_wasm_core_module.c +++ b/src/wasm/ngx_wasm_core_module.c @@ -52,6 +52,14 @@ static ngx_command_t ngx_wasm_core_commands[] = { 0, NULL }, + { ngx_string("cache_config"), + NGX_WASMTIME_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_WA_WASM_CONF_OFFSET, + offsetof(ngx_wasm_core_conf_t, vm_conf) + + offsetof(ngx_wavm_conf_t, cache_config), + NULL }, + { ngx_string("compiler"), NGX_WASM_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, diff --git a/src/wasm/wrt/ngx_wrt.h b/src/wasm/wrt/ngx_wrt.h index 1700f1f6c..6add6fe0b 100644 --- a/src/wasm/wrt/ngx_wrt.h +++ b/src/wasm/wrt/ngx_wrt.h @@ -16,6 +16,7 @@ typedef struct ngx_wavm_instance_s ngx_wavm_instance_t; typedef struct { const ngx_str_t *vm_name; const ngx_str_t *runtime_name; + ngx_str_t cache_config; ngx_str_t compiler; ngx_flag_t backtraces; ngx_array_t flags; diff --git a/src/wasm/wrt/ngx_wrt_wasmtime.c b/src/wasm/wrt/ngx_wrt_wasmtime.c index f42ee05fd..a8edb2742 100644 --- a/src/wasm/wrt/ngx_wrt_wasmtime.c +++ b/src/wasm/wrt/ngx_wrt_wasmtime.c @@ -17,6 +17,10 @@ typedef void (*wasmtime_config_set_int_pt)(wasm_config_t *config, typedef void (*wasmtime_config_set_bool_pt)(wasm_config_t *config, bool value); +static u_char *ngx_wasmtime_log_handler(ngx_wrt_res_t *res, u_char *buf, + size_t len); + + static ngx_int_t size_flag_handler(wasm_config_t *config, ngx_str_t *name, ngx_str_t *value, ngx_log_t *log, void *wrt_setter) @@ -129,10 +133,12 @@ profiler_flag_handler(wasm_config_t *config, ngx_str_t *name, ngx_str_t *value, static wasm_config_t * ngx_wasmtime_init_conf(ngx_wavm_conf_t *conf, ngx_log_t *log) { - wasm_config_t *config; + char *pathname; + u_char *errmsg; + wasm_config_t *config; + wasmtime_error_t *err; #if 0 wasm_name_t msg; - wasmtime_error_t *err = NULL; #endif ngx_wa_assert(conf->backtraces != NGX_CONF_UNSET); @@ -160,6 +166,39 @@ ngx_wasmtime_init_conf(ngx_wavm_conf_t *conf, ngx_log_t *log) wasmtime_config_static_memory_maximum_size_set(config, 0); #endif + if (conf->cache_config.len) { + ngx_wavm_log_error(NGX_LOG_INFO, log, NULL, + "setting wasmtime cache config file: \"%V\"", + &conf->cache_config); + + pathname = ngx_calloc(conf->cache_config.len + 1, log); + if (pathname == NULL) { + goto error; + } + + ngx_memcpy(pathname, conf->cache_config.data, conf->cache_config.len); + + err = wasmtime_config_cache_config_load(config, pathname); + + ngx_free(pathname); + + if (err) { + errmsg = ngx_calloc(NGX_MAX_ERROR_STR + 1, log); + if (errmsg == NULL) { + goto error; + } + + ngx_wasmtime_log_handler((ngx_wrt_res_t *) err, errmsg, + NGX_MAX_ERROR_STR); + + ngx_log_error(NGX_LOG_EMERG, log, 0, + "failed configuring wasmtime cache; %s", + errmsg); + + goto error; + } + } + if (conf->compiler.len) { if (ngx_str_eq(conf->compiler.data, conf->compiler.len, "auto", -1)) diff --git a/t/01-wasm/directives/011-wasmtime_cache_config_directive.t b/t/01-wasm/directives/011-wasmtime_cache_config_directive.t new file mode 100644 index 000000000..ffaa49f6f --- /dev/null +++ b/t/01-wasm/directives/011-wasmtime_cache_config_directive.t @@ -0,0 +1,114 @@ +# vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: + +use strict; +use lib '.'; +use t::TestWasmX; + +if ($t::TestWasmX::nginxV !~ m/wasmtime/) { + plan(skip_all => "not built with Wasmtime, skipping"); + +} else { + plan_tests(4); +} + +run_tests(); + +__DATA__ + +=== TEST 1: wasmtime cache_config - missing file +--- main_config + wasm { + wasmtime { + cache_config missing_file; + } + } +--- error_log eval +qr/\[emerg\] .*? failed configuring wasmtime cache; failed to read config file: missing_file/ +--- no_error_log +[error] +[crit] +--- must_die + + + +=== TEST 2: wasmtime cache_config - invalid contents file +--- user_files +>>> wasmtime_config.toml +invalid contents +--- main_config + wasm { + wasmtime { + cache_config $TEST_NGINX_HTML_DIR/wasmtime_config.toml; + } + } +--- error_log eval +qr@\[emerg\] .*? failed configuring wasmtime cache; failed to parse config file: .*/wasmtime_config.toml@ +--- no_error_log +[error] +[crit] +--- must_die + + + +=== TEST 3: wasmtime cache_config - valid file, cache disabled +--- user_files +>>> wasmtime_config.toml +[cache] +enabled = false +--- main_config eval +qq{ + wasm { + module hostcalls $t::TestWasmX::crates/hostcalls.wasm; + + wasmtime { + cache_config $ENV{TEST_NGINX_HTML_DIR}/wasmtime_config.toml; + } + } +} +--- config + location /t { + proxy_wasm hostcalls 'test=/t/set_request_header \ + value=Hello:wasm'; + proxy_wasm hostcalls 'test=/t/echo/headers'; + } +--- response_body +Host: localhost +Connection: close +Hello: wasm +--- error_log eval +qr@setting wasmtime cache config file: ".*/wasmtime_config.toml"@ +--- no_error_log +[error] + + + +=== TEST 4: wasmtime cache_config - valid file, cache enabled +--- user_files +>>> wasmtime_config.toml +[cache] +enabled = true +directory = "/tmp/ngx_wasm_module/cache/wasmtime" +--- main_config eval +qq{ + wasm { + module hostcalls $t::TestWasmX::crates/hostcalls.wasm; + + wasmtime { + cache_config $ENV{TEST_NGINX_HTML_DIR}/wasmtime_config.toml; + } + } +} +--- config + location /t { + proxy_wasm hostcalls 'test=/t/set_request_header \ + value=Hello:wasm'; + proxy_wasm hostcalls 'test=/t/echo/headers'; + } +--- response_body +Host: localhost +Connection: close +Hello: wasm +--- error_log eval +qr@setting wasmtime cache config file: ".*/wasmtime_config.toml"@ +--- no_error_log +[error]