提交 72d959d9 编写于 作者: N Nick Sieger

Split connection handler into single- and multiple-thread versions.

上级 ff97e9d0
......@@ -134,18 +134,17 @@ def clear_entries!(cache, keys, &block)
end
end
class ConnectionHandler
attr_reader :connection_pools_lock
module ConnectionHandlerMethods
def initialize(pools = {})
@connection_pools = pools
end
def initialize
@connection_pools = {}
@connection_pools_lock = Monitor.new
def connection_pools
@connection_pools ||= {}
end
def establish_connection(name, spec)
connection_pools_lock.synchronize do
@connection_pools[name] = ConnectionAdapters::ConnectionPool.new(spec)
end
@connection_pools[name] = ConnectionAdapters::ConnectionPool.new(spec)
end
# for internal use only and for testing
......@@ -168,7 +167,7 @@ def clear_reloadable_connections!
end
def clear_all_connections!
clear_cache!(@connection_pools) {|name, pool| pool.disconnect! }
@connection_pools.each_value {|pool| pool.disconnect! }
end
# Verify active connections.
......@@ -185,15 +184,6 @@ def retrieve_connection(klass) #:nodoc:
(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?
......@@ -210,16 +200,40 @@ def remove_connection(klass)
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
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
end
# This connection handler is not thread-safe, as it does not protect access
# to the underlying connection pools.
class SingleThreadConnectionHandler
include ConnectionHandlerMethods
end
# This connection handler is thread-safe. Each access or modification of a thread
# pool is synchronized by an internal monitor.
class MultipleThreadConnectionHandler
attr_reader :connection_pools_lock
include ConnectionHandlerMethods
def initialize(pools = {})
super
@connection_pools_lock = Monitor.new
end
# Apply monitor to all public methods that access the pool.
synchronize :establish_connection, :retrieve_connection,
:connected?, :remove_connection, :active_connections,
:clear_active_connections!, :clear_reloadable_connections!,
:clear_all_connections!, :verify_active_connections!,
:with => :connection_pools_lock
end
end
end
\ No newline at end of file
......@@ -14,12 +14,24 @@ def initialize (config, adapter_method)
# The connection handler
cattr_accessor :connection_handler, :instance_writer => false
@@connection_handler = ConnectionAdapters::ConnectionHandler.new
@@connection_handler = ConnectionAdapters::SingleThreadConnectionHandler.new
# 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.
# Turning on allow_concurrency changes the single threaded connection handler
# for a multiple threaded one, so that multi-threaded access of the
# connection pools is synchronized.
def self.allow_concurrency=(flag)
@@allow_concurrency = flag
if @@allow_concurrency != flag
@@allow_concurrency = flag
# When switching connection handlers, preserve the existing pools so that
# #establish_connection doesn't need to be called again.
if @@allow_concurrency
self.connection_handler = ConnectionAdapters::MultipleThreadConnectionHandler.new(
self.connection_handler.connection_pools)
else
self.connection_handler = ConnectionAdapters::SingleThreadConnectionHandler.new(
self.connection_handler.connection_pools)
end
end
end
# Returns the connection currently associated with the class. This can
......@@ -112,7 +124,7 @@ def connected?
connection_handler.connected?(self)
end
def remove_connection(klass=self)
def remove_connection(klass = self)
connection_handler.remove_connection(klass)
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册