add Time type (#4431)

Signed-off-by: Xiangyu Wang <xiangyu.wang@zilliz.com>
pull/4432/head
Wang Xiangyu 2020-12-10 09:55:36 +08:00 committed by GitHub
parent 8c9d5b2bf3
commit a10c794daf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 140 additions and 1 deletions

View File

@ -15,6 +15,8 @@
#include <algorithm>
#include <cassert>
#include <functional>
#include <map>
#include <regex>
#include <sstream>
#include <string>
@ -26,6 +28,13 @@ std::unordered_map<std::string, int64_t> BYTE_UNITS = {
{"g", 1024 * 1024 * 1024},
};
std::map<std::string, int64_t> TIME_UNITS = {
// {"seconds", 1ll},
// {"minutes", 1ll * 60},
{"hours", 1ll * 60 * 60},
{"days", 1ll * 60 * 60 * 24},
};
bool
is_integer(const std::string& s) {
if (not s.empty() && (std::isdigit(s[0]) || s[0] == '-')) {
@ -111,7 +120,7 @@ parse_bytes(const std::string& str, std::string& err) {
} else {
std::stringstream ss;
ss << "The specified value for memory (" << str << ") should specify the units."
<< "The postfix should be one of the `b` `k` `m` `g` characters";
<< " The postfix should be one of the `b` `k` `m` `g` characters.";
err = ss.str();
}
} catch (...) {
@ -120,6 +129,31 @@ parse_bytes(const std::string& str, std::string& err) {
return 0;
}
int64_t
parse_time(const std::string& str, std::string& err) {
try {
const std::regex regex(R"(\s*([0-9]+)\s*(seconds|minutes|hours|days)\s*)");
std::smatch base_match;
auto& units = TIME_UNITS;
if (std::regex_match(str, base_match, regex) && base_match.size() == 3 &&
units.find(base_match[2].str()) != units.end()) {
return stoll(base_match[1].str()) * units[base_match[2].str()];
} else {
std::stringstream ss;
ss << "The specified value for time (" << str << ") should specify the units."
<< " The postfix should be one of the ";
for (auto& pair : units) {
ss << "`" << pair.first << "` ";
}
ss << "words.";
err = ss.str();
}
} catch (...) {
err = "Unknown error happened on parse time.";
}
return 0;
}
} // namespace
// Use (void) to silent unused warnings.
@ -487,4 +521,75 @@ SizeValue::Get() {
}
}
TimeValue::TimeValue(const char* name, const char* alias, bool modifiable, int64_t lower_bound, int64_t upper_bound,
Value<int64_t>& config, int64_t default_value,
std::function<bool(int64_t val, std::string& err)> is_valid_fn)
: BaseValue(name, alias, modifiable),
config_(config),
lower_bound_(lower_bound),
upper_bound_(upper_bound),
default_value_(default_value),
is_valid_fn_(std::move(is_valid_fn)) {
}
void
TimeValue::Init() {
BaseValue::Init();
config_ = default_value_;
}
void
TimeValue::Set(const std::string& val, bool update) {
assertm(inited_, "uninitialized");
try {
/* Check modifiable */
if (update and not modifiable_) {
throw Immutable(name_, val);
}
/* Parse from string */
std::string err;
int64_t value = parse_time(val, err);
if (not err.empty()) {
throw Invalid(name_, val, err);
}
/* Boundary check */
if (not boundary_check<int64_t>(value, lower_bound_, upper_bound_)) {
throw OutOfRange<int64_t>(name_, val, lower_bound_, upper_bound_);
}
/* Validate */
if (is_valid_fn_ && not is_valid_fn_(value, err)) {
throw Invalid(name_, val, err);
}
/* Set value */
config_ = value;
} catch (ValueError& e) {
throw;
} catch (...) {
throw Unexpected(name_, val);
}
}
std::string
TimeValue::Get() {
assertm(inited_, "uninitialized");
auto val = config_();
const int64_t second = 1ll;
const int64_t minute = second * 60;
const int64_t hour = minute * 60;
const int64_t day = hour * 24;
if (val % day == 0) {
return std::to_string(val / day) + "days";
} else if (val % hour == 0) {
return std::to_string(val / hour) + "hours";
} else if (val % minute == 0) {
return std::to_string(val / minute) + "minutes";
} else {
return std::to_string(val) + "seconds";
}
}
} // namespace milvus

View File

@ -270,6 +270,30 @@ class SizeValue : public BaseValue {
Get() override;
};
class TimeValue : public BaseValue {
public:
TimeValue(const char* name, const char* alias, bool modifiable, int64_t lower_bound, int64_t upper_bound,
Value<int64_t>& config, int64_t default_value,
std::function<bool(int64_t val, std::string& err)> is_valid_fn = nullptr);
private:
Value<int64_t>& config_;
int64_t lower_bound_;
int64_t upper_bound_;
const int64_t default_value_;
std::function<bool(int64_t val, std::string& err)> is_valid_fn_;
public:
void
Init() override;
void
Set(const std::string& value, bool update) override;
std::string
Get() override;
};
/* create config with {is_valid} function */
#define CreateBoolValue(name, modifiable, config_addr, default, is_valid) \
@ -292,4 +316,7 @@ class SizeValue : public BaseValue {
#define CreateSizeValue(name, modifiable, lower_bound, upper_bound, config_addr, default, is_valid) \
std::make_shared<SizeValue>(name, nullptr, modifiable, lower_bound, upper_bound, config_addr, (default), is_valid)
#define CreateTimeValue(name, modifiable, lower_bound, upper_bound, config_addr, default, is_valid) \
std::make_shared<TimeValue>(name, nullptr, modifiable, lower_bound, upper_bound, config_addr, (default), is_valid)
} // namespace milvus

View File

@ -19,6 +19,8 @@
#define _IMMUTABLE (false)
const int64_t MB = (1024ll * 1024);
const int64_t GB = (1024ll * 1024 * 1024);
const int64_t HOURS = (3600ll);
const int64_t DAYS = (HOURS * 24);
namespace milvus {
@ -101,6 +103,8 @@ is_cachesize_valid(int64_t size, std::string& err) {
{ #name, CreateFloatingValue(#name, modifiable, lower_bound, upper_bound, config.name, default, is_valid) }
#define Size_(name, modifiable, lower_bound, upper_bound, default, is_valid) \
{ #name, CreateSizeValue(#name, modifiable, lower_bound, upper_bound, config.name, default, is_valid) }
#define Time_(name, modifiable, lower_bound, upper_bound, default, is_valid) \
{ #name, CreateTimeValue(#name, modifiable, lower_bound, upper_bound, config.name, default, is_valid) }
#define Bool(name, default) Bool_(name, true, default, nullptr)
#define String(name, default) String_(name, true, default, nullptr)
@ -110,6 +114,7 @@ is_cachesize_valid(int64_t size, std::string& err) {
#define Floating(name, lower_bound, upper_bound, default) \
Floating_(name, true, lower_bound, upper_bound, default, nullptr)
#define Size(name, lower_bound, upper_bound, default) Size_(name, true, lower_bound, upper_bound, default, nullptr)
#define Time(name, lower_bound, upper_bound, default) Time_(name, true, lower_bound, upper_bound, default, nullptr)
std::unordered_map<std::string, BaseValuePtr>
InitConfig() {
@ -170,6 +175,7 @@ InitConfig() {
Bool(logs.log_to_file, true),
String(log.min_messages, "warning"),
// Time(log.rotation_age, 0, 16384ll * HOURS, 24ll * HOURS),
/* tracing */
String(tracing.json_config_path, ""),

View File

@ -146,6 +146,7 @@ struct ServerConfig {
struct Log {
String min_messages;
// Integer rotation_age;
} log;
struct System {