private void MoveBinAssigment(MachineWithBinAssigments oldMachine, MachineWithBinAssigments?newMachine, uint binToMove, MachineWithBinAssigments?machineToResort) { if (machineToResort != null) { // Remove the machine to re-sort before any modifications _machineAssignmentsSortedByBinCount.Remove(machineToResort); } // Remove bin from old machine oldMachine.BinsAssignedTo.Remove(binToMove); // Add bin to new machine is specified if (newMachine != null) { newMachine.BinsAssignedTo.Add(binToMove); _binToMachineMap[binToMove] = newMachine.MachineId; } if (machineToResort != null) { // Remove the machine to resort after modifications _machineAssignmentsSortedByBinCount.Add(machineToResort); } // Accesses to the machine hash set (_machineSetBuffer) are not thread safe. foreach (var impactedBin in GetImpactedBins(binToMove, oldMachine.MachineId)) { // Mark the old assignment as expired _expiredAssignments.GetOrAdd(impactedBin, bin => new Dictionary <MachineId, DateTime>())[oldMachine.MachineId] = _clock.UtcNow + _expiryTime; } // Invalidate bins _bins = null; }
public BinManager(int locationsPerBin, IEnumerable <MachineId> startLocations, IClock clock, TimeSpan expiryTime) { LocationsPerBin = locationsPerBin; _clock = clock; _expiryTime = expiryTime; _binToMachineMap = new MachineId?[NumberOfBins]; if (startLocations.Any()) { foreach (var location in startLocations) { var assignments = new MachineWithBinAssigments(location); _machineAssignmentsSortedByBinCount.Add(assignments); _machinesToBinsMap[location] = assignments; } for (uint i = 0; i < NumberOfBins; i++) { var min = _machineAssignmentsSortedByBinCount.Min !; _machineAssignmentsSortedByBinCount.Remove(min); min.BinsAssignedTo.Add(i); _machineAssignmentsSortedByBinCount.Add(min); _binToMachineMap[i] = min.MachineId; } } }
public void AddLocation(MachineId id) { lock (_lockObject) { var addedMachine = new MachineWithBinAssigments(id); if (!_machinesToBinsMap.TryAdd(id, addedMachine)) { // Machine already registered. Nothing to do. return; } // If only one machine is registered, assign that machine to all bins if (_machinesToBinsMap.Count == 1) { for (uint binNumber = 0; binNumber < NumberOfBins; binNumber++) { _binToMachineMap[binNumber] = id; addedMachine.BinsAssignedTo.Add(binNumber); } _machinesToBinsMap[id] = addedMachine; _machineAssignmentsSortedByBinCount.Add(addedMachine); return; } // While the added machine's number of bins is less the the per machine bin count, // move bins from machines with greatest number of assigned bins while (addedMachine.BinsAssignedTo.Count < _machineAssignmentsSortedByBinCount.Max !.BinsAssignedTo.Count - 1) { var machineWithMaxNumOfBins = _machineAssignmentsSortedByBinCount.Max !; var binToReassign = machineWithMaxNumOfBins.BinsAssignedTo.First(); // Reassign bin from machine with most number of bin assigned to the added machine MoveBinAssigment(oldMachine: machineWithMaxNumOfBins, newMachine: addedMachine, binToMove: binToReassign, machineToResort: machineWithMaxNumOfBins); } _machinesToBinsMap[id] = addedMachine; _machineAssignmentsSortedByBinCount.Add(addedMachine); } }