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
2019-04-11 01:30:34 +08:00
# include <set>
# include <vector>
2019-02-27 08:47:04 +08:00
# include "fdbclient/FDBTypes.h"
2017-05-26 04:48:44 +08:00
# include "fdbrpc/ReplicationPolicy.h"
2019-04-09 05:45:16 +08:00
# include "fdbserver/LogSystemConfig.h"
2019-02-27 08:47:04 +08:00
# include "fdbserver/MasterInterface.h"
2017-05-26 04:48:44 +08:00
2019-04-19 01:18:11 +08:00
class LogSet ;
2019-04-19 04:41:37 +08:00
struct OldLogData ;
2019-04-19 01:18:11 +08:00
2017-05-26 04:48:44 +08:00
// 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
2019-03-14 04:14:39 +08:00
Reference < IReplicationPolicy > tLogPolicy ;
2017-07-10 05:46:16 +08:00
bool isLocal ;
2017-09-08 06:32:08 +08:00
int8_t locality ;
2018-03-30 06:12:38 +08:00
Version startVersion ;
2018-06-17 08:39:02 +08:00
std : : vector < std : : vector < int > > satelliteTagLocations ;
2019-02-27 08:47:04 +08:00
TLogVersion tLogVersion ;
2017-07-10 05:46:16 +08:00
2018-06-16 03:36:19 +08:00
CoreTLogSet ( ) : tLogWriteAntiQuorum ( 0 ) , tLogReplicationFactor ( 0 ) , isLocal ( true ) , locality ( tagLocalityUpgraded ) , startVersion ( invalidVersion ) { }
2019-04-19 01:18:11 +08:00
explicit CoreTLogSet ( const LogSet & logset ) ;
2017-07-10 05:46:16 +08:00
bool operator = = ( CoreTLogSet const & rhs ) const {
2018-06-17 08:39:02 +08:00
return tLogs = = rhs . tLogs & & tLogWriteAntiQuorum = = rhs . tLogWriteAntiQuorum & & tLogReplicationFactor = = rhs . tLogReplicationFactor & & isLocal = = rhs . isLocal & & satelliteTagLocations = = rhs . satelliteTagLocations & &
2019-04-19 04:41:37 +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 ) {
2019-04-19 04:41:37 +08:00
serializer ( ar , tLogs , tLogWriteAntiQuorum , tLogReplicationFactor , tLogPolicy , tLogLocalities , isLocal , locality , startVersion , satelliteTagLocations ) ;
2019-06-19 08:55:27 +08:00
if ( ar . isDeserializing & & ! ar . protocolVersion ( ) . hasTLogVersion ( ) ) {
2019-02-27 08:47:04 +08:00
tLogVersion = TLogVersion : : V2 ;
} else {
2019-02-27 09:14:41 +08:00
serializer ( ar , tLogVersion ) ;
2019-02-27 08:47:04 +08:00
}
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 ;
2019-06-29 03:33:24 +08:00
int32_t txsTags ;
2017-05-26 04:48:44 +08:00
Version epochEnd ;
2019-04-11 01:30:34 +08:00
std : : set < int8_t > pseudoLocalities ;
2017-05-26 04:48:44 +08:00
2019-06-29 03:33:24 +08:00
OldTLogCoreData ( ) : epochEnd ( 0 ) , logRouterTags ( 0 ) , txsTags ( 0 ) { }
2019-04-19 04:41:37 +08:00
explicit OldTLogCoreData ( const OldLogData & ) ;
2017-05-26 04:48:44 +08:00
2017-07-10 05:46:16 +08:00
bool operator = = ( OldTLogCoreData const & rhs ) const {
2019-06-29 03:33:24 +08:00
return tLogs = = rhs . tLogs & & logRouterTags = = rhs . logRouterTags & & txsTags = = rhs . txsTags & & epochEnd = = rhs . epochEnd & & pseudoLocalities = = rhs . pseudoLocalities ;
2017-07-10 05:46:16 +08:00
}
2017-05-26 04:48:44 +08:00
template < class Archive >
void serialize ( Archive & ar ) {
2019-06-19 08:55:27 +08:00
if ( ar . protocolVersion ( ) . hasTagLocality ( ) ) {
2019-04-20 05:29:32 +08:00
serializer ( 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 ( ) ) ;
2018-12-29 02:49:26 +08:00
serializer ( ar , tLogs [ 0 ] . tLogs , tLogs [ 0 ] . tLogWriteAntiQuorum , tLogs [ 0 ] . tLogReplicationFactor , tLogs [ 0 ] . tLogPolicy , epochEnd , tLogs [ 0 ] . tLogLocalities ) ;
2019-02-27 08:47:04 +08:00
tLogs [ 0 ] . tLogVersion = TLogVersion : : V2 ;
2017-06-30 06:50:19 +08:00
}
2019-06-19 08:55:27 +08:00
if ( ar . protocolVersion ( ) . hasPseudoLocalities ( ) ) {
2019-07-13 09:15:59 +08:00
serializer ( ar , pseudoLocalities ) ;
}
if ( ar . protocolVersion ( ) . hasShardedTxsTags ( ) ) {
serializer ( ar , txsTags ) ;
2019-04-20 05:29:32 +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 ;
2019-06-29 03:33:24 +08:00
int32_t txsTags ;
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.
2019-04-09 05:45:16 +08:00
LogSystemType logSystemType ;
2019-04-11 01:30:34 +08:00
std : : set < int8_t > pseudoLocalities ;
2017-07-10 05:46:16 +08:00
2019-06-29 03:33:24 +08:00
DBCoreState ( ) : logRouterTags ( 0 ) , txsTags ( 0 ) , recoveryCount ( 0 ) , logSystemType ( LogSystemType : : empty ) { }
2017-05-26 04:48:44 +08:00
vector < UID > getPriorCommittedLogServers ( ) {
vector < UID > priorCommittedLogServers ;
2018-09-29 03:13:46 +08:00
for ( auto & it : tLogs ) {
for ( auto & log : it . tLogs ) {
priorCommittedLogServers . push_back ( log ) ;
}
}
2017-05-26 04:48:44 +08:00
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 {
2019-06-29 03:33:24 +08:00
return logSystemType = = r . logSystemType & & recoveryCount = = r . recoveryCount & & tLogs = = r . tLogs & & oldTLogData = = r . oldTLogData & & logRouterTags = = r . logRouterTags & & txsTags = = r . txsTags & & pseudoLocalities = = r . pseudoLocalities ;
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
2019-06-19 08:55:27 +08:00
if ( g_network - > isSimulated ( ) & & ! ar . protocolVersion ( ) . hasMultiGenerationTLog ( ) ) {
2018-01-31 09:10:50 +08:00
TraceEvent ( " ElapsedTime " ) . detail ( " SimTime " , now ( ) ) . detail ( " RealTime " , 0 ) . detail ( " RandomUnseed " , 0 ) ;
flushAndExit ( 0 ) ;
}
2019-06-19 08:55:27 +08:00
ASSERT ( ar . protocolVersion ( ) . hasMultiGenerationTLog ( ) ) ;
if ( ar . protocolVersion ( ) . hasTagLocality ( ) ) {
2019-04-20 05:29:32 +08:00
serializer ( ar , tLogs , logRouterTags , oldTLogData , recoveryCount , logSystemType ) ;
2019-06-19 08:55:27 +08:00
if ( ar . protocolVersion ( ) . hasPseudoLocalities ( ) ) {
2019-07-13 09:17:30 +08:00
serializer ( ar , pseudoLocalities ) ;
}
if ( ar . protocolVersion ( ) . hasShardedTxsTags ( ) ) {
serializer ( ar , txsTags ) ;
2019-04-20 05:29:32 +08:00
}
2017-07-10 05:46:16 +08:00
} else if ( ar . isDeserializing ) {
tLogs . push_back ( CoreTLogSet ( ) ) ;
2018-12-29 02:49:26 +08:00
serializer ( ar , tLogs [ 0 ] . tLogs , tLogs [ 0 ] . tLogWriteAntiQuorum , recoveryCount , tLogs [ 0 ] . tLogReplicationFactor , logSystemType ) ;
2019-02-27 08:47:04 +08:00
tLogs [ 0 ] . tLogVersion = TLogVersion : : V2 ;
2017-07-10 05:46:16 +08:00
2017-07-11 08:41:32 +08:00
uint64_t tLocalitySize = ( uint64_t ) tLogs [ 0 ] . tLogLocalities . size ( ) ;
2018-12-29 02:49:26 +08:00
serializer ( ar , oldTLogData , tLogs [ 0 ] . tLogPolicy , tLocalitySize ) ;
2017-07-11 08:41:32 +08:00
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 ;
2018-12-29 02:49:26 +08:00
serializer ( 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