75950664a7
Summary: This diff splits single node and distributed storage from each other. Currently all of the storage code is copied into two directories (one single node, one distributed). The logic used in the storage implementation isn't touched, it will be refactored in following diffs. To clean the working directory after this diff you should execute: ``` rm database/state_delta.capnp rm database/state_delta.hpp rm storage/concurrent_id_mapper_rpc_messages.capnp rm storage/concurrent_id_mapper_rpc_messages.hpp ``` Reviewers: teon.banek, buda, msantl Reviewed By: teon.banek, msantl Subscribers: teon.banek, pullbot Differential Revision: https://phabricator.memgraph.io/D1625
108 lines
3.6 KiB
C++
108 lines
3.6 KiB
C++
#pragma once
|
|
|
|
#include <experimental/optional>
|
|
#include <random>
|
|
#include <unordered_map>
|
|
|
|
#include <glog/logging.h>
|
|
#include <json/json.hpp>
|
|
|
|
#include "storage/common/property_value.hpp"
|
|
|
|
namespace snapshot_generation {
|
|
|
|
// Helper class for property value generation.
|
|
class ValueGenerator {
|
|
using json = nlohmann::json;
|
|
|
|
public:
|
|
// Generates the whole property map based on the given config.
|
|
std::unordered_map<std::string, PropertyValue> MakeProperties(
|
|
const json &config) {
|
|
std::unordered_map<std::string, PropertyValue> props;
|
|
if (config.is_null()) return props;
|
|
|
|
CHECK(config.is_object()) << "Properties config must be a dict";
|
|
for (auto it = config.begin(); it != config.end(); it++) {
|
|
auto value = MakeValue(it.value());
|
|
if (value) props.emplace(it.key(), *value);
|
|
}
|
|
return props;
|
|
}
|
|
|
|
// Generates a single value based on the given config.
|
|
std::experimental::optional<PropertyValue> MakeValue(const json &config) {
|
|
if (config.is_object()) {
|
|
const std::string &type = config["type"];
|
|
const auto ¶m = config["param"];
|
|
if (type == "primitive") return Primitive(param);
|
|
if (type == "counter") return Counter(param);
|
|
if (type == "optional") return Optional(param);
|
|
if (type == "bernoulli") return Bernoulli(param);
|
|
if (type == "randint") return RandInt(param);
|
|
if (type == "randstring") return RandString(param);
|
|
|
|
LOG(FATAL) << "Unknown value type";
|
|
} else {
|
|
return Primitive(config);
|
|
}
|
|
}
|
|
|
|
// Returns whatever value is stored in the JSON
|
|
PropertyValue Primitive(const json &config) {
|
|
if (config.is_string()) return config.get<std::string>();
|
|
if (config.is_number_integer()) return config.get<int64_t>();
|
|
if (config.is_number_float()) return config.get<double>();
|
|
if (config.is_boolean()) return config.get<bool>();
|
|
|
|
LOG(FATAL) << "Unsupported primitive type";
|
|
}
|
|
|
|
// Increments the counter and returns its current value
|
|
int64_t Counter(const std::string &name) { return counters_[name]++; }
|
|
|
|
// Generates a random integer in range specified by JSON config
|
|
int64_t RandInt(const json &range) {
|
|
CHECK(range.is_array() && range.size() == 2)
|
|
<< "RandInt value gen config must be a list with 2 elements";
|
|
auto from = MakeValue(range[0])->Value<int64_t>();
|
|
auto to = MakeValue(range[1])->Value<int64_t>();
|
|
CHECK(from < to) << "RandInt lower range must be lesser than upper range";
|
|
return (int64_t)(rand_(gen_) * (to - from)) + from;
|
|
}
|
|
|
|
// Generates a random alphanumeric string with length specified by JSON config
|
|
std::string RandString(const json &length) {
|
|
static const char alphanum[] =
|
|
"0123456789"
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
"abcdefghijklmnopqrstuvwxyz";
|
|
|
|
int length_int = MakeValue(length)->Value<int64_t>();
|
|
std::string r_val(length_int, 'a');
|
|
for (int i = 0; i < length_int; ++i)
|
|
r_val[i] = alphanum[(int64_t)(rand_(gen_) * strlen(alphanum))];
|
|
|
|
return r_val;
|
|
}
|
|
|
|
// Returns true with given probability
|
|
bool Bernoulli(double p) { return rand_(gen_) < p; }
|
|
|
|
// Returns a value specified by config with some probability, and nullopt
|
|
// otherwise
|
|
std::experimental::optional<PropertyValue> Optional(const json &config) {
|
|
CHECK(config.is_array() && config.size() == 2)
|
|
<< "Optional value gen config must be a list with 2 elements";
|
|
return Bernoulli(config[0]) ? MakeValue(config[1])
|
|
: std::experimental::nullopt;
|
|
}
|
|
|
|
private:
|
|
std::mt19937 gen_{std::random_device{}()};
|
|
std::uniform_real_distribution<> rand_{0.0, 1.0};
|
|
std::unordered_map<std::string, int64_t> counters_;
|
|
};
|
|
|
|
} // namespace snapshot_generation
|