aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb57
-rw-r--r--activerecord/lib/active_record/connection_adapters/connection_specification.rb10
-rw-r--r--activerecord/lib/active_record/connection_handling.rb34
-rw-r--r--activerecord/lib/active_record/core.rb2
4 files changed, 53 insertions, 50 deletions
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 e389d818fd..67a2ac3050 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -829,9 +829,6 @@ module ActiveRecord
@owner_to_pool = Concurrent::Map.new(:initial_capacity => 2) do |h,k|
h[k] = Concurrent::Map.new(:initial_capacity => 2)
end
- @class_to_pool = Concurrent::Map.new(:initial_capacity => 2) do |h,k|
- h[k] = Concurrent::Map.new
- end
end
def connection_pool_list
@@ -839,10 +836,8 @@ module ActiveRecord
end
alias :connection_pools :connection_pool_list
- 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)
+ def establish_connection(spec)
+ owner_to_pool[spec.id] = ConnectionAdapters::ConnectionPool.new(spec)
end
# Returns true if there are any active connections among the connection
@@ -873,18 +868,18 @@ module ActiveRecord
# active or defined connection: if it is the latter, it will be
# opened and set as the active connection for the class it was defined
# for (not necessarily the current class).
- def retrieve_connection(klass) #:nodoc:
- pool = retrieve_connection_pool(klass)
- raise ConnectionNotEstablished, "No connection pool for #{klass}" unless pool
+ def retrieve_connection(spec_id) #:nodoc:
+ pool = retrieve_connection_pool(spec_id)
+ raise ConnectionNotEstablished, "No connection pool with id #{spec_id} found." unless pool
conn = pool.connection
- raise ConnectionNotEstablished, "No connection for #{klass} in connection pool" unless conn
+ raise ConnectionNotEstablished, "No connection for #{spec_id} in connection pool" unless conn
conn
end
# Returns true if a connection that's accessible to this class has
# already been opened.
- def connected?(klass)
- conn = retrieve_connection_pool(klass)
+ def connected?(spec_id)
+ conn = retrieve_connection_pool(spec_id)
conn && conn.connected?
end
@@ -892,9 +887,8 @@ module ActiveRecord
# connection and the defined connection (if they exist). The result
# can be used as an argument for establish_connection, for easily
# re-establishing the connection.
- def remove_connection(owner)
- if pool = owner_to_pool.delete(owner.name)
- @class_to_pool.clear
+ def remove_connection(spec_id)
+ if pool = owner_to_pool.delete(spec_id)
pool.automatic_reconnect = false
pool.disconnect!
pool.spec.config
@@ -910,15 +904,8 @@ module ActiveRecord
# #fetch is significantly slower than #[]. So in the nil case, no caching will
# take place, but that's ok since the nil case is not the common one that we wish
# to optimise for.
- 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
+ def retrieve_connection_pool(spec_id)
+ pool_for(spec_id)
end
private
@@ -927,28 +914,24 @@ module ActiveRecord
@owner_to_pool[Process.pid]
end
- def class_to_pool
- @class_to_pool[Process.pid]
- end
-
- def pool_for(owner)
- owner_to_pool.fetch(owner.name) {
- if ancestor_pool = pool_from_any_process_for(owner)
+ def pool_for(spec_id)
+ owner_to_pool.fetch(spec_id) {
+ if ancestor_pool = pool_from_any_process_for(spec_id)
# 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).tap do |pool|
+ establish_connection(ancestor_pool.spec).tap do |pool|
pool.schema_cache = ancestor_pool.schema_cache if ancestor_pool.schema_cache
end
else
- owner_to_pool[owner.name] = nil
+ owner_to_pool[spec_id] = nil
end
}
end
- 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]
+ def pool_from_any_process_for(spec_id)
+ owner_to_pool = @owner_to_pool.values.find { |v| v[spec_id] }
+ owner_to_pool && owner_to_pool[spec_id]
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
index 4bc6447368..5a18e95bcd 100644
--- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
@@ -3,10 +3,10 @@ require 'uri'
module ActiveRecord
module ConnectionAdapters
class ConnectionSpecification #:nodoc:
- attr_reader :config, :adapter_method
+ attr_reader :config, :adapter_method, :id
- def initialize(config, adapter_method)
- @config, @adapter_method = config, adapter_method
+ def initialize(id, config, adapter_method)
+ @config, @adapter_method, @id = config, adapter_method, id
end
def initialize_dup(original)
@@ -164,7 +164,7 @@ module ActiveRecord
# spec.config
# # => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" }
#
- def spec(config)
+ def spec(config, id = "primary")
spec = resolve(config).symbolize_keys
raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
@@ -179,7 +179,7 @@ module ActiveRecord
end
adapter_method = "#{spec[:adapter]}_connection"
- ConnectionSpecification.new(spec, adapter_method)
+ ConnectionSpecification.new(id, spec, adapter_method)
end
private
diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb
index a8b3d03ba5..c54b8adc4e 100644
--- a/activerecord/lib/active_record/connection_handling.rb
+++ b/activerecord/lib/active_record/connection_handling.rb
@@ -45,16 +45,19 @@ module ActiveRecord
# The exceptions AdapterNotSpecified, AdapterNotFound and +ArgumentError+
# may be returned on an error.
def establish_connection(spec = nil)
+ raise RuntimeError, "Anonymous class is not allowed." unless name
+
spec ||= DEFAULT_ENV.call.to_sym
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
- spec = resolver.spec(spec)
+ spec = resolver.spec(spec, self == Base ? "primary" : name)
+ self.specification_id = spec.id
unless respond_to?(spec.adapter_method)
raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
end
remove_connection
- connection_handler.establish_connection self, spec
+ connection_handler.establish_connection spec
end
class MergeAndResolveDefaultUrlConfig # :nodoc:
@@ -87,6 +90,23 @@ module ActiveRecord
retrieve_connection
end
+ def specification_id=(value)
+ @specification_id = value
+ end
+
+ def specification_id(fallback = true)
+ return @specification_id if defined?(@specification_id)
+ find_legacy_spec_id(self) if fallback
+ end
+
+ def find_legacy_spec_id(klass)
+ return "primary" if klass == Base
+ if id = klass.specification_id(false)
+ return id
+ end
+ find_legacy_spec_id(klass.superclass)
+ end
+
def connection_id
ActiveRecord::RuntimeRegistry.connection_id ||= Thread.current.object_id
end
@@ -106,20 +126,20 @@ module ActiveRecord
end
def connection_pool
- connection_handler.retrieve_connection_pool(self) or raise ConnectionNotEstablished
+ connection_handler.retrieve_connection_pool(specification_id) or raise ConnectionNotEstablished
end
def retrieve_connection
- connection_handler.retrieve_connection(self)
+ connection_handler.retrieve_connection(specification_id)
end
# Returns +true+ if Active Record is connected.
def connected?
- connection_handler.connected?(self)
+ connection_handler.connected?(specification_id)
end
- def remove_connection(klass = self)
- connection_handler.remove_connection(klass)
+ def remove_connection(id = specification_id)
+ connection_handler.remove_connection(id)
end
def clear_cache! # :nodoc:
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 5d74631e32..291cabb4bb 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -257,7 +257,7 @@ module ActiveRecord
# Returns the Arel engine.
def arel_engine # :nodoc:
@arel_engine ||=
- if Base == self || connection_handler.retrieve_connection_pool(self)
+ if Base == self || connection_handler.retrieve_connection_pool(specification_id)
self
else
superclass.arel_engine