From ff97e9d029d6164fa2e921a5d0acab13f39058b0 Mon Sep 17 00:00:00 2001 From: Nick Sieger Date: Sat, 7 Jun 2008 00:30:15 -0500 Subject: Connection handling methods extracted out into separate ConnectionHandler class - delegating methods left behind --- .../abstract/connection_pool.rb | 89 ++++++++++++++ .../abstract/connection_specification.rb | 131 +++++---------------- .../connection_adapters/abstract_adapter.rb | 2 +- 3 files changed, 117 insertions(+), 105 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index 08fc61daaa..01a75365d3 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -1,3 +1,4 @@ +require 'monitor' require 'set' module ActiveRecord @@ -132,5 +133,93 @@ module ActiveRecord end end end + + class ConnectionHandler + attr_reader :connection_pools_lock + + def initialize + @connection_pools = {} + @connection_pools_lock = Monitor.new + end + + def establish_connection(name, spec) + connection_pools_lock.synchronize do + @connection_pools[name] = ConnectionAdapters::ConnectionPool.new(spec) + end + end + + # for internal use only and for testing + def active_connections #:nodoc: + @connection_pools.inject({}) do |hash,kv| + hash[kv.first] = kv.last.active_connection + hash.delete(kv.first) unless hash[kv.first] + hash + end + end + + # Clears the cache which maps classes to connections. + def clear_active_connections! + @connection_pools.each_value {|pool| pool.clear_active_connections! } + end + + # Clears the cache which maps classes + def clear_reloadable_connections! + @connection_pools.each_value {|pool| pool.clear_reloadable_connections! } + end + + def clear_all_connections! + clear_cache!(@connection_pools) {|name, pool| pool.disconnect! } + end + + # Verify active connections. + def verify_active_connections! #:nodoc: + @connection_pools.each_value {|pool| pool.verify_active_connections!} + end + + # Locate the connection of the nearest super class. This can be an + # active or defined connection: if it is the latter, it will be + # opened and set as the active connection for the class it was defined + # for (not necessarily the current class). + def retrieve_connection(klass) #:nodoc: + pool = retrieve_connection_pool(klass) + (pool && pool.connection) or raise ConnectionNotEstablished + end + + def retrieve_connection_pool(klass) + loop do + pool = @connection_pools[klass.name] + return pool if pool + return nil if ActiveRecord::Base == klass + klass = klass.superclass + end + end + + # Returns true if a connection that's accessible to this class has already been opened. + def connected?(klass) + retrieve_connection_pool(klass).connected? + end + + # Remove the connection for this class. This will close the active + # connection and the defined connection (if they exist). The result + # can be used as an argument for establish_connection, for easily + # re-establishing the connection. + def remove_connection(klass) + pool = @connection_pools[klass.name] + @connection_pools.delete_if { |key, value| value == pool } + pool.disconnect! if pool + pool.spec.config if pool + end + + synchronize :retrieve_connection, :retrieve_connection_pool, :connected?, + :remove_connection, :active_connections, :clear_active_connections!, + :clear_reloadable_connections!, :clear_all_connections!, + :verify_active_connections!, :with => :connection_pools_lock + + private + def clear_cache!(cache, &block) + cache.each(&block) if block_given? + cache.clear + end + end end end \ No newline at end of file diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb index ddca97c3bf..2dc3201208 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb @@ -1,5 +1,3 @@ -require 'monitor' - module ActiveRecord class Base class ConnectionSpecification #:nodoc: @@ -9,80 +7,19 @@ module ActiveRecord end end - class NullMonitor - def synchronize - yield - end - end - - cattr_accessor :connection_pools_lock, :instance_writer => false - @@connection_pools_lock = NullMonitor.new - # Check for activity after at least +verification_timeout+ seconds. # Defaults to 0 (always check.) cattr_accessor :verification_timeout, :instance_writer => false @@verification_timeout = 0 - # The class -> connection pool map - @@connection_pools = {} - - class << self - # Turning on allow_concurrency basically switches a null mutex for a real one, so that - # multi-threaded access of the connection pools hash is synchronized. - def allow_concurrency=(flag) - if @@allow_concurrency != flag - @@allow_concurrency = flag - if flag - self.connection_pools_lock = Monitor.new - else - self.connection_pools_lock = NullMonitor.new - end - end - end - - # for internal use only and for testing - def active_connections #:nodoc: - @@connection_pools.inject({}) do |hash,kv| - hash[kv.first] = kv.last.active_connection - hash.delete(kv.first) unless hash[kv.first] - hash - end - end - - # Returns the connection currently associated with the class. This can - # also be used to "borrow" the connection to do database work unrelated - # to any of the specific Active Records. - def connection - retrieve_connection - end - - # Clears the cache which maps classes to connections. - def clear_active_connections! - @@connection_pools.each_value {|pool| pool.clear_active_connections! } - end - - # Clears the cache which maps classes - def clear_reloadable_connections! - @@connection_pools.each_value {|pool| pool.clear_reloadable_connections! } - end + # The connection handler + cattr_accessor :connection_handler, :instance_writer => false + @@connection_handler = ConnectionAdapters::ConnectionHandler.new - def clear_all_connections! - clear_cache!(@@connection_pools) {|name, pool| pool.disconnect! } - end - - # Verify active connections. - def verify_active_connections! #:nodoc: - @@connection_pools.each_value {|pool| pool.verify_active_connections!} - end - - synchronize :active_connections, :clear_active_connections!, :clear_reloadable_connections!, - :clear_all_connections!, :verify_active_connections!, :with => :connection_pools_lock - - private - def clear_cache!(cache, &block) - cache.each(&block) if block_given? - cache.clear - end + # Turning on allow_concurrency basically switches a null mutex for a real one, so that + # multi-threaded access of the connection pools hash is synchronized. + def self.allow_concurrency=(flag) + @@allow_concurrency = flag end # Returns the connection currently associated with the class. This can @@ -126,9 +63,7 @@ module ActiveRecord raise AdapterNotSpecified unless defined? RAILS_ENV establish_connection(RAILS_ENV) when ConnectionSpecification - connection_pools_lock.synchronize do - @@connection_pools[name] = ConnectionAdapters::ConnectionPool.new(spec) - end + @@connection_handler.establish_connection(name, spec) when Symbol, String if configuration = configurations[spec.to_s] establish_connection(configuration) @@ -161,41 +96,29 @@ module ActiveRecord end end - # Locate the connection of the nearest super class. This can be an - # active or defined connection: if it is the latter, it will be - # opened and set as the active connection for the class it was defined - # for (not necessarily the current class). - def self.retrieve_connection #:nodoc: - pool = retrieve_connection_pool - (pool && pool.connection) or raise ConnectionNotEstablished - end + class << self + # Returns the connection currently associated with the class. This can + # also be used to "borrow" the connection to do database work unrelated + # to any of the specific Active Records. + def connection + retrieve_connection + end - def self.retrieve_connection_pool - pool = @@connection_pools[name] - return pool if pool - return nil if ActiveRecord::Base == self - superclass.retrieve_connection_pool - end + def retrieve_connection + connection_handler.retrieve_connection(self) + end - # Returns true if a connection that's accessible to this class has already been opened. - def self.connected? - retrieve_connection_pool.connected? - end + def connected? + connection_handler.connected?(self) + end - # Remove the connection for this class. This will close the active - # connection and the defined connection (if they exist). The result - # can be used as an argument for establish_connection, for easily - # re-establishing the connection. - def self.remove_connection(klass=self) - pool = @@connection_pools[klass.name] - @@connection_pools.delete_if { |key, value| value == pool } - pool.disconnect! if pool - pool.spec.config if pool - end + def remove_connection(klass=self) + connection_handler.remove_connection(klass) + end - class << self - synchronize :retrieve_connection, :retrieve_connection_pool, :connected?, - :remove_connection, :with => :connection_pools_lock + delegate :active_connections, :clear_active_connections!, + :clear_reloadable_connections!, :clear_all_connections!, + :verify_active_connections!, :to => :connection_handler end end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index af8cfbee7a..4b78d9f2e9 100755 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -7,8 +7,8 @@ require 'active_record/connection_adapters/abstract/schema_definitions' require 'active_record/connection_adapters/abstract/schema_statements' require 'active_record/connection_adapters/abstract/database_statements' require 'active_record/connection_adapters/abstract/quoting' -require 'active_record/connection_adapters/abstract/connection_specification' require 'active_record/connection_adapters/abstract/connection_pool' +require 'active_record/connection_adapters/abstract/connection_specification' require 'active_record/connection_adapters/abstract/query_cache' module ActiveRecord -- cgit v1.2.3