This is an automated email from the ASF dual-hosted git repository.

kichan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new ab0a572882 Remove reference to WAVM (#10147)
ab0a572882 is described below

commit ab0a572882377165109fecc6f818154bdacb4bca
Author: Kit Chan <kic...@apache.org>
AuthorDate: Fri Aug 4 09:47:50 2023 -0700

    Remove reference to WAVM (#10147)
---
 configure.ac                                       |   3 -
 doc/admin-guide/plugins/wasm.en.rst                |  15 +--
 plugins/experimental/wasm/Makefile.inc             |   2 +
 .../wasm/lib/include/proxy-wasm/context.h          |   6 +-
 .../wasm/lib/include/proxy-wasm/wasm.h             |   1 +
 plugins/experimental/wasm/lib/src/context.cc       |   6 ++
 plugins/experimental/wasm/lib/src/hash.cc          |  54 ++++++++++
 plugins/experimental/wasm/lib/src/hash.h           |  27 +++++
 plugins/experimental/wasm/lib/src/wamr/wamr.cc     |  28 +++--
 plugins/experimental/wasm/lib/src/wasm.cc          | 116 +++++++++++++++------
 10 files changed, 201 insertions(+), 57 deletions(-)

diff --git a/configure.ac b/configure.ac
index 73d8a2c587..91445116c7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1441,9 +1441,6 @@ AC_SUBST(use_quic)
 AC_SUBST(has_quiche)
 AM_CONDITIONAL([ENABLE_QUIC], [test "x$enable_quic" = "xyes"])
 
-# Check for optional WAVM library
-TS_CHECK_WAVM
-
 #
 # Enable experimental/uri_signing plugin
 # This is here, instead of above, because it needs to know if PCRE is 
available.
diff --git a/doc/admin-guide/plugins/wasm.en.rst 
b/doc/admin-guide/plugins/wasm.en.rst
index cf92af6157..ad07543c5a 100644
--- a/doc/admin-guide/plugins/wasm.en.rst
+++ b/doc/admin-guide/plugins/wasm.en.rst
@@ -36,7 +36,7 @@ How it Works
 
 The plugin uses the library and header files from the Proxy-Wasm project.
 
-* 
https://github.com/proxy-wasm/proxy-wasm-cpp-host/tree/72ce32f7b11f9190edf874028255e1309e41690f
+* 
https://github.com/proxy-wasm/proxy-wasm-cpp-host/tree/b7e690703c7f26707438a2f1ebd7c197bc8f0296
 * 
https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/tree/fd0be8405db25de0264bdb78fae3a82668c03782
 
 Proxy-Wasm in turn uses an underlying WebAssembly runtime to execute the 
WebAssembly module. (Currently only WAMR and
@@ -56,9 +56,9 @@ Compiling the Plugin
 
 ::
 
-  wget 
https://github.com/bytecodealliance/wasm-micro-runtime/archive/c3d66f916ef8093e5c8cacf3329ed968f807cf58.tar.gz
-  tar zxvf c3d66f916ef8093e5c8cacf3329ed968f807cf58.tar.gz
-  cd wasm-micro-runtime-c3d66f916ef8093e5c8cacf3329ed968f807cf58
+  wget 
https://github.com/bytecodealliance/wasm-micro-runtime/archive/refs/tags/WAMR-1.2.1.tar.gz
+  tar zxvf WAMR-1.2.1.tar.gz
+  cd wasm-micro-runtime-WAMR-1.2.1
   cp core/iwasm/include/* /usr/local/include/
   cd product-mini/platforms/linux
   mkdir build
@@ -71,13 +71,14 @@ Compiling the Plugin
 
 ::
 
-  wget 
https://github.com/WasmEdge/WasmEdge/archive/refs/tags/proxy-wasm/0.11.2.tar.gz
-  tar zxvf 0.11.2.tar.gz
-  cd WasmEdge-proxy-wasm-0.11.2/utils
+  wget 
https://github.com/WasmEdge/WasmEdge/archive/refs/tags/proxy-wasm/0.13.1.tar.gz
+  tar zxvf 0.13.1.tar.gz
+  cd WasmEdge-proxy-wasm-0.13.1/utils
   ./install.sh
 
 * Copy contents from ~/.wasmedge/include to /usr/local/include
 * Copy contents from ~/.wasmedge/lib to /usr/local/lib
+* The installation script will make changes to your environment variables. You 
can comment those out for now before compiling the plugin.
 
 **Configure ATS to compile with experimental plugins**
 
diff --git a/plugins/experimental/wasm/Makefile.inc 
b/plugins/experimental/wasm/Makefile.inc
index ebd92050c5..340df03896 100755
--- a/plugins/experimental/wasm/Makefile.inc
+++ b/plugins/experimental/wasm/Makefile.inc
@@ -55,6 +55,8 @@ experimental_wasm_wasm_la_SOURCES = \
     experimental/wasm/lib/include/proxy-wasm/shared_data.h \
     experimental/wasm/lib/src/shared_queue.cc \
     experimental/wasm/lib/include/proxy-wasm/shared_queue.h \
+    experimental/wasm/lib/src/hash.cc \
+    experimental/wasm/lib/src/hash.h \
     experimental/wasm/lib/src/signature_util.cc \
     experimental/wasm/lib/include/proxy-wasm/signature_util.h \
     experimental/wasm/lib/src/vm_id_handle.cc \
diff --git a/plugins/experimental/wasm/lib/include/proxy-wasm/context.h 
b/plugins/experimental/wasm/lib/include/proxy-wasm/context.h
index 652b86b6e0..ab99cad70a 100644
--- a/plugins/experimental/wasm/lib/include/proxy-wasm/context.h
+++ b/plugins/experimental/wasm/lib/include/proxy-wasm/context.h
@@ -23,6 +23,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "include/proxy-wasm/context_interface.h"
@@ -53,8 +54,7 @@ struct PluginBase {
              std::string_view key)
       : name_(std::string(name)), root_id_(std::string(root_id)), 
vm_id_(std::string(vm_id)),
         engine_(std::string(engine)), 
plugin_configuration_(plugin_configuration),
-        fail_open_(fail_open),
-        key_(root_id_ + "||" + plugin_configuration_ + "||" + 
std::string(key)),
+        fail_open_(fail_open), key_(makePluginKey(root_id, 
plugin_configuration, key)),
         log_prefix_(makeLogPrefix()) {}
 
   const std::string name_;
@@ -69,6 +69,8 @@ struct PluginBase {
 
 private:
   std::string makeLogPrefix() const;
+  static std::string makePluginKey(std::string_view root_id, std::string_view 
plugin_configuration,
+                                   std::string_view key);
 
   const std::string key_;
   const std::string log_prefix_;
diff --git a/plugins/experimental/wasm/lib/include/proxy-wasm/wasm.h 
b/plugins/experimental/wasm/lib/include/proxy-wasm/wasm.h
index 23ed3c1da6..1a785a8f9a 100644
--- a/plugins/experimental/wasm/lib/include/proxy-wasm/wasm.h
+++ b/plugins/experimental/wasm/lib/include/proxy-wasm/wasm.h
@@ -337,6 +337,7 @@ public:
 
 protected:
   std::shared_ptr<WasmBase> wasm_base_;
+  std::unordered_map<std::string, bool> plugin_canary_cache_;
 };
 
 std::string makeVmKey(std::string_view vm_id, std::string_view configuration,
diff --git a/plugins/experimental/wasm/lib/src/context.cc 
b/plugins/experimental/wasm/lib/src/context.cc
index 29037ae438..5353a52a54 100644
--- a/plugins/experimental/wasm/lib/src/context.cc
+++ b/plugins/experimental/wasm/lib/src/context.cc
@@ -22,6 +22,7 @@
 
 #include "include/proxy-wasm/context.h"
 #include "include/proxy-wasm/wasm.h"
+#include "src/hash.h"
 #include "src/shared_data.h"
 #include "src/shared_queue.h"
 
@@ -85,6 +86,11 @@ std::string PluginBase::makeLogPrefix() const {
   return prefix;
 }
 
+std::string PluginBase::makePluginKey(std::string_view root_id,
+                                      std::string_view plugin_configuration, 
std::string_view key) {
+  return Sha256String({root_id, "||", plugin_configuration, "||", key});
+}
+
 ContextBase::ContextBase() : parent_context_(this) {}
 
 ContextBase::ContextBase(WasmBase *wasm) : wasm_(wasm), parent_context_(this) {
diff --git a/plugins/experimental/wasm/lib/src/hash.cc 
b/plugins/experimental/wasm/lib/src/hash.cc
new file mode 100644
index 0000000000..f2d1ded138
--- /dev/null
+++ b/plugins/experimental/wasm/lib/src/hash.cc
@@ -0,0 +1,54 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/hash.h"
+
+#include <string>
+#include <vector>
+
+#include <openssl/sha.h>
+
+namespace proxy_wasm {
+
+namespace {
+
+std::string BytesToHex(const std::vector<uint8_t> &bytes) {
+  static const char *const hex = "0123456789ABCDEF";
+  std::string result;
+  result.reserve(bytes.size() * 2);
+  for (auto byte : bytes) {
+    result.push_back(hex[byte >> 4]);
+    result.push_back(hex[byte & 0xf]);
+  }
+  return result;
+}
+
+} // namespace
+
+std::vector<uint8_t> Sha256(const std::vector<std::string_view> &parts) {
+  uint8_t sha256[SHA256_DIGEST_LENGTH];
+  SHA256_CTX sha_ctx;
+  SHA256_Init(&sha_ctx);
+  for (auto part : parts) {
+    SHA256_Update(&sha_ctx, part.data(), part.size());
+  }
+  SHA256_Final(sha256, &sha_ctx);
+  return std::vector<uint8_t>(std::begin(sha256), std::end(sha256));
+}
+
+std::string Sha256String(const std::vector<std::string_view> &parts) {
+  return BytesToHex(Sha256(parts));
+}
+
+} // namespace proxy_wasm
\ No newline at end of file
diff --git a/plugins/experimental/wasm/lib/src/hash.h 
b/plugins/experimental/wasm/lib/src/hash.h
new file mode 100644
index 0000000000..40d03e9d4c
--- /dev/null
+++ b/plugins/experimental/wasm/lib/src/hash.h
@@ -0,0 +1,27 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <openssl/sha.h>
+
+namespace proxy_wasm {
+
+std::vector<uint8_t> Sha256(const std::vector<std::string_view> &parts);
+std::string Sha256String(const std::vector<std::string_view> &parts);
+
+} // namespace proxy_wasm
diff --git a/plugins/experimental/wasm/lib/src/wamr/wamr.cc 
b/plugins/experimental/wasm/lib/src/wamr/wamr.cc
index 577b6784f3..ea3d140e7d 100644
--- a/plugins/experimental/wasm/lib/src/wamr/wamr.cc
+++ b/plugins/experimental/wasm/lib/src/wamr/wamr.cc
@@ -125,10 +125,12 @@ bool Wamr::load(std::string_view bytecode, 
std::string_view /*precompiled*/,
     return false;
   }
 
-  WasmByteVec vec;
-  wasm_byte_vec_new(vec.get(), bytecode.size(), bytecode.data());
-
-  module_ = wasm_module_new(store_.get(), vec.get());
+  wasm_byte_vec_t binary = {.size = bytecode.size(),
+                            .data = (char *)bytecode.data(),
+                            .num_elems = bytecode.size(),
+                            .size_of_elem = sizeof(byte_t),
+                            .lock = nullptr};
+  module_ = wasm_module_new(store_.get(), &binary);
   if (module_ == nullptr) {
     return false;
   }
@@ -259,9 +261,15 @@ bool Wamr::link(std::string_view /*debug_name*/) {
     const wasm_name_t *name_ptr = 
wasm_importtype_name(import_types.get()->data[i]);
     const wasm_externtype_t *extern_type = 
wasm_importtype_type(import_types.get()->data[i]);
 
-    std::string_view module_name(module_name_ptr->data, module_name_ptr->size);
-    std::string_view name(name_ptr->data, name_ptr->size);
-    assert(name_ptr->size > 0);
+    if (std::strlen(name_ptr->data) == 0) {
+      fail(FailState::UnableToInitializeCode, std::string("The name field of 
import_types[") +
+                                                  std::to_string(i) + 
std::string("] is empty"));
+      return false;
+    }
+
+    std::string_view module_name(module_name_ptr->data);
+    std::string_view name(name_ptr->data);
+
     switch (wasm_externtype_kind(extern_type)) {
     case WASM_EXTERN_FUNC: {
       auto it = host_functions_.find(std::string(module_name) + "." + 
std::string(name));
@@ -344,17 +352,15 @@ bool Wamr::link(std::string_view /*debug_name*/) {
   wasm_instance_exports(instance_.get(), exports.get());
 
   for (size_t i = 0; i < export_types.get()->size; i++) {
-    const wasm_externtype_t *exp_extern_type = 
wasm_exporttype_type(export_types.get()->data[i]);
     wasm_extern_t *actual_extern = exports.get()->data[i];
 
     wasm_externkind_t kind = wasm_extern_kind(actual_extern);
-    assert(kind == wasm_externtype_kind(exp_extern_type));
+    assert(kind == 
wasm_externtype_kind(wasm_exporttype_type(export_types.get()->data[i])));
     switch (kind) {
     case WASM_EXTERN_FUNC: {
       WasmFuncPtr func = wasm_func_copy(wasm_extern_as_func(actual_extern));
       const wasm_name_t *name_ptr = 
wasm_exporttype_name(export_types.get()->data[i]);
-      module_functions_.insert_or_assign(std::string(name_ptr->data, 
name_ptr->size),
-                                         std::move(func));
+      module_functions_.insert_or_assign(std::string(name_ptr->data), 
std::move(func));
     } break;
     case WASM_EXTERN_GLOBAL: {
       // TODO(mathetake): add support when/if needed.
diff --git a/plugins/experimental/wasm/lib/src/wasm.cc 
b/plugins/experimental/wasm/lib/src/wasm.cc
index 5519b3e774..cb1dd9b3ac 100644
--- a/plugins/experimental/wasm/lib/src/wasm.cc
+++ b/plugins/experimental/wasm/lib/src/wasm.cc
@@ -23,54 +23,75 @@
 #include <limits>
 #include <memory>
 #include <mutex>
+#include <queue>
 #include <string>
 #include <unordered_map>
 #include <utility>
 
-#include <openssl/sha.h>
-
 #include "include/proxy-wasm/bytecode_util.h"
 #include "include/proxy-wasm/signature_util.h"
 #include "include/proxy-wasm/vm_id_handle.h"
+#include "src/hash.h"
 
 namespace proxy_wasm {
 
 namespace {
 
-// Map from Wasm Key to the local Wasm instance.
+// Map from Wasm key to the thread-local Wasm instance.
 thread_local std::unordered_map<std::string, std::weak_ptr<WasmHandleBase>> 
local_wasms;
+// Wasm key queue to track stale entries in `local_wasms`.
+thread_local std::queue<std::string> local_wasms_keys;
+
+// Map from plugin key to the thread-local plugin instance.
 thread_local std::unordered_map<std::string, std::weak_ptr<PluginHandleBase>> 
local_plugins;
+// Plugin key queue to track stale entries in `local_plugins`.
+thread_local std::queue<std::string> local_plugins_keys;
+
+// Check no more than `MAX_LOCAL_CACHE_GC_CHUNK_SIZE` cache entries at a time 
during stale entries
+// cleanup.
+const size_t MAX_LOCAL_CACHE_GC_CHUNK_SIZE = 64;
+
 // Map from Wasm Key to the base Wasm instance, using a pointer to avoid the 
initialization fiasco.
 std::mutex base_wasms_mutex;
 std::unordered_map<std::string, std::weak_ptr<WasmHandleBase>> *base_wasms = 
nullptr;
 
-std::vector<uint8_t> Sha256(const std::vector<std::string_view> &parts) {
-  uint8_t sha256[SHA256_DIGEST_LENGTH];
-  SHA256_CTX sha_ctx;
-  SHA256_Init(&sha_ctx);
-  for (auto part : parts) {
-    SHA256_Update(&sha_ctx, part.data(), part.size());
-  }
-  SHA256_Final(sha256, &sha_ctx);
-  return std::vector<uint8_t>(std::begin(sha256), std::end(sha256));
+void cacheLocalWasm(const std::string &key, const 
std::shared_ptr<WasmHandleBase> &wasm_handle) {
+  local_wasms[key] = wasm_handle;
+  local_wasms_keys.emplace(key);
+}
+
+void cacheLocalPlugin(const std::string &key,
+                      const std::shared_ptr<PluginHandleBase> &plugin_handle) {
+  local_plugins[key] = plugin_handle;
+  local_plugins_keys.emplace(key);
 }
 
-std::string BytesToHex(const std::vector<uint8_t> &bytes) {
-  static const char *const hex = "0123456789ABCDEF";
-  std::string result;
-  result.reserve(bytes.size() * 2);
-  for (auto byte : bytes) {
-    result.push_back(hex[byte >> 4]);
-    result.push_back(hex[byte & 0xf]);
+template <class T>
+void removeStaleLocalCacheEntries(std::unordered_map<std::string, 
std::weak_ptr<T>> &cache,
+                                  std::queue<std::string> &keys) {
+  auto num_keys_to_check = std::min(MAX_LOCAL_CACHE_GC_CHUNK_SIZE, 
keys.size());
+  for (size_t i = 0; i < num_keys_to_check; i++) {
+    std::string key(keys.front());
+    keys.pop();
+
+    const auto it = cache.find(key);
+    if (it == cache.end()) {
+      continue;
+    }
+
+    if (it->second.expired()) {
+      cache.erase(it);
+    } else {
+      keys.push(std::move(key));
+    }
   }
-  return result;
 }
 
 } // namespace
 
 std::string makeVmKey(std::string_view vm_id, std::string_view 
vm_configuration,
                       std::string_view code) {
-  return BytesToHex(Sha256({vm_id, vm_configuration, code}));
+  return Sha256String({vm_id, "||", vm_configuration, "||", code});
 }
 
 class WasmBase::ShutdownHandle {
@@ -472,6 +493,10 @@ bool WasmHandleBase::canary(const 
std::shared_ptr<PluginBase> &plugin,
   if (this->wasm() == nullptr) {
     return false;
   }
+  auto it = plugin_canary_cache_.find(plugin->key());
+  if (it != plugin_canary_cache_.end()) {
+    return it->second;
+  }
   auto configuration_canary_handle = clone_factory(shared_from_this());
   if (!configuration_canary_handle) {
     this->wasm()->fail(FailState::UnableToCloneVm, "Failed to clone Base 
Wasm");
@@ -490,9 +515,11 @@ bool WasmHandleBase::canary(const 
std::shared_ptr<PluginBase> &plugin,
   if (!configuration_canary_handle->wasm()->configure(root_context, plugin)) {
     configuration_canary_handle->wasm()->fail(FailState::ConfigureFailed,
                                               "Failed to configure base Wasm 
plugin");
+    plugin_canary_cache_[plugin->key()] = false;
     return false;
   }
   configuration_canary_handle->kill();
+  plugin_canary_cache_[plugin->key()] = true;
   return true;
 }
 
@@ -542,14 +569,15 @@ std::shared_ptr<WasmHandleBase> createWasm(const 
std::string &vm_key, const std:
 
 std::shared_ptr<WasmHandleBase> getThreadLocalWasm(std::string_view vm_key) {
   auto it = local_wasms.find(std::string(vm_key));
-  if (it == local_wasms.end()) {
-    return nullptr;
-  }
-  auto wasm = it->second.lock();
-  if (!wasm) {
-    local_wasms.erase(std::string(vm_key));
+  if (it != local_wasms.end()) {
+    auto wasm = it->second.lock();
+    if (wasm) {
+      return wasm;
+    }
+    local_wasms.erase(it);
   }
-  return wasm;
+  removeStaleLocalCacheEntries(local_wasms, local_wasms_keys);
+  return nullptr;
 }
 
 static std::shared_ptr<WasmHandleBase>
@@ -563,9 +591,9 @@ getOrCreateThreadLocalWasm(const 
std::shared_ptr<WasmHandleBase> &base_handle,
     if (wasm_handle) {
       return wasm_handle;
     }
-    // Remove stale entry.
-    local_wasms.erase(vm_key);
+    local_wasms.erase(it);
   }
+  removeStaleLocalCacheEntries(local_wasms, local_wasms_keys);
   // Create and initialize new thread-local WasmVM.
   auto wasm_handle = clone_factory(base_handle);
   if (!wasm_handle) {
@@ -577,7 +605,7 @@ getOrCreateThreadLocalWasm(const 
std::shared_ptr<WasmHandleBase> &base_handle,
     base_handle->wasm()->fail(FailState::UnableToInitializeCode, "Failed to 
initialize Wasm code");
     return nullptr;
   }
-  local_wasms[vm_key] = wasm_handle;
+  cacheLocalWasm(vm_key, wasm_handle);
   
wasm_handle->wasm()->wasm_vm()->addFailCallback([vm_key](proxy_wasm::FailState 
fail_state) {
     if (fail_state == proxy_wasm::FailState::RuntimeError) {
       // If VM failed, erase the entry so that:
@@ -600,9 +628,9 @@ std::shared_ptr<PluginHandleBase> 
getOrCreateThreadLocalPlugin(
     if (plugin_handle) {
       return plugin_handle;
     }
-    // Remove stale entry.
-    local_plugins.erase(key);
+    local_plugins.erase(it);
   }
+  removeStaleLocalCacheEntries(local_plugins, local_plugins_keys);
   // Get thread-local WasmVM.
   auto wasm_handle = getOrCreateThreadLocalWasm(base_handle, clone_factory);
   if (!wasm_handle) {
@@ -620,7 +648,7 @@ std::shared_ptr<PluginHandleBase> 
getOrCreateThreadLocalPlugin(
     return nullptr;
   }
   auto plugin_handle = plugin_factory(wasm_handle, plugin);
-  local_plugins[key] = plugin_handle;
+  cacheLocalPlugin(key, plugin_handle);
   wasm_handle->wasm()->wasm_vm()->addFailCallback([key](proxy_wasm::FailState 
fail_state) {
     if (fail_state == proxy_wasm::FailState::RuntimeError) {
       // If VM failed, erase the entry so that:
@@ -642,4 +670,24 @@ void clearWasmCachesForTesting() {
   }
 }
 
+std::vector<std::string> staleLocalPluginsKeysForTesting() {
+  std::vector<std::string> keys;
+  for (const auto &kv : local_plugins) {
+    if (kv.second.expired()) {
+      keys.push_back(kv.first);
+    }
+  }
+  return keys;
+}
+
+std::vector<std::string> staleLocalWasmsKeysForTesting() {
+  std::vector<std::string> keys;
+  for (const auto &kv : local_wasms) {
+    if (kv.second.expired()) {
+      keys.push_back(kv.first);
+    }
+  }
+  return keys;
+}
+
 } // namespace proxy_wasm

Reply via email to