Skip to content

Commit

Permalink
cc: add support for registering a platform KV store (#2430)
Browse files Browse the repository at this point in the history
Description: Adds support for registering a platform KV store implementation via EngineBuilder.
Risk Level: Low
Testing: CI

Signed-off-by: Mike Schore <[email protected]>
  • Loading branch information
goaway authored Aug 3, 2022
1 parent 044195d commit 308f15c
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 1 deletion.
2 changes: 1 addition & 1 deletion docs/root/intro/version_history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Bugfixes:

Features:

- Android & iOS: add support for registering a platform KV store (:issue: `#2134 <2134>`) (:issue: `#2335 <2335>`)
- Android, iOS, & C++: add support for registering a platform KV store (:issue: `#2134 <2134>`, :issue: `#2335 <2335>`, :issue: `#2430 <2430>`)
- api: add option to extend the keepalive timeout when any frame is received on the owning HTTP/2 connection. (:issue:`#2229 <2229>`)
- api: add option to control whether Envoy should drain connections after a soft DNS refresh completes. (:issue:`#2225 <2225>`, :issue:`#2242 <2242>`)
- api: add option to disable the gzip decompressor. (:issue: `#2321 <2321>`) (:issue: `#2349 <2349>`)
Expand Down
3 changes: 3 additions & 0 deletions library/cc/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ envoy_cc_library(
"engine_callbacks.cc",
"headers.cc",
"headers_builder.cc",
"key_value_store.cc",
"log_level.cc",
"request_headers.cc",
"request_headers_builder.cc",
Expand All @@ -50,6 +51,7 @@ envoy_cc_library(
"envoy_error.h",
"headers.h",
"headers_builder.h",
"key_value_store.h",
"log_level.h",
"pulse_client.h",
"request_headers.h",
Expand All @@ -75,6 +77,7 @@ envoy_cc_library(
deps = [
"//library/common:envoy_main_interface_lib_no_stamp",
"//library/common/data:utility_lib",
"//library/common/extensions/key_value/platform:config",
],
)

Expand Down
14 changes: 14 additions & 0 deletions library/cc/engine_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ EngineBuilder& EngineBuilder::addVirtualClusters(const std::string& virtual_clus
return *this;
}

EngineBuilder& EngineBuilder::addKeyValueStore(const std::string& name,
KeyValueStoreSharedPtr key_value_store) {
this->key_value_stores_[name] = key_value_store;
return *this;
}

EngineBuilder& EngineBuilder::setAppVersion(const std::string& app_version) {
this->app_version_ = app_version;
return *this;
Expand Down Expand Up @@ -203,6 +209,14 @@ EngineSharedPtr EngineBuilder::build() {
}
auto envoy_engine =
init_engine(this->callbacks_->asEnvoyEngineCallbacks(), null_logger, null_tracker);

for (auto it = key_value_stores_.begin(); it != key_value_stores_.end(); ++it) {
// TODO(goaway): This leaks, but it's tied to the life of the engine.
envoy_kv_store* api = static_cast<envoy_kv_store*>(safe_malloc(sizeof(envoy_kv_store)));
*api = it->second->asEnvoyKeyValueStore();
register_platform_api(it->first.c_str(), api);
}

run_engine(envoy_engine, config_str.c_str(), logLevelToString(this->log_level_).c_str(),
this->admin_address_path_for_tests_.c_str());

Expand Down
5 changes: 5 additions & 0 deletions library/cc/engine_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
#include <memory>
#include <string>

#include "absl/container/flat_hash_map.h"
#include "engine.h"
#include "engine_callbacks.h"
#include "key_value_store.h"
#include "log_level.h"

namespace Envoy {
Expand All @@ -31,6 +33,7 @@ class EngineBuilder {
addH2ConnectionKeepaliveTimeoutSeconds(int h2_connection_keepalive_timeout_seconds);
EngineBuilder& addStatsFlushSeconds(int stats_flush_seconds);
EngineBuilder& addVirtualClusters(const std::string& virtual_clusters);
EngineBuilder& addKeyValueStore(const std::string& name, KeyValueStoreSharedPtr key_value_store);
EngineBuilder& setAppVersion(const std::string& app_version);
EngineBuilder& setAppId(const std::string& app_id);
EngineBuilder& setDeviceOs(const std::string& app_id);
Expand Down Expand Up @@ -79,6 +82,8 @@ class EngineBuilder {
bool gzip_filter_ = true;
bool brotli_filter_ = false;

absl::flat_hash_map<std::string, KeyValueStoreSharedPtr> key_value_stores_{};

// TODO(crockeo): add after filter integration
// private var platformFilterChain = mutableListOf<EnvoyHTTPFilterFactory>()
// private var nativeFilterChain = mutableListOf<EnvoyNativeFilterConfig>()
Expand Down
46 changes: 46 additions & 0 deletions library/cc/key_value_store.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "library/cc/key_value_store.h"

#include "library/common/data/utility.h"

namespace Envoy {
namespace Platform {

namespace {

envoy_data c_kv_store_read(envoy_data key, const void* context) {
auto kv_store = *static_cast<KeyValueStoreSharedPtr*>(const_cast<void*>(context));

auto value = kv_store->read(Data::Utility::copyToString(key));
release_envoy_data(key);

return value.has_value() ? Data::Utility::copyToBridgeData(value.value()) : envoy_nodata;
}

void c_kv_store_save(envoy_data key, envoy_data value, const void* context) {
auto kv_store = *static_cast<KeyValueStoreSharedPtr*>(const_cast<void*>(context));

kv_store->save(Data::Utility::copyToString(key), Data::Utility::copyToString(value));
release_envoy_data(key);
release_envoy_data(value);
}

void c_kv_store_remove(envoy_data key, const void* context) {
auto kv_store = *static_cast<KeyValueStoreSharedPtr*>(const_cast<void*>(context));

kv_store->remove(Data::Utility::copyToString(key));
release_envoy_data(key);
}

} // namespace

envoy_kv_store KeyValueStore::asEnvoyKeyValueStore() {
return envoy_kv_store{
&c_kv_store_read,
&c_kv_store_save,
&c_kv_store_remove,
new KeyValueStoreSharedPtr(shared_from_this()),
};
}

} // namespace Platform
} // namespace Envoy
51 changes: 51 additions & 0 deletions library/cc/key_value_store.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#include <memory>

#include "envoy/common/pure.h"

#include "absl/types/optional.h"
#include "library/common/extensions/key_value/platform/c_types.h"

namespace Envoy {
namespace Platform {

/**
* `KeyValueStore` is an interface that may be implemented to provide access to an arbitrary
* key-value store implementation that may be made accessible to internal Envoy Mobile code.
*/
struct KeyValueStore : public std::enable_shared_from_this<KeyValueStore> {
public:
virtual ~KeyValueStore() = default;

/**
* Returns the value associated with the provided key, if any.
* @param key supplies a key to return the value of.
* @return the value, if the key is in the store, absl::nullopt otherwise.
*/
virtual absl::optional<std::string> read(const std::string& key) PURE;

/**
* Adds or updates a key:value pair in the store.
* @param key supplies a key to add or update.
* @param value supplies the value to set for that key.
*/
virtual void save(std::string key, std::string value) PURE;

/**
* Removes a key:value pair from the store. This is a no-op if the key is not present.
* @param key supplies a key to remove from the store.
*/
virtual void remove(const std::string& key) PURE;

/**
* Maps an implementation to its internal representation.
* @return portable internal type used to call an implementation.
*/
virtual envoy_kv_store asEnvoyKeyValueStore() final;
};

using KeyValueStoreSharedPtr = std::shared_ptr<KeyValueStore>;

} // namespace Platform
} // namespace Envoy

0 comments on commit 308f15c

Please sign in to comment.