2017-05-26 04:48:44 +08:00
/*
* DBCoreState . h
*
* 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 .
*/
# ifndef FDBSERVER_DBCORESTATE_H
# define FDBSERVER_DBCORESTATE_H
# pragma once
# include "fdbrpc/ReplicationPolicy.h"
// This structure is stored persistently in CoordinatedState and must be versioned carefully!
// It records a synchronous replication topology which can be used in the absence of faults (or under a limited
// number of failures, in the case of less than full write quorums) to durably commit transactions. When faults or
// configuration changes require the topology to be changed, (a read quorum of) the old topology is locked, a new
// topology is constructed, and then committed to this coordinated state before becoming active. This process
// is called 'recovery'.
// At the moment, transaction logs are replicated but not partitioned, so the topology is as simple as a list of
// transaction log replicas and the write quorum that was used to commit to them. The read quorum required to
// ensure durability of locking and recovery is therefore tLogWriteAntiQuorum + 1.
2017-07-10 05:46:16 +08:00
struct CoreTLogSet {
std : : vector < UID > tLogs ;
int32_t tLogWriteAntiQuorum ; // The write anti quorum previously used to write to tLogs, which might be different from the anti quorum suggested by the current configuration going forward!
int32_t tLogReplicationFactor ; // The replication factor previously used to write to tLogs, which might be different from the current configuration
2017-05-26 04:48:44 +08:00
std : : vector < LocalityData > tLogLocalities ; // Stores the localities of the log servers
2017-07-10 05:46:16 +08:00
IRepPolicyRef tLogPolicy ;
bool isLocal ;
2018-01-30 09:48:18 +08:00
int32_t hasBestPolicy ;
2017-09-08 06:32:08 +08:00
int8_t locality ;
2018-03-30 06:12:38 +08:00
Version startVersion ;
2017-07-10 05:46:16 +08:00
2018-04-09 12:24:05 +08:00
CoreTLogSet ( ) : tLogWriteAntiQuorum ( 0 ) , tLogReplicationFactor ( 0 ) , isLocal ( true ) , hasBestPolicy ( HasBestPolicyId ) , locality ( tagLocalityUpgraded ) , startVersion ( invalidVersion ) { }
2017-07-10 05:46:16 +08:00
bool operator = = ( CoreTLogSet const & rhs ) const {
2018-03-30 06:12:38 +08:00
return tLogs = = rhs . tLogs & & tLogWriteAntiQuorum = = rhs . tLogWriteAntiQuorum & & tLogReplicationFactor = = rhs . tLogReplicationFactor & & isLocal = = rhs . isLocal & & hasBestPolicy = = rhs . hasBestPolicy & &
2018-04-09 12:24:05 +08:00
locality = = rhs . locality & & startVersion = = rhs . startVersion & & ( ( ! tLogPolicy & & ! rhs . tLogPolicy ) | | ( tLogPolicy & & rhs . tLogPolicy & & ( tLogPolicy - > info ( ) = = rhs . tLogPolicy - > info ( ) ) ) ) ;
2017-07-10 05:46:16 +08:00
}
template < class Archive >
void serialize ( Archive & ar ) {
2018-04-09 12:24:05 +08:00
ar & tLogs & tLogWriteAntiQuorum & tLogReplicationFactor & tLogPolicy & tLogLocalities & isLocal & hasBestPolicy & locality & startVersion ;
2017-07-10 05:46:16 +08:00
}
} ;
struct OldTLogCoreData {
std : : vector < CoreTLogSet > tLogs ;
2018-04-09 12:24:05 +08:00
int32_t logRouterTags ;
2017-05-26 04:48:44 +08:00
Version epochEnd ;
2018-04-09 12:24:05 +08:00
OldTLogCoreData ( ) : epochEnd ( 0 ) , logRouterTags ( 0 ) { }
2017-05-26 04:48:44 +08:00
2017-07-10 05:46:16 +08:00
bool operator = = ( OldTLogCoreData const & rhs ) const {
2018-04-09 12:24:05 +08:00
return tLogs = = rhs . tLogs & & logRouterTags = = rhs . logRouterTags & & epochEnd = = rhs . epochEnd ;
2017-07-10 05:46:16 +08:00
}
2017-05-26 04:48:44 +08:00
template < class Archive >
void serialize ( Archive & ar ) {
2017-06-30 06:50:19 +08:00
if ( ar . protocolVersion ( ) > = 0x0FDB00A560010001LL ) {
2018-04-09 12:24:05 +08:00
ar & tLogs & logRouterTags & epochEnd ;
2017-06-30 06:50:19 +08:00
}
else if ( ar . isDeserializing ) {
2017-07-10 05:46:16 +08:00
tLogs . push_back ( CoreTLogSet ( ) ) ;
ar & tLogs [ 0 ] . tLogs & tLogs [ 0 ] . tLogWriteAntiQuorum & tLogs [ 0 ] . tLogReplicationFactor & tLogs [ 0 ] . tLogPolicy & epochEnd & tLogs [ 0 ] . tLogLocalities ;
2017-06-30 06:50:19 +08:00
}
2017-05-26 04:48:44 +08:00
}
} ;
struct DBCoreState {
2017-07-10 05:46:16 +08:00
std : : vector < CoreTLogSet > tLogs ;
2018-04-09 12:24:05 +08:00
int32_t logRouterTags ;
2017-07-10 05:46:16 +08:00
std : : vector < OldTLogCoreData > oldTLogData ;
2017-05-26 04:48:44 +08:00
DBRecoveryCount recoveryCount ; // Increases with sequential successful recoveries.
int logSystemType ;
2017-07-10 05:46:16 +08:00
2018-04-09 12:24:05 +08:00
DBCoreState ( ) : logRouterTags ( 0 ) , recoveryCount ( 0 ) , logSystemType ( 0 ) { }
2017-05-26 04:48:44 +08:00
vector < UID > getPriorCommittedLogServers ( ) {
vector < UID > priorCommittedLogServers ;
for ( int i = 0 ; i < oldTLogData . size ( ) ; i + + ) {
2017-07-10 05:46:16 +08:00
for ( auto & it : oldTLogData [ i ] . tLogs ) {
for ( auto & log : it . tLogs ) {
priorCommittedLogServers . push_back ( log ) ;
}
2017-05-26 04:48:44 +08:00
}
}
return priorCommittedLogServers ;
}
bool isEqual ( DBCoreState const & r ) const {
2018-04-09 12:24:05 +08:00
return logSystemType = = r . logSystemType & & recoveryCount = = r . recoveryCount & & tLogs = = r . tLogs & & oldTLogData = = r . oldTLogData & & logRouterTags = = r . logRouterTags ;
2017-05-26 04:48:44 +08:00
}
bool operator = = ( const DBCoreState & rhs ) const { return isEqual ( rhs ) ; }
template < class Archive >
void serialize ( Archive & ar ) {
2018-01-31 09:10:50 +08:00
//FIXME: remove when we no longer need to test upgrades from 4.X releases
2018-06-15 04:48:30 +08:00
if ( g_network - > isSimulated ( ) & & ar . protocolVersion ( ) < 0x0FDB00A460010001LL ) {
2018-01-31 09:10:50 +08:00
TraceEvent ( " ElapsedTime " ) . detail ( " SimTime " , now ( ) ) . detail ( " RealTime " , 0 ) . detail ( " RandomUnseed " , 0 ) ;
flushAndExit ( 0 ) ;
}
ASSERT ( ar . protocolVersion ( ) > = 0x0FDB00A460010001LL ) ;
if ( ar . protocolVersion ( ) > = 0x0FDB00A560010001LL ) {
2018-04-09 12:24:05 +08:00
ar & tLogs & logRouterTags & oldTLogData & recoveryCount & logSystemType ;
2017-07-10 05:46:16 +08:00
} else if ( ar . isDeserializing ) {
tLogs . push_back ( CoreTLogSet ( ) ) ;
ar & tLogs [ 0 ] . tLogs & tLogs [ 0 ] . tLogWriteAntiQuorum & recoveryCount & tLogs [ 0 ] . tLogReplicationFactor & logSystemType ;
2017-07-11 08:41:32 +08:00
uint64_t tLocalitySize = ( uint64_t ) tLogs [ 0 ] . tLogLocalities . size ( ) ;
ar & oldTLogData & tLogs [ 0 ] . tLogPolicy & tLocalitySize ;
if ( ar . isDeserializing ) {
tLogs [ 0 ] . tLogLocalities . reserve ( tLocalitySize ) ;
for ( size_t i = 0 ; i < tLocalitySize ; i + + ) {
2017-07-10 05:46:16 +08:00
LocalityData locality ;
2017-07-11 08:41:32 +08:00
ar & locality ;
2017-07-10 05:46:16 +08:00
tLogs [ 0 ] . tLogLocalities . push_back ( locality ) ;
}
2018-04-12 08:33:17 +08:00
if ( oldTLogData . size ( ) ) {
2018-05-01 13:03:11 +08:00
tLogs [ 0 ] . startVersion = oldTLogData [ 0 ] . epochEnd ;
2018-04-12 08:33:17 +08:00
for ( int i = 0 ; i < oldTLogData . size ( ) - 1 ; i + + ) {
2018-05-01 13:03:11 +08:00
oldTLogData [ i ] . tLogs [ 0 ] . startVersion = oldTLogData [ i + 1 ] . epochEnd ;
2018-04-12 08:33:17 +08:00
}
}
2017-05-26 04:48:44 +08:00
}
2017-06-30 06:50:19 +08:00
}
2017-05-26 04:48:44 +08:00
}
} ;
# endif