0
@@ -14,156 +14,45 @@ module ActiveRecord
0
cattr_accessor :verification_timeout, :instance_writer => false
0
@@verification_timeout = 0
0
- # The class ->
[adapter_method, config] map
0
+ # The class ->
connection pool map
0
@@defined_connections = {}
0
- # The class -> thread id -> adapter cache. (class -> adapter if not allow_concurrency)
0
- @@active_connections = {}
0
- # Retrieve the connection cache.
0
- def thread_safe_active_connections #:nodoc:
0
- @@active_connections[Thread.current.object_id] ||= {}
0
- def single_threaded_active_connections #:nodoc:
0
- # pick up the right active_connection method from @@allow_concurrency
0
- if @@allow_concurrency
0
- alias_method :active_connections, :thread_safe_active_connections
0
- alias_method :active_connections, :single_threaded_active_connections
0
- # set concurrency support flag (not thread safe, like most of the methods in this file)
0
- def allow_concurrency=(threaded) #:nodoc:
0
- logger.debug "allow_concurrency=#{threaded}" if logger
0
- return if @@allow_concurrency == threaded
0
- clear_all_cached_connections!
0
- @@allow_concurrency = threaded
0
- method_prefix = threaded ? "thread_safe" : "single_threaded"
0
- sing = (class << self; self; end)
0
- [:active_connections, :scoped_methods].each do |method|
0
- sing.send(:alias_method, method, "#{method_prefix}_#{method}")
0
- log_connections if logger
0
- def active_connection_name #:nodoc:
0
- @active_connection_name ||=
0
- if active_connections[name] || @@defined_connections[name]
0
- elsif self == ActiveRecord::Base
0
- superclass.active_connection_name
0
- def clear_active_connection_name #:nodoc:
0
- @active_connection_name = nil
0
- subclasses.each { |klass| klass.clear_active_connection_name }
0
+ # for internal use only
0
+ def active_connections
0
+ @@defined_connections.inject([]) {|arr,kv| arr << kv.last.active_connection}.compact.uniq
0
# Returns the connection currently associated with the class. This can
0
# also be used to "borrow" the connection to do database work unrelated
0
# to any of the specific Active Records.
0
- if defined?(@active_connection_name) && (conn = active_connections[@active_connection_name])
0
- # retrieve_connection sets the cache key.
0
- conn = retrieve_connection
0
- active_connections[@active_connection_name] = conn
0
# Clears the cache which maps classes to connections.
0
def clear_active_connections!
0
- clear_cache!(@@active_connections) do |name, conn|
0
+ clear_cache!(@@defined_connections) do |name, pool|
0
# Clears the cache which maps classes
0
def clear_reloadable_connections!
0
- if @@allow_concurrency
0
- # With concurrent connections @@active_connections is
0
- # a hash keyed by thread id.
0
- @@active_connections.each do |thread_id, conns|
0
- conns.each do |name, conn|
0
- if conn.requires_reloading?
0
- @@active_connections[thread_id].delete(name)
0
- @@active_connections.each do |name, conn|
0
- if conn.requires_reloading?
0
- @@active_connections.delete(name)
0
+ clear_cache!(@@defined_connections) do |name, pool|
0
+ pool.clear_reloadable_connections!
0
# Verify active connections.
0
def verify_active_connections! #:nodoc:
0
- if @@allow_concurrency
0
- remove_stale_cached_threads!(@@active_connections) do |name, conn|
0
- active_connections.each_value do |connection|
0
- connection.verify!(@@verification_timeout)
0
+ @@defined_connections.each_value {|pool| pool.verify_active_connections!}
0
- def clear_cache!(cache, thread_id = nil, &block)
0
- if @@allow_concurrency
0
- thread_id ||= Thread.current.object_id
0
- thread_cache, cache = cache, cache[thread_id]
0
- cache.each(&block) if block_given?
0
- if thread_cache && @@allow_concurrency
0
- thread_cache.delete(thread_id)
0
- # Remove stale threads from the cache.
0
- def remove_stale_cached_threads!(cache, &block)
0
- stale = Set.new(cache.keys)
0
- Thread.list.each do |thread|
0
- stale.delete(thread.object_id) if thread.alive?
0
- stale.each do |thread_id|
0
- clear_cache!(cache, thread_id, &block)
0
- def clear_all_cached_connections!
0
- if @@allow_concurrency
0
- @@active_connections.each_value do |connection_hash_for_thread|
0
- connection_hash_for_thread.each_value {|conn| conn.disconnect! }
0
- connection_hash_for_thread.clear
0
- @@active_connections.each_value {|conn| conn.disconnect! }
0
- @@active_connections.clear
0
+ def clear_cache!(cache, &block)
0
+ cache.each(&block) if block_given?
0
@@ -208,9 +97,7 @@ module ActiveRecord
0
raise AdapterNotSpecified unless defined? RAILS_ENV
0
establish_connection(RAILS_ENV)
0
when ConnectionSpecification
0
- clear_active_connection_name
0
- @active_connection_name = name
0
- @@defined_connections[name] = spec
0
+ @@defined_connections[name] = ConnectionAdapters::ConnectionPool.new(spec)
0
if configuration = configurations[spec.to_s]
0
establish_connection(configuration)
0
@@ -248,26 +135,20 @@ module ActiveRecord
0
# opened and set as the active connection for the class it was defined
0
# for (not necessarily the current class).
0
def self.retrieve_connection #:nodoc:
0
- # Name is nil if establish_connection hasn't been called for
0
- # some class along the inheritance chain up to AR::Base yet.
0
- if name = active_connection_name
0
- if conn = active_connections[name]
0
- # Verify the connection.
0
- conn.verify!(@@verification_timeout)
0
- elsif spec = @@defined_connections[name]
0
- # Activate this connection specification.
0
- klass = name.constantize
0
- klass.connection = spec
0
- conn = active_connections[name]
0
+ pool = retrieve_connection_pool
0
+ (pool && pool.connection) or raise ConnectionNotEstablished
0
- conn or raise ConnectionNotEstablished
0
+ def self.retrieve_connection_pool
0
+ pool = @@defined_connections[name]
0
+ return nil if ActiveRecord::Base == self
0
+ superclass.retrieve_connection_pool
0
# Returns true if a connection that's accessible to this class has already been opened.
0
-
active_connections[active_connection_name] ? true : false0
+
retrieve_connection_pool.connected?0
# Remove the connection for this class. This will close the active
0
@@ -275,35 +156,10 @@ module ActiveRecord
0
# can be used as an argument for establish_connection, for easily
0
# re-establishing the connection.
0
def self.remove_connection(klass=self)
0
- spec = @@defined_connections[klass.name]
0
- konn = active_connections[klass.name]
0
- @@defined_connections.delete_if { |key, value| value == spec }
0
- active_connections.delete_if { |key, value| value == konn }
0
- konn.disconnect! if konn
0
- # Set the connection for the class.
0
- def self.connection=(spec) #:nodoc:
0
- if spec.kind_of?(ActiveRecord::ConnectionAdapters::AbstractAdapter)
0
- active_connections[name] = spec
0
- elsif spec.kind_of?(ConnectionSpecification)
0
- config = spec.config.reverse_merge(:allow_concurrency => @@allow_concurrency)
0
- self.connection = self.send(spec.adapter_method, config)
0
- raise ConnectionNotEstablished
0
- establish_connection spec
0
- # connection state logging
0
- def self.log_connections #:nodoc:
0
- logger.info "Defined connections: #{@@defined_connections.inspect}"
0
- logger.info "Active connections: #{active_connections.inspect}"
0
- logger.info "Active connection name: #{@active_connection_name}"
0
+ pool = @@defined_connections[klass.name]
0
+ @@defined_connections.delete_if { |key, value| value == pool }
0
+ pool.disconnect! if pool
0
+ pool.spec.config if pool