From 82fcd9d85fe245e8041f8d375175dde13688fce4 Mon Sep 17 00:00:00 2001
From: Nick Sieger <nick@nicksieger.com>
Date: Wed, 6 Aug 2008 22:54:06 -0700
Subject: Clean up the code, get rid of reserve/release, add some more docs

---
 .../abstract/connection_pool.rb                    | 85 +++++++++++++---------
 1 file changed, 51 insertions(+), 34 deletions(-)

(limited to 'activerecord/lib')

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 cebff0262d..28446fd64d 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -3,7 +3,7 @@ require 'set'
 
 module ActiveRecord
   module ConnectionAdapters
-    # Connection pool API for ActiveRecord database connections.
+    # Connection pool base class and ActiveRecord database connections.
     class ConnectionPool
       # Factory method for connection pools.
       # Determines pool type to use based on contents of connection specification.
@@ -14,6 +14,7 @@ module ActiveRecord
 
       delegate :verification_timeout, :to => "::ActiveRecord::Base"
       attr_reader :spec
+
       def initialize(spec)
         @spec = spec
         # The cache of reserved connections mapped to threads
@@ -22,21 +23,35 @@ module ActiveRecord
         @connection_mutex = Monitor.new
       end
 
-      # Retrieve the connection reserved for the current thread, or call #reserve to obtain one
-      # if necessary.
-      def open_connection
+      # Retrieve the connection associated with the current thread, or call
+      # #checkout to obtain one if necessary.
+      #
+      # #connection can be called any number of times; the connection is
+      # held in a hash keyed by the thread id.
+      def connection
         if conn = @reserved_connections[active_connection_name]
           conn.verify!(verification_timeout)
           conn
         else
-          @reserved_connections[active_connection_name] = reserve
+          @reserved_connections[active_connection_name] = checkout
         end
       end
-      alias connection open_connection
 
-      def close_connection
+      # Signal that the thread is finished with the current connection.
+      # #release_thread_connection releases the connection-thread association
+      # and returns the connection to the pool.
+      def release_thread_connection
         conn = @reserved_connections.delete(active_connection_name)
-        release conn if conn
+        checkin conn if conn
+      end
+
+      # Reserve a connection, and yield it to a block. Ensure the connection is
+      # checked back in when finished.
+      def with_connection
+        conn = checkout
+        yield conn
+      ensure
+        checkin conn
       end
 
       # Returns true if a connection has already been opened.
@@ -44,22 +59,10 @@ module ActiveRecord
         !connections.empty?
       end
 
-      # Reserve (check-out) a database connection for the current thread.
-      def reserve
-        raise NotImplementedError, "reserve is an abstract method"
-      end
-      alias checkout reserve
-
-      # Release (check-in) a database connection for the current thread.
-      def release(connection)
-        raise NotImplementedError, "release is an abstract method"
-      end
-      alias checkin release
-
       # Disconnect all connections in the pool.
       def disconnect!
         @reserved_connections.each do |name,conn|
-          release(conn)
+          checkin conn
         end
         connections.each do |conn|
           conn.disconnect!
@@ -70,7 +73,7 @@ module ActiveRecord
       # Clears the cache which maps classes
       def clear_reloadable_connections!
         @reserved_connections.each do |name, conn|
-          release(conn)
+          checkin conn
         end
         @reserved_connections = {}
         connections.each do |conn|
@@ -84,30 +87,42 @@ module ActiveRecord
       # Verify active connections.
       def verify_active_connections! #:nodoc:
         remove_stale_cached_threads!(@reserved_connections) do |name, conn|
-          release(conn)
+          checkin conn
         end
         connections.each do |connection|
           connection.verify!(verification_timeout)
         end
       end
 
-      synchronize :open_connection, :close_connection, :reserve, :release,
-        :clear_reloadable_connections!, :verify_active_connections!,
-        :connected?, :disconnect!, :with => :@connection_mutex
+      # Check-out a database connection from the pool.
+      def checkout
+        raise NotImplementedError, "checkout is an abstract method"
+      end
 
-      private
-      def active_connection_name #:nodoc:
-        Thread.current.object_id
+      # Check-in a database connection back into the pool.
+      def checkin(connection)
+        raise NotImplementedError, "checkin is an abstract method"
       end
 
       def remove_connection(conn)
         raise NotImplementedError, "remove_connection is an abstract method"
       end
+      private :remove_connection
 
       # Array containing all connections (reserved or available) in the pool.
       def connections
         raise NotImplementedError, "connections is an abstract method"
       end
+      private :connections
+
+      synchronize :connection, :release_thread_connection, :checkout, :checkin,
+        :clear_reloadable_connections!, :verify_active_connections!,
+        :connected?, :disconnect!, :with => :@connection_mutex
+
+      private
+      def active_connection_name #:nodoc:
+        Thread.current.object_id
+      end
 
       # Remove stale threads from the cache.
       def remove_stale_cached_threads!(cache, &block)
@@ -131,11 +146,11 @@ module ActiveRecord
 
       def active_connections; @reserved_connections; end
 
-      def reserve
+      def checkout
         new_connection
       end
 
-      def release(conn)
+      def checkin(conn)
         conn.disconnect!
       end
 
@@ -168,7 +183,8 @@ module ActiveRecord
         @connection_pools[name] = ConnectionAdapters::ConnectionPool.create(spec)
       end
 
-      # for internal use only and for testing
+      # for internal use only and for testing;
+      # only works with ConnectionPerThread pool class
       def active_connections #:nodoc:
         @connection_pools.inject({}) do |hash,kv|
           hash[kv.first] = kv.last.active_connection
@@ -179,7 +195,7 @@ module ActiveRecord
 
       # Clears the cache which maps classes to connections.
       def clear_active_connections!
-        @connection_pools.each_value {|pool| pool.close_connection }
+        @connection_pools.each_value {|pool| pool.release_thread_connection }
       end
 
       # Clears the cache which maps classes
@@ -205,7 +221,8 @@ module ActiveRecord
         (pool && pool.connection) or raise ConnectionNotEstablished
       end
 
-      # Returns true if a connection that's accessible to this class has already been opened.
+      # Returns true if a connection that's accessible to this class has
+      # already been opened.
       def connected?(klass)
         retrieve_connection_pool(klass).connected?
       end
-- 
cgit v1.2.3