Kagome
Polkadot Runtime Engine in C++17
topper_trie_batch_impl.cpp
Go to the documentation of this file.
1 
7 
8 #include <boost/algorithm/string/predicate.hpp>
9 
10 #include "common/buffer.hpp"
13 
16  e) {
18  switch (e) {
19  case E::PARENT_EXPIRED:
20  return "Pointer to the parent batch expired";
21  }
22  return "Unknown error";
23 }
24 
25 namespace kagome::storage::trie {
26 
28  const std::shared_ptr<TrieBatch> &parent)
29  : parent_(parent) {}
30 
31  outcome::result<common::BufferConstRef> TopperTrieBatchImpl::get(
32  const BufferView &key) const {
33  OUTCOME_TRY(opt_value, tryGet(key));
34  if (opt_value) {
35  return opt_value.value();
36  }
37  return TrieError::NO_VALUE;
38  }
39 
40  outcome::result<std::optional<common::BufferConstRef>>
42  if (auto it = cache_.find(key); it != cache_.end()) {
43  if (it->second.has_value()) {
44  return it->second.value();
45  }
46  return std::nullopt;
47  }
48  if (wasClearedByPrefix(key)) {
49  return std::nullopt;
50  }
51  if (auto p = parent_.lock(); p != nullptr) {
52  return p->tryGet(key);
53  }
54  return Error::PARENT_EXPIRED;
55  }
56 
57  std::unique_ptr<PolkadotTrieCursor> TopperTrieBatchImpl::trieCursor() {
58  if (auto p = parent_.lock(); p != nullptr) {
59  return p->trieCursor();
60  }
61  return nullptr;
62  }
63 
64  outcome::result<bool> TopperTrieBatchImpl::contains(
65  const BufferView &key) const {
66  if (auto it = cache_.find(key); it != cache_.end()) {
67  return it->second.has_value();
68  }
69  if (wasClearedByPrefix(key)) {
70  return false;
71  }
72  if (auto p = parent_.lock(); p != nullptr) {
73  return p->contains(key);
74  }
75  return false;
76  }
77 
79  if (not cache_.empty()
80  and std::any_of(cache_.begin(), cache_.end(), [](auto &p) {
81  return p.second.has_value();
82  })) {
83  return false;
84  }
85  // TODO(Harrm) PRE-462 consider clearPrefix here. Not an easy thing and is
86  // barely possible to happen, so leave it for the future
87  if (auto p = parent_.lock(); p != nullptr) {
88  return p->empty();
89  }
90  return true;
91  }
92 
93  outcome::result<void> TopperTrieBatchImpl::put(const BufferView &key,
94  const Buffer &value) {
95  return put(key, Buffer(value));
96  }
97 
98  outcome::result<void> TopperTrieBatchImpl::put(const BufferView &key,
99  Buffer &&value) {
100  cache_.insert_or_assign(Buffer{key}, std::move(value));
101  return outcome::success();
102  }
103 
104  outcome::result<void> TopperTrieBatchImpl::remove(const BufferView &key) {
105  cache_.insert_or_assign(Buffer{key}, std::nullopt);
106 
107  return outcome::success();
108  }
109 
110  outcome::result<std::tuple<bool, uint32_t>> TopperTrieBatchImpl::clearPrefix(
111  const BufferView &prefix, std::optional<uint64_t>) {
112  for (auto it = cache_.lower_bound(prefix);
113  it != cache_.end() && boost::starts_with(it->first, prefix);
114  ++it)
115  it->second = std::nullopt;
116 
117  cleared_prefixes_.emplace_back(prefix);
118  if (parent_.lock() != nullptr) {
119  return outcome::success(std::make_tuple(true, 0ULL));
120  }
121  return Error::PARENT_EXPIRED;
122  }
123 
124  outcome::result<void> TopperTrieBatchImpl::writeBack() {
125  if (auto p = parent_.lock()) {
126  for (const auto &prefix : cleared_prefixes_) {
127  OUTCOME_TRY(p->clearPrefix(prefix));
128  }
129  for (auto it = cache_.begin(); it != cache_.end(); it++) {
130  if (it->second.has_value()) {
131  OUTCOME_TRY(p->put(it->first, it->second.value()));
132  } else {
133  OUTCOME_TRY(p->remove(it->first));
134  }
135  }
136  return outcome::success();
137  }
138  return Error::PARENT_EXPIRED;
139  }
140 
142  for (const auto &prefix : cleared_prefixes_) {
143  if (boost::starts_with(key, prefix)) {
144  return true;
145  }
146  }
147  return false;
148  }
149 
150 } // namespace kagome::storage::trie
Class represents arbitrary (including empty) byte buffer.
Definition: buffer.hpp:29
outcome::result< common::BufferConstRef > get(const BufferView &key) const override
Get value by key.
outcome::result< std::optional< common::BufferConstRef > > tryGet(const BufferView &key) const override
Get value by key.
std::map< Buffer, std::optional< Buffer >, std::less<> > cache_
outcome::result< void > put(const BufferView &key, const Buffer &value) override
Store value by key.
bool empty() const override
Returns true if the storage is empty.
TopperTrieBatchImpl(const std::shared_ptr< TrieBatch > &parent)
common::SLBuffer< std::numeric_limits< size_t >::max()> Buffer
bool wasClearedByPrefix(const BufferView &key) const
outcome::result< void > remove(const BufferView &key) override
Remove value by key.
outcome::result< std::tuple< bool, uint32_t > > clearPrefix(const BufferView &prefix, std::optional< uint64_t > limit) override
OUTCOME_CPP_DEFINE_CATEGORY(kagome::storage::trie, TopperTrieBatchImpl::Error, e)
outcome::result< void > writeBack() override
std::unique_ptr< PolkadotTrieCursor > trieCursor() override
outcome::result< bool > contains(const BufferView &key) const override
Checks if given key-value binding exists in the storage.