2017-05-26 04:48:44 +08:00
|
|
|
/*
|
|
|
|
* DatabaseConfiguration.cpp
|
|
|
|
*
|
|
|
|
* This source file is part of the FoundationDB open source project
|
|
|
|
*
|
|
|
|
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2018-10-20 01:30:13 +08:00
|
|
|
#include "fdbclient/DatabaseConfiguration.h"
|
2017-05-26 04:48:44 +08:00
|
|
|
#include "fdbclient/SystemData.h"
|
|
|
|
|
|
|
|
DatabaseConfiguration::DatabaseConfiguration()
|
|
|
|
{
|
|
|
|
resetInternal();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseConfiguration::resetInternal() {
|
|
|
|
// does NOT reset rawConfiguration
|
|
|
|
initialized = false;
|
2018-06-22 15:04:00 +08:00
|
|
|
masterProxyCount = resolverCount = desiredTLogCount = tLogWriteAntiQuorum = tLogReplicationFactor = storageTeamSize = desiredLogRouterCount = -1;
|
2019-02-23 04:15:23 +08:00
|
|
|
tLogVersion = TLogVersion::DEFAULT;
|
2017-05-26 04:48:44 +08:00
|
|
|
tLogDataStoreType = storageServerStoreType = KeyValueStoreType::END;
|
2019-02-08 09:02:46 +08:00
|
|
|
tLogSpillType = TLogSpillType::DEFAULT;
|
2017-05-26 04:48:44 +08:00
|
|
|
autoMasterProxyCount = CLIENT_KNOBS->DEFAULT_AUTO_PROXIES;
|
|
|
|
autoResolverCount = CLIENT_KNOBS->DEFAULT_AUTO_RESOLVERS;
|
|
|
|
autoDesiredTLogCount = CLIENT_KNOBS->DEFAULT_AUTO_LOGS;
|
2018-06-18 10:31:15 +08:00
|
|
|
usableRegions = 1;
|
2018-03-06 11:27:46 +08:00
|
|
|
regions.clear();
|
2019-03-14 04:14:39 +08:00
|
|
|
tLogPolicy = storagePolicy = remoteTLogPolicy = Reference<IReplicationPolicy>();
|
2018-03-30 06:12:38 +08:00
|
|
|
remoteDesiredTLogCount = -1;
|
2018-07-04 13:59:04 +08:00
|
|
|
remoteTLogReplicationFactor = repopulateRegionAntiQuorum = 0;
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void parse( int* i, ValueRef const& v ) {
|
|
|
|
// FIXME: Sanity checking
|
|
|
|
*i = atoi(v.toString().c_str());
|
|
|
|
}
|
|
|
|
|
2019-03-14 04:14:39 +08:00
|
|
|
void parseReplicationPolicy(Reference<IReplicationPolicy>* policy, ValueRef const& v) {
|
2017-05-26 04:48:44 +08:00
|
|
|
BinaryReader reader(v, IncludeVersion());
|
|
|
|
serializeReplicationPolicy(reader, *policy);
|
|
|
|
}
|
|
|
|
|
2018-03-06 11:27:46 +08:00
|
|
|
void parse( std::vector<RegionInfo>* regions, ValueRef const& v ) {
|
|
|
|
try {
|
|
|
|
StatusObject statusObj = BinaryReader::fromStringRef<StatusObject>(v, IncludeVersion());
|
|
|
|
regions->clear();
|
2018-11-05 11:29:24 +08:00
|
|
|
if(statusObj["regions"].type() != json_spirit::array_type) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
StatusArray regionArray = statusObj["regions"].get_array();
|
2018-03-06 11:27:46 +08:00
|
|
|
for (StatusObjectReader dc : regionArray) {
|
|
|
|
RegionInfo info;
|
2018-06-14 08:55:55 +08:00
|
|
|
json_spirit::mArray datacenters;
|
|
|
|
dc.get("datacenters", datacenters);
|
2019-03-16 01:34:57 +08:00
|
|
|
bool foundNonSatelliteDatacenter = false;
|
2018-06-14 08:55:55 +08:00
|
|
|
for (StatusObjectReader s : datacenters) {
|
|
|
|
std::string idStr;
|
|
|
|
if (s.has("satellite") && s.last().get_int() == 1) {
|
|
|
|
SatelliteInfo satInfo;
|
|
|
|
s.get("id", idStr);
|
|
|
|
satInfo.dcId = idStr;
|
|
|
|
s.get("priority", satInfo.priority);
|
|
|
|
info.satellites.push_back(satInfo);
|
|
|
|
} else {
|
2019-03-16 01:34:57 +08:00
|
|
|
if (foundNonSatelliteDatacenter) throw invalid_option();
|
|
|
|
foundNonSatelliteDatacenter = true;
|
2018-06-14 08:55:55 +08:00
|
|
|
s.get("id", idStr);
|
|
|
|
info.dcId = idStr;
|
|
|
|
s.get("priority", info.priority);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::sort(info.satellites.begin(), info.satellites.end(), SatelliteInfo::sort_by_priority() );
|
2019-03-16 01:34:57 +08:00
|
|
|
if (!foundNonSatelliteDatacenter) throw invalid_option();
|
2018-03-06 11:27:46 +08:00
|
|
|
dc.tryGet("satellite_logs", info.satelliteDesiredTLogCount);
|
|
|
|
std::string satelliteReplication;
|
|
|
|
if(dc.tryGet("satellite_redundancy_mode", satelliteReplication)) {
|
|
|
|
if(satelliteReplication == "one_satellite_single") {
|
|
|
|
info.satelliteTLogReplicationFactor = 1;
|
|
|
|
info.satelliteTLogUsableDcs = 1;
|
|
|
|
info.satelliteTLogWriteAntiQuorum = 0;
|
2019-03-14 04:14:39 +08:00
|
|
|
info.satelliteTLogPolicy = Reference<IReplicationPolicy>(new PolicyOne());
|
2018-03-06 11:27:46 +08:00
|
|
|
} else if(satelliteReplication == "one_satellite_double") {
|
|
|
|
info.satelliteTLogReplicationFactor = 2;
|
|
|
|
info.satelliteTLogUsableDcs = 1;
|
|
|
|
info.satelliteTLogWriteAntiQuorum = 0;
|
2019-03-14 04:14:39 +08:00
|
|
|
info.satelliteTLogPolicy = Reference<IReplicationPolicy>(new PolicyAcross(2, "zoneid", Reference<IReplicationPolicy>(new PolicyOne())));
|
2018-03-06 11:27:46 +08:00
|
|
|
} else if(satelliteReplication == "one_satellite_triple") {
|
|
|
|
info.satelliteTLogReplicationFactor = 3;
|
|
|
|
info.satelliteTLogUsableDcs = 1;
|
|
|
|
info.satelliteTLogWriteAntiQuorum = 0;
|
2019-03-14 04:14:39 +08:00
|
|
|
info.satelliteTLogPolicy = Reference<IReplicationPolicy>(new PolicyAcross(3, "zoneid", Reference<IReplicationPolicy>(new PolicyOne())));
|
2018-03-06 11:27:46 +08:00
|
|
|
} else if(satelliteReplication == "two_satellite_safe") {
|
|
|
|
info.satelliteTLogReplicationFactor = 4;
|
|
|
|
info.satelliteTLogUsableDcs = 2;
|
|
|
|
info.satelliteTLogWriteAntiQuorum = 0;
|
2019-03-14 04:14:39 +08:00
|
|
|
info.satelliteTLogPolicy = Reference<IReplicationPolicy>(new PolicyAcross(2, "dcid", Reference<IReplicationPolicy>(new PolicyAcross(2, "zoneid", Reference<IReplicationPolicy>(new PolicyOne())))));
|
2018-06-29 14:15:32 +08:00
|
|
|
info.satelliteTLogReplicationFactorFallback = 2;
|
|
|
|
info.satelliteTLogUsableDcsFallback = 1;
|
|
|
|
info.satelliteTLogWriteAntiQuorumFallback = 0;
|
2019-03-14 04:14:39 +08:00
|
|
|
info.satelliteTLogPolicyFallback = Reference<IReplicationPolicy>(new PolicyAcross(2, "zoneid", Reference<IReplicationPolicy>(new PolicyOne())));
|
2018-03-06 11:27:46 +08:00
|
|
|
} else if(satelliteReplication == "two_satellite_fast") {
|
|
|
|
info.satelliteTLogReplicationFactor = 4;
|
|
|
|
info.satelliteTLogUsableDcs = 2;
|
|
|
|
info.satelliteTLogWriteAntiQuorum = 2;
|
2019-03-14 04:14:39 +08:00
|
|
|
info.satelliteTLogPolicy = Reference<IReplicationPolicy>(new PolicyAcross(2, "dcid", Reference<IReplicationPolicy>(new PolicyAcross(2, "zoneid", Reference<IReplicationPolicy>(new PolicyOne())))));
|
2018-06-29 14:15:32 +08:00
|
|
|
info.satelliteTLogReplicationFactorFallback = 2;
|
|
|
|
info.satelliteTLogUsableDcsFallback = 1;
|
|
|
|
info.satelliteTLogWriteAntiQuorumFallback = 0;
|
2019-03-14 04:14:39 +08:00
|
|
|
info.satelliteTLogPolicyFallback = Reference<IReplicationPolicy>(new PolicyAcross(2, "zoneid", Reference<IReplicationPolicy>(new PolicyOne())));
|
2018-03-06 11:27:46 +08:00
|
|
|
} else {
|
|
|
|
throw invalid_option();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dc.tryGet("satellite_log_replicas", info.satelliteTLogReplicationFactor);
|
|
|
|
dc.tryGet("satellite_usable_dcs", info.satelliteTLogUsableDcs);
|
|
|
|
dc.tryGet("satellite_anti_quorum", info.satelliteTLogWriteAntiQuorum);
|
2018-06-29 14:15:32 +08:00
|
|
|
dc.tryGet("satellite_log_replicas_fallback", info.satelliteTLogReplicationFactorFallback);
|
|
|
|
dc.tryGet("satellite_usable_dcs_fallback", info.satelliteTLogUsableDcsFallback);
|
|
|
|
dc.tryGet("satellite_anti_quorum_fallback", info.satelliteTLogWriteAntiQuorumFallback);
|
2018-03-06 11:27:46 +08:00
|
|
|
regions->push_back(info);
|
|
|
|
}
|
|
|
|
std::sort(regions->begin(), regions->end(), RegionInfo::sort_by_priority() );
|
2019-03-16 01:34:57 +08:00
|
|
|
} catch (Error&) {
|
2018-03-06 11:27:46 +08:00
|
|
|
regions->clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-26 04:48:44 +08:00
|
|
|
void DatabaseConfiguration::setDefaultReplicationPolicy() {
|
2018-02-16 10:32:39 +08:00
|
|
|
if(!storagePolicy) {
|
2019-03-14 04:14:39 +08:00
|
|
|
storagePolicy = Reference<IReplicationPolicy>(new PolicyAcross(storageTeamSize, "zoneid", Reference<IReplicationPolicy>(new PolicyOne())));
|
2018-02-16 10:32:39 +08:00
|
|
|
}
|
|
|
|
if(!tLogPolicy) {
|
2019-03-14 04:14:39 +08:00
|
|
|
tLogPolicy = Reference<IReplicationPolicy>(new PolicyAcross(tLogReplicationFactor, "zoneid", Reference<IReplicationPolicy>(new PolicyOne())));
|
2018-02-16 10:32:39 +08:00
|
|
|
}
|
|
|
|
if(remoteTLogReplicationFactor > 0 && !remoteTLogPolicy) {
|
2019-03-14 04:14:39 +08:00
|
|
|
remoteTLogPolicy = Reference<IReplicationPolicy>(new PolicyAcross(remoteTLogReplicationFactor, "zoneid", Reference<IReplicationPolicy>(new PolicyOne())));
|
2018-02-16 10:32:39 +08:00
|
|
|
}
|
2018-03-14 03:59:07 +08:00
|
|
|
for(auto& r : regions) {
|
2018-03-06 11:27:46 +08:00
|
|
|
if(r.satelliteTLogReplicationFactor > 0 && !r.satelliteTLogPolicy) {
|
2019-03-14 04:14:39 +08:00
|
|
|
r.satelliteTLogPolicy = Reference<IReplicationPolicy>(new PolicyAcross(r.satelliteTLogReplicationFactor, "zoneid", Reference<IReplicationPolicy>(new PolicyOne())));
|
2018-03-06 11:27:46 +08:00
|
|
|
}
|
2018-06-29 14:15:32 +08:00
|
|
|
if(r.satelliteTLogReplicationFactorFallback > 0 && !r.satelliteTLogPolicyFallback) {
|
2019-03-14 04:14:39 +08:00
|
|
|
r.satelliteTLogPolicyFallback = Reference<IReplicationPolicy>(new PolicyAcross(r.satelliteTLogReplicationFactorFallback, "zoneid", Reference<IReplicationPolicy>(new PolicyOne())));
|
2018-06-29 14:15:32 +08:00
|
|
|
}
|
2018-02-16 10:32:39 +08:00
|
|
|
}
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool DatabaseConfiguration::isValid() const {
|
2018-03-06 11:27:46 +08:00
|
|
|
if( !(initialized &&
|
2017-05-26 04:48:44 +08:00
|
|
|
tLogWriteAntiQuorum >= 0 &&
|
2019-02-19 07:22:32 +08:00
|
|
|
tLogWriteAntiQuorum <= tLogReplicationFactor/2 &&
|
2017-05-26 04:48:44 +08:00
|
|
|
tLogReplicationFactor >= 1 &&
|
|
|
|
storageTeamSize >= 1 &&
|
|
|
|
getDesiredProxies() >= 1 &&
|
|
|
|
getDesiredLogs() >= 1 &&
|
|
|
|
getDesiredResolvers() >= 1 &&
|
2019-02-23 04:15:23 +08:00
|
|
|
tLogVersion != TLogVersion::UNSET &&
|
|
|
|
tLogVersion >= TLogVersion::MIN_RECRUITABLE &&
|
|
|
|
tLogVersion <= TLogVersion::MAX_SUPPORTED &&
|
2017-05-26 04:48:44 +08:00
|
|
|
tLogDataStoreType != KeyValueStoreType::END &&
|
2019-02-08 09:02:46 +08:00
|
|
|
tLogSpillType != TLogSpillType::UNSET &&
|
2019-02-23 04:15:23 +08:00
|
|
|
!(tLogSpillType == TLogSpillType::REFERENCE && tLogVersion < TLogVersion::V3) &&
|
2017-05-26 04:48:44 +08:00
|
|
|
storageServerStoreType != KeyValueStoreType::END &&
|
|
|
|
autoMasterProxyCount >= 1 &&
|
|
|
|
autoResolverCount >= 1 &&
|
|
|
|
autoDesiredTLogCount >= 1 &&
|
|
|
|
storagePolicy &&
|
2017-06-30 06:50:19 +08:00
|
|
|
tLogPolicy &&
|
2018-02-10 08:48:55 +08:00
|
|
|
getDesiredRemoteLogs() >= 1 &&
|
2017-09-08 06:32:08 +08:00
|
|
|
remoteTLogReplicationFactor >= 0 &&
|
2018-07-04 13:59:04 +08:00
|
|
|
repopulateRegionAntiQuorum >= 0 &&
|
|
|
|
repopulateRegionAntiQuorum <= 1 &&
|
2018-06-18 10:31:15 +08:00
|
|
|
usableRegions >= 1 &&
|
|
|
|
usableRegions <= 2 &&
|
2018-03-16 01:59:30 +08:00
|
|
|
regions.size() <= 2 &&
|
2018-06-18 10:31:15 +08:00
|
|
|
( usableRegions == 1 || regions.size() == 2 ) &&
|
2018-09-06 04:00:52 +08:00
|
|
|
( regions.size() == 0 || regions[0].priority >= 0 ) &&
|
2018-09-06 04:42:10 +08:00
|
|
|
( regions.size() == 0 || tLogPolicy->info() != "dcid^2 x zoneid^2 x 1") ) ) { //We cannot specify regions with three_datacenter replication
|
2018-03-06 11:27:46 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::set<Key> dcIds;
|
|
|
|
dcIds.insert(Key());
|
2018-03-14 03:59:07 +08:00
|
|
|
for(auto& r : regions) {
|
2018-03-06 11:27:46 +08:00
|
|
|
if( !(!dcIds.count(r.dcId) &&
|
|
|
|
r.satelliteTLogReplicationFactor >= 0 &&
|
|
|
|
r.satelliteTLogWriteAntiQuorum >= 0 &&
|
2018-06-15 03:59:55 +08:00
|
|
|
r.satelliteTLogUsableDcs >= 1 &&
|
2018-06-29 14:15:32 +08:00
|
|
|
( r.satelliteTLogReplicationFactor == 0 || ( r.satelliteTLogPolicy && r.satellites.size() ) ) &&
|
|
|
|
( r.satelliteTLogUsableDcsFallback == 0 || ( r.satelliteTLogReplicationFactor > 0 && r.satelliteTLogReplicationFactorFallback > 0 ) ) ) ) {
|
2018-03-06 11:27:46 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
dcIds.insert(r.dcId);
|
2019-03-19 03:17:59 +08:00
|
|
|
std::set<Key> satelliteDcIds;
|
|
|
|
satelliteDcIds.insert(Key());
|
|
|
|
satelliteDcIds.insert(r.dcId);
|
2018-03-14 03:59:07 +08:00
|
|
|
for(auto& s : r.satellites) {
|
2019-03-19 03:17:59 +08:00
|
|
|
if (satelliteDcIds.count(s.dcId)) {
|
2018-03-06 11:27:46 +08:00
|
|
|
return false;
|
|
|
|
}
|
2019-03-19 03:17:59 +08:00
|
|
|
satelliteDcIds.insert(s.dcId);
|
2018-03-06 11:27:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
|
2018-03-06 11:27:46 +08:00
|
|
|
StatusObject DatabaseConfiguration::toJSON(bool noPolicies) const {
|
|
|
|
StatusObject result;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
if( initialized ) {
|
2017-09-20 07:35:42 +08:00
|
|
|
std::string tlogInfo = tLogPolicy->info();
|
|
|
|
std::string storageInfo = storagePolicy->info();
|
2018-03-06 11:27:46 +08:00
|
|
|
bool customRedundancy = false;
|
2018-06-19 01:24:57 +08:00
|
|
|
if( tLogWriteAntiQuorum == 0 ) {
|
|
|
|
if( tLogReplicationFactor == 1 && storageTeamSize == 1 ) {
|
2017-05-26 04:48:44 +08:00
|
|
|
result["redundancy_mode"] = "single";
|
2018-06-19 01:24:57 +08:00
|
|
|
} else if( tLogReplicationFactor == 2 && storageTeamSize == 2 ) {
|
2017-05-26 04:48:44 +08:00
|
|
|
result["redundancy_mode"] = "double";
|
2018-06-19 01:24:57 +08:00
|
|
|
} else if( tLogReplicationFactor == 4 && storageTeamSize == 6 && tlogInfo == "dcid^2 x zoneid^2 x 1" && storageInfo == "dcid^3 x zoneid^2 x 1" ) {
|
2017-09-20 07:35:42 +08:00
|
|
|
result["redundancy_mode"] = "three_datacenter";
|
2018-06-28 14:24:33 +08:00
|
|
|
} else if( tLogReplicationFactor == 4 && storageTeamSize == 4 && tlogInfo == "dcid^2 x zoneid^2 x 1" && storageInfo == "dcid^2 x zoneid^2 x 1" ) {
|
|
|
|
result["redundancy_mode"] = "three_datacenter_fallback";
|
2018-06-19 01:24:57 +08:00
|
|
|
} else if( tLogReplicationFactor == 3 && storageTeamSize == 3 ) {
|
2017-05-26 04:48:44 +08:00
|
|
|
result["redundancy_mode"] = "triple";
|
2018-06-19 01:24:57 +08:00
|
|
|
} else if( tLogReplicationFactor == 4 && storageTeamSize == 3 && tlogInfo == "data_hall^2 x zoneid^2 x 1" && storageInfo == "data_hall^3 x 1" ) {
|
2017-09-20 07:35:42 +08:00
|
|
|
result["redundancy_mode"] = "three_data_hall";
|
2019-04-08 13:58:18 +08:00
|
|
|
} else if( tLogReplicationFactor == 4 && storageTeamSize == 2 && tlogInfo == "data_hall^2 x zoneid^2 x 1" && storageInfo == "data_hall^2 x 1" ) {
|
|
|
|
result["redundancy_mode"] = "three_data_hall_fallback";
|
2018-03-06 11:27:46 +08:00
|
|
|
} else {
|
|
|
|
customRedundancy = true;
|
2017-09-08 06:32:08 +08:00
|
|
|
}
|
2018-03-06 11:27:46 +08:00
|
|
|
} else {
|
|
|
|
customRedundancy = true;
|
2017-09-08 06:32:08 +08:00
|
|
|
}
|
2018-03-06 11:27:46 +08:00
|
|
|
|
|
|
|
if(customRedundancy) {
|
|
|
|
result["storage_replicas"] = storageTeamSize;
|
|
|
|
result["log_replicas"] = tLogReplicationFactor;
|
|
|
|
result["log_anti_quorum"] = tLogWriteAntiQuorum;
|
|
|
|
if(!noPolicies) result["storage_replication_policy"] = storagePolicy->info();
|
|
|
|
if(!noPolicies) result["log_replication_policy"] = tLogPolicy->info();
|
2017-09-08 06:32:08 +08:00
|
|
|
}
|
|
|
|
|
2019-02-27 08:47:04 +08:00
|
|
|
if ( tLogVersion > TLogVersion::DEFAULT ) {
|
2019-02-23 04:15:23 +08:00
|
|
|
result["log_version"] = (int)tLogVersion;
|
|
|
|
}
|
|
|
|
|
2018-03-06 11:27:46 +08:00
|
|
|
if( tLogDataStoreType == KeyValueStoreType::SSD_BTREE_V1 && storageServerStoreType == KeyValueStoreType::SSD_BTREE_V1) {
|
2017-05-26 04:48:44 +08:00
|
|
|
result["storage_engine"] = "ssd-1";
|
2018-03-06 11:27:46 +08:00
|
|
|
} else if (tLogDataStoreType == KeyValueStoreType::SSD_BTREE_V2 && storageServerStoreType == KeyValueStoreType::SSD_BTREE_V2) {
|
2017-05-26 04:48:44 +08:00
|
|
|
result["storage_engine"] = "ssd-2";
|
2018-06-18 15:19:00 +08:00
|
|
|
} else if( tLogDataStoreType == KeyValueStoreType::SSD_BTREE_V2 && storageServerStoreType == KeyValueStoreType::SSD_REDWOOD_V1 ) {
|
2018-10-06 05:43:54 +08:00
|
|
|
result["storage_engine"] = "ssd-redwood-experimental";
|
2018-03-06 11:27:46 +08:00
|
|
|
} else if( tLogDataStoreType == KeyValueStoreType::MEMORY && storageServerStoreType == KeyValueStoreType::MEMORY ) {
|
2019-03-19 06:10:04 +08:00
|
|
|
result["storage_engine"] = "memory-1";
|
2019-03-17 13:48:24 +08:00
|
|
|
} else if( tLogDataStoreType == KeyValueStoreType::SSD_BTREE_V2 && storageServerStoreType == KeyValueStoreType::MEMORY ) {
|
2019-03-19 06:10:04 +08:00
|
|
|
result["storage_engine"] = "memory-2";
|
2018-04-25 08:22:21 +08:00
|
|
|
} else {
|
2017-05-26 04:48:44 +08:00
|
|
|
result["storage_engine"] = "custom";
|
2017-09-08 06:32:08 +08:00
|
|
|
}
|
|
|
|
|
2019-02-27 08:47:04 +08:00
|
|
|
result["log_spill"] = (int)tLogSpillType;
|
2019-02-08 09:02:46 +08:00
|
|
|
|
2018-06-18 10:31:15 +08:00
|
|
|
if( remoteTLogReplicationFactor == 1 ) {
|
2018-02-03 03:46:04 +08:00
|
|
|
result["remote_redundancy_mode"] = "remote_single";
|
2018-02-16 10:32:39 +08:00
|
|
|
} else if( remoteTLogReplicationFactor == 2 ) {
|
2018-02-03 03:46:04 +08:00
|
|
|
result["remote_redundancy_mode"] = "remote_double";
|
2018-02-16 10:32:39 +08:00
|
|
|
} else if( remoteTLogReplicationFactor == 3 ) {
|
2018-02-03 03:46:04 +08:00
|
|
|
result["remote_redundancy_mode"] = "remote_triple";
|
2018-06-18 10:31:15 +08:00
|
|
|
} else if( remoteTLogReplicationFactor > 3 ) {
|
2018-03-06 11:27:46 +08:00
|
|
|
result["remote_log_replicas"] = remoteTLogReplicationFactor;
|
|
|
|
if(noPolicies && remoteTLogPolicy) result["remote_log_policy"] = remoteTLogPolicy->info();
|
2018-02-16 10:32:39 +08:00
|
|
|
}
|
2018-06-18 10:31:15 +08:00
|
|
|
result["usable_regions"] = usableRegions;
|
2017-10-11 07:07:59 +08:00
|
|
|
|
2018-03-06 11:27:46 +08:00
|
|
|
if(regions.size()) {
|
2019-02-19 06:54:28 +08:00
|
|
|
result["regions"] = getRegionJSON();
|
2018-03-06 11:27:46 +08:00
|
|
|
}
|
2017-10-07 06:55:50 +08:00
|
|
|
|
2018-03-06 11:27:46 +08:00
|
|
|
if( desiredTLogCount != -1 ) {
|
|
|
|
result["logs"] = desiredTLogCount;
|
|
|
|
}
|
|
|
|
if( masterProxyCount != -1 ) {
|
|
|
|
result["proxies"] = masterProxyCount;
|
|
|
|
}
|
|
|
|
if( resolverCount != -1 ) {
|
|
|
|
result["resolvers"] = resolverCount;
|
|
|
|
}
|
2018-06-22 15:04:00 +08:00
|
|
|
if( desiredLogRouterCount != -1 ) {
|
|
|
|
result["log_routers"] = desiredLogRouterCount;
|
|
|
|
}
|
2018-03-06 11:27:46 +08:00
|
|
|
if( remoteDesiredTLogCount != -1 ) {
|
|
|
|
result["remote_logs"] = remoteDesiredTLogCount;
|
|
|
|
}
|
2018-07-04 13:59:04 +08:00
|
|
|
if( repopulateRegionAntiQuorum != 0 ) {
|
|
|
|
result["repopulate_anti_quorum"] = repopulateRegionAntiQuorum;
|
|
|
|
}
|
2018-03-06 11:27:46 +08:00
|
|
|
if( autoMasterProxyCount != CLIENT_KNOBS->DEFAULT_AUTO_PROXIES ) {
|
|
|
|
result["auto_proxies"] = autoMasterProxyCount;
|
|
|
|
}
|
|
|
|
if (autoResolverCount != CLIENT_KNOBS->DEFAULT_AUTO_RESOLVERS) {
|
|
|
|
result["auto_resolvers"] = autoResolverCount;
|
|
|
|
}
|
|
|
|
if (autoDesiredTLogCount != CLIENT_KNOBS->DEFAULT_AUTO_LOGS) {
|
|
|
|
result["auto_logs"] = autoDesiredTLogCount;
|
|
|
|
}
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-19 06:54:28 +08:00
|
|
|
StatusArray DatabaseConfiguration::getRegionJSON() const {
|
|
|
|
StatusArray regionArr;
|
|
|
|
for(auto& r : regions) {
|
|
|
|
StatusObject regionObj;
|
|
|
|
StatusArray dcArr;
|
|
|
|
StatusObject dcObj;
|
|
|
|
dcObj["id"] = r.dcId.toString();
|
|
|
|
dcObj["priority"] = r.priority;
|
|
|
|
dcArr.push_back(dcObj);
|
|
|
|
|
|
|
|
if(r.satelliteTLogReplicationFactor == 1 && r.satelliteTLogUsableDcs == 1 && r.satelliteTLogWriteAntiQuorum == 0 && r.satelliteTLogUsableDcsFallback == 0) {
|
|
|
|
regionObj["satellite_redundancy_mode"] = "one_satellite_single";
|
|
|
|
} else if(r.satelliteTLogReplicationFactor == 2 && r.satelliteTLogUsableDcs == 1 && r.satelliteTLogWriteAntiQuorum == 0 && r.satelliteTLogUsableDcsFallback == 0) {
|
|
|
|
regionObj["satellite_redundancy_mode"] = "one_satellite_double";
|
|
|
|
} else if(r.satelliteTLogReplicationFactor == 3 && r.satelliteTLogUsableDcs == 1 && r.satelliteTLogWriteAntiQuorum == 0 && r.satelliteTLogUsableDcsFallback == 0) {
|
|
|
|
regionObj["satellite_redundancy_mode"] = "one_satellite_triple";
|
|
|
|
} else if(r.satelliteTLogReplicationFactor == 4 && r.satelliteTLogUsableDcs == 2 && r.satelliteTLogWriteAntiQuorum == 0 && r.satelliteTLogUsableDcsFallback == 1 && r.satelliteTLogReplicationFactorFallback == 2 && r.satelliteTLogWriteAntiQuorumFallback == 0) {
|
|
|
|
regionObj["satellite_redundancy_mode"] = "two_satellite_safe";
|
|
|
|
} else if(r.satelliteTLogReplicationFactor == 4 && r.satelliteTLogUsableDcs == 2 && r.satelliteTLogWriteAntiQuorum == 2 && r.satelliteTLogUsableDcsFallback == 1 && r.satelliteTLogReplicationFactorFallback == 2 && r.satelliteTLogWriteAntiQuorumFallback == 0) {
|
|
|
|
regionObj["satellite_redundancy_mode"] = "two_satellite_fast";
|
|
|
|
} else if(r.satelliteTLogReplicationFactor != 0) {
|
|
|
|
regionObj["satellite_log_replicas"] = r.satelliteTLogReplicationFactor;
|
|
|
|
regionObj["satellite_usable_dcs"] = r.satelliteTLogUsableDcs;
|
|
|
|
regionObj["satellite_anti_quorum"] = r.satelliteTLogWriteAntiQuorum;
|
|
|
|
if(r.satelliteTLogPolicy) regionObj["satellite_log_policy"] = r.satelliteTLogPolicy->info();
|
|
|
|
regionObj["satellite_log_replicas_fallback"] = r.satelliteTLogReplicationFactorFallback;
|
|
|
|
regionObj["satellite_usable_dcs_fallback"] = r.satelliteTLogUsableDcsFallback;
|
|
|
|
regionObj["satellite_anti_quorum_fallback"] = r.satelliteTLogWriteAntiQuorumFallback;
|
|
|
|
if(r.satelliteTLogPolicyFallback) regionObj["satellite_log_policy_fallback"] = r.satelliteTLogPolicyFallback->info();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( r.satelliteDesiredTLogCount != -1 ) {
|
|
|
|
regionObj["satellite_logs"] = r.satelliteDesiredTLogCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(r.satellites.size()) {
|
|
|
|
for(auto& s : r.satellites) {
|
|
|
|
StatusObject satObj;
|
|
|
|
satObj["id"] = s.dcId.toString();
|
|
|
|
satObj["priority"] = s.priority;
|
|
|
|
satObj["satellite"] = 1;
|
|
|
|
|
|
|
|
dcArr.push_back(satObj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
regionObj["datacenters"] = dcArr;
|
|
|
|
regionArr.push_back(regionObj);
|
|
|
|
}
|
|
|
|
return regionArr;
|
|
|
|
}
|
|
|
|
|
2017-05-26 04:48:44 +08:00
|
|
|
std::string DatabaseConfiguration::toString() const {
|
2018-03-06 11:27:46 +08:00
|
|
|
return json_spirit::write_string(json_spirit::mValue(toJSON()), json_spirit::Output_options::none);
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool DatabaseConfiguration::setInternal(KeyRef key, ValueRef value) {
|
|
|
|
KeyRef ck = key.removePrefix( configKeysPrefix );
|
|
|
|
int type;
|
|
|
|
|
|
|
|
if (ck == LiteralStringRef("initialized")) initialized = true;
|
|
|
|
else if (ck == LiteralStringRef("proxies")) parse(&masterProxyCount, value);
|
|
|
|
else if (ck == LiteralStringRef("resolvers")) parse(&resolverCount, value);
|
|
|
|
else if (ck == LiteralStringRef("logs")) parse(&desiredTLogCount, value);
|
2019-02-28 07:16:49 +08:00
|
|
|
else if (ck == LiteralStringRef("log_replicas")) {
|
|
|
|
parse(&tLogReplicationFactor, value);
|
|
|
|
tLogWriteAntiQuorum = std::min(tLogWriteAntiQuorum, tLogReplicationFactor/2);
|
2019-02-28 07:21:06 +08:00
|
|
|
}
|
|
|
|
else if (ck == LiteralStringRef("log_anti_quorum")) {
|
2019-02-28 07:16:49 +08:00
|
|
|
parse(&tLogWriteAntiQuorum, value);
|
|
|
|
if(tLogReplicationFactor > 0) {
|
|
|
|
tLogWriteAntiQuorum = std::min(tLogWriteAntiQuorum, tLogReplicationFactor/2);
|
|
|
|
}
|
2019-02-28 07:21:06 +08:00
|
|
|
}
|
2017-05-26 04:48:44 +08:00
|
|
|
else if (ck == LiteralStringRef("storage_replicas")) parse(&storageTeamSize, value);
|
2019-02-27 08:47:04 +08:00
|
|
|
else if (ck == LiteralStringRef("log_version")) {
|
|
|
|
parse((&type), value);
|
|
|
|
type = std::max((int)TLogVersion::MIN_RECRUITABLE, type);
|
|
|
|
type = std::min((int)TLogVersion::MAX_SUPPORTED, type);
|
|
|
|
tLogVersion = (TLogVersion::Version)type;
|
|
|
|
}
|
2018-06-18 15:19:00 +08:00
|
|
|
else if (ck == LiteralStringRef("log_engine")) { parse((&type), value); tLogDataStoreType = (KeyValueStoreType::StoreType)type;
|
|
|
|
// TODO: Remove this once Redwood works as a log engine
|
|
|
|
if(tLogDataStoreType == KeyValueStoreType::SSD_REDWOOD_V1)
|
|
|
|
tLogDataStoreType = KeyValueStoreType::SSD_BTREE_V2;
|
|
|
|
}
|
2019-02-08 09:02:46 +08:00
|
|
|
else if (ck == LiteralStringRef("log_spill")) { parse((&type), value); tLogSpillType = (TLogSpillType::SpillType)type; }
|
2017-05-26 04:48:44 +08:00
|
|
|
else if (ck == LiteralStringRef("storage_engine")) { parse((&type), value); storageServerStoreType = (KeyValueStoreType::StoreType)type; }
|
|
|
|
else if (ck == LiteralStringRef("auto_proxies")) parse(&autoMasterProxyCount, value);
|
|
|
|
else if (ck == LiteralStringRef("auto_resolvers")) parse(&autoResolverCount, value);
|
|
|
|
else if (ck == LiteralStringRef("auto_logs")) parse(&autoDesiredTLogCount, value);
|
|
|
|
else if (ck == LiteralStringRef("storage_replication_policy")) parseReplicationPolicy(&storagePolicy, value);
|
|
|
|
else if (ck == LiteralStringRef("log_replication_policy")) parseReplicationPolicy(&tLogPolicy, value);
|
2018-06-22 15:04:00 +08:00
|
|
|
else if (ck == LiteralStringRef("log_routers")) parse(&desiredLogRouterCount, value);
|
2017-09-08 06:32:08 +08:00
|
|
|
else if (ck == LiteralStringRef("remote_logs")) parse(&remoteDesiredTLogCount, value);
|
|
|
|
else if (ck == LiteralStringRef("remote_log_replicas")) parse(&remoteTLogReplicationFactor, value);
|
|
|
|
else if (ck == LiteralStringRef("remote_log_policy")) parseReplicationPolicy(&remoteTLogPolicy, value);
|
2018-06-18 10:31:15 +08:00
|
|
|
else if (ck == LiteralStringRef("usable_regions")) parse(&usableRegions, value);
|
2018-07-04 13:59:04 +08:00
|
|
|
else if (ck == LiteralStringRef("repopulate_anti_quorum")) parse(&repopulateRegionAntiQuorum, value);
|
2018-03-06 11:27:46 +08:00
|
|
|
else if (ck == LiteralStringRef("regions")) parse(®ions, value);
|
2017-05-26 04:48:44 +08:00
|
|
|
else return false;
|
|
|
|
return true; // All of the above options currently require recovery to take effect
|
|
|
|
}
|
|
|
|
|
|
|
|
inline static KeyValueRef * lower_bound( VectorRef<KeyValueRef> & config, KeyRef const& key ) {
|
|
|
|
return std::lower_bound( config.begin(), config.end(), KeyValueRef(key, ValueRef()), KeyValueRef::OrderByKey() );
|
|
|
|
}
|
|
|
|
inline static KeyValueRef const* lower_bound( VectorRef<KeyValueRef> const& config, KeyRef const& key ) {
|
|
|
|
return lower_bound( const_cast<VectorRef<KeyValueRef> &>(config), key );
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseConfiguration::applyMutation( MutationRef m ) {
|
|
|
|
if( m.type == MutationRef::SetValue && m.param1.startsWith(configKeysPrefix) ) {
|
|
|
|
set(m.param1, m.param2);
|
|
|
|
} else if( m.type == MutationRef::ClearRange ) {
|
|
|
|
KeyRangeRef range(m.param1, m.param2);
|
|
|
|
if( range.intersects( configKeys ) ) {
|
|
|
|
clear(range & configKeys);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DatabaseConfiguration::set(KeyRef key, ValueRef value) {
|
|
|
|
makeConfigurationMutable();
|
|
|
|
mutableConfiguration.get()[ key.toString() ] = value.toString();
|
|
|
|
return setInternal(key,value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DatabaseConfiguration::clear( KeyRangeRef keys ) {
|
|
|
|
makeConfigurationMutable();
|
|
|
|
auto& mc = mutableConfiguration.get();
|
|
|
|
mc.erase( mc.lower_bound( keys.begin.toString() ), mc.lower_bound( keys.end.toString() ) );
|
|
|
|
|
|
|
|
// FIXME: More efficient
|
|
|
|
bool wasValid = isValid();
|
|
|
|
resetInternal();
|
|
|
|
for(auto c = mc.begin(); c != mc.end(); ++c)
|
|
|
|
setInternal(c->first, c->second);
|
|
|
|
return wasValid && !isValid();
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional<ValueRef> DatabaseConfiguration::get( KeyRef key ) const {
|
|
|
|
if (mutableConfiguration.present()) {
|
|
|
|
auto i = mutableConfiguration.get().find(key.toString());
|
|
|
|
if (i == mutableConfiguration.get().end()) return Optional<ValueRef>();
|
|
|
|
return ValueRef(i->second);
|
|
|
|
} else {
|
|
|
|
auto i = lower_bound(rawConfiguration, key);
|
|
|
|
if (i == rawConfiguration.end() || i->key != key) return Optional<ValueRef>();
|
|
|
|
return i->value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DatabaseConfiguration::isExcludedServer( NetworkAddress a ) const {
|
|
|
|
return get( encodeExcludedServersKey( AddressExclusion(a.ip, a.port) ) ).present() ||
|
|
|
|
get( encodeExcludedServersKey( AddressExclusion(a.ip) ) ).present();
|
|
|
|
}
|
|
|
|
std::set<AddressExclusion> DatabaseConfiguration::getExcludedServers() const {
|
|
|
|
const_cast<DatabaseConfiguration*>(this)->makeConfigurationImmutable();
|
|
|
|
std::set<AddressExclusion> addrs;
|
|
|
|
for( auto i = lower_bound(rawConfiguration, excludedServersKeys.begin); i != rawConfiguration.end() && i->key < excludedServersKeys.end; ++i ) {
|
|
|
|
AddressExclusion a = decodeExcludedServersKey( i->key );
|
|
|
|
if (a.isValid()) addrs.insert(a);
|
|
|
|
}
|
|
|
|
return addrs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseConfiguration::makeConfigurationMutable() {
|
|
|
|
if (mutableConfiguration.present()) return;
|
|
|
|
mutableConfiguration = std::map<std::string,std::string>();
|
|
|
|
auto& mc = mutableConfiguration.get();
|
|
|
|
for(auto r = rawConfiguration.begin(); r != rawConfiguration.end(); ++r)
|
|
|
|
mc[ r->key.toString() ] = r->value.toString();
|
|
|
|
rawConfiguration = Standalone<VectorRef<KeyValueRef>>();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseConfiguration::makeConfigurationImmutable() {
|
|
|
|
if (!mutableConfiguration.present()) return;
|
|
|
|
auto & mc = mutableConfiguration.get();
|
|
|
|
rawConfiguration = Standalone<VectorRef<KeyValueRef>>();
|
|
|
|
rawConfiguration.resize( rawConfiguration.arena(), mc.size() );
|
|
|
|
int i = 0;
|
|
|
|
for(auto r = mc.begin(); r != mc.end(); ++r)
|
|
|
|
rawConfiguration[i++] = KeyValueRef( rawConfiguration.arena(), KeyValueRef( r->first, r->second ) );
|
|
|
|
mutableConfiguration = Optional<std::map<std::string,std::string>>();
|
|
|
|
}
|