From 60499774c2a8ecd9d87b140ffbe24634559c3fcd Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 10 Jul 2005 04:54:34 +0000 Subject: [PATCH] Fixed that each request with the WEBrick adapter would open a new database connection #1685 [Sam Stephenson]. Added ActiveRecord::Base.threaded_connections flag to turn off 1-connection per thread (required for thread safety). By default it's on, but WEBrick in Rails need it off #1685 [Sam Stephenson] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1792 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activerecord/CHANGELOG | 2 ++ activerecord/lib/active_record/base.rb | 5 +++ .../connection_adapters/abstract_adapter.rb | 18 ++++++---- activerecord/lib/active_record/query_cache.rb | 3 +- .../test/threaded_connections_test.rb | 34 +++++++++++++++++++ railties/CHANGELOG | 2 ++ railties/lib/webrick_server.rb | 2 ++ 7 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 activerecord/test/threaded_connections_test.rb diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 0ad70cd2d7..26b8c52d59 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Added ActiveRecord::Base.threaded_connections flag to turn off 1-connection per thread (required for thread safety). By default it's on, but WEBrick in Rails need it off #1685 [Sam Stephenson] + * Correct reflected table name for singular associations. #1688 [court3nay@gmail.com] * Fixed optimistic locking with SQL Server #1660 [tom@popdog.net] diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 6ff0e4a9e0..b32843d069 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -289,6 +289,11 @@ def self.inherited(child) #:nodoc: # This is set to :local by default. cattr_accessor :default_timezone @@default_timezone = :local + + # Determines whether or not to use a connection for each thread, or a single shared connection for all threads. + # Defaults to true; Railties' WEBrick server sets this to false. + cattr_accessor :threaded_connections + @@threaded_connections = true class << self # Class methods # Find operates with three different retreval approaches: diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 75fd170269..163925df42 100755 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -86,6 +86,14 @@ def self.establish_connection(spec = nil) end end + def self.active_connections #:nodoc: + if threaded_connections + Thread.current['active_connections'] ||= {} + else + @@active_connections ||= {} + end + end + # Locate the connection of the nearest super class. This can be an # active or defined connections: if it is the latter, it will be # opened and set as the active connection for the class it was defined @@ -94,7 +102,7 @@ def self.retrieve_connection #:nodoc: klass = self ar_super = ActiveRecord::Base.superclass until klass == ar_super - if conn = (Thread.current['active_connections'] ||= {})[klass] + if conn = active_connections[klass] return conn elsif conn = @@defined_connections[klass] klass.connection = conn @@ -109,7 +117,7 @@ def self.retrieve_connection #:nodoc: def self.connected? klass = self until klass == ActiveRecord::Base.superclass - if Thread.current['active_connections'].is_a?(Hash) && Thread.current['active_connections'][klass] + if active_connections[klass] return true else klass = klass.superclass @@ -125,8 +133,7 @@ def self.connected? def self.remove_connection(klass=self) conn = @@defined_connections[klass] @@defined_connections.delete(klass) - Thread.current['active_connections'] ||= {} - Thread.current['active_connections'][klass] = nil + active_connections[klass] = nil conn.config if conn end @@ -134,8 +141,7 @@ def self.remove_connection(klass=self) def self.connection=(spec) raise ConnectionNotEstablished unless spec conn = self.send(spec.adapter_method, spec.config) - Thread.current['active_connections'] ||= {} - Thread.current['active_connections'][self] = conn + active_connections[self] = conn end # Converts all strings in a hash to symbols. diff --git a/activerecord/lib/active_record/query_cache.rb b/activerecord/lib/active_record/query_cache.rb index 95b4d8c915..c41567375f 100644 --- a/activerecord/lib/active_record/query_cache.rb +++ b/activerecord/lib/active_record/query_cache.rb @@ -51,8 +51,7 @@ def self.connection=(spec) QueryCache.new(self.send(spec.adapter_method, spec.config)) : self.send(spec.adapter_method, spec.config) - Thread.current['active_connections'] ||= {} - Thread.current['active_connections'][self] = conn + active_connections[self] = conn end end diff --git a/activerecord/test/threaded_connections_test.rb b/activerecord/test/threaded_connections_test.rb new file mode 100644 index 0000000000..29c16b1a5c --- /dev/null +++ b/activerecord/test/threaded_connections_test.rb @@ -0,0 +1,34 @@ +require 'abstract_unit' + +class ThreadedConnectionsTest < Test::Unit::TestCase + self.use_transactional_fixtures = false + + fixtures :topics + + def setup + @connection = ActiveRecord::Base.remove_connection + @connections = [] + end + + def gather_connections(use_threaded_connections) + ActiveRecord::Base.threaded_connections = use_threaded_connections + ActiveRecord::Base.establish_connection(@connection) + + 5.times do + Thread.new do + Topic.find :first + @connections << ActiveRecord::Base.active_connections.values.first + end.join + end + end + + def test_threaded_connections + gather_connections(true) + assert_equal @connections.uniq.length, 5 + end + + def test_unthreaded_connections + gather_connections(false) + assert_equal @connections.uniq.length, 1 + end +end diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 8f375a3774..8bba746431 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Fixed that each request with the WEBrick adapter would open a new database connection #1685 [Sam Stephenson] + * Added support for SQL Server in the database rake tasks #1652 [ken.barker@gmail.com] Note: osql and scptxfr may need to be installed on your development environment. This involves getting the .exes and a .rll (scptxfr) from a production SQL Server (not developer level SQL Server). Add their location to your Environment PATH and you are all set. * Added a VERSION parameter to the migrate task that allows you to do "rake migrate VERSION=34" to migrate to the 34th version traveling up or down depending on the current version diff --git a/railties/lib/webrick_server.rb b/railties/lib/webrick_server.rb index 71df5432e1..ba0541e7c6 100644 --- a/railties/lib/webrick_server.rb +++ b/railties/lib/webrick_server.rb @@ -8,6 +8,8 @@ ABSOLUTE_RAILS_ROOT = File.expand_path(RAILS_ROOT) +ActiveRecord::Base.threaded_connections = false + class CGI def stdinput @stdin || $stdin -- GitLab