def select_server(cluster, ping = nil)
if cluster.replica_set?
validate_max_staleness_value_early!
end
if cluster.addresses.empty?
if Lint.enabled?
unless cluster.servers.empty?
raise Error::LintError, "Cluster has no addresses but has servers: #{cluster.servers.map(&:inspect).join(', ')}"
end
end
msg = "Cluster has no addresses, and therefore will never have a server"
raise Error::NoServerAvailable.new(self, cluster, msg)
end
??
@local_threshold = cluster.options[:local_threshold] || LOCAL_THRESHOLD
@server_selection_timeout = cluster.options[:server_selection_timeout] || SERVER_SELECTION_TIMEOUT
deadline = Time.now + server_selection_timeout
while (time_remaining = deadline - Time.now) > 0
servers = candidates(cluster)
if Lint.enabled?
servers.each do |server|
if server.average_round_trip_time.nil?
raise Error::LintError, "Server #{server.address} has nil average rtt"
end
end
end
if servers && !servers.compact.empty?
unless cluster.topology.compatible?
raise Error::UnsupportedFeatures, cluster.topology.compatibility_error.to_s
end
server = servers.first
if cluster.topology.single? &&
cluster.topology.replica_set_name &&
cluster.topology.replica_set_name != server.description.replica_set_name
then
msg = "Cluster topology specifies replica set name #{cluster.topology.replica_set_name}, but the server has replica set name #{server.description.replica_set_name || '<nil>'}"
raise Error::NoServerAvailable.new(self, cluster, msg)
end
return server
end
cluster.scan!(false)
if cluster.server_selection_semaphore
cluster.server_selection_semaphore.wait(time_remaining)
else
if Lint.enabled?
raise Error::LintError, 'Waiting for server selection without having a server selection semaphore'
end
sleep 0.25
end
end
msg = "No #{name} server is available in cluster: #{cluster.summary} " +
"with timeout=#{server_selection_timeout}, " +
"LT=#{local_threshold}"
dead_monitors = []
cluster.servers_list.each do |server|
thread = server.monitor.instance_variable_get('@thread')
if thread.nil? || !thread.alive?
dead_monitors << server
end
end
if dead_monitors.any?
msg += ". The following servers have dead monitor threads: #{dead_monitors.map(&:summary).join(', ')}"
end
unless cluster.connected?
msg += ". The cluster is disconnected (client may have been closed)"
end
raise Error::NoServerAvailable.new(self, cluster, msg)
end