diff --git a/src/common/function/FunctionManager.cpp b/src/common/function/FunctionManager.cpp index dd9fa3516f5..9a1bea2df48 100644 --- a/src/common/function/FunctionManager.cpp +++ b/src/common/function/FunctionManager.cpp @@ -422,6 +422,11 @@ std::unordered_map> FunctionManager::typ TypeSignature({Value::Type::STRING, Value::Type::STRING,Value::Type::STRING}, Value::Type::BOOL), }}, + {"delete_wasm", // wasm function,params([Function Name] [Function Handler] [Function Content(TODO://base64)]) + { // return BOOL + TypeSignature({Value::Type::STRING}, + Value::Type::BOOL), + }}, }; // static @@ -474,40 +479,28 @@ FunctionManager::FunctionManager() { } auto wasmFunctionName = args[0].get().getStr(); auto wasmFunctionHandler = args[1].get().getStr(); -// auto watStr = args[2].get().getStr(); - - auto watStr = "(module\n" - " (func $gcd (param i32 i32) (result i32)\n" - " (local i32)\n" - " block ;; label = @1\n" - " block ;; label = @2\n" - " local.get 0\n" - " br_if 0 (;@2;)\n" - " local.get 1\n" - " local.set 2\n" - " br 1 (;@1;)\n" - " end\n" - " loop ;; label = @2\n" - " local.get 1\n" - " local.get 0\n" - " local.tee 2\n" - " i32.rem_u\n" - " local.set 0\n" - " local.get 2\n" - " local.set 1\n" - " local.get 0\n" - " br_if 0 (;@2;)\n" - " end\n" - " end\n" - " local.get 2\n" - " )\n" - " (export \"main\" (func $gcd))\n" - ")"; + auto watStr = args[2].get().getStr(); WasmFunctionManager& wasmFunctionManager = WasmFunctionManager::getInstance(); wasmFunctionManager.RegisterFunction(wasmFunctionName,wasmFunctionHandler,watStr); return true; }; } + { + auto &attr = functions_["delete_wasm"]; + attr.minArity_ = 1; + attr.maxArity_ = 2; + attr.isPure_ = false; + // begin wasm call + attr.body_ = [](const auto &args) -> Value { + if (!args[0].get().isStr()) { + return Value::kNullBadType; + } + auto wasmFunctionName = args[0].get().getStr(); + WasmFunctionManager& wasmFunctionManager = WasmFunctionManager::getInstance(); + wasmFunctionManager.DeleteFunction(wasmFunctionName); + return true; + }; + } { auto &attr = functions_["wasm"]; attr.minArity_ = 1; @@ -521,7 +514,8 @@ FunctionManager::FunctionManager() { auto wasmFunctionName = args[0].get().getStr(); auto ¶ms = args[1].get().getList(); WasmFunctionManager& wasmFunctionManager = WasmFunctionManager::getInstance(); - auto wasmRuntimeResult = wasmFunctionManager.runWithHandle(wasmFunctionName,params); + auto wasmRuntimeResult = + wasmFunctionManager.runWithNebulaDataHandle(wasmFunctionName, params); return wasmRuntimeResult; }; } diff --git a/src/common/function/WasmFunctionManager.cpp b/src/common/function/WasmFunctionManager.cpp index ff2ad2d06df..ff7eaff85f8 100644 --- a/src/common/function/WasmFunctionManager.cpp +++ b/src/common/function/WasmFunctionManager.cpp @@ -32,7 +32,7 @@ std::string readFile(const std::string name) { // std::cout << "gcd(6, 27) = " << results[0].i32() << "\n"; //} -WasmRuntime WasmFunctionManager::createInstanceAndFunction(const std::string &watString, +WasmtimeRunInstance WasmFunctionManager::createInstanceAndFunction(const std::string &watString, const std::string functionHandler) { auto module = wasmtime::Module::compile(*engine, watString).unwrap(); auto instance = wasmtime::Instance::create(store, module, {}).unwrap(); @@ -40,10 +40,10 @@ WasmRuntime WasmFunctionManager::createInstanceAndFunction(const std::string &wa auto function_obj = instance.get(store, functionHandler); wasmtime::Func *func = std::get_if(&*function_obj); - return WasmRuntime(*func, instance); + return WasmtimeRunInstance(*func, instance); } -nebula::List WasmFunctionManager::runWithHandle(std::string functionName, nebula::List args) { +nebula::List WasmFunctionManager::runWithNebulaDataHandle(std::string functionName, nebula::List args) { if(modules.find(functionName) == modules.end()){ // return not found! @@ -51,7 +51,7 @@ nebula::List WasmFunctionManager::runWithHandle(std::string functionName, nebula Error.emplace_back("Not Found Function"); return nebula::List(Error); } - auto value = modules.at(functionName); + auto module = modules.at(functionName); // prepostcess auto values = args.values; std::vector functionArgs; @@ -60,7 +60,7 @@ nebula::List WasmFunctionManager::runWithHandle(std::string functionName, nebula functionArgs.push_back(val.getInt()); } // run - auto functionResult = WasmFunctionManager::run(value, functionArgs); + auto functionResult = WasmFunctionManager::run(module, functionArgs); // postprocess std::vector tmpProcess; @@ -69,7 +69,17 @@ nebula::List WasmFunctionManager::runWithHandle(std::string functionName, nebula } return nebula::List(tmpProcess); } -std::vector WasmFunctionManager::run(const WasmRuntime &wasmRuntime, std::vector args) { + +std::vector WasmFunctionManager::run(std::string functionName, std::vector args) { + if(modules.find(functionName) == modules.end()){ + return std::vector(); + } + auto module = modules.at(functionName); + // run + return WasmFunctionManager::run(module, args); + +} +std::vector WasmFunctionManager::run(const WasmtimeRunInstance &wasmRuntime, std::vector args) { // the args which wasm run std::vector argv; @@ -88,11 +98,17 @@ std::vector WasmFunctionManager::run(const WasmRuntime &wasmRuntime, std::v return result; } -bool WasmFunctionManager::RegisterFunction(std::string functionName,std::string functionHandler,const std::string &watString) { +bool WasmFunctionManager::RegisterFunction(std::string functionName,std::string functionHandler,const std::string &watBase64String) { // default functionHandler = "main" + auto watString = myBase64Decode(watBase64String); auto wasmRuntime = createInstanceAndFunction(watString,functionHandler); modules.emplace(functionName,wasmRuntime); return true; } +bool WasmFunctionManager::DeleteFunction(std::string functionName) { + modules.erase(functionName); + return true; +} + } // namespace nebula diff --git a/src/common/function/WasmFunctionManager.h b/src/common/function/WasmFunctionManager.h index fa02a991eee..4aabba56e27 100644 --- a/src/common/function/WasmFunctionManager.h +++ b/src/common/function/WasmFunctionManager.h @@ -6,15 +6,20 @@ #define NEBULA_GRAPH_WASMFUNCTIONMANAGER_H #include "common/datatypes/Value.h" #include "common/function/FunctionManager.h" +#include +#include +#include +#include +#include #include namespace nebula { -struct WasmRuntime { +struct WasmtimeRunInstance { wasmtime::Func func; wasmtime::Instance instance; - WasmRuntime(const wasmtime::Func &func, const wasmtime::Instance &instance) + WasmtimeRunInstance(const wasmtime::Func &func, const wasmtime::Instance &instance) : func(func), instance(instance) {} }; @@ -23,7 +28,7 @@ class WasmFunctionManager { wasmtime::Engine *engine; wasmtime::Store *store; /* data */ - std::unordered_map modules; + std::unordered_map modules; WasmFunctionManager() { engine = new wasmtime::Engine; store = new wasmtime::Store(*engine); @@ -35,6 +40,20 @@ class WasmFunctionManager { } WasmFunctionManager(const WasmFunctionManager&); WasmFunctionManager& operator=(const WasmFunctionManager&); + + // base64 tool + constexpr static const char b64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + constexpr static const char reverse_table[128] = { + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, + 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, + 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64 + }; public: // static WasmFunctionManager& getInstance() { // static WasmFunctionManager instance; @@ -54,13 +73,78 @@ class WasmFunctionManager { void runWat(const std::string &watString) const; - WasmRuntime createInstanceAndFunction(const std::string &watString, + WasmtimeRunInstance createInstanceAndFunction(const std::string &watString, const std::string functionHandler); - std::vector run(const WasmRuntime &wasmRuntime, std::vector args); + std::vector run(const WasmtimeRunInstance &wasmRuntime, std::vector args); bool RegisterFunction(std::string functionName, std::string functionHandler, - const std::string &watString); - List runWithHandle(std::string functionName, List args); + const std::string &watBase64String); + bool DeleteFunction(std::string functionName); + List runWithNebulaDataHandle(std::string functionName, List args); + std::vector run(std::string functionName, std::vector args); + + // base64 tool + static std::string myBase64Encode(const ::std::string &bindata) + { + using ::std::string; + using ::std::numeric_limits; + + if (bindata.size() > (numeric_limits::max() / 4u) * 3u) { + throw ::std::length_error("Converting too large a string to base64."); + } + + const ::std::size_t binlen = bindata.size(); + // Use = signs so the end is properly padded. + string retval((((binlen + 2) / 3) * 4), '='); + ::std::size_t outpos = 0; + int bits_collected = 0; + unsigned int accumulator = 0; + const string::const_iterator binend = bindata.end(); + + for (string::const_iterator i = bindata.begin(); i != binend; ++i) { + accumulator = (accumulator << 8) | (*i & 0xffu); + bits_collected += 8; + while (bits_collected >= 6) { + bits_collected -= 6; + retval[outpos++] = b64_table[(accumulator >> bits_collected) & 0x3fu]; + } + } + if (bits_collected > 0) { // Any trailing bits that are missing. + assert(bits_collected < 6); + accumulator <<= 6 - bits_collected; + retval[outpos++] = b64_table[accumulator & 0x3fu]; + } + assert(outpos >= (retval.size() - 2)); + assert(outpos <= retval.size()); + return retval; + } + + static std::string myBase64Decode(const ::std::string &ascdata) + { + using ::std::string; + string retval; + const string::const_iterator last = ascdata.end(); + int bits_collected = 0; + unsigned int accumulator = 0; + + for (string::const_iterator i = ascdata.begin(); i != last; ++i) { + const int c = *i; + if (::std::isspace(c) || c == '=') { + // Skip whitespace and padding. Be liberal in what you accept. + continue; + } + if ((c > 127) || (c < 0) || (reverse_table[c] > 63)) { + throw ::std::invalid_argument("This contains characters not legal in a base64 encoded string."); + } + accumulator = (accumulator << 6) | reverse_table[c]; + bits_collected += 6; + if (bits_collected >= 8) { + bits_collected -= 8; + retval += static_cast((accumulator >> bits_collected) & 0xffu); + } + } + return retval; + } }; } // namespace nebula diff --git a/src/common/function/test/WasmFunctionManagerTest.cpp b/src/common/function/test/WasmFunctionManagerTest.cpp index af0e021b837..73b9290eef0 100644 --- a/src/common/function/test/WasmFunctionManagerTest.cpp +++ b/src/common/function/test/WasmFunctionManagerTest.cpp @@ -7,36 +7,38 @@ namespace nebula { namespace graph { TEST(WasmFunctionTest, gen) { - auto WatStr = "(module\n" - " (func $gcd (param i32 i32) (result i32)\n" - " (local i32)\n" - " block ;; label = @1\n" - " block ;; label = @2\n" - " local.get 0\n" - " br_if 0 (;@2;)\n" - " local.get 1\n" - " local.set 2\n" - " br 1 (;@1;)\n" - " end\n" - " loop ;; label = @2\n" - " local.get 1\n" - " local.get 0\n" - " local.tee 2\n" - " i32.rem_u\n" - " local.set 0\n" - " local.get 2\n" - " local.set 1\n" - " local.get 0\n" - " br_if 0 (;@2;)\n" - " end\n" - " end\n" - " local.get 2\n" - " )\n" - " (export \"main\" (func $gcd))\n" - ")"; - auto wasmRuntime = WasmFunctionManager::createInstanceAndFunction(WatStr,"main"); - auto result = WasmFunctionManager::run(wasmRuntime,{6, 27}); +// auto watStr = "(module\n" +// " (func $gcd (param i32 i32) (result i32)\n" +// " (local i32)\n" +// " block ;; label = @1\n" +// " block ;; label = @2\n" +// " local.get 0\n" +// " br_if 0 (;@2;)\n" +// " local.get 1\n" +// " local.set 2\n" +// " br 1 (;@1;)\n" +// " end\n" +// " loop ;; label = @2\n" +// " local.get 1\n" +// " local.get 0\n" +// " local.tee 2\n" +// " i32.rem_u\n" +// " local.set 0\n" +// " local.get 2\n" +// " local.set 1\n" +// " local.get 0\n" +// " br_if 0 (;@2;)\n" +// " end\n" +// " end\n" +// " local.get 2\n" +// " )\n" +// " (export \"main\" (func $gcd))\n" +// ")"; + auto WatBase64Str = "KG1vZHVsZQogIChmdW5jICRnY2QgKHBhcmFtIGkzMiBpMzIpIChyZXN1bHQgaTMyKQogICAgKGxvY2FsIGkzMikKICAgIGJsb2NrICA7OyBsYWJlbCA9IEAxCiAgICAgIGJsb2NrICA7OyBsYWJlbCA9IEAyCiAgICAgICAgbG9jYWwuZ2V0IDAKICAgICAgICBicl9pZiAwICg7QDI7KQogICAgICAgIGxvY2FsLmdldCAxCiAgICAgICAgbG9jYWwuc2V0IDIKICAgICAgICBiciAxICg7QDE7KQogICAgICBlbmQKICAgICAgbG9vcCAgOzsgbGFiZWwgPSBAMgogICAgICAgIGxvY2FsLmdldCAxCiAgICAgICAgbG9jYWwuZ2V0IDAKICAgICAgICBsb2NhbC50ZWUgMgogICAgICAgIGkzMi5yZW1fdQogICAgICAgIGxvY2FsLnNldCAwCiAgICAgICAgbG9jYWwuZ2V0IDIKICAgICAgICBsb2NhbC5zZXQgMQogICAgICAgIGxvY2FsLmdldCAwCiAgICAgICAgYnJfaWYgMCAoO0AyOykKICAgICAgZW5kCiAgICBlbmQKICAgIGxvY2FsLmdldCAyCiAgKQogIChleHBvcnQgIm1haW4iIChmdW5jICRnY2QpKSA7OyBleHBvcnQgd2l0aCBtYWluCikK"; + WasmFunctionManager& wasmFunctionManager = WasmFunctionManager::getInstance(); + wasmFunctionManager.RegisterFunction("gcd","main",WatBase64Str); + auto result = wasmFunctionManager.run("gcd",{6, 27}); std::cout << result[0] << "\n"; } // namespace graph }} \ No newline at end of file