TARAXA
Loading...
Searching...
No Matches
util.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <execinfo.h>
4#include <json/json.h>
5#include <libdevcore/RLP.h>
6
7#include <boost/asio.hpp>
8#include <boost/format.hpp>
9#include <boost/iostreams/device/back_inserter.hpp>
10#include <boost/iostreams/stream.hpp>
11#include <boost/iostreams/stream_buffer.hpp>
12#include <boost/thread.hpp>
13#include <iostream>
14#include <list>
15#include <shared_mutex>
16#include <streambuf>
17#include <string>
18#include <unordered_set>
19
20#include "logger_formatters.hpp"
21
22namespace taraxa {
23
28std::string jsonToUnstyledString(const Json::Value &value);
29
30template <typename T>
31std::weak_ptr<T> as_weak(std::shared_ptr<T> sp) {
32 return std::weak_ptr<T>(sp);
33}
34
35template <typename Int1, typename Int2>
36auto int_pow(Int1 x, Int2 y) {
37 if (!y) {
38 return 1;
39 }
40 while (--y > 0) {
41 x *= x;
42 }
43 return x;
44}
45
46template <typename T>
47std::vector<T> asVector(const Json::Value &json) {
48 std::vector<T> v;
49 v.reserve(json.size());
50 std::transform(json.begin(), json.end(), std::back_inserter(v),
51 [](const Json::Value &item) { return T(item.asString()); });
52 return v;
53}
54
55std::vector<uint64_t> asUInt64Vector(const Json::Value &json);
56
57using stream = std::basic_streambuf<uint8_t>;
58using bufferstream = boost::iostreams::stream_buffer<boost::iostreams::basic_array_source<uint8_t>>;
59using vectorstream = boost::iostreams::stream_buffer<boost::iostreams::back_insert_device<std::vector<uint8_t>>>;
60
61// Read a raw byte stream the size of T and fill value
62// return true if success
63template <typename T>
64bool read(stream &stm, T &value) {
65 static_assert(std::is_standard_layout<T>::value, "Cannot stream read non-standard layout types");
66 auto bytes(stm.sgetn(reinterpret_cast<uint8_t *>(&value), sizeof(value)));
67 return bytes == sizeof(value);
68}
69
70template <typename T>
71bool write(stream &stm, T const &value) {
72 static_assert(std::is_standard_layout<T>::value, "Cannot stream write non-standard layout types");
73 auto bytes(stm.sputn(reinterpret_cast<uint8_t const *>(&value), sizeof(value)));
74 assert(bytes == sizeof(value));
75 return bytes == sizeof(value);
76}
77
78void thisThreadSleepForSeconds(unsigned sec);
79void thisThreadSleepForMilliSeconds(unsigned millisec);
80void thisThreadSleepForMicroSeconds(unsigned microsec);
81
82unsigned long getCurrentTimeMilliSeconds();
83
84std::string getFormattedVersion(std::initializer_list<uint32_t> list);
85
91template <typename K, typename V>
93 public:
94 using UnsafeStatusTable = std::unordered_map<K, V>;
95 StatusTable(size_t capacity = 10000) : capacity_(capacity) {}
96 std::pair<V, bool> get(K const &hash) {
97 std::scoped_lock lock(shared_mutex_);
98 auto iter = status_.find(hash);
99 if (iter != status_.end()) {
100 auto kv = *(iter->second);
101 auto &k = kv.first;
102 auto &v = kv.second;
103 lru_.erase(iter->second);
104 lru_.push_front(kv);
105 status_[k] = lru_.begin();
106 return {v, true};
107 } else {
108 return {V(), false};
109 }
110 }
111 unsigned long size() const {
112 std::shared_lock lock(shared_mutex_);
113 return status_.size();
114 }
115 bool insert(K const &hash, V status) {
116 std::scoped_lock lock(shared_mutex_);
117 bool ret = false;
118 if (status_.count(hash)) {
119 ret = false;
120 } else {
121 if (status_.size() == capacity_) {
122 clearOldData();
123 }
124 lru_.push_front({hash, status});
125 status_[hash] = lru_.begin();
126 ret = true;
127 }
128 assert(status_.size() == lru_.size());
129 return ret;
130 }
131 void update(K const &hash, V status) {
132 std::scoped_lock lock(shared_mutex_);
133 auto iter = status_.find(hash);
134 if (iter != status_.end()) {
135 lru_.erase(iter->second);
136 lru_.push_front({hash, status});
137 status_[hash] = lru_.begin();
138 }
139 assert(status_.size() == lru_.size());
140 }
141
142 bool update(K const &hash, V status, V expected_status) {
143 bool ret = false;
144 std::scoped_lock lock(shared_mutex_);
145 auto iter = status_.find(hash);
146 if (iter != status_.end() && iter->second == expected_status) {
147 lru_.erase(iter->second);
148 lru_.push_front({hash, status});
149 status_[hash] = lru_.begin();
150 ret = true;
151 }
152 assert(status_.size() == lru_.size());
153 return ret;
154 }
155 // clear everything
156 void clear() {
157 std::scoped_lock lock(shared_mutex_);
158 status_.clear();
159 lru_.clear();
160 }
161 bool erase(K const &hash) {
162 bool ret = false;
163 std::scoped_lock lock(shared_mutex_);
164 auto iter = status_.find(hash);
165 if (iter != status_.end()) {
166 lru_.erase(iter->second);
167 status_.erase(hash);
168 }
169 assert(status_.size() == lru_.size());
170 return ret;
171 }
172
174 std::shared_lock lock(shared_mutex_);
175 return status_;
176 }
177
178 private:
180 int sz = capacity_ / 10;
181 for (int i = 0; i < sz; ++i) {
182 auto kv = lru_.rbegin();
183 auto &k = kv->first;
184 status_.erase(k);
185 lru_.pop_back();
186 assert(!lru_.empty()); // should not happen
187 }
188 }
189 using Element = std::list<std::pair<K, V>>;
190 size_t capacity_;
191 mutable std::shared_mutex shared_mutex_;
192 std::unordered_map<K, typename std::list<std::pair<K, V>>::iterator> status_;
193 std::list<std::pair<K, V>> lru_;
194}; // namespace taraxa
195
196template <typename... TS>
197std::string fmt(const std::string &pattern, const TS &...args) {
198 return (boost::format(pattern) % ... % args).str();
199}
200
201} // namespace taraxa
202
203template <class Key>
205 public:
206 ExpirationCache(uint32_t max_size, uint32_t delete_step) : kMaxSize(max_size), kDeleteStep(delete_step) {}
207
216 bool insert(Key const &key) {
217 if (contains(key)) {
218 return false;
219 }
220
221 // There must be double check if key is not already in cache due to possible race condition
222 std::unique_lock lock(mtx_);
223 if (!cache_.insert(key).second) {
224 return false;
225 }
226
227 expiration_.push_back(key);
228 if (cache_.size() > kMaxSize) {
229 for (uint32_t i = 0; i < kDeleteStep; i++) {
230 cache_.erase(expiration_.front());
231 expiration_.pop_front();
232 }
233 }
234
235 return true;
236 }
237
238 bool contains(Key const &key) const {
239 std::shared_lock lck(mtx_);
240 return cache_.contains(key);
241 }
242
243 void erase(Key const &key) {
244 std::unique_lock lck(mtx_);
245 cache_.erase(key);
246 }
247
248 std::size_t count(Key const &key) const {
249 std::shared_lock lck(mtx_);
250 return cache_.count(key);
251 }
252
253 std::size_t size() const {
254 std::shared_lock lck(mtx_);
255 return cache_.size();
256 }
257
258 void clear() {
259 std::unique_lock lck(mtx_);
260 cache_.clear();
261 expiration_.clear();
262 }
263
264 protected:
265 std::unordered_set<Key> cache_;
266 const uint32_t kMaxSize;
267 const uint32_t kDeleteStep;
268 mutable std::shared_mutex mtx_;
269
270 private:
271 std::deque<Key> expiration_;
272};
273
274template <class Key>
276 public:
277 ExpirationBlockNumberCache(uint32_t max_size, uint32_t delete_step, uint32_t blocks_to_keep)
278 : ExpirationCache<Key>(max_size, delete_step), kBlocksToKeep(blocks_to_keep) {}
279
289 bool insert(Key const &key, uint64_t block_number) {
290 if (this->contains(key)) {
291 return false;
292 }
293 // There must be double check if key is not already in cache due to possible race condition
294 std::unique_lock lock(this->mtx_);
295 if (!this->cache_.insert(key).second) {
296 return false;
297 }
298
299 if (block_number > last_block_number_) {
300 last_block_number_ = block_number;
301 while (block_expiration_.size() > 0) {
302 const auto &exp = block_expiration_.front();
303 if (block_number > kBlocksToKeep && exp.second < block_number - kBlocksToKeep) {
304 this->cache_.erase(exp.first);
305 block_expiration_.pop_front();
306 } else {
307 break;
308 }
309 }
310 }
311 block_expiration_.push_back({key, block_number});
312 if (this->cache_.size() > this->kMaxSize) {
313 for (uint32_t i = 0; i < this->kDeleteStep; i++) {
314 this->cache_.erase(block_expiration_.front().first);
315 block_expiration_.pop_front();
316 }
317 }
318
319 return true;
320 }
321
322 void clear() {
323 std::shared_lock lck(this->mtx_);
324 this->cache_.clear();
325 block_expiration_.clear();
326 }
327
328 private:
329 std::deque<std::pair<Key, uint64_t>> block_expiration_;
330 const uint32_t kBlocksToKeep;
331 uint64_t last_block_number_ = 0;
332};
333
334template <typename T>
335auto slice(std::vector<T> const &v, std::size_t from = -1, std::size_t to = -1) {
336 auto b = v.begin();
337 return std::vector<T>(from == (std::size_t)-1 ? b : b + from, to == (std::size_t)-1 ? v.end() : b + to);
338}
339
340template <typename T>
341auto getRlpBytes(T const &t) {
343 s << t;
344 return s.invalidate();
345}
346
347template <class Key, class Value>
349 public:
350 ExpirationCacheMap(uint32_t max_size, uint32_t delete_step) : kMaxSize(max_size), kDeleteStep(delete_step) {}
351
361 bool insert(Key const &key, Value const &value) {
362 {
363 std::shared_lock lock(mtx_);
364 if (cache_.count(key)) {
365 return false;
366 }
367 }
368
369 std::unique_lock lock(mtx_);
370
371 // There must be double check if key is not already in cache due to possible race condition
372 if (!cache_.emplace(key, value).second) {
373 return false;
374 }
375
376 expiration_.push_back(key);
377 if (cache_.size() > kMaxSize) {
378 eraseOldest();
379 }
380 return true;
381 }
382
383 std::size_t count(Key const &key) const {
384 std::shared_lock lck(mtx_);
385 return cache_.count(key);
386 }
387
388 std::size_t size() const {
389 std::shared_lock lck(mtx_);
390 return cache_.size();
391 }
392
393 std::pair<Value, bool> get(Key const &key) const {
394 std::shared_lock lck(mtx_);
395 auto it = cache_.find(key);
396 if (it == cache_.end()) return std::make_pair(Value(), false);
397 return std::make_pair(it->second, true);
398 }
399
400 void clear() {
401 std::unique_lock lck(mtx_);
402 cache_.clear();
403 expiration_.clear();
404 }
405
406 void update(Key const &key, Value value) {
407 std::unique_lock lck(mtx_);
408
409 if (cache_.find(key) != cache_.end()) {
410 expiration_.erase(std::remove(expiration_.begin(), expiration_.end(), key), expiration_.end());
411 }
412
413 cache_[key] = value;
414 expiration_.push_back(key);
415
416 if (cache_.size() > kMaxSize) {
417 for (uint32_t i = 0; i < kDeleteStep; i++) {
418 cache_.erase(expiration_.front());
419 expiration_.pop_front();
420 }
421 }
422 }
423
424 void erase(const Key &key) {
425 std::unique_lock lck(mtx_);
426 cache_.erase(key);
427 expiration_.erase(std::remove(expiration_.begin(), expiration_.end(), key), expiration_.end());
428 }
429
430 std::pair<Value, bool> updateWithGet(Key const &key, Value value) {
431 std::unique_lock lck(mtx_);
432 std::pair<Value, bool> ret;
433 auto it = cache_.find(key);
434 if (it == cache_.end()) {
435 ret = std::make_pair(Value(), false);
436 } else {
437 ret = std::make_pair(it->second, true);
438 }
439 cache_[key] = value;
440 expiration_.push_back(key);
441 if (cache_.size() > kMaxSize) {
442 for (uint32_t i = 0; i < kDeleteStep; i++) {
443 cache_.erase(expiration_.front());
444 expiration_.pop_front();
445 }
446 }
447 return ret;
448 }
449
450 std::unordered_map<Key, Value> getRawMap() {
451 std::shared_lock lck(mtx_);
452 return cache_;
453 }
454
455 bool update(Key const &key, Value value, Value expected_value) {
456 std::unique_lock lck(mtx_);
457 auto it = cache_.find(key);
458 if (it != cache_.end() && it->second == expected_value) {
459 it->second = value;
460 expiration_.push_back(key);
461 if (cache_.size() > kMaxSize) {
462 for (auto i = 0; i < kDeleteStep; i++) {
463 cache_.erase(expiration_.front());
464 expiration_.pop_front();
465 }
466 }
467 return true;
468 }
469 return false;
470 }
471
472 protected:
473 virtual void eraseOldest() {
474 for (uint32_t i = 0; i < kDeleteStep; i++) {
475 cache_.erase(expiration_.front());
476 expiration_.pop_front();
477 }
478 }
479
480 std::unordered_map<Key, Value> cache_;
481 std::deque<Key> expiration_;
482 const uint32_t kMaxSize;
483 const uint32_t kDeleteStep;
484 mutable std::shared_mutex mtx_;
485};
486
487template <class Key, class Value>
489 public:
490 bool emplace(Key const &key, Value const &value) {
491 std::unique_lock lock(mtx_);
492 return map_.emplace(key, value).second;
493 }
494
495 std::size_t count(Key const &key) const {
496 std::shared_lock lck(mtx_);
497 return map_.count(key);
498 }
499
500 std::size_t size() const {
501 std::shared_lock lck(mtx_);
502 return map_.size();
503 }
504
505 std::pair<Value, bool> get(Key const &key) const {
506 std::shared_lock lck(mtx_);
507 auto it = map_.find(key);
508 if (it == map_.end()) return std::make_pair(Value(), false);
509 return std::make_pair(it->second, true);
510 }
511
512 std::vector<Value> getValues(uint32_t count = 0) const {
513 std::vector<Value> values;
514 uint32_t counter = 0;
515 std::shared_lock lck(mtx_);
516 values.reserve(map_.size());
517 for (auto const &t : map_) {
518 values.emplace_back(t.second);
519 if (count != 0) {
520 counter++;
521 if (counter == count) {
522 break;
523 }
524 }
525 }
526 return values;
527 }
528
529 void erase(std::function<bool(Value)> condition) {
530 std::unique_lock lck(mtx_);
531 for (auto it = map_.cbegin(), next_it = it; it != map_.cend(); it = next_it) {
532 ++next_it;
533 if (condition(it->second)) {
534 map_.erase(it);
535 }
536 }
537 }
538
539 void clear() {
540 std::unique_lock lck(mtx_);
541 map_.clear();
542 }
543
544 bool erase(const Key &key) {
545 std::unique_lock lck(mtx_);
546 return map_.erase(key);
547 }
548
549 protected:
550 std::unordered_map<Key, Value> map_;
551 mutable std::shared_mutex mtx_;
552};
553
554template <class Key>
556 public:
557 bool emplace(Key const &key) {
558 std::unique_lock lock(mtx_);
559 return set_.insert(key).second;
560 }
561
562 std::size_t count(Key const &key) const {
563 std::shared_lock lck(mtx_);
564 return set_.count(key);
565 }
566
567 void clear() {
568 std::unique_lock lck(mtx_);
569 set_.clear();
570 }
571
572 bool erase(const Key &key) {
573 std::unique_lock lck(mtx_);
574 return set_.erase(key);
575 }
576
577 std::size_t size() const {
578 std::shared_lock lck(mtx_);
579 return set_.size();
580 }
581
582 private:
583 std::unordered_set<Key> set_;
584 mutable std::shared_mutex mtx_;
585};
Definition util.hpp:275
ExpirationBlockNumberCache(uint32_t max_size, uint32_t delete_step, uint32_t blocks_to_keep)
Definition util.hpp:277
void clear()
Definition util.hpp:322
std::deque< std::pair< Key, uint64_t > > block_expiration_
Definition util.hpp:329
const uint32_t kBlocksToKeep
Definition util.hpp:330
bool insert(Key const &key, uint64_t block_number)
Inserts key into the cache map. In case provided key is already in cache, only shared lock is acquire...
Definition util.hpp:289
uint64_t last_block_number_
Definition util.hpp:331
Definition util.hpp:204
const uint32_t kDeleteStep
Definition util.hpp:267
bool insert(Key const &key)
Inserts key into the cache map. In case provided key is already in cache, only shared lock is acquire...
Definition util.hpp:216
std::size_t count(Key const &key) const
Definition util.hpp:248
const uint32_t kMaxSize
Definition util.hpp:266
std::shared_mutex mtx_
Definition util.hpp:268
ExpirationCache(uint32_t max_size, uint32_t delete_step)
Definition util.hpp:206
void clear()
Definition util.hpp:258
bool contains(Key const &key) const
Definition util.hpp:238
void erase(Key const &key)
Definition util.hpp:243
std::unordered_set< Key > cache_
Definition util.hpp:265
std::size_t size() const
Definition util.hpp:253
std::deque< Key > expiration_
Definition util.hpp:271
Definition util.hpp:348
virtual void eraseOldest()
Definition util.hpp:473
bool insert(Key const &key, Value const &value)
Inserts <key,value> pair into the cache map. In case provided key is already in cache,...
Definition util.hpp:361
std::size_t size() const
Definition util.hpp:388
std::unordered_map< Key, Value > getRawMap()
Definition util.hpp:450
std::size_t count(Key const &key) const
Definition util.hpp:383
std::pair< Value, bool > get(Key const &key) const
Definition util.hpp:393
std::deque< Key > expiration_
Definition util.hpp:481
std::unordered_map< Key, Value > cache_
Definition util.hpp:480
ExpirationCacheMap(uint32_t max_size, uint32_t delete_step)
Definition util.hpp:350
void erase(const Key &key)
Definition util.hpp:424
const uint32_t kDeleteStep
Definition util.hpp:483
void update(Key const &key, Value value)
Definition util.hpp:406
std::shared_mutex mtx_
Definition util.hpp:484
std::pair< Value, bool > updateWithGet(Key const &key, Value value)
Definition util.hpp:430
const uint32_t kMaxSize
Definition util.hpp:482
bool update(Key const &key, Value value, Value expected_value)
Definition util.hpp:455
void clear()
Definition util.hpp:400
Definition util.hpp:488
std::shared_mutex mtx_
Definition util.hpp:551
std::unordered_map< Key, Value > map_
Definition util.hpp:550
bool erase(const Key &key)
Definition util.hpp:544
bool emplace(Key const &key, Value const &value)
Definition util.hpp:490
std::size_t count(Key const &key) const
Definition util.hpp:495
std::vector< Value > getValues(uint32_t count=0) const
Definition util.hpp:512
std::size_t size() const
Definition util.hpp:500
std::pair< Value, bool > get(Key const &key) const
Definition util.hpp:505
void clear()
Definition util.hpp:539
void erase(std::function< bool(Value)> condition)
Definition util.hpp:529
Definition util.hpp:555
void clear()
Definition util.hpp:567
bool emplace(Key const &key)
Definition util.hpp:557
bool erase(const Key &key)
Definition util.hpp:572
std::unordered_set< Key > set_
Definition util.hpp:583
std::size_t size() const
Definition util.hpp:577
std::size_t count(Key const &key) const
Definition util.hpp:562
std::shared_mutex mtx_
Definition util.hpp:584
Class for writing to an RLP bytestream.
Definition RLP.h:484
bytes && invalidate()
Invalidate the object and steal the output byte stream.
Definition RLP.h:620
Definition util.hpp:92
void clearOldData()
Definition util.hpp:179
size_t capacity_
Definition util.hpp:190
bool update(K const &hash, V status, V expected_status)
Definition util.hpp:142
StatusTable(size_t capacity=10000)
Definition util.hpp:95
bool erase(K const &hash)
Definition util.hpp:161
std::list< std::pair< K, V > > lru_
Definition util.hpp:193
void update(K const &hash, V status)
Definition util.hpp:131
std::shared_mutex shared_mutex_
Definition util.hpp:191
bool insert(K const &hash, V status)
Definition util.hpp:115
std::unordered_map< K, typename std::list< std::pair< K, V > >::iterator > status_
Definition util.hpp:192
void clear()
Definition util.hpp:156
std::unordered_map< K, V > UnsafeStatusTable
Definition util.hpp:94
std::pair< V, bool > get(K const &hash)
Definition util.hpp:96
unsigned long size() const
Definition util.hpp:111
std::list< std::pair< K, V > > Element
Definition util.hpp:189
UnsafeStatusTable getThreadUnsafeCopy() const
Definition util.hpp:173
Definition app.hpp:16
std::basic_streambuf< uint8_t > stream
Definition util.hpp:57
void thisThreadSleepForMicroSeconds(unsigned microsec)
Definition util.cpp:17
bool read(stream &stm, T &value)
Definition util.hpp:64
void thisThreadSleepForMilliSeconds(unsigned millisec)
Definition util.cpp:13
std::weak_ptr< T > as_weak(std::shared_ptr< T > sp)
Definition util.hpp:31
boost::iostreams::stream_buffer< boost::iostreams::back_insert_device< std::vector< uint8_t > > > vectorstream
Definition util.hpp:59
std::vector< byte > bytes
Definition types.hpp:53
std::string getFormattedVersion(std::initializer_list< uint32_t > list)
Definition util.cpp:26
void thisThreadSleepForSeconds(unsigned sec)
Definition util.cpp:11
std::string fmt(const std::string &pattern, const TS &...args)
Definition util.hpp:197
bool write(stream &stm, T const &value)
Definition util.hpp:71
std::vector< T > asVector(const Json::Value &json)
Definition util.hpp:47
std::vector< uint64_t > asUInt64Vector(const Json::Value &json)
Definition util.cpp:34
std::string jsonToUnstyledString(const Json::Value &value)
Definition util.cpp:5
boost::iostreams::stream_buffer< boost::iostreams::basic_array_source< uint8_t > > bufferstream
Definition util.hpp:58
auto int_pow(Int1 x, Int2 y)
Definition util.hpp:36
unsigned long getCurrentTimeMilliSeconds()
Definition util.cpp:21
auto slice(std::vector< T > const &v, std::size_t from=-1, std::size_t to=-1)
Definition util.hpp:335
auto getRlpBytes(T const &t)
Definition util.hpp:341