diff --git a/docker/Dockerfile b/docker/Dockerfile index 830d498d24c5b8cf314684466264ea2b99791592..67adf677feea19c5d444046e71bb05c138dc0eee 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -29,7 +29,7 @@ RUN cp -f /home/opengauss/bashrc /home/opengauss/.bashrc && \ wget -q https://opengauss.obs.cn-south-1.myhuaweicloud.com/5.0.0/binarylibs/openGauss-third_party_binarylibs_openEuler_arm.tar.gz -O openGauss_third.tar.gz; \ fi && \ tar -xf openGauss_third.tar.gz && mv openGauss-third_party_binarylibs* binarylibs && rm -f openGauss_third.tar.gz && \ - curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash -s -- -v 0.11.2 && source /home/opengauss/.wasmedge/env && \ + curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash -s -- -v 0.11.2 && source /home/opengauss/.bashrc && \ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && source "$HOME/.cargo/env" && \ rustup target add wasm32-unknown-unknown && \ cargo install wasm-gc && source /home/opengauss/.bashrc && \ @@ -45,7 +45,7 @@ RUN cp -f /home/opengauss/bashrc /home/opengauss/.bashrc && \ cd openGauss-server-v5.0.0/contrib/wasm && make && make install && \ cd /home/opengauss && \ chmod +x /home/opengauss/entrypoint.sh && \ - cp /home/opengauss/openGauss-server-v5.0.0/contrib/wasm/examples/* /home/opengauss && \ + cp -rf /home/opengauss/openGauss-server-v5.0.0/contrib/wasm/examples/* /home/opengauss && \ sudo rm -rf /home/opengauss/binarylibs && \ sudo rm -rf /home/opengauss/openGauss-server-v5.0.0 && \ sudo rm -rf /home/opengauss/openGauss-wasm && \ diff --git a/wasm/benchmarks/fib.wasm b/wasm/benchmarks/fib.wasm deleted file mode 100644 index cbbd88bb8d4f6c82376deb46084f043ff8b4b80e..0000000000000000000000000000000000000000 Binary files a/wasm/benchmarks/fib.wasm and /dev/null differ diff --git a/wasm/examples/encrypt_decrypt/README b/wasm/examples/encrypt_decrypt/README index a8d595098268dc3b4e0b998305941958e3325412..d72c98d03af1210271239b6fbc5804b51103dd68 100644 --- a/wasm/examples/encrypt_decrypt/README +++ b/wasm/examples/encrypt_decrypt/README @@ -22,7 +22,7 @@ $$LANGUAGE PLPGSQL; CREATE TRIGGER encrypt_passwd_trigger AFTER INSERT ON users FOR EACH ROW EXECUTE PROCEDURE encrypt_password(); -INSERT INTO users VALUES ('peter', 'peter@huawei.com', 'roe-deer'); -INSERT INTO users VALUES ('josh', 'josh@huawei.com', 'turso'); +INSERT INTO users VALUES ('nelson', 'nelson@huawei.com', 'nelson_passwd'); +INSERT INTO users VALUES ('mickle', 'josh@huawei.com', 'mickle_passwd'); SELECT username, passwd, gs_decrypt(passwd, (SELECT secret FROM secrets LIMIT 1)) AS decrypted FROM users; diff --git a/wasm/examples/fib.wasm b/wasm/examples/fib.wasm deleted file mode 100644 index cbbd88bb8d4f6c82376deb46084f043ff8b4b80e..0000000000000000000000000000000000000000 Binary files a/wasm/examples/fib.wasm and /dev/null differ diff --git a/wasm/examples/fib.wat b/wasm/examples/fib.wat deleted file mode 100644 index 42a5a8b797149dce9495a471ea1c02d43fc3784b..0000000000000000000000000000000000000000 --- a/wasm/examples/fib.wat +++ /dev/null @@ -1,39 +0,0 @@ -(module - (type (;0;) (func (param i64) (result i64))) - (func $fib (type 0) (param i64) (result i64) - (local i64) - i64.const 0 - local.set 1 - block ;; label = @1 - local.get 0 - i64.const 2 - i64.lt_u - br_if 0 (;@1;) - i64.const 0 - local.set 1 - loop ;; label = @2 - local.get 0 - i64.const -1 - i64.add - call $fib - local.get 1 - i64.add - local.set 1 - local.get 0 - i64.const -2 - i64.add - local.tee 0 - i64.const 1 - i64.gt_u - br_if 0 (;@2;) - end - end - local.get 0 - local.get 1 - i64.add) - (memory (;0;) 16) - (global $__stack_pointer (mut i32) (i32.const 1048576)) - (global (;1;) i32 (i32.const 1048576)) - (global (;2;) i32 (i32.const 1048576)) - (export "memory" (memory 0)) - (export "fib" (func $fib))) diff --git a/wasm/examples/fib/Cargo.toml b/wasm/examples/fib/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..a3bfce995f76d83a3f8fadf7cc5f2766684b9f39 --- /dev/null +++ b/wasm/examples/fib/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "fib" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +opengauss_bindgen = "0.1.0" + +[lib] +crate-type = ["cdylib"] diff --git a/wasm/benchmarks/fib.sql b/wasm/examples/fib/fib.sql similarity index 69% rename from wasm/benchmarks/fib.sql rename to wasm/examples/fib/fib.sql index 86ad7676208c43b3c8c6f0856c009122676f5b10..c8e865817b38f8c76ae468c531aaba39dd9a611e 100644 --- a/wasm/benchmarks/fib.sql +++ b/wasm/examples/fib/fib.sql @@ -1,11 +1,11 @@ -CREATE OR REPLACE FUNCTION fibonacci (n integer) RETURNS decimal AS $$ +CREATE OR REPLACE FUNCTION sql_fib (n integer) RETURNS decimal AS $$ DECLARE counter bigint := 1; i decimal := 0; j decimal := 1; BEGIN - IF (n < 1) THEN - RETURN 0; + IF (n <= 1) THEN + RETURN n; END IF; WHILE counter <= n LOOP @@ -16,3 +16,4 @@ BEGIN RETURN i; END; $$ LANGUAGE plpgsql; + diff --git a/wasm/examples/fib/fib.wasm b/wasm/examples/fib/fib.wasm new file mode 100644 index 0000000000000000000000000000000000000000..75a4e448bd398371aa2ba06b73f13fb5b0e0f130 Binary files /dev/null and b/wasm/examples/fib/fib.wasm differ diff --git a/wasm/examples/fib/fib_aot.wasm b/wasm/examples/fib/fib_aot.wasm new file mode 100644 index 0000000000000000000000000000000000000000..46133eb84821472f618e02a79e9d1d30545258cf Binary files /dev/null and b/wasm/examples/fib/fib_aot.wasm differ diff --git a/wasm/examples/fib/gen_wasm.sh b/wasm/examples/fib/gen_wasm.sh new file mode 100755 index 0000000000000000000000000000000000000000..27778627ef2e4c34db50316b60c0ece71c00c0d9 --- /dev/null +++ b/wasm/examples/fib/gen_wasm.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -e + +OPENGAUSS_EXPORTED_FUNC=$1 +OPENGAUSS_COMPILED_WASM=opengauss-target/wasm32-unknown-unknown/release/fib.wasm +OPENGAUSS_OPTIMIZED_WASM=opengauss-target/fib.wasm + +CARGO_TARGET_DIR=opengauss-target cargo build --release --target wasm32-unknown-unknown +wasm-opt -Os $OPENGAUSS_COMPILED_WASM -o $OPENGAUSS_OPTIMIZED_WASM || : + diff --git a/wasm/benchmarks/fib.rs b/wasm/examples/fib/src/lib.rs similarity index 69% rename from wasm/benchmarks/fib.rs rename to wasm/examples/fib/src/lib.rs index d566ccf648ea822e74487d2d920912a568479cdf..821e520fc63d6e3d6d3741144c0e678003ca37dd 100644 --- a/wasm/benchmarks/fib.rs +++ b/wasm/examples/fib/src/lib.rs @@ -1,9 +1,9 @@ -#[no_mangle] -pub extern "C" fn fibonacci(n: u32) -> u64 { - if n <= 0 { - 0 - } else if n == 1 { - 1 +use opengauss_bindgen::*; + +#[opengauss_bindgen::opengauss_bindgen] +fn fib(n: u64) -> u64 { + if n <= 1 { + n } else { let mut accumulator = 0; let mut last = 0; diff --git a/wasm/examples/gcd.wat b/wasm/examples/others/gcd.wat similarity index 100% rename from wasm/examples/gcd.wat rename to wasm/examples/others/gcd.wat diff --git a/wasm/examples/sum.rs b/wasm/examples/others/sum.rs similarity index 100% rename from wasm/examples/sum.rs rename to wasm/examples/others/sum.rs diff --git a/wasm/examples/sum.wasm b/wasm/examples/others/sum.wasm similarity index 100% rename from wasm/examples/sum.wasm rename to wasm/examples/others/sum.wasm diff --git a/wasm/examples/tools/compile_wasm_to_ast b/wasm/examples/tools/compile_wasm_to_ast new file mode 100755 index 0000000000000000000000000000000000000000..d449adf1cc47eff036addc345c5573be4890470e Binary files /dev/null and b/wasm/examples/tools/compile_wasm_to_ast differ diff --git a/wasm/examples/tools/compile_wasm_to_ast.cpp b/wasm/examples/tools/compile_wasm_to_ast.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b445b698b14244cfaffd96109371dd7cdf81732 --- /dev/null +++ b/wasm/examples/tools/compile_wasm_to_ast.cpp @@ -0,0 +1,22 @@ +#include +#include +int main(int Argc, const char* Argv[]) { + /* Create the configure context. */ + WasmEdge_ConfigureContext *ConfCxt = WasmEdge_ConfigureCreate(); + /* ... Adjust settings in the configure context. */ + /* Result. */ + WasmEdge_Result Res; + + /* Create the compiler context. The configure context can be NULL. */ + WasmEdge_CompilerContext *CompilerCxt = WasmEdge_CompilerCreate(ConfCxt); + /* Compile the WASM file with input and output paths. */ + Res = WasmEdge_CompilerCompile(CompilerCxt, Argv[1], Argv[2]); + if (!WasmEdge_ResultOK(Res)) { + printf("Compilation failed: %s\n", WasmEdge_ResultGetMessage(Res)); + return 1; + } + + WasmEdge_CompilerDelete(CompilerCxt); + WasmEdge_ConfigureDelete(ConfCxt); + return 0; +} diff --git a/wasm/wasm_executor.cpp b/wasm/wasm_executor.cpp index 87513aa1eb61e1d71d022e31552690cf0b85c839..e69996258a027f6536d7c01a1505ae2f49692368 100644 --- a/wasm/wasm_executor.cpp +++ b/wasm/wasm_executor.cpp @@ -4,6 +4,7 @@ #include "access/hash.h" #include "miscadmin.h" #include "funcapi.h" +#include "executor/spi.h" #include #include #include @@ -28,10 +29,15 @@ extern "C" Datum wasm_invoke_function_text_2(PG_FUNCTION_ARGS); static const char * const malloc_func = "opengauss_malloc"; static const char OPENGAUSS_TEXT = 3; +typedef struct WasmVM { + WasmEdge_VMContext *vm_context; + std::string wasm_file; +} WasmVM; + typedef struct TupleInstanceState { TupleDesc tupd; - std::map::iterator currindex; - std::map::iterator lastindex; + std::map::iterator currindex; + std::map::iterator lastindex; } TupleInstanceState; typedef struct WasmFuncInfo { @@ -50,23 +56,23 @@ typedef struct TupleFuncState { #define MAX_PARAMS 5 #define MAX_RETURNS 1 -// Store the wasm file info globally -static std::map instances; +// Store the wasm vm info globally +static std::map instances; // Store the wasm exported function info globally static std::map*> exported_functions; -static std::string find_wasm_file(int64 instanceid) +static WasmVM* find_wasm_vm(int64 instanceid) { - std::map::iterator itor = instances.begin(); + std::map::iterator itor = instances.begin(); while (itor != instances.end()) { if (itor->first == instanceid) { return itor->second; } itor++; } - elog(DEBUG1, "wasm_executor: not find instance info for instanceid %ld", instanceid); - return ""; + // elog(DEBUG1, "wasm_executor: not find instance info for instanceid %ld", instanceid); + return NULL; } static std::vector* find_exported_func_list(int64 instanceid) @@ -78,7 +84,7 @@ static std::vector* find_exported_func_list(int64 instanceid) } itor++; } - elog(DEBUG1, "wasm_executor: not find exported func info for instanceid %ld", instanceid); + // elog(DEBUG1, "wasm_executor: not find exported func info for instanceid %ld", instanceid); return NULL; } @@ -91,15 +97,11 @@ static int64 generate_uuid(Datum input) static int64 wasm_invoke_function(char *instanceid_str, char* funcname, std::vector &args) { int64 instanceid = atol(instanceid_str); - std::string wasm_file = find_wasm_file(instanceid); - if (wasm_file == "") { + WasmVM* wasmVM = find_wasm_vm(instanceid); + if (wasmVM == NULL) { ereport(ERROR, (errmsg("wasm_executor: instance with id %ld is not find", instanceid))); } - WasmEdge_ConfigureContext *config_context = WasmEdge_ConfigureCreate(); - WasmEdge_ConfigureAddHostRegistration(config_context, WasmEdge_HostRegistration_Wasi); - WasmEdge_VMContext *vm_conext = WasmEdge_VMCreate(config_context, NULL); - WasmEdge_Value params[args.size()]; for (unsigned int i = 0; i < args.size(); ++i) { params[i] = WasmEdge_ValueGenI64(args[i]); @@ -107,18 +109,14 @@ static int64 wasm_invoke_function(char *instanceid_str, char* funcname, std::vec WasmEdge_Value result[1]; WasmEdge_String wasm_func = WasmEdge_StringCreateByCString(funcname); - WasmEdge_Result ret = WasmEdge_VMRunWasmFromFile(vm_conext, wasm_file.c_str(), wasm_func, params, args.size(), result, 1); + WasmEdge_Result ret = WasmEdge_VMExecute(wasmVM->vm_context, wasm_func, params, args.size(), result, 1); if (!WasmEdge_ResultOK(ret)) { - WasmEdge_VMDelete(vm_conext); - WasmEdge_ConfigureDelete(config_context); WasmEdge_StringDelete(wasm_func); ereport(ERROR, (errmsg("wasm_executor: call func %s failed", funcname))); } int64 ret_val = 0; ret_val = WasmEdge_ValueGetI64(result[0]); /* Resources deallocations. */ - WasmEdge_VMDelete(vm_conext); - WasmEdge_ConfigureDelete(config_context); WasmEdge_StringDelete(wasm_func); return ret_val; @@ -127,32 +125,13 @@ static int64 wasm_invoke_function(char *instanceid_str, char* funcname, std::vec static char* wasm_invoke_function2(char *instanceid_str, char* funcname, std::vector args) { int64 instanceid = atol(instanceid_str); - std::string wasm_file = find_wasm_file(instanceid); - if (wasm_file == "") { + WasmVM* wasmVM = find_wasm_vm(instanceid); + if (wasmVM == NULL) { ereport(ERROR, (errmsg("wasm_executor: instance with id %ld is not find", instanceid))); } - WasmEdge_ConfigureContext *config_context = WasmEdge_ConfigureCreate(); - WasmEdge_ConfigureAddHostRegistration(config_context, WasmEdge_HostRegistration_Wasi); - WasmEdge_ConfigureAddHostRegistration(config_context, WasmEdge_HostRegistration_WasiNN); - WasmEdge_VMContext *vm_conext = WasmEdge_VMCreate(config_context, NULL); - - WasmEdge_Result res = WasmEdge_VMLoadWasmFromFile(vm_conext, wasm_file.c_str()); - if (!WasmEdge_ResultOK(res)) { - ereport(ERROR, (errmsg("wasm_executor: wasm vm load failed: %s", WasmEdge_ResultGetMessage(res)))); - } - - res = WasmEdge_VMValidate(vm_conext); - if (!WasmEdge_ResultOK(res)) { - ereport(ERROR, (errmsg("wasm_executor: wasm vm validate failed: %s", WasmEdge_ResultGetMessage(res)))); - } - - res = WasmEdge_VMInstantiate(vm_conext); - if (!WasmEdge_ResultOK(res)) { - ereport(ERROR, (errmsg("wasm_executor: wasm vm initialize failed: %s", WasmEdge_ResultGetMessage(res)))); - } - - const WasmEdge_ModuleInstanceContext* instance_ctx = WasmEdge_VMGetActiveModule(vm_conext); + WasmEdge_VMContext *vm_context = wasmVM->vm_context; + const WasmEdge_ModuleInstanceContext* instance_ctx = WasmEdge_VMGetActiveModule(vm_context); WasmEdge_String mem_name = WasmEdge_StringCreateByCString("memory"); WasmEdge_MemoryInstanceContext* mem_ctx = WasmEdge_ModuleInstanceFindMemory(instance_ctx, mem_name); WasmEdge_StringDelete(mem_name); @@ -164,12 +143,13 @@ static char* wasm_invoke_function2(char *instanceid_str, char* funcname, std::ve int mem_size = WasmEdge_MemoryInstanceGetPageSize(mem_ctx) * 65536; int mem_offset = mem_size; + WasmEdge_Result res; for (unsigned int i = 0; i < args.size(); ++i) { int text_len = strlen(args[i]); const char *text = args[i]; malloc_param[0] = WasmEdge_ValueGenI32(text_len + 2); WasmEdge_String wasmedge_func_name = WasmEdge_StringCreateByCString("opengauss_malloc"); - res = WasmEdge_VMExecute(vm_conext, wasmedge_func_name, malloc_param, 1, results, 1); + res = WasmEdge_VMExecute(vm_context, wasmedge_func_name, malloc_param, 1, results, 1); WasmEdge_StringDelete(wasmedge_func_name); if (!WasmEdge_ResultOK(res)) { ereport(ERROR, (errmsg("wasm_executor: call opengauss malloc failed"))); @@ -184,7 +164,7 @@ static char* wasm_invoke_function2(char *instanceid_str, char* funcname, std::ve } WasmEdge_String wasmedge_func_name = WasmEdge_StringCreateByCString(funcname); - res = WasmEdge_VMExecute(vm_conext, wasmedge_func_name, params, args.size(), results, 1); + res = WasmEdge_VMExecute(vm_context, wasmedge_func_name, params, args.size(), results, 1); WasmEdge_StringDelete(wasmedge_func_name); if (!WasmEdge_ResultOK(res)) { ereport(ERROR, (errmsg("wasm_executor: call func %s failed", funcname))); @@ -209,17 +189,13 @@ static char* wasm_invoke_function2(char *instanceid_str, char* funcname, std::ve memcpy(result, wasm_result, wasm_result_len); result[wasm_result_len] = '\0'; - /* Resources deallocations. */ - WasmEdge_VMDelete(vm_conext); - WasmEdge_ConfigureDelete(config_context); - return result; } static void wasm_export_funcs_query(int64 instanceid, TupleFuncState* inter_call_data) { - std::string wasm_file = find_wasm_file(instanceid); - if (wasm_file == "") { + WasmVM *wasmVM = find_wasm_vm(instanceid); + if (wasmVM == NULL) { ereport(ERROR, (errmsg("wasm_executor: instance with id %ld is not find", instanceid))); } @@ -227,47 +203,36 @@ static void wasm_export_funcs_query(int64 instanceid, TupleFuncState* inter_call if (functions != NULL) { inter_call_data->currindex = functions->begin(); inter_call_data->lastindex = functions->end(); - elog(DEBUG1, "wasm_executor:find exported func info for instanceid %ld", instanceid); + //elog(DEBUG1, "wasm_executor:find exported func info for instanceid %ld", instanceid); return; } functions = new(std::nothrow)std::vector; exported_functions.insert(std::pair*>(instanceid, functions)); - WasmEdge_StoreContext *store_cxt = WasmEdge_StoreCreate(); - WasmEdge_VMContext *vm_cxt = WasmEdge_VMCreate(NULL, store_cxt); - - WasmEdge_VMLoadWasmFromFile(vm_cxt, wasm_file.c_str()); - WasmEdge_VMValidate(vm_cxt); - WasmEdge_VMInstantiate(vm_cxt); - WasmEdge_String func_name_list[BUF_LEN]; const WasmEdge_FunctionTypeContext *func_type_list[BUF_LEN]; /* * If the list length is larger than the buffer length, the overflowed data * will be discarded. */ - uint32_t rel_func_num = WasmEdge_VMGetFunctionList(vm_cxt, func_name_list, func_type_list, BUF_LEN); + uint32_t rel_func_num = WasmEdge_VMGetFunctionList(wasmVM->vm_context, func_name_list, func_type_list, BUF_LEN); for (unsigned int i = 0; i < rel_func_num && i < BUF_LEN; ++i) { char tmp_buffer[BUF_LEN] = {0}; uint32_t func_name_len = WasmEdge_StringCopy(func_name_list[i], tmp_buffer, sizeof(tmp_buffer)); - elog(DEBUG1, "wasm_executor: exported function string length: %u, name: %s\n", func_name_len, tmp_buffer); + // elog(DEBUG1, "wasm_executor: exported function string length: %u, name: %s\n", func_name_len, tmp_buffer); if (strcmp(tmp_buffer, malloc_func) == 0) { - elog(DEBUG1, "wasm_executor: opengauss_malloc is not need to export to user\n"); + // elog(DEBUG1, "wasm_executor: opengauss_malloc is not need to export to user\n"); continue; } uint32_t param_nums = WasmEdge_FunctionTypeGetParametersLength(func_type_list[i]); if (param_nums > MAX_PARAMS) { - WasmEdge_StoreDelete(store_cxt); - WasmEdge_VMDelete(vm_cxt); ereport(ERROR, (errmsg("wasm_executor: func %s has more than 10 params which not support", tmp_buffer))); } uint32_t return_num = WasmEdge_FunctionTypeGetReturnsLength(func_type_list[i]); if (return_num > MAX_RETURNS) { - WasmEdge_StoreDelete(store_cxt); - WasmEdge_VMDelete(vm_cxt); ereport(ERROR, (errmsg("wasm_executor: func %s has more than 1 return value which not support", tmp_buffer))); } @@ -281,8 +246,6 @@ static void wasm_export_funcs_query(int64 instanceid, TupleFuncState* inter_call } else if (param_buffer[j] == WasmEdge_ValType_I64) { funcinfo->inputs.push_back("bigint"); } else { - WasmEdge_StoreDelete(store_cxt); - WasmEdge_VMDelete(vm_cxt); ereport(ERROR, (errmsg("wasm_executor: not support the value type(%d) for now", param_buffer[j]))); } } @@ -293,8 +256,6 @@ static void wasm_export_funcs_query(int64 instanceid, TupleFuncState* inter_call } else if (param_buffer[0] == WasmEdge_ValType_I64) { funcinfo->outputs = "bigint"; } else { - WasmEdge_StoreDelete(store_cxt); - WasmEdge_VMDelete(vm_cxt); ereport(ERROR, (errmsg("wasm_executor: not support the value type(%d) for now", param_buffer[0]))); } @@ -302,54 +263,65 @@ static void wasm_export_funcs_query(int64 instanceid, TupleFuncState* inter_call functions->push_back(funcinfo); } - WasmEdge_StoreDelete(store_cxt); - WasmEdge_VMDelete(vm_cxt); - inter_call_data->currindex = functions->begin(); inter_call_data->lastindex = functions->end(); - elog(DEBUG1, "wasm_executor:init exported func info for instanceid %ld", instanceid); + // elog(DEBUG1, "wasm_executor:init exported func info for instanceid %ld", instanceid); } -PG_FUNCTION_INFO_V1(wasm_create_instance); -Datum wasm_create_instance(PG_FUNCTION_ARGS) -{ - int64 uuid = generate_uuid(PG_GETARG_DATUM(0)); - text *arg = PG_GETARG_TEXT_P(0); - char* filepath = text_to_cstring(arg); - canonicalize_path(filepath); - - if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("wasm_executor: must be system admin to create wasm instance")))); - - std::string wasm_file = find_wasm_file(uuid); - if (wasm_file != "") { - ereport(NOTICE, (errmsg("wasm_executor: instance already created for %s", filepath))); - return UInt32GetDatum(uuid); - } - +static WasmVM* create_wasm_instance_internal(char* filepath) +{ WasmEdge_ConfigureContext *config_context = WasmEdge_ConfigureCreate(); WasmEdge_ConfigureAddHostRegistration(config_context, WasmEdge_HostRegistration_Wasi); + WasmEdge_ConfigureAddHostRegistration(config_context, WasmEdge_HostRegistration_WasiNN); WasmEdge_VMContext *vm_cxt = WasmEdge_VMCreate(config_context, NULL); WasmEdge_Result result = WasmEdge_VMLoadWasmFromFile(vm_cxt, filepath); if (!WasmEdge_ResultOK(result)) { - WasmEdge_VMDelete(vm_cxt); WasmEdge_ConfigureDelete(config_context); ereport(ERROR, (errmsg("wasm_executor: failed to load %s", filepath))); } result = WasmEdge_VMValidate(vm_cxt); if (!WasmEdge_ResultOK(result)) { - WasmEdge_VMDelete(vm_cxt); WasmEdge_ConfigureDelete(config_context); ereport(ERROR, (errmsg("wasm_executor: wasm file validation failed %s", WasmEdge_ResultGetMessage(result)))); } - wasm_file = filepath; - instances.insert(std::pair(uuid, wasm_file)); - WasmEdge_VMDelete(vm_cxt); + result = WasmEdge_VMInstantiate(vm_cxt); + if (!WasmEdge_ResultOK(result)) { + WasmEdge_ConfigureDelete(config_context); + ereport(ERROR, (errmsg("wasm_executor: wasm vm initialize failed: %s", WasmEdge_ResultGetMessage(result)))); + } WasmEdge_ConfigureDelete(config_context); + + WasmVM *wasmVM = new (std::nothrow)WasmVM(); + wasmVM->vm_context = vm_cxt; + wasmVM->wasm_file = filepath; + + return wasmVM; +} + +PG_FUNCTION_INFO_V1(wasm_create_instance); +Datum wasm_create_instance(PG_FUNCTION_ARGS) +{ + int64 uuid = generate_uuid(PG_GETARG_DATUM(0)); + text *arg = PG_GETARG_TEXT_P(0); + char* filepath = text_to_cstring(arg); + canonicalize_path(filepath); + + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("wasm_executor: must be system admin to create wasm instance")))); + + WasmVM *wasmVM = find_wasm_vm(uuid); + if (wasmVM != NULL) { + ereport(NOTICE, (errmsg("wasm_executor: instance already created for %s", filepath))); + return UInt32GetDatum(uuid); + } + + wasmVM = create_wasm_instance_internal(filepath); + instances.insert(std::pair(uuid, wasmVM)); + return Int64GetDatum(uuid); } @@ -363,14 +335,14 @@ Datum wasm_drop_instance(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("wasm_executor: must be system admin to delete wasm instance")))); - std::map::iterator institor = instances.begin(); + std::map::iterator institor = instances.begin(); while (institor != instances.end() && institor->first != instanceid) { institor++; } if (institor == instances.end()) { ereport(ERROR, (errmsg("wasm_executor:instance with id=%ld not exist", instanceid))); } - module_path = CStringGetTextDatum((institor->second).c_str()); + module_path = CStringGetTextDatum((institor->second->wasm_file).c_str()); instances.erase(institor); std::map*>::iterator funcitor = exported_functions.begin(); @@ -418,7 +390,7 @@ Datum wasm_get_instances(PG_FUNCTION_ARGS) errno_t rc = memset_s(nulls, sizeof(nulls), 0, sizeof(nulls)); securec_check_c(rc, "\0", "\0"); - std::string wasm_file = inter_call_data->currindex->second; + std::string wasm_file = inter_call_data->currindex->second->wasm_file; values[0] = Int64GetDatum(inter_call_data->currindex->first); values[1] = CStringGetTextDatum(wasm_file.c_str()); @@ -599,4 +571,41 @@ Datum wasm_invoke_function_text_2(PG_FUNCTION_ARGS) char* result = wasm_invoke_function2(instanceid, funcname, params); return CStringGetTextDatum(result); +} + +/* + * Module Load Callback + */ +void _PG_init(void) +{ + /** + * When openGauss start up and load the wasm_executor.so, it should call + * this function to check whether it has created instances. + * If has, call the create instance interface to restore them. + */ + int ret; + if ((ret = SPI_connect()) < 0) { + elog(ERROR, "wasm_executor: SPI_connect returned %d", ret); + } + + if ((ret = SPI_exec("SELECT id, wasm_file FROM wasm.instances", 0)) < 0) { + elog(ERROR, "wasm_executor: SPI_connect exec query failed: %d", ret); + } + + if (SPI_tuptable) { + TupleDesc tupdesc = SPI_tuptable->tupdesc; + SPITupleTable *tuptable = SPI_tuptable; + + int64 rows = SPI_processed; + for (int i = 0; i < rows; i++) { + HeapTuple tuple = tuptable->vals[i]; + char* instanceId = SPI_getvalue(tuple, tupdesc, 1); + char *filepath = SPI_getvalue(tuple, tupdesc, 2); + + WasmVM *wasmVM = create_wasm_instance_internal(filepath); + instances.insert(std::pair(atol(instanceId), wasmVM)); + } + } + + SPI_finish(); } \ No newline at end of file