1 /* 2 * CoordinationInterface.h 3 * 4 * This source file is part of the FoundationDB open source project 5 * 6 * Copyright 2013-2018 Apple Inc. and the FoundationDB project authors 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 #ifndef FDBCLIENT_COORDINATIONINTERFACE_H 22 #define FDBCLIENT_COORDINATIONINTERFACE_H 23 #pragma once 24 25 #include "fdbclient/FDBTypes.h" 26 #include "fdbrpc/fdbrpc.h" 27 #include "fdbrpc/Locality.h" 28 29 const int MAX_CLUSTER_FILE_BYTES = 60000; 30 31 struct ClientLeaderRegInterface { 32 RequestStream< struct GetLeaderRequest > getLeader; 33 ClientLeaderRegInterfaceClientLeaderRegInterface34 ClientLeaderRegInterface() {} 35 ClientLeaderRegInterface( NetworkAddress remote ); 36 ClientLeaderRegInterface( INetwork* local ); 37 }; 38 39 class ClusterConnectionString { 40 public: ClusterConnectionString()41 ClusterConnectionString() {} 42 ClusterConnectionString( std::string const& connectionString ); 43 ClusterConnectionString( vector<NetworkAddress>, Key ); coordinators()44 vector<NetworkAddress> const& coordinators() const { return coord; } clusterKey()45 Key clusterKey() const { return key; } clusterKeyName()46 Key clusterKeyName() const { return keyDesc; } // Returns the "name" or "description" part of the clusterKey (the part before the ':') 47 std::string toString() const; 48 static std::string getErrorString(std::string const& source, Error const& e); 49 private: 50 void parseKey( std::string const& key ); 51 52 vector<NetworkAddress> coord; 53 Key key, keyDesc; 54 }; 55 56 class ClusterConnectionFile : NonCopyable, public ReferenceCounted<ClusterConnectionFile> { 57 public: ClusterConnectionFile()58 ClusterConnectionFile() {} 59 // Loads and parses the file at 'path', throwing errors if the file cannot be read or the format is invalid. 60 // 61 // The format of the file is: description:id@[addrs]+ 62 // The description and id together are called the "key" 63 // 64 // The following is enforced about the format of the file: 65 // - The key must contain one (and only one) ':' character 66 // - The description contains only allowed characters (a-z, A-Z, 0-9, _) 67 // - The ID contains only allowed characters (a-z, A-Z, 0-9) 68 // - At least one address is specified 69 // - There is no address present more than once 70 explicit ClusterConnectionFile( std::string const& path ); ClusterConnectionFile(ClusterConnectionString const & cs)71 explicit ClusterConnectionFile(ClusterConnectionString const& cs) : cs(cs), setConn(false) {} 72 explicit ClusterConnectionFile(std::string const& filename, ClusterConnectionString const& contents); 73 74 // returns <resolved name, was default file> 75 static std::pair<std::string, bool> lookupClusterFileName( std::string const& filename ); 76 // get a human readable error message describing the error returned from the constructor 77 static std::string getErrorString( std::pair<std::string, bool> const& resolvedFile, Error const& e ); 78 79 ClusterConnectionString const& getConnectionString() const; 80 bool writeFile(); 81 void setConnectionString( ClusterConnectionString const& ); getFilename()82 std::string const& getFilename() const { ASSERT( filename.size() ); return filename; } canGetFilename()83 bool canGetFilename() const { return filename.size() != 0; } 84 bool fileContentsUpToDate() const; 85 bool fileContentsUpToDate(ClusterConnectionString &fileConnectionString) const; 86 void notifyConnected(); 87 private: 88 ClusterConnectionString cs; 89 std::string filename; 90 bool setConn; 91 }; 92 93 struct LeaderInfo { 94 UID changeID; 95 static const uint64_t mask = ~(127ll << 57); 96 Value serializedInfo; 97 bool forward; // If true, serializedInfo is a connection string instead! 98 LeaderInfoLeaderInfo99 LeaderInfo() : forward(false) {} LeaderInfoLeaderInfo100 LeaderInfo(UID changeID) : changeID(changeID), forward(false) {} 101 102 bool operator < (LeaderInfo const& r) const { return changeID < r.changeID; } 103 bool operator == (LeaderInfo const& r) const { return changeID == r.changeID; } 104 105 // The first 7 bits of ChangeID represent cluster controller process class fitness, the lower the better updateChangeIDLeaderInfo106 void updateChangeID(ClusterControllerPriorityInfo info) { 107 changeID = UID( ((uint64_t)info.processClassFitness << 57) | ((uint64_t)info.isExcluded << 60) | ((uint64_t)info.dcFitness << 61) | (changeID.first() & mask), changeID.second() ); 108 } 109 110 // All but the first 7 bits are used to represent process id equalInternalIdLeaderInfo111 bool equalInternalId(LeaderInfo const& leaderInfo) const { 112 return ((changeID.first() & mask) == (leaderInfo.changeID.first() & mask)) && changeID.second() == leaderInfo.changeID.second(); 113 } 114 115 // Change leader only if 116 // 1. the candidate has better process class fitness and the candidate is not the leader 117 // 2. the leader process class fitness becomes worse leaderChangeRequiredLeaderInfo118 bool leaderChangeRequired(LeaderInfo const& candidate) const { 119 return ((changeID.first() & ~mask) > (candidate.changeID.first() & ~mask) && !equalInternalId(candidate)) || ((changeID.first() & ~mask) < (candidate.changeID.first() & ~mask) && equalInternalId(candidate)); 120 } 121 122 template <class Ar> serializeLeaderInfo123 void serialize(Ar& ar) { 124 serializer(ar, changeID, serializedInfo, forward); 125 } 126 }; 127 128 struct GetLeaderRequest { 129 Key key; 130 UID knownLeader; 131 ReplyPromise< Optional<LeaderInfo> > reply; 132 GetLeaderRequestGetLeaderRequest133 GetLeaderRequest() {} GetLeaderRequestGetLeaderRequest134 explicit GetLeaderRequest(Key key, UID kl) : key(key), knownLeader(kl) {} 135 136 template <class Ar> serializeGetLeaderRequest137 void serialize(Ar& ar) { 138 serializer(ar, key, knownLeader, reply); 139 } 140 }; 141 142 class ClientCoordinators { 143 public: 144 vector< ClientLeaderRegInterface > clientLeaderServers; 145 Key clusterKey; 146 Reference<ClusterConnectionFile> ccf; 147 148 explicit ClientCoordinators( Reference<ClusterConnectionFile> ccf ); ClientCoordinators()149 ClientCoordinators() {} 150 }; 151 152 #endif 153