class ActiveRecord::ConnectionAdapters::ConnectionHandler

determine the connection pool that they should use.
ActiveRecord::Base.connection_handler. Active Record models use this to
Normally there is only a single ConnectionHandler instance, accessible via
is not the same as the one used by Book/ScaryBook/GoodBook.
same connection pool. However, the connection pool used by Author/BankAccount
the same connection pool. Likewise, Author and BankAccount will use the
than the default database). Then Book, ScaryBook and GoodBook will all use
Suppose that Book is to connect to a separate database (i.e. one other
+– BankAccount
+– Author
| +– GoodBook
| +– ScaryBook
| |
+– Book
|
For example, suppose that you have 5 models, with the following hierarchy:
to different databases.
for keeping separate connection pools for Active Record models that connect
ConnectionHandler is a collection of ConnectionPool objects. It is used

def active_connections?

pools that the ConnectionHandler is managing.
Returns true if there are any active connections among the connection
def active_connections?
  connection_pool_list.any?(&:active_connection?)
end

def class_to_pool

def class_to_pool
  @class_to_pool[Process.pid]
end

def clear_active_connections!

longer alive.
and also returns connections to the pool cached by threads that are no
Returns any connections in use by the current thread back to the pool,
def clear_active_connections!
  connection_pool_list.each(&:release_connection)
end

def clear_all_connections!

def clear_all_connections!
  connection_pool_list.each(&:disconnect!)
end

def clear_reloadable_connections!

Clears the cache which maps classes.
def clear_reloadable_connections!
  connection_pool_list.each(&:clear_reloadable_connections!)
end

def connected?(klass)

already been opened.
Returns true if a connection that's accessible to this class has
def connected?(klass)
  conn = retrieve_connection_pool(klass)
  conn && conn.connected?
end

def connection_pool_list

def connection_pool_list
  owner_to_pool.values.compact
end

def connection_pools

def connection_pools
  ActiveSupport::Deprecation.warn(
    "In the next release, this will return the same as #connection_pool_list. " \
    "(An array of pools, rather than a hash mapping specs to pools.)"
  )
  Hash[connection_pool_list.map { |pool| [pool.spec, pool] }]
end

def establish_connection(owner, spec)

def establish_connection(owner, spec)
  @class_to_pool.clear
  raise RuntimeError, "Anonymous class is not allowed." unless owner.name
  owner_to_pool[owner.name] = ConnectionAdapters::ConnectionPool.new(spec)
end

def initialize

def initialize
  # These caches are keyed by klass.name, NOT klass. Keying them by klass
  # alone would lead to memory leaks in development mode as all previous
  # instances of the class would stay in memory.
  @owner_to_pool = ThreadSafe::Cache.new(:initial_capacity => 2) do |h,k|
    h[k] = ThreadSafe::Cache.new(:initial_capacity => 2)
  end
  @class_to_pool = ThreadSafe::Cache.new(:initial_capacity => 2) do |h,k|
    h[k] = ThreadSafe::Cache.new
  end
end

def owner_to_pool

def owner_to_pool
  @owner_to_pool[Process.pid]
end

def pool_for(owner)

def pool_for(owner)
  owner_to_pool.fetch(owner.name) {
    if ancestor_pool = pool_from_any_process_for(owner)
      # A connection was established in an ancestor process that must have
      # subsequently forked. We can't reuse the connection, but we can copy
      # the specification and establish a new connection with it.
      establish_connection owner, ancestor_pool.spec
    else
      owner_to_pool[owner.name] = nil
    end
  }
end

def pool_from_any_process_for(owner)

def pool_from_any_process_for(owner)
  owner_to_pool = @owner_to_pool.values.find { |v| v[owner.name] }
  owner_to_pool && owner_to_pool[owner.name]
end

def remove_connection(owner)

re-establishing the connection.
can be used as an argument for establish_connection, for easily
connection and the defined connection (if they exist). The result
Remove the connection for this class. This will close the active
def remove_connection(owner)
  if pool = owner_to_pool.delete(owner.name)
    @class_to_pool.clear
    pool.automatic_reconnect = false
    pool.disconnect!
    pool.spec.config
  end
end

def retrieve_connection(klass) #:nodoc:

:nodoc:
for (not necessarily the current class).
opened and set as the active connection for the class it was defined
active or defined connection: if it is the latter, it will be
Locate the connection of the nearest super class. This can be an
def retrieve_connection(klass) #:nodoc:
  pool = retrieve_connection_pool(klass)
  (pool && pool.connection) or raise ConnectionNotEstablished
end

def retrieve_connection_pool(klass)

to optimise for.
take place, but that's ok since the nil case is not the common one that we wish
#fetch is significantly slower than #[]. So in the nil case, no caching will
However, benchmarking (https://gist.github.com/jonleighton/3552829) showed that
Ideally we would use #fetch here, as class_to_pool[klass] may sometimes be nil.

When a connection is established or removed, we invalidate the cache.
This makes retrieving the connection pool O(1) once the process is warm.
Retrieving the connection pool happens a lot so we cache it in @class_to_pool.
def retrieve_connection_pool(klass)
  class_to_pool[klass.name] ||= begin
    until pool = pool_for(klass)
      klass = klass.superclass
      break unless klass <= Base
    end
    class_to_pool[klass.name] = pool
  end
end