throws Exception {
// 1. If there is only one conflicting database version header, return it (no need for a complex algorithm)
if (winningFirstConflictingDatabaseVersionHeaders.size() == 1) {
String winningMachineName = winningFirstConflictingDatabaseVersionHeaders.firstKey();
DatabaseVersionHeader winnersWinnersLastDatabaseVersionHeader = allBranches.getBranch(winningMachineName).getLast();
return new AbstractMap.SimpleEntry<String, DatabaseVersionHeader>(winningMachineName, winnersWinnersLastDatabaseVersionHeader);
}
// 2. Find position of first conflicting header in branch (per client)
Map<String, Integer> machineInBranchPosition = findWinningFirstConflictDatabaseVersionHeaderPerClientPosition(
winningFirstConflictingDatabaseVersionHeaders, allBranches);
// 3. Compare all, go forward if all are identical
int machineInRaceCount = winningFirstConflictingDatabaseVersionHeaders.size();
while (machineInRaceCount > 1) {
String firstMachineName = null;
DatabaseVersionHeader firstMachineDatabaseVersionHeader = null;
for (Map.Entry<String, Integer> secondMachineNamePositionEntry : machineInBranchPosition.entrySet()) {
// 3a. Get second machine and make sure we can use it (= it hasn't been eliminated before)
// - Get machine name, position of next database version to be compared, and the machine branch
String secondMachineName = secondMachineNamePositionEntry.getKey();
Integer secondMachinePosition = secondMachineNamePositionEntry.getValue();
// - If machine position is 'null', it has been marked 'eliminated'
if (secondMachinePosition == null) {
continue;
}
// - If machine position is greater than the machine's branch size (out of bound),
// eliminate the machine (= position to 'null')
DatabaseBranch secondMachineBranch = allBranches.getBranch(secondMachineName);
if (secondMachinePosition >= secondMachineBranch.size()) {
machineInBranchPosition.put(secondMachineName, null);
machineInRaceCount--;
continue;
}
DatabaseVersionHeader secondMachineDatabaseVersionHeader = secondMachineBranch.get(secondMachinePosition);
// 3b. Now compare 'firstMachine*' and 'secondMachine*'
// If this is the first iteration of the loop, there is nothing to compare it to.
if (firstMachineDatabaseVersionHeader == null) {
firstMachineName = secondMachineName;
firstMachineDatabaseVersionHeader = secondMachineDatabaseVersionHeader;
}
else {
// Compare the two machines 'firstMachine*' and 'secondMachine*'
// Keep the winner, eliminate the loser
VectorClockComparison comparison = VectorClock.compare(firstMachineDatabaseVersionHeader.getVectorClock(),
secondMachineDatabaseVersionHeader.getVectorClock());
if (comparison != VectorClockComparison.EQUAL) {
Boolean eliminateFirstMachine = determineEliminateMachine(firstMachineName, firstMachineDatabaseVersionHeader,
secondMachineName, secondMachineDatabaseVersionHeader);
if (eliminateFirstMachine) {
machineInBranchPosition.put(firstMachineName, null);
machineInRaceCount--;
firstMachineName = secondMachineName;
firstMachineDatabaseVersionHeader = secondMachineDatabaseVersionHeader;
}
else {
machineInBranchPosition.put(secondMachineName, null);
machineInRaceCount--;
}
}
}
}
// 3c. If more than one machine are still in the race, increase positions
if (machineInRaceCount > 1) {
increaseBranchPosition(machineInBranchPosition);
}
}
// 4. Return the last remaining machine and its last database version header (= winner!)
for (String machineName : machineInBranchPosition.keySet()) {
Integer machineCurrentPosition = machineInBranchPosition.get(machineName);
if (machineCurrentPosition != null) {
DatabaseVersionHeader winnersWinnersLastDatabaseVersionHeader = allBranches.getBranch(machineName).getLast();
return new AbstractMap.SimpleEntry<String, DatabaseVersionHeader>(machineName, winnersWinnersLastDatabaseVersionHeader);
}
}
return null;