/// <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);
            }
        }