/// <summary> /// Checks whether the host <paramref name="h"/> should be skipped. /// </summary> private static bool ShouldSkipHost(NetworkTopologyTokenMapContext context, Host h, HashSet <string> racksPlacedInDc) { var replicaForRackAlreadySelected = h.Rack != null && racksPlacedInDc.Contains(h.Rack); var racksMissing = racksPlacedInDc.Count < context.Datacenters[h.Datacenter].Racks.Count; return(replicaForRackAlreadySelected && racksMissing); }
/// <summary> /// Get collection that contains the already added racks in the provided datacenter (<paramref name="dc"/>). /// If there's no such collection for the specified datacenter, then create one. /// </summary> private static HashSet <string> GetAddedRacksInDatacenter(NetworkTopologyTokenMapContext context, string dc) { if (!context.RacksAdded.TryGetValue(dc, out var racksAddedInDc)) { context.RacksAdded[dc] = racksAddedInDc = new HashSet <string>(); } return(racksAddedInDc); }
/// <summary> /// This method doesn't guarantee that the host will be added to the skipped hosts collection. /// It will depend on whether the collection already has enough hosts to satisfy the replication factor for the host's datacenter. /// </summary> private static void TryAddToSkippedHostsCollection(NetworkTopologyTokenMapContext context, Host h, int dcRf, int dcAddedReplicas) { // We already added a replica for this rack, skip until replicas in other racks are added var remainingReplicasNeededToSatisfyRf = dcRf - dcAddedReplicas; if (context.SkippedHosts.Count < remainingReplicasNeededToSatisfyRf) { // these replicas will be added in the end after a replica has been selected for every rack context.SkippedHosts.Add(h); } }
/// <summary> /// Add replicas that were skipped before to satisfy replication factor /// </summary> /// <returns>Number of replicas added to <see cref="NetworkTopologyTokenMapContext.TokenReplicas"/> of <paramref name="context"/></returns> private static int AddSkippedHosts(NetworkTopologyTokenMapContext context, string dc, int dcRf, int dcReplicas) { var counter = 0; var length = dcRf - dcReplicas; foreach (var h in context.SkippedHosts.Where(h => h.Datacenter == dc)) { context.TokenReplicas.Add(h); if (++counter == length) { break; } } return(counter); }
private ISet <Host> ComputeReplicasForToken( IReadOnlyList <IToken> ring, IReadOnlyDictionary <IToken, Host> primaryReplicas, IReadOnlyDictionary <string, DatacenterInfo> datacenters, int i) { var context = new NetworkTopologyTokenMapContext(ring, primaryReplicas, datacenters); for (var j = 0; j < ring.Count; j++) { // wrap around if necessary var replicaIndex = (i + j) % ring.Count; var replica = primaryReplicas[ring[replicaIndex]]; var dc = replica.Datacenter; if (!_replicationFactorsMap.TryGetValue(dc, out var dcRfObj)) { continue; } var dcRf = Math.Min(dcRfObj.FullReplicas, datacenters[dc].HostLength); context.ReplicasByDc.TryGetValue(dc, out var dcAddedReplicas); if (dcAddedReplicas >= dcRf) { // replication factor for the datacenter has already been satisfied continue; } var racksAddedInDc = NetworkTopologyStrategy.GetAddedRacksInDatacenter(context, dc); if (NetworkTopologyStrategy.ShouldSkipHost(context, replica, racksAddedInDc)) { NetworkTopologyStrategy.TryAddToSkippedHostsCollection(context, replica, dcRf, dcAddedReplicas); continue; } NetworkTopologyStrategy.AddReplica(context, replica, dcRf, dcAddedReplicas, racksAddedInDc); if (NetworkTopologyStrategy.AreReplicationFactorsSatisfied(_replicationFactorsMap, context.ReplicasByDc, datacenters)) { break; } } return(context.TokenReplicas); }
/// <summary> /// Adds replica (<paramref name="host"/>) to <see cref="NetworkTopologyTokenMapContext.TokenReplicas"/> of <paramref name="context"/> /// and adds skipped hosts if a replica has been added to every rack in datacenter the host's datacenter. /// </summary> private static void AddReplica(NetworkTopologyTokenMapContext context, Host host, int dcRf, int dcAddedReplicas, HashSet <string> racksPlacedInDc) { var dc = host.Datacenter; if (context.TokenReplicas.Add(host)) { dcAddedReplicas++; } context.ReplicasByDc[dc] = dcAddedReplicas; var rackAdded = host.Rack != null && racksPlacedInDc.Add(host.Rack); var allRacksPlacedInDc = racksPlacedInDc.Count == context.Datacenters[dc].Racks.Count; if (rackAdded && allRacksPlacedInDc) { // We finished placing all replicas for all racks in this dc, add the skipped hosts context.ReplicasByDc[dc] += NetworkTopologyStrategy.AddSkippedHosts(context, dc, dcRf, dcAddedReplicas); } }