Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 3693

Show
Ignore:
Timestamp:
02/27/06 21:37:30 (4 years ago)
Author:
bitsweat
Message:

Speed up class -> connection caching and stale connection verification. Closes #3979.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r3691 r3693  
    11*SVN* 
     2 
     3* Speed up class -> connection caching and stale connection verification.  #3979 [Stefan Kaes] 
    24 
    35* Add set_fixture_class to allow the use of table name accessors with models which use set_table_name. [Kevin Clark] 
  • trunk/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb

    r3674 r3693  
    2222      include Quoting, DatabaseStatements, SchemaStatements 
    2323      @@row_even = true 
    24  
     24       
    2525      def initialize(connection, logger = nil) #:nodoc: 
    2626        @connection, @logger = connection, logger 
    2727        @runtime = 0 
     28        @last_verification = 0 
    2829      end 
    2930 
     
    7778      end 
    7879 
     80      # Lazily verify this connection, calling +active?+ only if it hasn't 
     81      # been called for +timeout+ seconds.        
     82      def verify!(timeout) 
     83        now = Time.now.to_i 
     84        if (now - @last_verification) > timeout 
     85          reconnect! unless active? 
     86          @last_verification = now 
     87        end 
     88      end 
    7989 
    8090      protected 
     
    96106        rescue Exception => e 
    97107          # Log message and raise exception. 
     108          # Set last_verfication to 0, so that connection gets verified 
     109          # upon reentering the request loop 
     110          @last_verification = 0 
    98111          message = "#{e.class.name}: #{e.message}: #{sql}" 
    99112          log_info(message, name, 0) 
  • trunk/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb

    r3674 r3693  
    88    end 
    99 
     10    # Check connections for active? after +@@connection_cache_timeout+ seconds 
     11    # defaults to 5 minutes 
     12    cattr_accessor :connection_cache_timeout 
     13    @@connection_cache_timeout = 300 
     14     
    1015    # The class -> [adapter_method, config] map 
    1116    @@defined_connections = {} 
    1217 
    13     # The class -> thread id -> adapter cache. 
    14     @@connection_cache = Hash.new { |h, k| h[k] = Hash.new } 
    15  
     18    # The class -> thread id -> adapter cache. (class -> adapter if not allow_concurrency) 
     19    @@connection_cache = {} 
     20 
     21    # retrieve the connection cache 
     22    def self.connection_cache 
     23      if @@allow_concurrency 
     24        @@connection_cache[Thread.current.object_id] ||= {} 
     25      else 
     26        @@connection_cache 
     27      end 
     28    end 
     29     
     30    @connection_cache_key = nil 
     31    def self.connection_cache_key 
     32      @connection_cache_key ||= 
     33         if active_connections[name] || @@defined_connections[name] 
     34           name 
     35         elsif self == ActiveRecord::Base 
     36           nil 
     37         else 
     38           superclass.connection_cache_key 
     39         end 
     40    end 
     41     
     42    def self.clear_connection_cache_key 
     43      @connection_cache_key = nil 
     44      subclasses.each{|klass| klass.clear_connection_cache_key } 
     45    end 
     46     
    1647    # Returns the connection currently associated with the class. This can 
    1748    # also be used to "borrow" the connection to do database work unrelated 
    1849    # to any of the specific Active Records. 
    1950    def self.connection 
    20       @@connection_cache[Thread.current.object_id][name] ||= retrieve_connection 
     51      if (cache_key = @connection_cache_key) && (conn = connection_cache[cache_key]) 
     52        conn 
     53      else 
     54        conn = retrieve_connection # this will set @connection_cache_key 
     55        connection_cache[@connection_cache_key] = conn 
     56      end 
    2157    end 
    2258 
    2359    # Clears the cache which maps classes to connections. 
    2460    def self.clear_connection_cache! 
    25       @@connection_cache.clear 
    26     end 
    27  
     61      if @@allow_concurrency 
     62        @@connection_cache.delete(Thread.current.object_id) 
     63      else 
     64        @@connection_cache = {} 
     65      end 
     66    end 
     67    
     68    # Verify connection cache. 
     69    def self.verify_connection_cache! 
     70      timeout = @@connection_cache_timeout 
     71      connection_cache.each_value { |connection| connection.verify!(timeout) } 
     72    end 
     73    
    2874    # Returns the connection currently associated with the class. This can 
    2975    # also be used to "borrow" the connection to do database work that isn't 
     
    66112          establish_connection(RAILS_ENV) 
    67113        when ConnectionSpecification 
     114          clear_connection_cache_key 
     115          @connection_cache_key = name  
    68116          @@defined_connections[name] = spec 
    69117        when Symbol, String 
     
    84132 
    85133    def self.active_connections #:nodoc: 
    86       if allow_concurrency 
     134      if @@allow_concurrency 
    87135        Thread.current['active_connections'] ||= {} 
    88136      else 
     
    96144    # for (not necessarily the current class). 
    97145    def self.retrieve_connection #:nodoc: 
    98       klass = self 
    99       ar_super = ActiveRecord::Base.superclass 
    100       until klass == ar_super 
    101         if conn = active_connections[klass.name] 
    102           # Reconnect if the connection is inactive. 
    103           conn.reconnect! unless conn.active? 
    104           return conn 
    105         elsif conn = @@defined_connections[klass.name] 
    106           # Activate this connection specification. 
    107           klass.connection = conn 
    108           return self.connection 
    109         end 
    110         klass = klass.superclass 
    111       end 
    112       raise ConnectionNotEstablished 
     146      cache_key = connection_cache_key 
     147      # cache_key is nil if establish_connection hasn't been called for 
     148      # some class along the inheritance chain up to AR::Base yet 
     149      raise ConnectionNotEstablished unless cache_key 
     150      if conn = active_connections[cache_key] 
     151        # Verify the connection. 
     152        conn.verify!(@@connection_cache_timeout) 
     153        return conn 
     154      elsif conn = @@defined_connections[cache_key] 
     155        # Activate this connection specification. 
     156        klass = cache_key.constantize 
     157        klass.connection = conn 
     158        return active_connections[cache_key] 
     159      else 
     160        raise ConnectionNotEstablished 
     161      end 
    113162    end 
    114163 
    115164    # Returns true if a connection that's accessible to this class have already been opened. 
    116165    def self.connected? 
    117       klass = self 
    118       until klass == ActiveRecord::Base.superclass 
    119         if active_connections[klass.name] 
    120           return true 
    121         else 
    122           klass = klass.superclass 
    123         end 
    124       end 
    125       return false 
     166      active_connections[connection_cache_key] ? true : false 
    126167    end 
    127168 
     
    134175      konn = active_connections[klass.name] 
    135176      @@defined_connections.delete_if { |key, value| value == spec } 
    136       @@connection_cache[Thread.current.object_id].delete_if { |key, value| value == konn } 
     177      connection_cache.delete_if { |key, value| value == konn } 
    137178      active_connections.delete_if { |key, value| value == konn } 
    138179      konn.disconnect! if konn 
     
    152193      end 
    153194    end 
     195       
     196    # connection state logging 
     197    def self.log_connections 
     198      if logger 
     199        logger.info "Defined connections: #{@@defined_connections.inspect}" 
     200        logger.info "Active connections: #{active_connections.inspect}" 
     201        logger.info "Connection cache: #{connection_cache.inspect}" 
     202        logger.info "Connection cache key: #{@connection_cache_key}" 
     203      end 
     204    end 
    154205  end 
    155206end 
  • trunk/railties/lib/dispatcher.rb

    r3526 r3693  
    6868        prepare_breakpoint 
    6969        require_dependency('application.rb') unless Object.const_defined?(:ApplicationController) 
     70        ActiveRecord::Base.verify_connection_cache! 
    7071      end 
    7172     
    7273      def reset_after_dispatch 
    7374        reset_application! if Dependencies.load? 
    74         ActiveRecord::Base.clear_connection_cache! 
    7575        Breakpoint.deactivate_drb if defined?(BREAKPOINT_SERVER_PORT) 
     76        # ActiveRecord::Base.clear_connection_cache! 
    7677      end 
    7778