2017-05-26 04:48:44 +08:00
/*
* LogSystemConfig . 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_LOGSYSTEMCONFIG_H
# define FDBSERVER_LOGSYSTEMCONFIG_H
# pragma once
2018-10-20 01:30:13 +08:00
# include "fdbserver/TLogInterface.h"
2017-05-26 04:48:44 +08:00
# include "fdbrpc/ReplicationPolicy.h"
2018-04-09 12:24:05 +08:00
# include "fdbclient/DatabaseConfiguration.h"
2017-05-26 04:48:44 +08:00
template < class Interface >
struct OptionalInterface {
// Represents an interface with a known id() and possibly known actual endpoints.
// For example, an OptionalInterface<TLogInterface> represents a particular tlog by id, which you might or might not presently know how to communicate with
UID id ( ) const { return ident ; }
bool present ( ) const { return iface . present ( ) ; }
Interface const & interf ( ) const { return iface . get ( ) ; }
explicit OptionalInterface ( UID id ) : ident ( id ) { }
explicit OptionalInterface ( Interface const & i ) : ident ( i . id ( ) ) , iface ( i ) { }
OptionalInterface ( ) { }
std : : string toString ( ) const { return ident . toString ( ) ; }
bool operator = = ( UID const & r ) const { return ident = = r ; }
template < class Ar >
void serialize ( Ar & ar ) {
2018-12-29 02:49:26 +08:00
serializer ( ar , iface ) ;
if ( ! iface . present ( ) ) serializer ( ar , ident ) ;
2017-05-26 04:48:44 +08:00
else ident = iface . get ( ) . id ( ) ;
}
protected :
UID ident ;
Optional < Interface > iface ;
} ;
2017-07-10 05:46:16 +08:00
struct TLogSet {
std : : vector < OptionalInterface < TLogInterface > > tLogs ;
2017-07-11 08:41:32 +08:00
std : : vector < OptionalInterface < TLogInterface > > logRouters ;
2017-05-26 04:48:44 +08:00
int32_t tLogWriteAntiQuorum , tLogReplicationFactor ;
std : : vector < LocalityData > tLogLocalities ; // Stores the localities of the log servers
2019-02-27 08:47:04 +08:00
TLogVersion tLogVersion ;
2019-03-14 04:14:39 +08:00
Reference < IReplicationPolicy > tLogPolicy ;
2017-07-10 05:46:16 +08:00
bool isLocal ;
2018-03-30 06:12:38 +08:00
int8_t locality ;
Version startVersion ;
2018-06-17 08:39:02 +08:00
std : : vector < std : : vector < int > > satelliteTagLocations ;
2017-05-26 04:48:44 +08:00
2018-06-16 03:36:19 +08:00
TLogSet ( ) : tLogWriteAntiQuorum ( 0 ) , tLogReplicationFactor ( 0 ) , isLocal ( true ) , locality ( tagLocalityInvalid ) , startVersion ( invalidVersion ) { }
2017-05-26 04:48:44 +08:00
std : : string toString ( ) const {
2018-06-16 03:36:19 +08:00
return format ( " anti: %d replication: %d local: %d routers: %d tLogs: %s locality: %d " , tLogWriteAntiQuorum , tLogReplicationFactor , isLocal , logRouters . size ( ) , describe ( tLogs ) . c_str ( ) , locality ) ;
2017-07-10 05:46:16 +08:00
}
2017-05-26 04:48:44 +08:00
2017-07-10 05:46:16 +08:00
bool operator = = ( const TLogSet & rhs ) const {
2018-06-17 08:39:02 +08:00
if ( tLogWriteAntiQuorum ! = rhs . tLogWriteAntiQuorum | | tLogReplicationFactor ! = rhs . tLogReplicationFactor | | isLocal ! = rhs . isLocal | | satelliteTagLocations ! = rhs . satelliteTagLocations | |
2018-04-13 06:20:54 +08:00
startVersion ! = rhs . startVersion | | tLogs . size ( ) ! = rhs . tLogs . size ( ) | | locality ! = rhs . locality | | logRouters . size ( ) ! = rhs . logRouters . size ( ) ) {
2017-07-10 05:46:16 +08:00
return false ;
2017-05-26 04:48:44 +08:00
}
2017-07-10 05:46:16 +08:00
if ( ( tLogPolicy & & ! rhs . tLogPolicy ) | | ( ! tLogPolicy & & rhs . tLogPolicy ) | | ( tLogPolicy & & ( tLogPolicy - > info ( ) ! = rhs . tLogPolicy - > info ( ) ) ) ) {
return false ;
2017-05-26 04:48:44 +08:00
}
2017-07-10 05:46:16 +08:00
for ( int j = 0 ; j < tLogs . size ( ) ; j + + ) {
if ( tLogs [ j ] . id ( ) ! = rhs . tLogs [ j ] . id ( ) | | tLogs [ j ] . present ( ) ! = rhs . tLogs [ j ] . present ( ) | | ( tLogs [ j ] . present ( ) & & tLogs [ j ] . interf ( ) . commit . getEndpoint ( ) . token ! = rhs . tLogs [ j ] . interf ( ) . commit . getEndpoint ( ) . token ) ) {
return false ;
}
2017-05-26 04:48:44 +08:00
}
2018-04-13 06:20:54 +08:00
for ( int j = 0 ; j < logRouters . size ( ) ; j + + ) {
if ( logRouters [ j ] . id ( ) ! = rhs . logRouters [ j ] . id ( ) | | logRouters [ j ] . present ( ) ! = rhs . logRouters [ j ] . present ( ) | | ( logRouters [ j ] . present ( ) & & logRouters [ j ] . interf ( ) . commit . getEndpoint ( ) . token ! = rhs . logRouters [ j ] . interf ( ) . commit . getEndpoint ( ) . token ) ) {
return false ;
}
}
2017-07-10 05:46:16 +08:00
return true ;
}
bool isEqualIds ( TLogSet const & r ) const {
2018-06-17 08:39:02 +08:00
if ( tLogWriteAntiQuorum ! = r . tLogWriteAntiQuorum | | tLogReplicationFactor ! = r . tLogReplicationFactor | | isLocal ! = r . isLocal | | satelliteTagLocations ! = r . satelliteTagLocations | |
startVersion ! = r . startVersion | | tLogs . size ( ) ! = r . tLogs . size ( ) | | locality ! = r . locality ) {
2017-07-10 05:46:16 +08:00
return false ;
2017-05-26 04:48:44 +08:00
}
2017-07-10 05:46:16 +08:00
if ( ( tLogPolicy & & ! r . tLogPolicy ) | | ( ! tLogPolicy & & r . tLogPolicy ) | | ( tLogPolicy & & ( tLogPolicy - > info ( ) ! = r . tLogPolicy - > info ( ) ) ) ) {
return false ;
2017-06-30 06:50:19 +08:00
}
2017-07-10 05:46:16 +08:00
for ( int i = 0 ; i < tLogs . size ( ) ; i + + ) {
if ( tLogs [ i ] . id ( ) ! = r . tLogs [ i ] . id ( ) ) {
return false ;
2017-05-26 04:48:44 +08:00
}
}
2017-07-10 05:46:16 +08:00
return true ;
2017-05-26 04:48:44 +08:00
}
template < class Ar >
void serialize ( Ar & ar ) {
2018-12-29 02:49:26 +08:00
serializer ( ar , tLogs , logRouters , tLogWriteAntiQuorum , tLogReplicationFactor , tLogPolicy , tLogLocalities , isLocal , locality , startVersion , satelliteTagLocations ) ;
2019-02-27 08:47:04 +08:00
if ( ar . isDeserializing & & ar . protocolVersion ( ) < 0x0FDB00B061030001LL ) {
tLogVersion = TLogVersion : : V2 ;
} else {
2019-02-27 09:14:41 +08:00
serializer ( ar , tLogVersion ) ;
2019-02-27 08:47:04 +08:00
}
ASSERT ( tLogPolicy . getPtr ( ) = = nullptr | | tLogVersion ! = TLogVersion : : UNSET ) ;
2017-07-10 05:46:16 +08:00
}
} ;
struct OldTLogConf {
std : : vector < TLogSet > tLogs ;
Version epochEnd ;
2018-04-09 12:24:05 +08:00
int32_t logRouterTags ;
2017-07-10 05:46:16 +08:00
2018-04-09 12:24:05 +08:00
OldTLogConf ( ) : epochEnd ( 0 ) , logRouterTags ( 0 ) { }
2017-07-10 05:46:16 +08:00
std : : string toString ( ) const {
2018-04-09 12:24:05 +08:00
return format ( " end: %d tags: %d %s " , epochEnd , logRouterTags , describe ( tLogs ) . c_str ( ) ) ;
2017-07-10 05:46:16 +08:00
}
bool operator = = ( const OldTLogConf & rhs ) const {
2018-04-09 12:24:05 +08:00
return tLogs = = rhs . tLogs & & epochEnd = = rhs . epochEnd & & logRouterTags = = rhs . logRouterTags ;
2017-07-10 05:46:16 +08:00
}
bool isEqualIds ( OldTLogConf const & r ) const {
if ( tLogs . size ( ) ! = r . tLogs . size ( ) ) {
return false ;
}
for ( int i = 0 ; i < tLogs . size ( ) ; i + + ) {
if ( ! tLogs [ i ] . isEqualIds ( r . tLogs [ i ] ) ) {
return false ;
2017-06-30 06:50:19 +08:00
}
2017-05-26 04:48:44 +08:00
}
2017-07-10 05:46:16 +08:00
return true ;
2017-05-26 04:48:44 +08:00
}
template < class Ar >
void serialize ( Ar & ar ) {
2018-12-29 02:49:26 +08:00
serializer ( ar , tLogs , epochEnd , logRouterTags ) ;
2017-05-26 04:48:44 +08:00
}
} ;
struct LogSystemConfig {
2018-04-09 12:24:05 +08:00
int32_t logSystemType ;
2017-07-10 05:46:16 +08:00
std : : vector < TLogSet > tLogs ;
2018-04-09 12:24:05 +08:00
int32_t logRouterTags ;
2017-05-26 04:48:44 +08:00
std : : vector < OldTLogConf > oldTLogs ;
2018-04-09 12:24:05 +08:00
int32_t expectedLogSets ;
2018-04-21 04:25:22 +08:00
UID recruitmentID ;
2018-05-06 08:56:00 +08:00
bool stopped ;
2018-06-27 09:20:28 +08:00
Optional < Version > recoveredAt ;
2017-05-26 04:48:44 +08:00
2018-05-06 08:56:00 +08:00
LogSystemConfig ( ) : logSystemType ( 0 ) , logRouterTags ( 0 ) , expectedLogSets ( 0 ) , stopped ( false ) { }
2017-05-26 04:48:44 +08:00
2018-06-27 09:20:28 +08:00
std : : string toString ( ) const {
2018-04-09 12:24:05 +08:00
return format ( " type: %d oldGenerations: %d tags: %d %s " , logSystemType , oldTLogs . size ( ) , logRouterTags , describe ( tLogs ) . c_str ( ) ) ;
2017-07-10 05:46:16 +08:00
}
2017-05-26 04:48:44 +08:00
2018-05-30 01:51:23 +08:00
std : : vector < TLogInterface > allLocalLogs ( ) const {
std : : vector < TLogInterface > results ;
for ( int i = 0 ; i < tLogs . size ( ) ; i + + ) {
if ( tLogs [ i ] . isLocal ) {
for ( int j = 0 ; j < tLogs [ i ] . tLogs . size ( ) ; j + + ) {
if ( tLogs [ i ] . tLogs [ j ] . present ( ) ) {
results . push_back ( tLogs [ i ] . tLogs [ j ] . interf ( ) ) ;
}
}
}
}
return results ;
}
2017-05-26 04:48:44 +08:00
std : : vector < TLogInterface > allPresentLogs ( ) const {
std : : vector < TLogInterface > results ;
2017-07-10 05:46:16 +08:00
for ( int i = 0 ; i < tLogs . size ( ) ; i + + ) {
for ( int j = 0 ; j < tLogs [ i ] . tLogs . size ( ) ; j + + ) {
if ( tLogs [ i ] . tLogs [ j ] . present ( ) ) {
results . push_back ( tLogs [ i ] . tLogs [ j ] . interf ( ) ) ;
}
}
}
2017-05-26 04:48:44 +08:00
return results ;
}
2019-02-22 08:52:27 +08:00
std : : pair < int8_t , int8_t > getLocalityForDcId ( Optional < Key > dcId ) const {
2018-09-29 03:21:08 +08:00
std : : map < int8_t , int > matchingLocalities ;
std : : map < int8_t , int > allLocalities ;
for ( auto & tLogSet : tLogs ) {
for ( auto & tLog : tLogSet . tLogs ) {
2019-02-23 06:02:34 +08:00
if ( tLogSet . locality > = 0 ) {
if ( tLog . present ( ) & & tLog . interf ( ) . locality . dcId ( ) = = dcId ) {
2018-09-29 03:21:08 +08:00
matchingLocalities [ tLogSet . locality ] + + ;
} else {
allLocalities [ tLogSet . locality ] + + ;
}
}
}
}
for ( auto & oldLog : oldTLogs ) {
for ( auto & tLogSet : oldLog . tLogs ) {
for ( auto & tLog : tLogSet . tLogs ) {
2019-02-23 06:02:34 +08:00
if ( tLogSet . locality > = 0 ) {
if ( tLog . present ( ) & & tLog . interf ( ) . locality . dcId ( ) = = dcId ) {
2018-09-29 03:21:08 +08:00
matchingLocalities [ tLogSet . locality ] + + ;
} else {
allLocalities [ tLogSet . locality ] + + ;
}
}
}
}
}
2019-02-22 08:52:27 +08:00
int8_t bestLoc = tagLocalityInvalid ;
int bestLocalityCount = - 1 ;
for ( auto & it : matchingLocalities ) {
if ( it . second > bestLocalityCount ) {
bestLoc = it . first ;
bestLocalityCount = it . second ;
2018-09-29 03:21:08 +08:00
}
}
2019-02-22 08:52:27 +08:00
int8_t secondLoc = tagLocalityInvalid ;
int8_t thirdLoc = tagLocalityInvalid ;
int secondLocalityCount = - 1 ;
int thirdLocalityCount = - 1 ;
for ( auto & it : allLocalities ) {
if ( bestLoc ! = it . first ) {
if ( it . second > secondLocalityCount ) {
thirdLoc = secondLoc ;
thirdLocalityCount = secondLocalityCount ;
secondLoc = it . first ;
secondLocalityCount = it . second ;
} else if ( it . second > thirdLocalityCount ) {
thirdLoc = it . first ;
thirdLocalityCount = it . second ;
2018-09-29 03:21:08 +08:00
}
}
}
2019-02-22 08:52:27 +08:00
if ( bestLoc ! = tagLocalityInvalid ) {
return std : : make_pair ( bestLoc , secondLoc ) ;
}
2019-02-23 06:02:34 +08:00
return std : : make_pair ( secondLoc , thirdLoc ) ;
2018-09-29 03:21:08 +08:00
}
2018-03-03 08:50:30 +08:00
std : : vector < std : : pair < UID , NetworkAddress > > allSharedLogs ( ) const {
typedef std : : pair < UID , NetworkAddress > IdAddrPair ;
std : : vector < IdAddrPair > results ;
2018-03-06 07:18:14 +08:00
for ( auto & tLogSet : tLogs ) {
for ( auto & tLog : tLogSet . tLogs ) {
if ( tLog . present ( ) )
results . push_back ( IdAddrPair ( tLog . interf ( ) . getSharedTLogID ( ) , tLog . interf ( ) . address ( ) ) ) ;
}
2018-03-03 09:56:49 +08:00
}
2018-03-03 08:50:30 +08:00
for ( auto & oldLog : oldTLogs ) {
2018-03-06 07:18:14 +08:00
for ( auto & tLogSet : oldLog . tLogs ) {
for ( auto & tLog : tLogSet . tLogs ) {
if ( tLog . present ( ) )
results . push_back ( IdAddrPair ( tLog . interf ( ) . getSharedTLogID ( ) , tLog . interf ( ) . address ( ) ) ) ;
}
2018-03-03 08:50:30 +08:00
}
}
uniquify ( results ) ;
// This assert depends on the fact that uniquify will sort the elements based on <UID, NetworkAddr> order
ASSERT_WE_THINK ( std : : unique ( results . begin ( ) , results . end ( ) , [ ] ( IdAddrPair & x , IdAddrPair & y ) { return x . first = = y . first ; } ) = = results . end ( ) ) ;
return results ;
}
2017-05-26 04:48:44 +08:00
bool operator = = ( const LogSystemConfig & rhs ) const { return isEqual ( rhs ) ; }
bool isEqual ( LogSystemConfig const & r ) const {
2018-06-27 09:20:28 +08:00
return logSystemType = = r . logSystemType & & tLogs = = r . tLogs & & oldTLogs = = r . oldTLogs & & expectedLogSets = = r . expectedLogSets & & logRouterTags = = r . logRouterTags & & recruitmentID = = r . recruitmentID & & stopped = = r . stopped & & recoveredAt = = r . recoveredAt ;
2017-05-26 04:48:44 +08:00
}
bool isEqualIds ( LogSystemConfig const & r ) const {
2017-10-25 06:09:31 +08:00
for ( auto & i : r . tLogs ) {
for ( auto & j : tLogs ) {
if ( i . isEqualIds ( j ) ) {
return true ;
}
2017-05-26 04:48:44 +08:00
}
}
2017-10-25 06:09:31 +08:00
return false ;
2017-05-26 04:48:44 +08:00
}
bool isNextGenerationOf ( LogSystemConfig const & r ) const {
2017-10-25 06:09:31 +08:00
if ( ! oldTLogs . size ( ) ) {
2017-05-26 04:48:44 +08:00
return false ;
}
2017-10-25 06:09:31 +08:00
for ( auto & i : r . tLogs ) {
for ( auto & j : oldTLogs [ 0 ] . tLogs ) {
if ( i . isEqualIds ( j ) ) {
return true ;
}
2017-07-10 05:46:16 +08:00
}
2017-06-30 06:50:19 +08:00
}
2017-10-25 06:09:31 +08:00
return false ;
2017-05-26 04:48:44 +08:00
}
template < class Ar >
void serialize ( Ar & ar ) {
2018-12-29 02:49:26 +08:00
serializer ( ar , logSystemType , tLogs , logRouterTags , oldTLogs , expectedLogSets , recruitmentID , stopped , recoveredAt ) ;
2017-05-26 04:48:44 +08:00
}
} ;
# endif