Skip to content

Commit 819dcc0

Browse files
authored
Add keys() and remove() methods to SharedData. (#203)
Signed-off-by: James Mulcahy <[email protected]>
1 parent 10d5b06 commit 819dcc0

File tree

6 files changed

+114
-2
lines changed

6 files changed

+114
-2
lines changed

include/proxy-wasm/context.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,9 @@ class ContextBase : public RootInterface,
353353
WasmResult getSharedData(std::string_view key,
354354
std::pair<std::string, uint32_t /* cas */> *data) override;
355355
WasmResult setSharedData(std::string_view key, std::string_view value, uint32_t cas) override;
356+
WasmResult getSharedDataKeys(std::vector<std::string> *result) override;
357+
WasmResult removeSharedDataKey(std::string_view key, uint32_t cas,
358+
std::pair<std::string, uint32_t> *result) override;
356359

357360
// Shared Queue
358361
WasmResult registerSharedQueue(std::string_view queue_name,

include/proxy-wasm/context_interface.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ struct GeneralInterface {
596596
};
597597

598598
/**
599-
* SharedDataInterface is for shaing data between VMs. In general the VMs may be on different
599+
* SharedDataInterface is for sharing data between VMs. In general the VMs may be on different
600600
* threads. Keys can have any format, but good practice would use reverse DNS and namespacing
601601
* prefixes to avoid conflicts.
602602
*/
@@ -621,6 +621,23 @@ struct SharedDataInterface {
621621
* @param data is a location to store the returned value.
622622
*/
623623
virtual WasmResult setSharedData(std::string_view key, std::string_view value, uint32_t cas) = 0;
624+
625+
/**
626+
* Return all the keys from the data shraed between VMs
627+
* @param data is a location to store the returned value.
628+
*/
629+
virtual WasmResult getSharedDataKeys(std::vector<std::string> *result) = 0;
630+
631+
/**
632+
* Removes the given key from the data shared between VMs.
633+
* @param key is a proxy-wide key mapping to the shared data value.
634+
* @param cas is a compare-and-swap value. If it is zero it is ignored, otherwise it must match
635+
* @param cas is a location to store value, and cas number, associated with the removed key
636+
* the cas associated with the value.
637+
*/
638+
virtual WasmResult
639+
removeSharedDataKey(std::string_view key, uint32_t cas,
640+
std::pair<std::string /* value */, uint32_t /* cas */> *result) = 0;
624641
}; // namespace proxy_wasm
625642

626643
struct SharedQueueInterface {

src/context.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,15 @@ WasmResult ContextBase::setSharedData(std::string_view key, std::string_view val
192192
return getGlobalSharedData().set(wasm_->vm_id(), key, value, cas);
193193
}
194194

195+
WasmResult ContextBase::getSharedDataKeys(std::vector<std::string> *result) {
196+
return getGlobalSharedData().keys(wasm_->vm_id(), result);
197+
}
198+
199+
WasmResult ContextBase::removeSharedDataKey(std::string_view key, uint32_t cas,
200+
std::pair<std::string, uint32_t> *result) {
201+
return getGlobalSharedData().remove(wasm_->vm_id(), key, cas, result);
202+
}
203+
195204
// Shared Queue
196205

197206
WasmResult ContextBase::registerSharedQueue(std::string_view queue_name,

src/shared_data.cc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,22 @@ WasmResult SharedData::get(std::string_view vm_id, const std::string_view key,
5656
return WasmResult::NotFound;
5757
}
5858

59+
WasmResult SharedData::keys(std::string_view vm_id, std::vector<std::string> *result) {
60+
result->clear();
61+
62+
std::lock_guard<std::mutex> lock(mutex_);
63+
auto map = data_.find(std::string(vm_id));
64+
if (map == data_.end()) {
65+
return WasmResult::Ok;
66+
}
67+
68+
for (auto kv : map->second) {
69+
result->push_back(kv.first);
70+
}
71+
72+
return WasmResult::Ok;
73+
}
74+
5975
WasmResult SharedData::set(std::string_view vm_id, std::string_view key, std::string_view value,
6076
uint32_t cas) {
6177
std::lock_guard<std::mutex> lock(mutex_);
@@ -78,4 +94,29 @@ WasmResult SharedData::set(std::string_view vm_id, std::string_view key, std::st
7894
return WasmResult::Ok;
7995
}
8096

97+
WasmResult SharedData::remove(std::string_view vm_id, std::string_view key, uint32_t cas,
98+
std::pair<std::string, uint32_t> *result) {
99+
std::lock_guard<std::mutex> lock(mutex_);
100+
std::unordered_map<std::string, std::pair<std::string, uint32_t>> *map;
101+
auto map_it = data_.find(std::string(vm_id));
102+
if (map_it == data_.end()) {
103+
return WasmResult::NotFound;
104+
} else {
105+
map = &map_it->second;
106+
}
107+
108+
auto it = map->find(std::string(key));
109+
if (it != map->end()) {
110+
if (cas && cas != it->second.second) {
111+
return WasmResult::CasMismatch;
112+
}
113+
if (result != nullptr) {
114+
*result = it->second;
115+
}
116+
map->erase(it);
117+
return WasmResult::Ok;
118+
}
119+
return WasmResult::NotFound;
120+
}
121+
81122
} // namespace proxy_wasm

src/shared_data.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ class SharedData {
2525
SharedData(bool register_vm_id_callback = true);
2626
WasmResult get(std::string_view vm_id, const std::string_view key,
2727
std::pair<std::string, uint32_t> *result);
28+
WasmResult keys(std::string_view vm_id, std::vector<std::string> *result);
2829
WasmResult set(std::string_view vm_id, std::string_view key, std::string_view value,
2930
uint32_t cas);
31+
WasmResult remove(std::string_view vm_id, const std::string_view key, uint32_t cas,
32+
std::pair<std::string, uint32_t> *result);
3033
void deleteByVmId(std::string_view vm_id);
3134

3235
private:

test/shared_data_test.cc

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,24 @@ namespace proxy_wasm {
2424

2525
TEST(SharedData, SingleThread) {
2626
SharedData shared_data(false);
27+
std::string_view vm_id = "id";
28+
29+
// Validate we get an 'Ok' response when fetching keys before anything
30+
// is initialized.
31+
std::vector<std::string> keys;
32+
EXPECT_EQ(WasmResult::Ok, shared_data.keys(vm_id, &keys));
33+
EXPECT_EQ(0, keys.size());
34+
35+
// Validate that we clear the result set
36+
std::vector<std::string> nonEmptyKeys(2);
37+
nonEmptyKeys[0] = "valueA";
38+
nonEmptyKeys[1] = "valueB";
39+
EXPECT_EQ(WasmResult::Ok, shared_data.keys(vm_id, &nonEmptyKeys));
40+
EXPECT_EQ(0, nonEmptyKeys.size());
41+
2742
std::pair<std::string, uint32_t> result;
2843
EXPECT_EQ(WasmResult::NotFound, shared_data.get("non-exist", "non-exists", &result));
2944

30-
std::string_view vm_id = "id";
3145
std::string_view key = "key";
3246
std::string_view value = "1";
3347
EXPECT_EQ(WasmResult::Ok, shared_data.set(vm_id, key, value, 0));
@@ -44,6 +58,31 @@ TEST(SharedData, SingleThread) {
4458
EXPECT_EQ(WasmResult::Ok, shared_data.get(vm_id, key, &result));
4559
EXPECT_EQ(value, result.first);
4660
EXPECT_EQ(result.second, 3);
61+
62+
EXPECT_EQ(WasmResult::Ok, shared_data.keys(vm_id, &keys));
63+
EXPECT_EQ(1, keys.size());
64+
EXPECT_EQ(key, keys[0]);
65+
66+
keys.clear();
67+
EXPECT_EQ(WasmResult::CasMismatch, shared_data.remove(vm_id, key, 911, nullptr));
68+
EXPECT_EQ(WasmResult::Ok, shared_data.keys(vm_id, &keys));
69+
EXPECT_EQ(1, keys.size());
70+
71+
EXPECT_EQ(WasmResult::Ok, shared_data.remove(vm_id, key, 0, nullptr));
72+
EXPECT_EQ(WasmResult::NotFound, shared_data.get(vm_id, key, &result));
73+
74+
EXPECT_EQ(WasmResult::NotFound, shared_data.remove(vm_id, "non-existent_key", 0, nullptr));
75+
76+
EXPECT_EQ(WasmResult::Ok, shared_data.set(vm_id, key, value, 0));
77+
EXPECT_EQ(WasmResult::Ok, shared_data.set(vm_id, key, value, 0));
78+
EXPECT_EQ(WasmResult::Ok, shared_data.get(vm_id, key, &result));
79+
80+
uint32_t expectedCasValue = result.second;
81+
82+
std::pair<std::string, uint32_t> removeResult;
83+
EXPECT_EQ(WasmResult::Ok, shared_data.remove(vm_id, key, 0, &removeResult));
84+
EXPECT_EQ(value, removeResult.first);
85+
EXPECT_EQ(removeResult.second, expectedCasValue);
4786
}
4887

4988
void incrementData(SharedData *shared_data, std::string_view vm_id, std::string_view key) {

0 commit comments

Comments
 (0)