From c25b1f1585d4ab1d13e5f710c33d218d47d4353a Mon Sep 17 00:00:00 2001 From: Kyle Banker Date: Mon, 5 Dec 2011 12:27:19 -0500 Subject: [PATCH] RUBY-376 separate original seeds nodes from discovered ones --- lib/mongo/repl_set_connection.rb | 27 +++++++++----------- lib/mongo/util/pool_manager.rb | 42 ++++++++++++++++++++++---------- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/lib/mongo/repl_set_connection.rb b/lib/mongo/repl_set_connection.rb index d2a160c..20bd1e2 100644 --- a/lib/mongo/repl_set_connection.rb +++ b/lib/mongo/repl_set_connection.rb @@ -91,8 +91,10 @@ module Mongo raise MongoArgumentError, "A ReplSetConnection requires at least one seed node." end - # The list of seed nodes + # The original, immutable list of seed node. + # TODO: add a method for replacing this list of node. @seeds = args + @seeds.freeze # TODO: get rid of this @nodes = @seeds.dup @@ -152,11 +154,12 @@ module Mongo def connect log(:info, "Connecting...") return if @connected - manager = PoolManager.new(self, @seeds) - @manager = manager - manager.connect - update_config(manager) + discovered_seeds = @manager ? @manager.seeds : [] + @manager = PoolManager.new(self, discovered_seeds) + + @manager.connect + @refresh_version += 1 if @require_primary && self.primary.nil? #TODO: in v2.0, we'll let this be optional and do a lazy connect. close @@ -201,13 +204,15 @@ module Mongo # to get the refresh lock. def hard_refresh! log(:info, "Initiating hard refresh...") - background_manager = PoolManager.new(self, @seeds) + discovered_seeds = @manager ? @manager.seeds : [] + background_manager = PoolManager.new(self, discovered_seeds | @original_seeds) background_manager.connect # TODO: make sure that connect has succeeded old_manager = @manager - update_config(background_manager) + @manager = background_manager old_manager.close(:soft => true) + @refresh_version += 1 return true end @@ -479,14 +484,6 @@ module Mongo connect if should_connect end - # Given a pool manager, update this connection's - # view of the replica set. - def update_config(new_manager) - @manager = new_manager - @seeds = @manager.seeds.dup - @refresh_version += 1 - end - # Checkout a socket connected to a node with one of # the provided tags. If no such node exists, raise # an exception. diff --git a/lib/mongo/util/pool_manager.rb b/lib/mongo/util/pool_manager.rb index 65faf84..6654cfd 100644 --- a/lib/mongo/util/pool_manager.rb +++ b/lib/mongo/util/pool_manager.rb @@ -1,15 +1,22 @@ module Mongo class PoolManager - attr_reader :connection, :seeds, :arbiters, :primary, :secondaries, - :primary_pool, :read_pool, :secondary_pools, :hosts, :nodes, :max_bson_size, + attr_reader :connection, :arbiters, :primary, :secondaries, :primary_pool, + :read_pool, :secondary_pools, :hosts, :nodes, :max_bson_size, :tags_to_pools, :tag_map, :members - def initialize(connection, seeds) + # Create a new set of connection pools. + # + # The pool manager will by default use the original seed list passed + # to the connection objects, accessible via connection.seeds. In addition, + # the user may pass an additional list of seeds nodes discovered in real + # time. The union of these lists will be used when attempting to connect, + # with the newly-discovered nodes being used first. + def initialize(connection, seeds=[]) @connection = connection + @original_seeds = connection.seeds @seeds = seeds @previously_connected = false - @refresh_required = false end def inspect @@ -17,14 +24,12 @@ module Mongo end def connect - if @previously_connected - close - end + close if @previously_connected initialize_data members = connect_to_members initialize_pools(members) - update_seed_list(members) + cache_discovered_seeds(members) set_read_pool set_tag_mappings @@ -35,7 +40,7 @@ module Mongo # We're healthy if all members are pingable and if the view # of the replica set returned by isMaster is equivalent # to our view. If any of these isn't the case, - # set @refresh_require to true, and return. + # set @refresh_required to true, and return. def check_connection_health begin seed = get_valid_seed_node @@ -101,6 +106,12 @@ module Mongo end end + # The set of nodes that this class has discovered and + # successfully connected to. + def seeds + @seeds + end + private def validate_existing_member(member) @@ -124,6 +135,7 @@ module Mongo end def initialize_data + @seeds = [] @primary = nil @primary_pool = nil @read_pool = nil @@ -134,6 +146,7 @@ module Mongo @members = Set.new @tags_to_pools = {} @tag_map = {} + @refresh_required = false end # Connect to each member of the replica set @@ -255,7 +268,7 @@ module Mongo # # If we don't get a response, raise an exception. def get_valid_seed_node - @seeds.each do |seed| + seed_list.each do |seed| node = Mongo::Node.new(self.connection, seed) if !node.connect next @@ -270,9 +283,12 @@ module Mongo "#{@seeds.map {|s| "#{s[0]}:#{s[1]}" }.join(', ')}" end - def update_seed_list(members) - current_members = members.map { |n| n.host_port } - @seeds = (current_members + @seeds).uniq + def seed_list + @seeds | @original_seeds + end + + def cache_discovered_seeds(members) + @seeds = members.map { |n| n.host_port } end end