| 4098 | } |
| 4099 | |
| 4100 | int DDTeamCollection::addBestMachineTeams(int machineTeamsToBuild) { |
| 4101 | int addedMachineTeams = 0; |
| 4102 | |
| 4103 | ASSERT_GE(machineTeamsToBuild, 0); |
| 4104 | // The number of machines is always no smaller than the storageTeamSize in a correct configuration |
| 4105 | ASSERT_GE(machine_info.size(), configuration.storageTeamSize); |
| 4106 | // Future: Consider if we should overbuild more machine teams to |
| 4107 | // allow machineTeamRemover() to get a more balanced machine teams per machine |
| 4108 | |
| 4109 | // Step 1: Create machineLocalityMap which will be used in building machine team |
| 4110 | rebuildMachineLocalityMap(); |
| 4111 | |
| 4112 | // Add a team in each iteration |
| 4113 | while (addedMachineTeams < machineTeamsToBuild || notEnoughMachineTeamsForAMachine()) { |
| 4114 | // Step 2: Get least used machines from which we choose machines as a machine team |
| 4115 | std::vector<Reference<TCMachineInfo>> leastUsedMachines; // A less used machine has less number of teams |
| 4116 | int minTeamCount = std::numeric_limits<int>::max(); |
| 4117 | for (auto& machine : machine_info) { |
| 4118 | // Skip invalid machine whose representative server is not in server_info |
| 4119 | ASSERT_WE_THINK(server_info.find(machine.second->serversOnMachine[0]->getId()) != server_info.end()); |
| 4120 | // Skip unhealthy machines |
| 4121 | if (!isMachineHealthy(machine.second)) |
| 4122 | continue; |
| 4123 | // Skip machine with incomplete locality |
| 4124 | if (!isValidLocality(configuration.storagePolicy, |
| 4125 | machine.second->serversOnMachine[0]->getLastKnownInterface().locality)) { |
| 4126 | continue; |
| 4127 | } |
| 4128 | |
| 4129 | // Invariant: We only create correct size machine teams. |
| 4130 | // When configuration (e.g., team size) is changed, the DDTeamCollection will be destroyed and rebuilt |
| 4131 | // so that the invariant will not be violated. |
| 4132 | int teamCount = machine.second->machineTeams.size(); |
| 4133 | |
| 4134 | if (teamCount < minTeamCount) { |
| 4135 | leastUsedMachines.clear(); |
| 4136 | minTeamCount = teamCount; |
| 4137 | } |
| 4138 | if (teamCount == minTeamCount) { |
| 4139 | leastUsedMachines.push_back(machine.second); |
| 4140 | } |
| 4141 | } |
| 4142 | |
| 4143 | std::vector<UID*> team; |
| 4144 | std::vector<LocalityEntry> forcedAttributes; |
| 4145 | |
| 4146 | // Step 4: Reuse Policy's selectReplicas() to create team for the representative process. |
| 4147 | std::vector<UID*> bestTeam; |
| 4148 | int bestScore = std::numeric_limits<int>::max(); |
| 4149 | int maxAttempts = SERVER_KNOBS->BEST_OF_AMT; // BEST_OF_AMT = 4 |
| 4150 | for (int i = 0; i < maxAttempts && i < 100; ++i) { |
| 4151 | // Step 3: Create a representative process for each machine. |
| 4152 | // Construct forcedAttribute from leastUsedMachines. |
| 4153 | // We will use forcedAttribute to call existing function to form a team |
| 4154 | if (leastUsedMachines.size()) { |
| 4155 | forcedAttributes.clear(); |
| 4156 | // Randomly choose 1 least used machine |
| 4157 | Reference<TCMachineInfo> tcMachineInfo = deterministicRandom()->randomChoice(leastUsedMachines); |
no test coverage detected