/// <summary>Chooses datanode locations for caching from a list of valid possibilities. /// </summary> /// <remarks> /// Chooses datanode locations for caching from a list of valid possibilities. /// Non-stale nodes are chosen before stale nodes. /// </remarks> /// <param name="possibilities">List of candidate datanodes</param> /// <param name="neededCached">Number of replicas needed</param> /// <param name="staleInterval">Age of a stale datanode</param> /// <returns>A list of chosen datanodes</returns> private static IList <DatanodeDescriptor> ChooseDatanodesForCaching(IList <DatanodeDescriptor > possibilities, int neededCached, long staleInterval) { // Make a copy that we can modify IList <DatanodeDescriptor> targets = new AList <DatanodeDescriptor>(possibilities); // Selected targets IList <DatanodeDescriptor> chosen = new List <DatanodeDescriptor>(); // Filter out stale datanodes IList <DatanodeDescriptor> stale = new List <DatanodeDescriptor>(); IEnumerator <DatanodeDescriptor> it = targets.GetEnumerator(); while (it.HasNext()) { DatanodeDescriptor d = it.Next(); if (d.IsStale(staleInterval)) { it.Remove(); stale.AddItem(d); } } // Select targets while (chosen.Count < neededCached) { // Try to use stale nodes if we're out of non-stale nodes, else we're done if (targets.IsEmpty()) { if (!stale.IsEmpty()) { targets = stale; } else { break; } } // Select a random target DatanodeDescriptor target = ChooseRandomDatanodeByRemainingCapacity(targets); chosen.AddItem(target); targets.Remove(target); } return(chosen); }