// ----------------------------------------------------------------------
// File: RaftConfig.cc
// Author: Georgios Bitzes - CERN
// ----------------------------------------------------------------------
/************************************************************************
* quarkdb - a redis-like highly available key-value store *
* Copyright (C) 2016 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
#include "raft/RaftConfig.hh"
#include "raft/RaftDispatcher.hh"
#include "Connection.hh"
#include "StateMachine.hh"
#include "utils/ParseUtils.hh"
using namespace quarkdb;
const std::string kTrimConfigKey("raft.trimming");
const std::string kResilveringEnabledKey("raft.resilvering.enabled");
bool TrimmingConfig::parse(const std::string &str) {
std::vector parts;
if(!ParseUtils::parseIntegerList(str, ":", parts)) {
return false;
}
if(parts.size() != 2) {
return false;
}
keepAtLeast = parts[0];
step = parts[1];
return true;
}
std::string TrimmingConfig::toString() const {
return SSTR(keepAtLeast << ":" << step);
}
RaftConfig::RaftConfig(StateMachine &sm) : stateMachine(sm) {
}
bool RaftConfig::getResilveringEnabled() {
std::string value;
rocksdb::Status st = stateMachine.configGet(kResilveringEnabledKey, value);
if(st.IsNotFound()) {
return true;
}
if(!st.ok()) {
qdb_throw("Error when retrieving whether resilvering is enabled: " << st.ToString());
}
if(value == "TRUE") {
return true;
}
if(value == "FALSE") {
return false;
}
qdb_throw("Invalid value for raft resilvering flag: " << value);
}
EncodedConfigChange RaftConfig::setResilveringEnabled(bool value) {
RedisRequest req { "CONFIG_SET", kResilveringEnabledKey, boolToString(value) };
return { "", req };
}
TrimmingConfig RaftConfig::getTrimmingConfig() {
std::string trimConfig;
rocksdb::Status st = stateMachine.configGet(kTrimConfigKey, trimConfig);
if(st.IsNotFound()) {
// Return default values
return { 50000000, 200000 };
}
else if(!st.ok()) {
qdb_throw("Error when retrieving journal trim limit: " << st.ToString());
}
TrimmingConfig ret;
if(!ret.parse(trimConfig)) {
qdb_misconfig("Unable to parse trimming configuration key: " << kTrimConfigKey << " => " << trimConfig);
}
return ret;
}
EncodedConfigChange RaftConfig::setTrimmingConfig(const TrimmingConfig &trimConfig, bool overrideSafety) {
// A 'keepAtLeast' value lower than 100k probably means an operator error.
// By default, prevent such low values unless overrideSafety is set.
if(!overrideSafety && trimConfig.keepAtLeast <= 100000) {
qdb_critical("attempted to set journal 'keepAtLeast' configuration to very low value: " << trimConfig.keepAtLeast);
return { SSTR("new 'keepAtLeast' too small: " << trimConfig.keepAtLeast), {} };
}
// A step value lower than 10k probably means an operator error.
if(!overrideSafety && trimConfig.step <= 10000) {
qdb_critical("attempted to set journal 'step' configuration to very low value: " << trimConfig.step);
return { SSTR("new 'step' too small: " << trimConfig.step), {} };
}
RedisRequest req { "CONFIG_SET", kTrimConfigKey, trimConfig.toString() };
return { "", req};
}