Clean utils folder (namespaces, function names)
Reviewers: teon.banek Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1359
This commit is contained in:
parent
44474b55e3
commit
c76170a9db
@ -64,7 +64,7 @@ class RhBase {
|
|||||||
|
|
||||||
// Base for all iterators. It can start from any point in map.
|
// Base for all iterators. It can start from any point in map.
|
||||||
template <class It>
|
template <class It>
|
||||||
class IteratorBase : public Crtp<It> {
|
class IteratorBase : public utils::Crtp<It> {
|
||||||
protected:
|
protected:
|
||||||
IteratorBase() : map(nullptr) { advanced = index = ~((size_t)0); }
|
IteratorBase() : map(nullptr) { advanced = index = ~((size_t)0); }
|
||||||
IteratorBase(const RhBase *map) {
|
IteratorBase(const RhBase *map) {
|
||||||
|
@ -209,7 +209,7 @@ class Decoder {
|
|||||||
DLOG(WARNING) << "[ReadInt] Int16 missing data!";
|
DLOG(WARNING) << "[ReadInt] Int16 missing data!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ret = bswap(tmp);
|
ret = utils::Bswap(tmp);
|
||||||
} else if (marker == Marker::Int32) {
|
} else if (marker == Marker::Int32) {
|
||||||
VLOG(20) << "[ReadInt] Found an Int32";
|
VLOG(20) << "[ReadInt] Found an Int32";
|
||||||
int32_t tmp;
|
int32_t tmp;
|
||||||
@ -217,14 +217,14 @@ class Decoder {
|
|||||||
DLOG(WARNING) << "[ReadInt] Int32 missing data!";
|
DLOG(WARNING) << "[ReadInt] Int32 missing data!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ret = bswap(tmp);
|
ret = utils::Bswap(tmp);
|
||||||
} else if (marker == Marker::Int64) {
|
} else if (marker == Marker::Int64) {
|
||||||
VLOG(20) << "[ReadInt] Found an Int64";
|
VLOG(20) << "[ReadInt] Found an Int64";
|
||||||
if (!buffer_.Read(reinterpret_cast<uint8_t *>(&ret), sizeof(ret))) {
|
if (!buffer_.Read(reinterpret_cast<uint8_t *>(&ret), sizeof(ret))) {
|
||||||
DLOG(WARNING) << "[ReadInt] Int64 missing data!";
|
DLOG(WARNING) << "[ReadInt] Int64 missing data!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ret = bswap(ret);
|
ret = utils::Bswap(ret);
|
||||||
} else {
|
} else {
|
||||||
DLOG(WARNING) << "[ReadInt] Received invalid marker "
|
DLOG(WARNING) << "[ReadInt] Received invalid marker "
|
||||||
<< utils::UnderlyingCast(marker);
|
<< utils::UnderlyingCast(marker);
|
||||||
@ -244,7 +244,7 @@ class Decoder {
|
|||||||
DLOG(WARNING) << "[ReadDouble] Missing data!";
|
DLOG(WARNING) << "[ReadDouble] Missing data!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
value = bswap(value);
|
value = utils::Bswap(value);
|
||||||
// cppcheck-suppress invalidPointerCast
|
// cppcheck-suppress invalidPointerCast
|
||||||
ret = *reinterpret_cast<double *>(&value);
|
ret = *reinterpret_cast<double *>(&value);
|
||||||
*data = DecodedValue(ret);
|
*data = DecodedValue(ret);
|
||||||
@ -272,7 +272,7 @@ class Decoder {
|
|||||||
DLOG(WARNING) << "[ReadTypeSize] Type16 missing data!";
|
DLOG(WARNING) << "[ReadTypeSize] Type16 missing data!";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
tmp = bswap(tmp);
|
tmp = utils::Bswap(tmp);
|
||||||
return tmp;
|
return tmp;
|
||||||
} else if (marker == Marker32[type]) {
|
} else if (marker == Marker32[type]) {
|
||||||
VLOG(20) << "[ReadTypeSize] Found a Type32";
|
VLOG(20) << "[ReadTypeSize] Found a Type32";
|
||||||
@ -281,7 +281,7 @@ class Decoder {
|
|||||||
DLOG(WARNING) << "[ReadTypeSize] Type32 missing data!";
|
DLOG(WARNING) << "[ReadTypeSize] Type32 missing data!";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
tmp = bswap(tmp);
|
tmp = utils::Bswap(tmp);
|
||||||
return tmp;
|
return tmp;
|
||||||
} else {
|
} else {
|
||||||
DLOG(WARNING) << "[ReadTypeSize] Received invalid marker "
|
DLOG(WARNING) << "[ReadTypeSize] Received invalid marker "
|
||||||
|
@ -20,7 +20,7 @@ namespace communication::bolt {
|
|||||||
template <typename Buffer>
|
template <typename Buffer>
|
||||||
class PrimitiveEncoder {
|
class PrimitiveEncoder {
|
||||||
public:
|
public:
|
||||||
PrimitiveEncoder(Buffer &buffer) : buffer_(buffer) {}
|
explicit PrimitiveEncoder(Buffer &buffer) : buffer_(buffer) {}
|
||||||
|
|
||||||
void WriteRAW(const uint8_t *data, uint64_t len) { buffer_.Write(data, len); }
|
void WriteRAW(const uint8_t *data, uint64_t len) { buffer_.Write(data, len); }
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ class PrimitiveEncoder {
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void WriteValue(T value) {
|
void WriteValue(T value) {
|
||||||
value = bswap(value);
|
value = utils::Bswap(value);
|
||||||
WriteRAW(reinterpret_cast<const uint8_t *>(&value), sizeof(value));
|
WriteRAW(reinterpret_cast<const uint8_t *>(&value), sizeof(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,9 +11,9 @@ template <typename TKey, typename TValue>
|
|||||||
class ConcurrentMap {
|
class ConcurrentMap {
|
||||||
/// At item in the concurrent map. A pair of <TKey, TValue> that compares on
|
/// At item in the concurrent map. A pair of <TKey, TValue> that compares on
|
||||||
/// the first value (key). Comparable to another Item, or only to the TKey.
|
/// the first value (key). Comparable to another Item, or only to the TKey.
|
||||||
class Item : public TotalOrdering<Item>,
|
class Item : public utils::TotalOrdering<Item>,
|
||||||
public TotalOrdering<TKey, Item>,
|
public utils::TotalOrdering<TKey, Item>,
|
||||||
public TotalOrdering<Item, TKey>,
|
public utils::TotalOrdering<Item, TKey>,
|
||||||
public std::pair<const TKey, TValue> {
|
public std::pair<const TKey, TValue> {
|
||||||
public:
|
public:
|
||||||
using std::pair<const TKey, TValue>::pair;
|
using std::pair<const TKey, TValue>::pair;
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
* computes the height for the new node from the interval [1...H]
|
* computes the height for the new node from the interval [1...H]
|
||||||
* with p(k) = (1/2)^k for all k from the interval
|
* with p(k) = (1/2)^k for all k from the interval
|
||||||
*/
|
*/
|
||||||
static thread_local FastBinomial<> rnd;
|
static thread_local utils::random::FastBinomial<> rnd;
|
||||||
|
|
||||||
/** @brief Concurrent lock-based skiplist with fine grained locking
|
/** @brief Concurrent lock-based skiplist with fine grained locking
|
||||||
*
|
*
|
||||||
@ -230,7 +230,7 @@ class SkipList : private Lockable<lock_t> {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Placeholder<T> data;
|
utils::Placeholder<T> data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this creates an array of the size zero. we can't put any sensible
|
* this creates an array of the size zero. we can't put any sensible
|
||||||
@ -245,7 +245,7 @@ class SkipList : private Lockable<lock_t> {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
template <class It>
|
template <class It>
|
||||||
class IteratorBase : public Crtp<It> {
|
class IteratorBase : public utils::Crtp<It> {
|
||||||
protected:
|
protected:
|
||||||
explicit IteratorBase(Node *node) : node(node) {}
|
explicit IteratorBase(Node *node) : node(node) {}
|
||||||
|
|
||||||
@ -344,7 +344,7 @@ class SkipList : private Lockable<lock_t> {
|
|||||||
@todo
|
@todo
|
||||||
Research possible better and faster more optimized traversals.
|
Research possible better and faster more optimized traversals.
|
||||||
*/
|
*/
|
||||||
class ReverseIterator : public Crtp<ReverseIterator> {
|
class ReverseIterator : public utils::Crtp<ReverseIterator> {
|
||||||
friend class SkipList;
|
friend class SkipList;
|
||||||
|
|
||||||
explicit ReverseIterator(Node *node) : node_(node) {}
|
explicit ReverseIterator(Node *node) : node_(node) {}
|
||||||
|
@ -160,9 +160,9 @@ class SkipListGC {
|
|||||||
/// Constructs executor depending on flag - has to be done this way because of
|
/// Constructs executor depending on flag - has to be done this way because of
|
||||||
/// C++14
|
/// C++14
|
||||||
auto ConstructExecutor() {
|
auto ConstructExecutor() {
|
||||||
std::unique_ptr<Executor> executor;
|
std::unique_ptr<utils::Executor> executor;
|
||||||
if (FLAGS_skiplist_gc_interval != -1) {
|
if (FLAGS_skiplist_gc_interval != -1) {
|
||||||
executor = std::make_unique<Executor>(
|
executor = std::make_unique<utils::Executor>(
|
||||||
std::chrono::seconds(FLAGS_skiplist_gc_interval));
|
std::chrono::seconds(FLAGS_skiplist_gc_interval));
|
||||||
}
|
}
|
||||||
return executor;
|
return executor;
|
||||||
|
@ -443,7 +443,7 @@ MasterBase::MasterBase(std::unique_ptr<impl::PrivateBase> impl)
|
|||||||
: PublicBase(std::move(impl)) {
|
: PublicBase(std::move(impl)) {
|
||||||
if (impl_->config_.durability_enabled) {
|
if (impl_->config_.durability_enabled) {
|
||||||
impl_->wal().Enable();
|
impl_->wal().Enable();
|
||||||
snapshot_creator_ = std::make_unique<Scheduler>();
|
snapshot_creator_ = std::make_unique<utils::Scheduler>();
|
||||||
snapshot_creator_->Run(
|
snapshot_creator_->Run(
|
||||||
"Snapshot", std::chrono::seconds(impl_->config_.snapshot_cycle_sec),
|
"Snapshot", std::chrono::seconds(impl_->config_.snapshot_cycle_sec),
|
||||||
[this] {
|
[this] {
|
||||||
|
@ -171,7 +171,7 @@ class PublicBase : public GraphDb {
|
|||||||
private:
|
private:
|
||||||
/** When this is false, no new transactions should be created. */
|
/** When this is false, no new transactions should be created. */
|
||||||
std::atomic<bool> is_accepting_transactions_{true};
|
std::atomic<bool> is_accepting_transactions_{true};
|
||||||
Scheduler transaction_killer_;
|
utils::Scheduler transaction_killer_;
|
||||||
};
|
};
|
||||||
} // namespace impl
|
} // namespace impl
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ class MasterBase : public impl::PublicBase {
|
|||||||
~MasterBase();
|
~MasterBase();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Scheduler> snapshot_creator_;
|
std::unique_ptr<utils::Scheduler> snapshot_creator_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SingleNode : public MasterBase {
|
class SingleNode : public MasterBase {
|
||||||
|
@ -104,7 +104,7 @@ class KeyIndex {
|
|||||||
/**
|
/**
|
||||||
* @brief - Contains vlist and record pointers.
|
* @brief - Contains vlist and record pointers.
|
||||||
*/
|
*/
|
||||||
class IndexEntry : public TotalOrdering<IndexEntry> {
|
class IndexEntry : public utils::TotalOrdering<IndexEntry> {
|
||||||
public:
|
public:
|
||||||
IndexEntry(const IndexEntry &entry, const TRecord *const new_record)
|
IndexEntry(const IndexEntry &entry, const TRecord *const new_record)
|
||||||
: IndexEntry(entry.vlist_, new_record) {}
|
: IndexEntry(entry.vlist_, new_record) {}
|
||||||
|
@ -34,7 +34,7 @@ class LabelPropertyIndex {
|
|||||||
/**
|
/**
|
||||||
* @brief - Contain Label + property, to be used as an index key.
|
* @brief - Contain Label + property, to be used as an index key.
|
||||||
*/
|
*/
|
||||||
class Key : public TotalOrdering<Key> {
|
class Key : public utils::TotalOrdering<Key> {
|
||||||
public:
|
public:
|
||||||
const storage::Label label_;
|
const storage::Label label_;
|
||||||
const storage::Property property_;
|
const storage::Property property_;
|
||||||
@ -381,7 +381,7 @@ class LabelPropertyIndex {
|
|||||||
* @brief - Contains value, vlist and vertex record to distinguish between
|
* @brief - Contains value, vlist and vertex record to distinguish between
|
||||||
* index entries.
|
* index entries.
|
||||||
*/
|
*/
|
||||||
class IndexEntry : public TotalOrdering<IndexEntry> {
|
class IndexEntry : public utils::TotalOrdering<IndexEntry> {
|
||||||
public:
|
public:
|
||||||
IndexEntry(const IndexEntry &entry, const Vertex *new_record)
|
IndexEntry(const IndexEntry &entry, const Vertex *new_record)
|
||||||
: IndexEntry(entry.value_, entry.vlist_, new_record) {}
|
: IndexEntry(entry.value_, entry.vlist_, new_record) {}
|
||||||
|
@ -141,7 +141,7 @@ class StorageGc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tx::Engine &tx_engine_;
|
tx::Engine &tx_engine_;
|
||||||
Scheduler scheduler_;
|
utils::Scheduler scheduler_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Storage &storage_;
|
Storage &storage_;
|
||||||
@ -150,7 +150,6 @@ class StorageGc {
|
|||||||
|
|
||||||
// History of <oldest active transaction, next transaction to be ran> ranges
|
// History of <oldest active transaction, next transaction to be ran> ranges
|
||||||
// that gc operated on at some previous time - used to clear commit log
|
// that gc operated on at some previous time - used to clear commit log
|
||||||
std::queue<std::pair<tx::TransactionId, tx::TransactionId>>
|
std::queue<std::pair<tx::TransactionId, tx::TransactionId>> gc_txid_ranges_;
|
||||||
gc_txid_ranges_;
|
|
||||||
};
|
};
|
||||||
} // namespace database
|
} // namespace database
|
||||||
|
@ -5,9 +5,8 @@
|
|||||||
#include "utils/future.hpp"
|
#include "utils/future.hpp"
|
||||||
|
|
||||||
namespace distributed {
|
namespace distributed {
|
||||||
utils::Future<bool> DurabilityRpcClients::MakeSnapshot(
|
utils::Future<bool> DurabilityRpcClients::MakeSnapshot(tx::TransactionId tx) {
|
||||||
tx::TransactionId tx) {
|
return utils::make_future(std::async(std::launch::async, [this, tx] {
|
||||||
return std::async(std::launch::async, [this, tx] {
|
|
||||||
auto futures = clients_.ExecuteOnWorkers<bool>(
|
auto futures = clients_.ExecuteOnWorkers<bool>(
|
||||||
0, [tx](communication::rpc::ClientPool &client_pool) {
|
0, [tx](communication::rpc::ClientPool &client_pool) {
|
||||||
auto res = client_pool.Call<MakeSnapshotRpc>(tx);
|
auto res = client_pool.Call<MakeSnapshotRpc>(tx);
|
||||||
@ -21,6 +20,6 @@ utils::Future<bool> DurabilityRpcClients::MakeSnapshot(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return created;
|
return created;
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
} // namespace distributed
|
} // namespace distributed
|
||||||
|
@ -54,9 +54,8 @@ class TransactionalCacheCleaner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tx::Engine &tx_engine_;
|
tx::Engine &tx_engine_;
|
||||||
std::vector<std::function<void(tx::TransactionId &oldest_active)>>
|
std::vector<std::function<void(tx::TransactionId &oldest_active)>> functions_;
|
||||||
functions_;
|
utils::Scheduler cache_clearing_scheduler_;
|
||||||
Scheduler cache_clearing_scheduler_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Registers a RPC server that listens for `WaitOnTransactionEnd` requests
|
/// Registers a RPC server that listens for `WaitOnTransactionEnd` requests
|
||||||
|
@ -51,7 +51,7 @@ class HashedFileReader {
|
|||||||
if (!Read(reinterpret_cast<uint8_t *>(&val), sizeof(TValue), hash))
|
if (!Read(reinterpret_cast<uint8_t *>(&val), sizeof(TValue), hash))
|
||||||
return false;
|
return false;
|
||||||
// TODO: must be platform specific in the future
|
// TODO: must be platform specific in the future
|
||||||
val = bswap(val);
|
val = utils::Bswap(val);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class HashedFileWriter {
|
|||||||
*/
|
*/
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
void WriteValue(const TValue &val, bool hash = true) {
|
void WriteValue(const TValue &val, bool hash = true) {
|
||||||
TValue val_bswapped = bswap(val);
|
TValue val_bswapped = utils::Bswap(val);
|
||||||
Write(reinterpret_cast<const uint8_t *>(&val_bswapped), sizeof(TValue),
|
Write(reinterpret_cast<const uint8_t *>(&val_bswapped), sizeof(TValue),
|
||||||
hash);
|
hash);
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
#include "glog/logging.h"
|
#include "glog/logging.h"
|
||||||
|
|
||||||
#include "transactions/type.hpp"
|
#include "transactions/type.hpp"
|
||||||
#include "utils/datetime/timestamp.hpp"
|
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
#include "utils/timestamp.hpp"
|
||||||
|
|
||||||
namespace durability {
|
namespace durability {
|
||||||
namespace fs = std::experimental::filesystem;
|
namespace fs = std::experimental::filesystem;
|
||||||
@ -66,7 +66,7 @@ std::experimental::optional<tx::TransactionId> TransactionIdFromWalFilename(
|
|||||||
fs::path MakeSnapshotPath(const fs::path &durability_dir, const int worker_id,
|
fs::path MakeSnapshotPath(const fs::path &durability_dir, const int worker_id,
|
||||||
tx::TransactionId tx_id) {
|
tx::TransactionId tx_id) {
|
||||||
std::string date_str =
|
std::string date_str =
|
||||||
Timestamp(Timestamp::Now())
|
utils::Timestamp(utils::Timestamp::Now())
|
||||||
.ToString("{:04d}_{:02d}_{:02d}__{:02d}_{:02d}_{:02d}_{:05d}");
|
.ToString("{:04d}_{:02d}_{:02d}__{:02d}_{:02d}_{:02d}_{:05d}");
|
||||||
auto file_name = date_str + "_worker_" + std::to_string(worker_id) + "_tx_" +
|
auto file_name = date_str + "_worker_" + std::to_string(worker_id) + "_tx_" +
|
||||||
std::to_string(tx_id);
|
std::to_string(tx_id);
|
||||||
@ -79,7 +79,7 @@ fs::path MakeSnapshotPath(const fs::path &durability_dir, const int worker_id,
|
|||||||
fs::path WalFilenameForTransactionId(
|
fs::path WalFilenameForTransactionId(
|
||||||
const std::experimental::filesystem::path &wal_dir, int worker_id,
|
const std::experimental::filesystem::path &wal_dir, int worker_id,
|
||||||
std::experimental::optional<tx::TransactionId> tx_id) {
|
std::experimental::optional<tx::TransactionId> tx_id) {
|
||||||
auto file_name = Timestamp::Now().ToIso8601();
|
auto file_name = utils::Timestamp::Now().ToIso8601();
|
||||||
if (tx_id) {
|
if (tx_id) {
|
||||||
file_name += "__max_transaction_" + std::to_string(*tx_id);
|
file_name += "__max_transaction_" + std::to_string(*tx_id);
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "durability/paths.hpp"
|
#include "durability/paths.hpp"
|
||||||
#include "durability/snapshot_encoder.hpp"
|
#include "durability/snapshot_encoder.hpp"
|
||||||
#include "durability/version.hpp"
|
#include "durability/version.hpp"
|
||||||
#include "utils/datetime/timestamp.hpp"
|
|
||||||
|
|
||||||
namespace fs = std::experimental::filesystem;
|
namespace fs = std::experimental::filesystem;
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ class WriteAheadLog {
|
|||||||
};
|
};
|
||||||
|
|
||||||
RingBuffer<database::StateDelta> deltas_;
|
RingBuffer<database::StateDelta> deltas_;
|
||||||
Scheduler scheduler_;
|
utils::Scheduler scheduler_;
|
||||||
WalFile wal_file_;
|
WalFile wal_file_;
|
||||||
// Used for disabling the WAL during DB recovery.
|
// Used for disabling the WAL during DB recovery.
|
||||||
bool enabled_{false};
|
bool enabled_{false};
|
||||||
|
@ -152,7 +152,7 @@ int main(int argc, char **argv) {
|
|||||||
google::SetLogSymlink(google::INFO, FLAGS_log_link_basename.c_str());
|
google::SetLogSymlink(google::INFO, FLAGS_log_link_basename.c_str());
|
||||||
|
|
||||||
// Unhandled exception handler init.
|
// Unhandled exception handler init.
|
||||||
std::set_terminate(&terminate_handler);
|
std::set_terminate(&utils::TerminateHandler);
|
||||||
|
|
||||||
std::string stats_prefix;
|
std::string stats_prefix;
|
||||||
if (FLAGS_master) {
|
if (FLAGS_master) {
|
||||||
@ -166,10 +166,10 @@ int main(int argc, char **argv) {
|
|||||||
utils::OnScopeExit stop_stats([] { stats::StopStatsLogging(); });
|
utils::OnScopeExit stop_stats([] { stats::StopStatsLogging(); });
|
||||||
|
|
||||||
// Start memory warning logger.
|
// Start memory warning logger.
|
||||||
Scheduler mem_log_scheduler;
|
utils::Scheduler mem_log_scheduler;
|
||||||
if (FLAGS_memory_warning_threshold > 0) {
|
if (FLAGS_memory_warning_threshold > 0) {
|
||||||
mem_log_scheduler.Run("Memory warning", std::chrono::seconds(3), [] {
|
mem_log_scheduler.Run("Memory warning", std::chrono::seconds(3), [] {
|
||||||
auto free_ram_mb = utils::AvailableMem() / 1024;
|
auto free_ram_mb = utils::sysinfo::AvailableMem() / 1024;
|
||||||
if (free_ram_mb < FLAGS_memory_warning_threshold)
|
if (free_ram_mb < FLAGS_memory_warning_threshold)
|
||||||
LOG(WARNING) << "Running out of available RAM, only " << free_ram_mb
|
LOG(WARNING) << "Running out of available RAM, only " << free_ram_mb
|
||||||
<< " MB left.";
|
<< " MB left.";
|
||||||
|
@ -414,32 +414,32 @@ std::unique_ptr<Cursor> ScanAllByLabelPropertyRange::MakeCursor(
|
|||||||
-> std::experimental::optional<decltype(
|
-> std::experimental::optional<decltype(
|
||||||
db.Vertices(label_, property_, std::experimental::nullopt,
|
db.Vertices(label_, property_, std::experimental::nullopt,
|
||||||
std::experimental::nullopt, false))> {
|
std::experimental::nullopt, false))> {
|
||||||
ExpressionEvaluator evaluator(frame, context.parameters_,
|
ExpressionEvaluator evaluator(frame, context.parameters_,
|
||||||
context.symbol_table_, db, graph_view_);
|
context.symbol_table_, db, graph_view_);
|
||||||
auto convert = [&evaluator](const auto &bound)
|
auto convert = [&evaluator](const auto &bound)
|
||||||
-> std::experimental::optional<utils::Bound<PropertyValue>> {
|
-> std::experimental::optional<utils::Bound<PropertyValue>> {
|
||||||
if (!bound) return std::experimental::nullopt;
|
if (!bound) return std::experimental::nullopt;
|
||||||
auto value = bound->value()->Accept(evaluator);
|
auto value = bound->value()->Accept(evaluator);
|
||||||
try {
|
try {
|
||||||
|
return std::experimental::make_optional(
|
||||||
|
utils::Bound<PropertyValue>(value, bound->type()));
|
||||||
|
} catch (const TypedValueException &) {
|
||||||
|
throw QueryRuntimeException(
|
||||||
|
"'{}' cannot be used as a property value.", value.type());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
auto maybe_lower = convert(lower_bound());
|
||||||
|
auto maybe_upper = convert(upper_bound());
|
||||||
|
// If any bound is null, then the comparison would result in nulls. This
|
||||||
|
// is treated as not satisfying the filter, so return no vertices.
|
||||||
|
if (maybe_lower && maybe_lower->value().IsNull())
|
||||||
|
return std::experimental::nullopt;
|
||||||
|
if (maybe_upper && maybe_upper->value().IsNull())
|
||||||
|
return std::experimental::nullopt;
|
||||||
return std::experimental::make_optional(
|
return std::experimental::make_optional(
|
||||||
utils::Bound<PropertyValue>(value, bound->type()));
|
db.Vertices(label_, property_, maybe_lower, maybe_upper,
|
||||||
} catch (const TypedValueException &) {
|
graph_view_ == GraphView::NEW));
|
||||||
throw QueryRuntimeException("'{}' cannot be used as a property value.",
|
};
|
||||||
value.type());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
auto maybe_lower = convert(lower_bound());
|
|
||||||
auto maybe_upper = convert(upper_bound());
|
|
||||||
// If any bound is null, then the comparison would result in nulls. This is
|
|
||||||
// treated as not satisfying the filter, so return no vertices.
|
|
||||||
if (maybe_lower && maybe_lower->value().IsNull())
|
|
||||||
return std::experimental::nullopt;
|
|
||||||
if (maybe_upper && maybe_upper->value().IsNull())
|
|
||||||
return std::experimental::nullopt;
|
|
||||||
return std::experimental::make_optional(
|
|
||||||
db.Vertices(label_, property_, maybe_lower, maybe_upper,
|
|
||||||
graph_view_ == GraphView::NEW));
|
|
||||||
};
|
|
||||||
return std::make_unique<ScanAllCursor<decltype(vertices)>>(
|
return std::make_unique<ScanAllCursor<decltype(vertices)>>(
|
||||||
output_symbol_, input_->MakeCursor(db), std::move(vertices), db);
|
output_symbol_, input_->MakeCursor(db), std::move(vertices), db);
|
||||||
}
|
}
|
||||||
@ -462,18 +462,18 @@ std::unique_ptr<Cursor> ScanAllByLabelPropertyValue::MakeCursor(
|
|||||||
auto vertices = [this, &db](Frame &frame, Context &context)
|
auto vertices = [this, &db](Frame &frame, Context &context)
|
||||||
-> std::experimental::optional<decltype(
|
-> std::experimental::optional<decltype(
|
||||||
db.Vertices(label_, property_, TypedValue::Null, false))> {
|
db.Vertices(label_, property_, TypedValue::Null, false))> {
|
||||||
ExpressionEvaluator evaluator(frame, context.parameters_,
|
ExpressionEvaluator evaluator(frame, context.parameters_,
|
||||||
context.symbol_table_, db, graph_view_);
|
context.symbol_table_, db, graph_view_);
|
||||||
auto value = expression_->Accept(evaluator);
|
auto value = expression_->Accept(evaluator);
|
||||||
if (value.IsNull()) return std::experimental::nullopt;
|
if (value.IsNull()) return std::experimental::nullopt;
|
||||||
try {
|
try {
|
||||||
return std::experimental::make_optional(
|
return std::experimental::make_optional(db.Vertices(
|
||||||
db.Vertices(label_, property_, value, graph_view_ == GraphView::NEW));
|
label_, property_, value, graph_view_ == GraphView::NEW));
|
||||||
} catch (const TypedValueException &) {
|
} catch (const TypedValueException &) {
|
||||||
throw QueryRuntimeException("'{}' cannot be used as a property value.",
|
throw QueryRuntimeException(
|
||||||
value.type());
|
"'{}' cannot be used as a property value.", value.type());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return std::make_unique<ScanAllCursor<decltype(vertices)>>(
|
return std::make_unique<ScanAllCursor<decltype(vertices)>>(
|
||||||
output_symbol_, input_->MakeCursor(db), std::move(vertices), db);
|
output_symbol_, input_->MakeCursor(db), std::move(vertices), db);
|
||||||
}
|
}
|
||||||
@ -551,7 +551,7 @@ bool Expand::ExpandCursor::Pull(Frame &frame, Context &context) {
|
|||||||
LOG(FATAL) << "Must indicate exact expansion direction here";
|
LOG(FATAL) << "Must indicate exact expansion direction here";
|
||||||
});
|
});
|
||||||
future_expands_.emplace_back(
|
future_expands_.emplace_back(
|
||||||
FutureExpand{std::move(edge_to), frame.elems()});
|
FutureExpand{utils::make_future(std::move(edge_to)), frame.elems()});
|
||||||
};
|
};
|
||||||
|
|
||||||
auto find_ready_future = [this]() {
|
auto find_ready_future = [this]() {
|
||||||
@ -1402,7 +1402,7 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
|||||||
|
|
||||||
struct WspStateHash {
|
struct WspStateHash {
|
||||||
size_t operator()(const std::pair<VertexAccessor, int> &key) const {
|
size_t operator()(const std::pair<VertexAccessor, int> &key) const {
|
||||||
return HashCombine<VertexAccessor, int>{}(key.first, key.second);
|
return utils::HashCombine<VertexAccessor, int>{}(key.first, key.second);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1812,7 +1812,8 @@ class Aggregate : public LogicalOperator {
|
|||||||
std::unordered_map<
|
std::unordered_map<
|
||||||
std::vector<TypedValue>, AggregationValue,
|
std::vector<TypedValue>, AggregationValue,
|
||||||
// use FNV collection hashing specialized for a vector of TypedValues
|
// use FNV collection hashing specialized for a vector of TypedValues
|
||||||
FnvCollection<std::vector<TypedValue>, TypedValue, TypedValue::Hash>,
|
utils::FnvCollection<std::vector<TypedValue>, TypedValue,
|
||||||
|
TypedValue::Hash>,
|
||||||
// custom equality
|
// custom equality
|
||||||
TypedValueVectorEqual>
|
TypedValueVectorEqual>
|
||||||
aggregation_;
|
aggregation_;
|
||||||
@ -2352,7 +2353,8 @@ class Distinct : public LogicalOperator {
|
|||||||
std::unordered_set<
|
std::unordered_set<
|
||||||
std::vector<TypedValue>,
|
std::vector<TypedValue>,
|
||||||
// use FNV collection hashing specialized for a vector of TypedValues
|
// use FNV collection hashing specialized for a vector of TypedValues
|
||||||
FnvCollection<std::vector<TypedValue>, TypedValue, TypedValue::Hash>,
|
utils::FnvCollection<std::vector<TypedValue>, TypedValue,
|
||||||
|
TypedValue::Hash>,
|
||||||
TypedValueVectorEqual>
|
TypedValueVectorEqual>
|
||||||
seen_rows_;
|
seen_rows_;
|
||||||
};
|
};
|
||||||
|
@ -70,8 +70,8 @@ class VertexCountCache {
|
|||||||
|
|
||||||
struct LabelPropertyHash {
|
struct LabelPropertyHash {
|
||||||
size_t operator()(const LabelPropertyKey &key) const {
|
size_t operator()(const LabelPropertyKey &key) const {
|
||||||
return HashCombine<storage::Label, storage::Property>{}(key.first,
|
return utils::HashCombine<storage::Label, storage::Property>{}(
|
||||||
key.second);
|
key.first, key.second);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ class VertexCountCache {
|
|||||||
if (maybe_lower) lower = maybe_lower->value();
|
if (maybe_lower) lower = maybe_lower->value();
|
||||||
if (maybe_upper) upper = maybe_upper->value();
|
if (maybe_upper) upper = maybe_upper->value();
|
||||||
query::TypedValue::Hash hash;
|
query::TypedValue::Hash hash;
|
||||||
return HashCombine<size_t, size_t>{}(hash(lower), hash(upper));
|
return utils::HashCombine<size_t, size_t>{}(hash(lower), hash(upper));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -671,7 +671,7 @@ size_t TypedValue::Hash::operator()(const TypedValue &value) const {
|
|||||||
case TypedValue::Type::String:
|
case TypedValue::Type::String:
|
||||||
return std::hash<std::string>{}(value.Value<std::string>());
|
return std::hash<std::string>{}(value.Value<std::string>());
|
||||||
case TypedValue::Type::List: {
|
case TypedValue::Type::List: {
|
||||||
return FnvCollection<std::vector<TypedValue>, TypedValue, Hash>{}(
|
return utils::FnvCollection<std::vector<TypedValue>, TypedValue, Hash>{}(
|
||||||
value.Value<std::vector<TypedValue>>());
|
value.Value<std::vector<TypedValue>>());
|
||||||
}
|
}
|
||||||
case TypedValue::Type::Map: {
|
case TypedValue::Type::Map: {
|
||||||
@ -687,9 +687,10 @@ size_t TypedValue::Hash::operator()(const TypedValue &value) const {
|
|||||||
case TypedValue::Type::Edge:
|
case TypedValue::Type::Edge:
|
||||||
return value.Value<EdgeAccessor>().gid();
|
return value.Value<EdgeAccessor>().gid();
|
||||||
case TypedValue::Type::Path:
|
case TypedValue::Type::Path:
|
||||||
return FnvCollection<std::vector<VertexAccessor>, VertexAccessor>{}(
|
return utils::FnvCollection<std::vector<VertexAccessor>,
|
||||||
|
VertexAccessor>{}(
|
||||||
value.ValuePath().vertices()) ^
|
value.ValuePath().vertices()) ^
|
||||||
FnvCollection<std::vector<EdgeAccessor>, EdgeAccessor>{}(
|
utils::FnvCollection<std::vector<EdgeAccessor>, EdgeAccessor>{}(
|
||||||
value.ValuePath().edges());
|
value.ValuePath().edges());
|
||||||
}
|
}
|
||||||
LOG(FATAL) << "Unhandled TypedValue.type() in hash function";
|
LOG(FATAL) << "Unhandled TypedValue.type() in hash function";
|
||||||
|
@ -25,7 +25,8 @@ namespace query {
|
|||||||
* Values can be of a number of predefined types that are enumerated in
|
* Values can be of a number of predefined types that are enumerated in
|
||||||
* TypedValue::Type. Each such type corresponds to exactly one C++ type.
|
* TypedValue::Type. Each such type corresponds to exactly one C++ type.
|
||||||
*/
|
*/
|
||||||
class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
|
class TypedValue
|
||||||
|
: public utils::TotalOrdering<TypedValue, TypedValue, TypedValue> {
|
||||||
public:
|
public:
|
||||||
/** Custom TypedValue equality function that returns a bool
|
/** Custom TypedValue equality function that returns a bool
|
||||||
* (as opposed to returning TypedValue as the default equality does).
|
* (as opposed to returning TypedValue as the default equality does).
|
||||||
@ -152,7 +153,7 @@ class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
const T &Value() const;
|
const T &Value() const;
|
||||||
|
|
||||||
// TODO consider adding getters for primitives by value (and not by ref)
|
// TODO consider adding getters for primitives by value (and not by ref)
|
||||||
|
|
||||||
#define DECLARE_VALUE_AND_TYPE_GETTERS(type_param, field) \
|
#define DECLARE_VALUE_AND_TYPE_GETTERS(type_param, field) \
|
||||||
/** Gets the value of type field. Throws if value is not field*/ \
|
/** Gets the value of type field. Throws if value is not field*/ \
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "boost/serialization/vector.hpp"
|
#include "boost/serialization/vector.hpp"
|
||||||
|
|
||||||
#include "communication/rpc/messages.hpp"
|
#include "communication/rpc/messages.hpp"
|
||||||
#include "utils/datetime/timestamp.hpp"
|
#include "utils/timestamp.hpp"
|
||||||
|
|
||||||
namespace stats {
|
namespace stats {
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ struct StatsReq : public communication::rpc::Message {
|
|||||||
: metric_path(metric_path),
|
: metric_path(metric_path),
|
||||||
tags(tags),
|
tags(tags),
|
||||||
value(value),
|
value(value),
|
||||||
timestamp(Timestamp::Now().SecSinceTheEpoch()) {}
|
timestamp(utils::Timestamp::Now().SecSinceTheEpoch()) {}
|
||||||
|
|
||||||
std::string metric_path;
|
std::string metric_path;
|
||||||
std::vector<std::pair<std::string, std::string>> tags;
|
std::vector<std::pair<std::string, std::string>> tags;
|
||||||
@ -39,7 +39,7 @@ RPC_NO_MEMBER_MESSAGE(StatsRes);
|
|||||||
|
|
||||||
struct BatchStatsReq : public communication::rpc::Message {
|
struct BatchStatsReq : public communication::rpc::Message {
|
||||||
BatchStatsReq() {}
|
BatchStatsReq() {}
|
||||||
BatchStatsReq(std::vector<StatsReq> requests) : requests(requests) {}
|
explicit BatchStatsReq(std::vector<StatsReq> requests) : requests(requests) {}
|
||||||
|
|
||||||
std::vector<StatsReq> requests;
|
std::vector<StatsReq> requests;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ struct StateDelta;
|
|||||||
* @tparam TRecord Type of record (MVCC Version) of the accessor.
|
* @tparam TRecord Type of record (MVCC Version) of the accessor.
|
||||||
*/
|
*/
|
||||||
template <typename TRecord>
|
template <typename TRecord>
|
||||||
class RecordAccessor : public TotalOrdering<RecordAccessor<TRecord>> {
|
class RecordAccessor : public utils::TotalOrdering<RecordAccessor<TRecord>> {
|
||||||
protected:
|
protected:
|
||||||
using AddressT = storage::Address<mvcc::VersionList<TRecord>>;
|
using AddressT = storage::Address<mvcc::VersionList<TRecord>>;
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
namespace storage {
|
namespace storage {
|
||||||
|
|
||||||
template <typename TSpecificType>
|
template <typename TSpecificType>
|
||||||
class Common : public TotalOrdering<TSpecificType> {
|
class Common : public utils::TotalOrdering<TSpecificType> {
|
||||||
public:
|
public:
|
||||||
using StorageT = uint16_t;
|
using StorageT = uint16_t;
|
||||||
|
|
||||||
|
@ -5,35 +5,39 @@
|
|||||||
|
|
||||||
#include <byteswap.h>
|
#include <byteswap.h>
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T bswap(T value);
|
inline T Bswap(T value);
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline int16_t bswap<int16_t>(int16_t value) {
|
inline int16_t Bswap<int16_t>(int16_t value) {
|
||||||
return __bswap_16(value);
|
return __bswap_16(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline uint16_t bswap<uint16_t>(uint16_t value) {
|
inline uint16_t Bswap<uint16_t>(uint16_t value) {
|
||||||
return __bswap_16(value);
|
return __bswap_16(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline int32_t bswap<int32_t>(int32_t value) {
|
inline int32_t Bswap<int32_t>(int32_t value) {
|
||||||
return __bswap_32(value);
|
return __bswap_32(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline uint32_t bswap<uint32_t>(uint32_t value) {
|
inline uint32_t Bswap<uint32_t>(uint32_t value) {
|
||||||
return __bswap_32(value);
|
return __bswap_32(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline int64_t bswap<int64_t>(int64_t value) {
|
inline int64_t Bswap<int64_t>(int64_t value) {
|
||||||
return __bswap_64(value);
|
return __bswap_64(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline uint64_t bswap<uint64_t>(uint64_t value) {
|
inline uint64_t Bswap<uint64_t>(uint64_t value) {
|
||||||
return __bswap_64(value);
|
return __bswap_64(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -3,9 +3,13 @@
|
|||||||
// a helper class for implementing static casting to a derived class using the
|
// a helper class for implementing static casting to a derived class using the
|
||||||
// curiously recurring template pattern
|
// curiously recurring template pattern
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
template <class Derived>
|
template <class Derived>
|
||||||
struct Crtp {
|
struct Crtp {
|
||||||
Derived& derived() { return *static_cast<Derived*>(this); }
|
Derived &derived() { return *static_cast<Derived *>(this); }
|
||||||
|
|
||||||
const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
const Derived &derived() const { return *static_cast<const Derived *>(this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "utils/datetime/datetime_error.hpp"
|
|
||||||
|
|
||||||
class Datetime {
|
|
||||||
public:
|
|
||||||
Datetime() {}
|
|
||||||
|
|
||||||
Datetime(std::time_t time_point) {
|
|
||||||
auto result = gmtime_r(&time_point, &time);
|
|
||||||
|
|
||||||
if (result == nullptr)
|
|
||||||
throw DatetimeError("Unable to construct from {}", time_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
Datetime(const Datetime&) = default;
|
|
||||||
Datetime(Datetime&&) = default;
|
|
||||||
|
|
||||||
static Datetime now() {
|
|
||||||
timespec
|
|
||||||
|
|
||||||
return Datetime();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::tm time;
|
|
||||||
};
|
|
@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "utils/exceptions.hpp"
|
|
||||||
|
|
||||||
class DatetimeError : public utils::StacktraceException {
|
|
||||||
public:
|
|
||||||
using utils::StacktraceException::StacktraceException;
|
|
||||||
};
|
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "utils/scheduler.hpp"
|
#include "utils/scheduler.hpp"
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief - Provides execution of jobs in job queue on one thread with 'pause'
|
* @brief - Provides execution of jobs in job queue on one thread with 'pause'
|
||||||
* time between two consecutives starts.
|
* time between two consecutives starts.
|
||||||
@ -93,3 +95,5 @@ class Executor {
|
|||||||
Scheduler scheduler_;
|
Scheduler scheduler_;
|
||||||
std::vector<std::pair<int, std::function<void()>>> id_job_pairs_;
|
std::vector<std::pair<int, std::function<void()>>> id_job_pairs_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -29,8 +29,8 @@ namespace fs = std::experimental::filesystem;
|
|||||||
#include "utils/likely.hpp"
|
#include "utils/likely.hpp"
|
||||||
#include "utils/underlying_cast.hpp"
|
#include "utils/underlying_cast.hpp"
|
||||||
|
|
||||||
namespace utils {
|
namespace utils::linux_os {
|
||||||
namespace linux_os {
|
|
||||||
void set_non_blocking(int fd) {
|
void set_non_blocking(int fd) {
|
||||||
auto flags = fcntl(fd, F_GETFL, 0);
|
auto flags = fcntl(fd, F_GETFL, 0);
|
||||||
|
|
||||||
@ -44,7 +44,6 @@ void set_non_blocking(int fd) {
|
|||||||
if (UNLIKELY(status == -1))
|
if (UNLIKELY(status == -1))
|
||||||
throw BasicException("Can't set NON_BLOCK flag to file descriptor");
|
throw BasicException("Can't set NON_BLOCK flag to file descriptor");
|
||||||
}
|
}
|
||||||
} // namespace linux_os
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Goes from first to last item in a container, if an element satisfying the
|
* Goes from first to last item in a container, if an element satisfying the
|
||||||
@ -194,7 +193,8 @@ class FSWatcher {
|
|||||||
/**
|
/**
|
||||||
* Initialize underlying notification system.
|
* Initialize underlying notification system.
|
||||||
*/
|
*/
|
||||||
FSWatcher(ms check_interval = ms(100)) : check_interval_(check_interval) {
|
explicit FSWatcher(ms check_interval = ms(100))
|
||||||
|
: check_interval_(check_interval) {
|
||||||
DLOG(INFO) << fmt::format("Inotify header length: {}", IN_HEADER_SIZE);
|
DLOG(INFO) << fmt::format("Inotify header length: {}", IN_HEADER_SIZE);
|
||||||
DLOG(INFO) << fmt::format("Inotify buffer length: {}", IN_BUFF_LEN);
|
DLOG(INFO) << fmt::format("Inotify buffer length: {}", IN_BUFF_LEN);
|
||||||
inotify_fd_ = inotify_init();
|
inotify_fd_ = inotify_init();
|
||||||
@ -469,4 +469,5 @@ class FSWatcher {
|
|||||||
*/
|
*/
|
||||||
char *buffer_[IN_BUFF_LEN];
|
char *buffer_[IN_BUFF_LEN];
|
||||||
};
|
};
|
||||||
} // namespace utils
|
|
||||||
|
} // namespace utils::linux_os
|
||||||
|
@ -11,7 +11,7 @@ template <typename TResult>
|
|||||||
class Future {
|
class Future {
|
||||||
public:
|
public:
|
||||||
Future() {}
|
Future() {}
|
||||||
Future(std::future<TResult> future) : future_(std::move(future)) {}
|
explicit Future(std::future<TResult> future) : future_(std::move(future)) {}
|
||||||
|
|
||||||
Future(const Future &) = delete;
|
Future(const Future &) = delete;
|
||||||
Future(Future &&) = default;
|
Future(Future &&) = default;
|
||||||
@ -42,4 +42,5 @@ template <typename TResult>
|
|||||||
Future<TResult> make_future(std::future<TResult> future) {
|
Future<TResult> make_future(std::future<TResult> future) {
|
||||||
return Future<TResult>(std::move(future));
|
return Future<TResult>(std::move(future));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -32,6 +32,8 @@ using HashType = uint32_t;
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does FNV-like hashing on a collection. Not truly FNV
|
* Does FNV-like hashing on a collection. Not truly FNV
|
||||||
* because it operates on 8-bit elements, while this
|
* because it operates on 8-bit elements, while this
|
||||||
@ -83,3 +85,5 @@ struct HashCombine {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <glog/logging.h>
|
|
||||||
|
|
||||||
#include "utils/stacktrace.hpp"
|
|
||||||
|
|
||||||
class LogDestructor {
|
|
||||||
protected:
|
|
||||||
~LogDestructor() {
|
|
||||||
Stacktrace st;
|
|
||||||
DLOG(INFO) << st.dump();
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace memory {
|
|
||||||
namespace literals {
|
|
||||||
|
|
||||||
constexpr unsigned long long operator"" _GB(unsigned long long gb) {
|
|
||||||
return 1024 * 1024 * 1024 * gb;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr unsigned long long operator"" _MB(unsigned long long mb) {
|
|
||||||
return 1024 * 1024 * mb;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr unsigned long long operator"" _kB(unsigned long long kb) {
|
|
||||||
return 1024 * kb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,4 +15,5 @@ std::experimental::optional<std::string> GetHostname();
|
|||||||
|
|
||||||
// Try to establish a connection to a remote host
|
// Try to establish a connection to a remote host
|
||||||
bool CanEstablishConnection(const io::network::Endpoint &endpoint);
|
bool CanEstablishConnection(const io::network::Endpoint &endpoint);
|
||||||
}; // namespace utils
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -32,4 +32,5 @@ class OnScopeExit {
|
|||||||
private:
|
private:
|
||||||
std::function<void()> function_;
|
std::function<void()> function_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
@ -1,197 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ext/aligned_buffer.h>
|
|
||||||
#include "glog/logging.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
// Optional object storage. It maybe has and maybe
|
|
||||||
// dosent have objet of type T.
|
|
||||||
template <class T>
|
|
||||||
class Option {
|
|
||||||
public:
|
|
||||||
Option() { std::memset(data._M_addr(), 0, sizeof(T)); }
|
|
||||||
|
|
||||||
Option(T const &item) {
|
|
||||||
new (data._M_addr()) T(item);
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Option(T &&item) {
|
|
||||||
new (data._M_addr()) T(std::move(item));
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Option(const Option &other) {
|
|
||||||
if (other.initialized) {
|
|
||||||
new (data._M_addr()) T(other.get());
|
|
||||||
initialized = true;
|
|
||||||
} else {
|
|
||||||
std::memset(data._M_addr(), 0, sizeof(T));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Containers from std which have strong exception
|
|
||||||
// guarantees wont use move constructors and operators
|
|
||||||
// wihtout noexcept. "Optimized C++,2016 , Kurt
|
|
||||||
// Guntheroth, page: 142, title: Moving instances into
|
|
||||||
// std::vector"
|
|
||||||
Option(Option &&other) noexcept {
|
|
||||||
if (other.initialized) {
|
|
||||||
new (data._M_addr()) T(std::move(other.get()));
|
|
||||||
other.initialized = false;
|
|
||||||
initialized = true;
|
|
||||||
} else {
|
|
||||||
std::memset(data._M_addr(), 0, sizeof(T));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~Option() {
|
|
||||||
if (initialized) {
|
|
||||||
get().~T();
|
|
||||||
initialized = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Option &operator=(const Option &other) {
|
|
||||||
if (initialized) {
|
|
||||||
get().~T();
|
|
||||||
initialized = false;
|
|
||||||
}
|
|
||||||
if (other.initialized) {
|
|
||||||
new (data._M_addr()) T(other.get());
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Option &operator=(Option &&other) {
|
|
||||||
if (initialized) {
|
|
||||||
get().~T();
|
|
||||||
initialized = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (other.initialized) {
|
|
||||||
new (data._M_addr()) T(std::move(other.get()));
|
|
||||||
other.initialized = false;
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// True if object i present.
|
|
||||||
bool is_present() const { return initialized; }
|
|
||||||
|
|
||||||
T &get() noexcept {
|
|
||||||
DCHECK(initialized) << "Not initialized.";
|
|
||||||
return *data._M_ptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
T &get_or(T &other) {
|
|
||||||
if (is_present()) {
|
|
||||||
return get();
|
|
||||||
} else {
|
|
||||||
return other;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns ref to object if present else other.
|
|
||||||
T const &get_or(T const &other) const {
|
|
||||||
if (is_present()) {
|
|
||||||
return get();
|
|
||||||
} else {
|
|
||||||
return other;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const T &get() const noexcept {
|
|
||||||
DCHECK(initialized) << "Not initialized.";
|
|
||||||
return *data._M_ptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U>
|
|
||||||
Option<U> map() {
|
|
||||||
if (is_present()) {
|
|
||||||
return Option<U>(U(take()));
|
|
||||||
} else {
|
|
||||||
return Option<U>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U, class F>
|
|
||||||
Option<U> map(F f) {
|
|
||||||
if (is_present()) {
|
|
||||||
return Option<U>(f(take()));
|
|
||||||
} else {
|
|
||||||
return Option<U>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U, class F>
|
|
||||||
U map_or(F f, U &&def) {
|
|
||||||
if (is_present()) {
|
|
||||||
return f(take());
|
|
||||||
} else {
|
|
||||||
return std::move(def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U, class F>
|
|
||||||
U call_or(F f, U &&def) {
|
|
||||||
if (is_present()) {
|
|
||||||
return f(get());
|
|
||||||
} else {
|
|
||||||
return std::move(def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T take() {
|
|
||||||
DCHECK(initialized) << "Not initialized.";
|
|
||||||
initialized = false;
|
|
||||||
return std::move(*data._M_ptr());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Takes if it exists otherwise returns given value.
|
|
||||||
T take_or(T &&value) {
|
|
||||||
if (initialized) {
|
|
||||||
initialized = false;
|
|
||||||
return std::move(*data._M_ptr());
|
|
||||||
} else {
|
|
||||||
return std::move(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const { return initialized; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Aligned buffer is here to ensure aligment for
|
|
||||||
// data of type T. It isn't applicable to just put T
|
|
||||||
// field because the field has to be able to be
|
|
||||||
// uninitialized to fulfill the semantics of Option class.
|
|
||||||
__gnu_cxx::__aligned_buffer<T> data;
|
|
||||||
bool initialized = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
auto make_option() {
|
|
||||||
return Option<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
auto make_option(T &&data) {
|
|
||||||
return Option<T>(std::move(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
auto make_option_const(const T &&data) {
|
|
||||||
return Option<const T>(std::move(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
// HELPER FUNCTIONS
|
|
||||||
template <class R>
|
|
||||||
bool option_fill(Option<R> &o) {
|
|
||||||
return o.is_present() && o.get().fill();
|
|
||||||
}
|
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include <ext/aligned_buffer.h>
|
#include <ext/aligned_buffer.h>
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Placeholder
|
* @class Placeholder
|
||||||
*
|
*
|
||||||
@ -91,3 +93,5 @@ class Placeholder {
|
|||||||
__gnu_cxx::__aligned_buffer<T> data;
|
__gnu_cxx::__aligned_buffer<T> data;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include "utils/likely.hpp"
|
#include "utils/likely.hpp"
|
||||||
#include "utils/random/xorshift128plus.hpp"
|
#include "utils/random/xorshift128plus.hpp"
|
||||||
|
|
||||||
|
namespace utils::random {
|
||||||
|
|
||||||
template <class R = Xorshift128plus>
|
template <class R = Xorshift128plus>
|
||||||
class FastBinomial {
|
class FastBinomial {
|
||||||
// fast binomial draws coin tosses from a single generated random number
|
// fast binomial draws coin tosses from a single generated random number
|
||||||
@ -55,3 +57,5 @@ class FastBinomial {
|
|||||||
uint64_t mask(const int n) { return (1ULL << n) - 1; }
|
uint64_t mask(const int n) { return (1ULL << n) - 1; }
|
||||||
R random;
|
R random;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace utils::random
|
||||||
|
@ -2,11 +2,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// namespace ::utils
|
namespace utils::random {
|
||||||
namespace utils {
|
|
||||||
|
|
||||||
// namespace utils::random
|
|
||||||
namespace random {
|
|
||||||
|
|
||||||
template <class Distribution, class Generator>
|
template <class Distribution, class Generator>
|
||||||
class RandomGenerator {
|
class RandomGenerator {
|
||||||
@ -28,7 +24,7 @@ class StringGenerator
|
|||||||
int size_;
|
int size_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StringGenerator(int size)
|
explicit StringGenerator(int size)
|
||||||
: RandomGenerator(std::uniform_int_distribution<int>(32, 126)),
|
: RandomGenerator(std::uniform_int_distribution<int>(32, 126)),
|
||||||
size_(size) {}
|
size_(size) {}
|
||||||
|
|
||||||
@ -82,5 +78,4 @@ auto generate_set(RandomGenerator &gen, int size) {
|
|||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace utils::random
|
} // namespace utils::random
|
||||||
}; // namespace ::utils
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
|
namespace utils::random {
|
||||||
|
|
||||||
/* Xorshift algorithm (plus variant)
|
/* Xorshift algorithm (plus variant)
|
||||||
*
|
*
|
||||||
* This is the fastest generator passing BigCrush without systematic failures,
|
* This is the fastest generator passing BigCrush without systematic failures,
|
||||||
@ -54,3 +56,5 @@ struct Xorshift128plus {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace utils::random
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include "utils/thread.hpp"
|
#include "utils/thread.hpp"
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to run scheduled function execution.
|
* Class used to run scheduled function execution.
|
||||||
*/
|
*/
|
||||||
@ -99,3 +101,5 @@ class Scheduler {
|
|||||||
*/
|
*/
|
||||||
std::thread thread_;
|
std::thread thread_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include "utils/on_scope_exit.hpp"
|
#include "utils/on_scope_exit.hpp"
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
class Stacktrace {
|
class Stacktrace {
|
||||||
public:
|
public:
|
||||||
class Line {
|
class Line {
|
||||||
@ -92,3 +94,5 @@ class Stacktrace {
|
|||||||
return {original, function, location};
|
return {original, function, location};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "glog/logging.h"
|
#include "glog/logging.h"
|
||||||
|
|
||||||
namespace utils {
|
namespace utils::sysinfo {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the amount of available RAM in kilobytes. If the information is
|
* Gets the amount of available RAM in kilobytes. If the information is
|
||||||
@ -27,4 +27,5 @@ inline auto AvailableMem() {
|
|||||||
LOG(ERROR) << "Failed to read amount of available memory from /proc/meminfo";
|
LOG(ERROR) << "Failed to read amount of available memory from /proc/meminfo";
|
||||||
return 0UL;
|
return 0UL;
|
||||||
}
|
}
|
||||||
} // namespace utils
|
|
||||||
|
} // namespace utils::sysinfo
|
||||||
|
@ -1,27 +1,30 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "utils/stacktrace.hpp"
|
|
||||||
|
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// TODO: log to local file or remote database
|
#include "utils/stacktrace.hpp"
|
||||||
void stacktrace(std::ostream &stream) noexcept {
|
|
||||||
Stacktrace stacktrace;
|
|
||||||
stacktrace.dump(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: log to local file or remote database
|
namespace utils {
|
||||||
void terminate_handler(std::ostream &stream) noexcept {
|
|
||||||
|
/**
|
||||||
|
* Dump stacktrace to the stream and abort the probram. For more details
|
||||||
|
* about the abort please take a look at
|
||||||
|
* http://en.cppreference.com/w/cpp/utility/program/abort.
|
||||||
|
*/
|
||||||
|
void TerminateHandler(std::ostream &stream) noexcept {
|
||||||
if (auto exc = std::current_exception()) {
|
if (auto exc = std::current_exception()) {
|
||||||
try {
|
try {
|
||||||
std::rethrow_exception(exc);
|
std::rethrow_exception(exc);
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
stream << ex.what() << std::endl << std::endl;
|
stream << ex.what() << std::endl << std::endl;
|
||||||
stacktrace(stream);
|
utils::Stacktrace stacktrace;
|
||||||
|
stacktrace.dump(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminate_handler() noexcept { terminate_handler(std::cout); }
|
void TerminateHandler() noexcept { TerminateHandler(std::cout); }
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -16,4 +16,5 @@ class Timer {
|
|||||||
std::chrono::time_point<std::chrono::steady_clock> start_time_ =
|
std::chrono::time_point<std::chrono::steady_clock> start_time_ =
|
||||||
std::chrono::steady_clock::now();
|
std::chrono::steady_clock::now();
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -7,9 +7,16 @@
|
|||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "utils/datetime/datetime_error.hpp"
|
#include "utils/exceptions.hpp"
|
||||||
#include "utils/total_ordering.hpp"
|
#include "utils/total_ordering.hpp"
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
class TimestampError : public StacktraceException {
|
||||||
|
public:
|
||||||
|
using StacktraceException::StacktraceException;
|
||||||
|
};
|
||||||
|
|
||||||
class Timestamp : public TotalOrdering<Timestamp> {
|
class Timestamp : public TotalOrdering<Timestamp> {
|
||||||
public:
|
public:
|
||||||
Timestamp() : Timestamp(0, 0) {}
|
Timestamp() : Timestamp(0, 0) {}
|
||||||
@ -18,11 +25,11 @@ class Timestamp : public TotalOrdering<Timestamp> {
|
|||||||
auto result = gmtime_r(&time, &this->time);
|
auto result = gmtime_r(&time, &this->time);
|
||||||
|
|
||||||
if (result == nullptr)
|
if (result == nullptr)
|
||||||
throw DatetimeError("Unable to construct from {}", time);
|
throw TimestampError("Unable to construct from {}", time);
|
||||||
}
|
}
|
||||||
|
|
||||||
Timestamp(const Timestamp&) = default;
|
Timestamp(const Timestamp &) = default;
|
||||||
Timestamp(Timestamp&&) = default;
|
Timestamp(Timestamp &&) = default;
|
||||||
|
|
||||||
static Timestamp Now() {
|
static Timestamp Now() {
|
||||||
timespec time;
|
timespec time;
|
||||||
@ -54,22 +61,22 @@ class Timestamp : public TotalOrdering<Timestamp> {
|
|||||||
Subsec());
|
Subsec());
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string ToString(const std::string& format = fiso8601) const {
|
const std::string ToString(const std::string &format = fiso8601) const {
|
||||||
return fmt::format(format, Year(), Month(), Day(), Hour(), Min(), Sec(),
|
return fmt::format(format, Year(), Month(), Day(), Hour(), Min(), Sec(),
|
||||||
Subsec());
|
Subsec());
|
||||||
}
|
}
|
||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& stream, const Timestamp& ts) {
|
friend std::ostream &operator<<(std::ostream &stream, const Timestamp &ts) {
|
||||||
return stream << ts.ToIso8601();
|
return stream << ts.ToIso8601();
|
||||||
}
|
}
|
||||||
|
|
||||||
operator std::string() const { return ToString(); }
|
operator std::string() const { return ToString(); }
|
||||||
|
|
||||||
constexpr friend bool operator==(const Timestamp& a, const Timestamp& b) {
|
constexpr friend bool operator==(const Timestamp &a, const Timestamp &b) {
|
||||||
return a.unix_time == b.unix_time && a.nsec == b.nsec;
|
return a.unix_time == b.unix_time && a.nsec == b.nsec;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr friend bool operator<(const Timestamp& a, const Timestamp& b) {
|
constexpr friend bool operator<(const Timestamp &a, const Timestamp &b) {
|
||||||
return a.unix_time < b.unix_time ||
|
return a.unix_time < b.unix_time ||
|
||||||
(a.unix_time == b.unix_time && a.nsec < b.nsec);
|
(a.unix_time == b.unix_time && a.nsec < b.nsec);
|
||||||
}
|
}
|
||||||
@ -84,3 +91,5 @@ class Timestamp : public TotalOrdering<Timestamp> {
|
|||||||
static constexpr auto fiso8601 =
|
static constexpr auto fiso8601 =
|
||||||
"{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}.{:05d}Z";
|
"{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}.{:05d}Z";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace utils
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements all the logical comparison operators based on '=='
|
* Implements all the logical comparison operators based on '=='
|
||||||
* and '<' operators.
|
* and '<' operators.
|
||||||
@ -13,19 +15,19 @@ template <typename TLhs, typename TRhs = TLhs, typename TReturn = bool>
|
|||||||
struct TotalOrdering {
|
struct TotalOrdering {
|
||||||
virtual ~TotalOrdering() {}
|
virtual ~TotalOrdering() {}
|
||||||
|
|
||||||
friend constexpr TReturn operator!=(const TLhs& a, const TRhs& b) {
|
friend constexpr TReturn operator!=(const TLhs &a, const TRhs &b) {
|
||||||
return !(a == b);
|
return !(a == b);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr TReturn operator<=(const TLhs& a, const TRhs& b) {
|
friend constexpr TReturn operator<=(const TLhs &a, const TRhs &b) {
|
||||||
return a < b || a == b;
|
return a < b || a == b;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr TReturn operator>(const TLhs& a, const TRhs& b) {
|
friend constexpr TReturn operator>(const TLhs &a, const TRhs &b) {
|
||||||
return !(a <= b);
|
return !(a <= b);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr TReturn operator>=(const TLhs& a, const TRhs& b) {
|
friend constexpr TReturn operator>=(const TLhs &a, const TRhs &b) {
|
||||||
return !(a < b);
|
return !(a < b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -34,35 +36,37 @@ template <class Derived, class T>
|
|||||||
struct TotalOrderingWith {
|
struct TotalOrderingWith {
|
||||||
virtual ~TotalOrderingWith() {}
|
virtual ~TotalOrderingWith() {}
|
||||||
|
|
||||||
friend constexpr bool operator!=(const Derived& a, const T& b) {
|
friend constexpr bool operator!=(const Derived &a, const T &b) {
|
||||||
return !(a == b);
|
return !(a == b);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool operator<=(const Derived& a, const T& b) {
|
friend constexpr bool operator<=(const Derived &a, const T &b) {
|
||||||
return a < b || a == b;
|
return a < b || a == b;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool operator>(const Derived& a, const T& b) {
|
friend constexpr bool operator>(const Derived &a, const T &b) {
|
||||||
return !(a <= b);
|
return !(a <= b);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool operator>=(const Derived& a, const T& b) {
|
friend constexpr bool operator>=(const Derived &a, const T &b) {
|
||||||
return !(a < b);
|
return !(a < b);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool operator!=(const T& a, const Derived& b) {
|
friend constexpr bool operator!=(const T &a, const Derived &b) {
|
||||||
return !(a == b);
|
return !(a == b);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool operator<=(const T& a, const Derived& b) {
|
friend constexpr bool operator<=(const T &a, const Derived &b) {
|
||||||
return a < b || a == b;
|
return a < b || a == b;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool operator>(const T& a, const Derived& b) {
|
friend constexpr bool operator>(const T &a, const Derived &b) {
|
||||||
return !(a <= b);
|
return !(a <= b);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool operator>=(const T& a, const Derived& b) {
|
friend constexpr bool operator>=(const T &a, const Derived &b) {
|
||||||
return !(a < b);
|
return !(a < b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// USAGE:
|
|
||||||
// type_name<decltype(variable)>();
|
|
||||||
// current solution has been taken from
|
|
||||||
// http://stackoverflow.com/questions/81870/is-it-possible-to-print-a-variables-type-in-standard-c
|
|
||||||
// TODO: create more appropriate solution
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstring>
|
|
||||||
#include <ostream>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
#if __cplusplus < 201103
|
|
||||||
#define CONSTEXPR11_TN
|
|
||||||
#define CONSTEXPR14_TN
|
|
||||||
#define NOEXCEPT_TN
|
|
||||||
#elif __cplusplus < 201402
|
|
||||||
#define CONSTEXPR11_TN constexpr
|
|
||||||
#define CONSTEXPR14_TN
|
|
||||||
#define NOEXCEPT_TN noexcept
|
|
||||||
#else
|
|
||||||
#define CONSTEXPR11_TN constexpr
|
|
||||||
#define CONSTEXPR14_TN constexpr
|
|
||||||
#define NOEXCEPT_TN noexcept
|
|
||||||
#endif
|
|
||||||
#else // _MSC_VER
|
|
||||||
#if _MSC_VER < 1900
|
|
||||||
#define CONSTEXPR11_TN
|
|
||||||
#define CONSTEXPR14_TN
|
|
||||||
#define NOEXCEPT_TN
|
|
||||||
#elif _MSC_VER < 2000
|
|
||||||
#define CONSTEXPR11_TN constexpr
|
|
||||||
#define CONSTEXPR14_TN
|
|
||||||
#define NOEXCEPT_TN noexcept
|
|
||||||
#else
|
|
||||||
#define CONSTEXPR11_TN constexpr
|
|
||||||
#define CONSTEXPR14_TN constexpr
|
|
||||||
#define NOEXCEPT_TN noexcept
|
|
||||||
#endif
|
|
||||||
#endif // _MSC_VER
|
|
||||||
|
|
||||||
class static_string {
|
|
||||||
const char* const p_;
|
|
||||||
const std::size_t sz_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef const char* const_iterator;
|
|
||||||
|
|
||||||
template <std::size_t N>
|
|
||||||
CONSTEXPR11_TN static_string(const char (&a)[N]) NOEXCEPT_TN : p_(a),
|
|
||||||
sz_(N - 1) {}
|
|
||||||
|
|
||||||
CONSTEXPR11_TN static_string(const char *p, std::size_t N) NOEXCEPT_TN
|
|
||||||
: p_(p),
|
|
||||||
sz_(N) {}
|
|
||||||
|
|
||||||
CONSTEXPR11_TN const char* data() const NOEXCEPT_TN { return p_; }
|
|
||||||
CONSTEXPR11_TN std::size_t size() const NOEXCEPT_TN { return sz_; }
|
|
||||||
|
|
||||||
CONSTEXPR11_TN const_iterator begin() const NOEXCEPT_TN { return p_; }
|
|
||||||
CONSTEXPR11_TN const_iterator end() const NOEXCEPT_TN { return p_ + sz_; }
|
|
||||||
|
|
||||||
CONSTEXPR11_TN char operator[](std::size_t n) const {
|
|
||||||
return n < sz_ ? p_[n] : throw std::out_of_range("static_string");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string to_string() { return std::string(p_, sz_); }
|
|
||||||
};
|
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& os, static_string const& s) {
|
|
||||||
return os.write(s.data(), s.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
CONSTEXPR14_TN static_string type_name() {
|
|
||||||
#ifdef __clang__
|
|
||||||
static_string p = __PRETTY_FUNCTION__;
|
|
||||||
return static_string(p.data() + 31, p.size() - 31 - 1);
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
static_string p = __PRETTY_FUNCTION__;
|
|
||||||
#if __cplusplus < 201402
|
|
||||||
return static_string(p.data() + 36, p.size() - 36 - 1);
|
|
||||||
#else
|
|
||||||
return static_string(p.data() + 46, p.size() - 46 - 1);
|
|
||||||
#endif
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
static_string p = __FUNCSIG__;
|
|
||||||
return static_string(p.data() + 38, p.size() - 38 - 7);
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -11,10 +11,11 @@
|
|||||||
using std::chrono::milliseconds;
|
using std::chrono::milliseconds;
|
||||||
using std::chrono::steady_clock;
|
using std::chrono::steady_clock;
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
Watchdog::Watchdog(const milliseconds &min_timeout,
|
Watchdog::Watchdog(const milliseconds &min_timeout,
|
||||||
const milliseconds &max_timeout,
|
const milliseconds &max_timeout,
|
||||||
const std::function<void()> &callback,
|
const std::function<void()> &callback, bool blocked)
|
||||||
bool blocked)
|
|
||||||
: min_timeout_(min_timeout),
|
: min_timeout_(min_timeout),
|
||||||
max_timeout_(max_timeout),
|
max_timeout_(max_timeout),
|
||||||
generator_(std::random_device{}()),
|
generator_(std::random_device{}()),
|
||||||
@ -66,3 +67,5 @@ void Watchdog::Run() {
|
|||||||
std::this_thread::sleep_until(t);
|
std::this_thread::sleep_until(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include <random>
|
#include <random>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief - Keeps track of how long it's been since `Notify` method was called.
|
* @brief - Keeps track of how long it's been since `Notify` method was called.
|
||||||
* If it wasn't called for a sufficiently long time interval (randomly chosen
|
* If it wasn't called for a sufficiently long time interval (randomly chosen
|
||||||
@ -54,3 +56,5 @@ class Watchdog {
|
|||||||
std::atomic<bool> blocked_;
|
std::atomic<bool> blocked_;
|
||||||
std::thread thread_;
|
std::thread thread_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
@ -27,7 +27,7 @@ int main(int argc, char **argv) {
|
|||||||
google::InitGoogleLogging(argv[0]);
|
google::InitGoogleLogging(argv[0]);
|
||||||
|
|
||||||
// Unhandled exception handler init.
|
// Unhandled exception handler init.
|
||||||
std::set_terminate(&terminate_handler);
|
std::set_terminate(&utils::TerminateHandler);
|
||||||
|
|
||||||
Server server(io::network::Endpoint(FLAGS_interface, stoul(FLAGS_port)));
|
Server server(io::network::Endpoint(FLAGS_interface, stoul(FLAGS_port)));
|
||||||
std::ofstream log(FLAGS_log, std::ios_base::app);
|
std::ofstream log(FLAGS_log, std::ios_base::app);
|
||||||
|
@ -11,7 +11,7 @@ using namespace communication::rpc;
|
|||||||
|
|
||||||
struct AppendEntryReq : public Message {
|
struct AppendEntryReq : public Message {
|
||||||
AppendEntryReq() {}
|
AppendEntryReq() {}
|
||||||
AppendEntryReq(int val) : val(val) {}
|
explicit AppendEntryReq(int val) : val(val) {}
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -21,7 +21,8 @@ TEST(Antlr, Sigsegv) {
|
|||||||
|
|
||||||
for (int i = 0; i < N; ++i) {
|
for (int i = 0; i < N; ++i) {
|
||||||
threads.push_back(std::thread([&run]() {
|
threads.push_back(std::thread([&run]() {
|
||||||
while (!run);
|
while (!run)
|
||||||
|
;
|
||||||
while (run) {
|
while (run) {
|
||||||
query::frontend::opencypher::Parser parser(
|
query::frontend::opencypher::Parser parser(
|
||||||
"CREATE (:Label_T7 {x: 903}) CREATE (:Label_T7 {x: 720}) CREATE "
|
"CREATE (:Label_T7 {x: 903}) CREATE (:Label_T7 {x: 720}) CREATE "
|
||||||
@ -97,7 +98,7 @@ int main(int argc, char **argv) {
|
|||||||
});
|
});
|
||||||
utils::SignalHandler::RegisterHandler(utils::Signal::Abort, []() {
|
utils::SignalHandler::RegisterHandler(utils::Signal::Abort, []() {
|
||||||
// Log the stacktrace and let the abort continue.
|
// Log the stacktrace and let the abort continue.
|
||||||
Stacktrace stacktrace;
|
utils::Stacktrace stacktrace;
|
||||||
std::cerr << "Abort signal raised" << std::endl
|
std::cerr << "Abort signal raised" << std::endl
|
||||||
<< stacktrace.dump() << std::endl;
|
<< stacktrace.dump() << std::endl;
|
||||||
});
|
});
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "utils/random/fast_binomial.hpp"
|
#include "utils/random/fast_binomial.hpp"
|
||||||
|
|
||||||
static constexpr unsigned B = 24;
|
static constexpr unsigned B = 24;
|
||||||
static thread_local FastBinomial<> rnd;
|
static thread_local utils::random::FastBinomial<> rnd;
|
||||||
|
|
||||||
static constexpr unsigned M = 4;
|
static constexpr unsigned M = 4;
|
||||||
static constexpr size_t N = 1ULL << 34;
|
static constexpr size_t N = 1ULL << 34;
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include "durability/snapshot_encoder.hpp"
|
#include "durability/snapshot_encoder.hpp"
|
||||||
#include "durability/version.hpp"
|
#include "durability/version.hpp"
|
||||||
#include "storage/address_types.hpp"
|
#include "storage/address_types.hpp"
|
||||||
#include "utils/datetime/timestamp.hpp"
|
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
#include "utils/timer.hpp"
|
#include "utils/timer.hpp"
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
|
|
||||||
#include "query/frontend/stripped.hpp"
|
#include "query/frontend/stripped.hpp"
|
||||||
#include "utils/type_discovery.hpp"
|
|
||||||
|
|
||||||
DEFINE_string(q, "CREATE (n) RETURN n", "Query");
|
DEFINE_string(q, "CREATE (n) RETURN n", "Query");
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include "utils/random/xorshift128plus.hpp"
|
#include "utils/random/xorshift128plus.hpp"
|
||||||
|
|
||||||
static thread_local Xorshift128plus rnd;
|
static thread_local utils::random::Xorshift128plus rnd;
|
||||||
static constexpr unsigned B = 1 << 10;
|
static constexpr unsigned B = 1 << 10;
|
||||||
static constexpr uint64_t K = (uint64_t)(-1) / B;
|
static constexpr uint64_t K = (uint64_t)(-1) / B;
|
||||||
|
|
||||||
@ -35,20 +35,20 @@ int main(void) {
|
|||||||
|
|
||||||
std::array<std::thread, M> threads;
|
std::array<std::thread, M> threads;
|
||||||
|
|
||||||
for (auto& bucket : buckets) bucket.store(0);
|
for (auto &bucket : buckets) bucket.store(0);
|
||||||
|
|
||||||
for (auto& t : threads) t = std::thread([]() { generate(); });
|
for (auto &t : threads) t = std::thread([]() { generate(); });
|
||||||
|
|
||||||
for (auto& t : threads) t.join();
|
for (auto &t : threads) t.join();
|
||||||
|
|
||||||
auto max = std::accumulate(
|
auto max = std::accumulate(
|
||||||
buckets.begin(), buckets.end(), 0u,
|
buckets.begin(), buckets.end(), 0u,
|
||||||
[](auto& acc, auto& x) { return std::max(acc, x.load()); });
|
[](auto &acc, auto &x) { return std::max(acc, x.load()); });
|
||||||
DCHECK(max != 0u) << "max is 0.";
|
DCHECK(max != 0u) << "max is 0.";
|
||||||
|
|
||||||
std::cout << std::fixed;
|
std::cout << std::fixed;
|
||||||
|
|
||||||
for (auto& bucket : buckets) {
|
for (auto &bucket : buckets) {
|
||||||
auto x = bucket.load();
|
auto x = bucket.load();
|
||||||
auto rel = bar_len * x / max;
|
auto rel = bar_len * x / max;
|
||||||
|
|
||||||
|
@ -63,7 +63,8 @@ class TestOutputStream {
|
|||||||
*/
|
*/
|
||||||
class TestBuffer {
|
class TestBuffer {
|
||||||
public:
|
public:
|
||||||
TestBuffer(TestOutputStream &output_stream) : output_stream_(output_stream) {}
|
explicit TestBuffer(TestOutputStream &output_stream)
|
||||||
|
: output_stream_(output_stream) {}
|
||||||
|
|
||||||
void Write(const uint8_t *data, size_t n) { output_stream_.Write(data, n); }
|
void Write(const uint8_t *data, size_t n) { output_stream_.Write(data, n); }
|
||||||
void Chunk() {}
|
void Chunk() {}
|
||||||
|
@ -46,7 +46,7 @@ const uint8_t ignored_resp[] = {0x00, 0x02, 0xb0, 0x7e, 0x00, 0x00};
|
|||||||
|
|
||||||
// Write bolt chunk header (length)
|
// Write bolt chunk header (length)
|
||||||
void WriteChunkHeader(TestInputStream &input_stream, uint16_t len) {
|
void WriteChunkHeader(TestInputStream &input_stream, uint16_t len) {
|
||||||
len = bswap(len);
|
len = utils::Bswap(len);
|
||||||
input_stream.Write(reinterpret_cast<uint8_t *>(&len), sizeof(len));
|
input_stream.Write(reinterpret_cast<uint8_t *>(&len), sizeof(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
TEST(Executor, Run) {
|
TEST(Executor, Run) {
|
||||||
std::atomic<int> count{0};
|
std::atomic<int> count{0};
|
||||||
{
|
{
|
||||||
Executor exec(std::chrono::milliseconds(500));
|
utils::Executor exec(std::chrono::milliseconds(500));
|
||||||
// Be sure executor is sleeping.
|
// Be sure executor is sleeping.
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ TEST(Executor, RunUnregister) {
|
|||||||
std::atomic<int> count1{0};
|
std::atomic<int> count1{0};
|
||||||
std::atomic<int> count2{0};
|
std::atomic<int> count2{0};
|
||||||
{
|
{
|
||||||
Executor exec(std::chrono::milliseconds(500));
|
utils::Executor exec(std::chrono::milliseconds(500));
|
||||||
// Be sure executor is sleeping.
|
// Be sure executor is sleeping.
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
auto job = exec.RegisterJob([&count1]() { ++count1; });
|
auto job = exec.RegisterJob([&count1]() { ++count1; });
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
TEST(Scheduler, TestFunctionExecuting) {
|
TEST(Scheduler, TestFunctionExecuting) {
|
||||||
std::atomic<int> x{0};
|
std::atomic<int> x{0};
|
||||||
std::function<void()> func{[&x]() { ++x; }};
|
std::function<void()> func{[&x]() { ++x; }};
|
||||||
Scheduler scheduler;
|
utils::Scheduler scheduler;
|
||||||
scheduler.Run("Test", std::chrono::seconds(1), func);
|
scheduler.Run("Test", std::chrono::seconds(1), func);
|
||||||
|
|
||||||
EXPECT_EQ(x, 0);
|
EXPECT_EQ(x, 0);
|
||||||
|
@ -18,7 +18,7 @@ TEST(Signals, Handler) {
|
|||||||
ASSERT_TRUE(utils::SignalHandler::RegisterHandler(
|
ASSERT_TRUE(utils::SignalHandler::RegisterHandler(
|
||||||
utils::Signal::SegmentationFault, []() {
|
utils::Signal::SegmentationFault, []() {
|
||||||
std::cout << "Segmentation Fault" << std::endl;
|
std::cout << "Segmentation Fault" << std::endl;
|
||||||
Stacktrace stacktrace;
|
utils::Stacktrace stacktrace;
|
||||||
std::cout << stacktrace.dump() << std::endl;
|
std::cout << stacktrace.dump() << std::endl;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -3,28 +3,28 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "utils/datetime/timestamp.hpp"
|
#include "utils/timestamp.hpp"
|
||||||
|
|
||||||
TEST(TimestampTest, BasicUsage) {
|
TEST(TimestampTest, BasicUsage) {
|
||||||
auto timestamp = Timestamp::Now();
|
auto timestamp = utils::Timestamp::Now();
|
||||||
|
|
||||||
std::cout << timestamp << std::endl;
|
std::cout << timestamp << std::endl;
|
||||||
std::cout << Timestamp::Now() << std::endl;
|
std::cout << utils::Timestamp::Now() << std::endl;
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||||
|
|
||||||
std::cout << Timestamp::Now().ToIso8601() << std::endl;
|
std::cout << utils::Timestamp::Now().ToIso8601() << std::endl;
|
||||||
|
|
||||||
ASSERT_GT(Timestamp::Now(), timestamp);
|
ASSERT_GT(utils::Timestamp::Now(), timestamp);
|
||||||
|
|
||||||
std::cout << std::boolalpha;
|
std::cout << std::boolalpha;
|
||||||
|
|
||||||
std::cout << (timestamp == Timestamp::Now()) << std::endl;
|
std::cout << (timestamp == utils::Timestamp::Now()) << std::endl;
|
||||||
|
|
||||||
ASSERT_NE(timestamp, Timestamp::Now());
|
ASSERT_NE(timestamp, utils::Timestamp::Now());
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char **argv) {
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
return RUN_ALL_TESTS();
|
return RUN_ALL_TESTS();
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ using namespace std::chrono_literals;
|
|||||||
|
|
||||||
TEST(Watchdog, Run) {
|
TEST(Watchdog, Run) {
|
||||||
std::atomic<int> count(0);
|
std::atomic<int> count(0);
|
||||||
Watchdog dog(200ms, 200ms, [&count]() { ++count; });
|
utils::Watchdog dog(200ms, 200ms, [&count]() { ++count; });
|
||||||
|
|
||||||
std::this_thread::sleep_for(250ms);
|
std::this_thread::sleep_for(250ms);
|
||||||
EXPECT_EQ(count, 1);
|
EXPECT_EQ(count, 1);
|
||||||
@ -29,7 +29,7 @@ TEST(Watchdog, Run) {
|
|||||||
|
|
||||||
TEST(Watchdog, Blocker) {
|
TEST(Watchdog, Blocker) {
|
||||||
std::atomic<int> count(0);
|
std::atomic<int> count(0);
|
||||||
Watchdog dog(200ms, 200ms, [&count]() { ++count; });
|
utils::Watchdog dog(200ms, 200ms, [&count]() { ++count; });
|
||||||
|
|
||||||
std::this_thread::sleep_for(250ms);
|
std::this_thread::sleep_for(250ms);
|
||||||
EXPECT_EQ(count, 1);
|
EXPECT_EQ(count, 1);
|
||||||
|
Loading…
Reference in New Issue
Block a user