Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 458 lines (397 sloc) 15.831 kb
d869298 @raggi Don't depend on rubygems loading thread (for Mutex)
raggi authored
1 require 'thread'
ff97e9d @nicksieger Connection handling methods extracted out into separate ConnectionHan…
nicksieger authored
2 require 'monitor'
50cd4bd @nicksieger Introduce synchronization around connection pool access
nicksieger authored
3 require 'set'
e8550ee @jeremy Cherry-pick core extensions
jeremy authored
4 require 'active_support/core_ext/module/synchronization'
50cd4bd @nicksieger Introduce synchronization around connection pool access
nicksieger authored
5
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
6 module ActiveRecord
fe575dd @nicksieger Nearing the finish line. Initial fixed-size connection pool implement…
nicksieger authored
7 # Raised when a connection could not be obtained within the connection
8 # acquisition timeout period.
9 class ConnectionTimeoutError < ConnectionNotEstablished
10 end
11
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
12 module ConnectionAdapters
f17159b @fxn edit pass: the names of Rails components have a space, ie, "Active Re…
fxn authored
13 # Connection pool base class for managing Active Record database
fe575dd @nicksieger Nearing the finish line. Initial fixed-size connection pool implement…
nicksieger authored
14 # connections.
15 #
a293278 @lifo Merge docrails
lifo authored
16 # == Introduction
17 #
18 # A connection pool synchronizes thread access to a limited number of
19 # database connections. The basic idea is that each thread checks out a
20 # database connection from the pool, uses that connection, and checks the
21 # connection back in. ConnectionPool is completely thread-safe, and will
22 # ensure that a connection cannot be used by two threads at the same time,
23 # as long as ConnectionPool's contract is correctly followed. It will also
24 # handle cases in which there are more threads than connections: if all
25 # connections have been checked out, and a thread tries to checkout a
26 # connection anyway, then ConnectionPool will wait until some other thread
27 # has checked in a connection.
28 #
29 # == Obtaining (checking out) a connection
30 #
fe575dd @nicksieger Nearing the finish line. Initial fixed-size connection pool implement…
nicksieger authored
31 # Connections can be obtained and used from a connection pool in several
32 # ways:
33 #
f17159b @fxn edit pass: the names of Rails components have a space, ie, "Active Re…
fxn authored
34 # 1. Simply use ActiveRecord::Base.connection as with Active Record 2.1 and
817a07b @nicksieger More doco and class/method renames. Now have a strategy for integrati…
nicksieger authored
35 # earlier (pre-connection-pooling). Eventually, when you're done with
36 # the connection(s) and wish it to be returned to the pool, you call
37 # ActiveRecord::Base.clear_active_connections!. This will be the
f17159b @fxn edit pass: the names of Rails components have a space, ie, "Active Re…
fxn authored
38 # default behavior for Active Record when used in conjunction with
39 # Action Pack's request handling cycle.
fe575dd @nicksieger Nearing the finish line. Initial fixed-size connection pool implement…
nicksieger authored
40 # 2. Manually check out a connection from the pool with
41 # ActiveRecord::Base.connection_pool.checkout. You are responsible for
42 # returning this connection to the pool when finished by calling
43 # ActiveRecord::Base.connection_pool.checkin(connection).
44 # 3. Use ActiveRecord::Base.connection_pool.with_connection(&block), which
45 # obtains a connection, yields it as the sole argument to the block,
46 # and returns it to the pool after the block completes.
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
47 #
a293278 @lifo Merge docrails
lifo authored
48 # Connections in the pool are actually AbstractAdapter objects (or objects
49 # compatible with AbstractAdapter's interface).
50 #
51 # == Options
52 #
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
53 # There are two connection-pooling-related options that you can add to
54 # your database connection configuration:
55 #
56 # * +pool+: number indicating size of connection pool (default 5)
57 # * +wait_timeout+: number of seconds to block and wait for a connection
58 # before giving up and raising a timeout error (default 5 seconds).
817a07b @nicksieger More doco and class/method renames. Now have a strategy for integrati…
nicksieger authored
59 class ConnectionPool
acccb72 @tenderlove column cache now lives on the connection pool
tenderlove authored
60 attr_accessor :automatic_reconnect
cccb998 @josevalim Expose connections available in the connection pool.
josevalim authored
61 attr_reader :spec, :connections
0de661d @tenderlove the connection pool caches table_exists? calls
tenderlove authored
62 attr_reader :columns, :columns_hash, :primary_keys, :tables
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
63
a293278 @lifo Merge docrails
lifo authored
64 # Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
65 # object which describes database connection information (e.g. adapter,
66 # host name, username, password, etc), as well as the maximum size for
67 # this ConnectionPool.
68 #
69 # The default ConnectionPool maximum size is 5.
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
70 def initialize(spec)
71 @spec = spec
dd77733 @jeremy Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
72
029952e @nicksieger Extract a base class for connection pools, start to flesh out reserve…
nicksieger authored
73 # The cache of reserved connections mapped to threads
74 @reserved_connections = {}
dd77733 @jeremy Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
75
cab76ce @nicksieger Add synchronization to connection pool also
nicksieger authored
76 # The mutex used to synchronize pool access
77 @connection_mutex = Monitor.new
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
78 @queue = @connection_mutex.new_cond
2a04110 fix ruby 1.9 deadlock problem, fixes #5736 add connection pool tests
Hemant Kumar authored
79 @timeout = spec.config[:wait_timeout] || 5
dd77733 @jeremy Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
80
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
81 # default max pool size to 5
82 @size = (spec.config[:pool] && spec.config[:pool].to_i) || 5
dd77733 @jeremy Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
83
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
84 @connections = []
85 @checked_out = []
acccb72 @tenderlove column cache now lives on the connection pool
tenderlove authored
86 @automatic_reconnect = true
0de661d @tenderlove the connection pool caches table_exists? calls
tenderlove authored
87 @tables = {}
59f7780 @tenderlove adjust query counts to be consistent across databases, make sure data…
tenderlove authored
88
5f3cf42 @tenderlove connection pool can cache column, table, and primary key information
tenderlove authored
89 @columns = Hash.new do |h, table_name|
90 h[table_name] = with_connection do |conn|
0cd4286 @tenderlove making sure primary key is set on the columns
tenderlove authored
91
92 # Fetch a list of columns
93 conn.columns(table_name, "#{table_name} Columns").tap do |columns|
94
95 # set primary key information
96 columns.each do |column|
97 column.primary = column.name == primary_keys[table_name]
98 end
99 end
5f3cf42 @tenderlove connection pool can cache column, table, and primary key information
tenderlove authored
100 end
101 end
102
103 @columns_hash = Hash.new do |h, table_name|
104 h[table_name] = Hash[columns[table_name].map { |col|
105 [col.name, col]
106 }]
107 end
108
109 @primary_keys = Hash.new do |h, table_name|
110 h[table_name] = with_connection do |conn|
0de661d @tenderlove the connection pool caches table_exists? calls
tenderlove authored
111 table_exists?(table_name) ? conn.primary_key(table_name) : 'id'
5f3cf42 @tenderlove connection pool can cache column, table, and primary key information
tenderlove authored
112 end
113 end
114 end
115
8f1b141 @smartinez87 Fixed punctuation errors.
smartinez87 authored
116 # A cached lookup for table existence.
0de661d @tenderlove the connection pool caches table_exists? calls
tenderlove authored
117 def table_exists?(name)
118 return true if @tables.key? name
119
120 with_connection do |conn|
121 conn.tables.each { |table| @tables[table] = true }
122 end
123
124 @tables.key? name
125 end
126
5f3cf42 @tenderlove connection pool can cache column, table, and primary key information
tenderlove authored
127 # Clears out internal caches:
128 #
129 # * columns
130 # * columns_hash
59f7780 @tenderlove adjust query counts to be consistent across databases, make sure data…
tenderlove authored
131 # * tables
5f3cf42 @tenderlove connection pool can cache column, table, and primary key information
tenderlove authored
132 def clear_cache!
133 @columns.clear
134 @columns_hash.clear
59f7780 @tenderlove adjust query counts to be consistent across databases, make sure data…
tenderlove authored
135 @tables.clear
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
136 end
137
8f1b141 @smartinez87 Fixed punctuation errors.
smartinez87 authored
138 # Clear out internal caches for table with +table_name+.
c94651f @tenderlove almost fisted
tenderlove authored
139 def clear_table_cache!(table_name)
140 @columns.delete table_name
141 @columns_hash.delete table_name
142 @primary_keys.delete table_name
143 end
144
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
145 # Retrieve the connection associated with the current thread, or call
146 # #checkout to obtain one if necessary.
147 #
148 # #connection can be called any number of times; the connection is
149 # held in a hash keyed by the thread id.
150 def connection
072cd60 @tenderlove refactor if / else to ||=
tenderlove authored
151 @reserved_connections[current_connection_id] ||= checkout
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
152 end
153
4211866 @tenderlove adding active_connection? to the connection pool
tenderlove authored
154 # Check to see if there is an active connection in this connection
155 # pool.
156 def active_connection?
157 @reserved_connections.key? current_connection_id
158 end
159
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
160 # Signal that the thread is finished with the current connection.
817a07b @nicksieger More doco and class/method renames. Now have a strategy for integrati…
nicksieger authored
161 # #release_connection releases the connection-thread association
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
162 # and returns the connection to the pool.
3344520 @tenderlove reduce the number of times current_connection_id is called in with_co…
tenderlove authored
163 def release_connection(with_id = current_connection_id)
164 conn = @reserved_connections.delete(with_id)
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
165 checkin conn if conn
166 end
167
5501b99 @coderrr Ensure ActiveRecord::Base.connection_pool.with_connection creates a n…
coderrr authored
168 # If a connection already exists yield it to the block. If no connection
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
169 # exists checkout a connection, yield it to the block, and checkin the
5501b99 @coderrr Ensure ActiveRecord::Base.connection_pool.with_connection creates a n…
coderrr authored
170 # connection when finished.
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
171 def with_connection
3344520 @tenderlove reduce the number of times current_connection_id is called in with_co…
tenderlove authored
172 connection_id = current_connection_id
173 fresh_connection = true unless @reserved_connections[connection_id]
5501b99 @coderrr Ensure ActiveRecord::Base.connection_pool.with_connection creates a n…
coderrr authored
174 yield connection
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
175 ensure
3344520 @tenderlove reduce the number of times current_connection_id is called in with_co…
tenderlove authored
176 release_connection(connection_id) if fresh_connection
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
177 end
178
029952e @nicksieger Extract a base class for connection pools, start to flesh out reserve…
nicksieger authored
179 # Returns true if a connection has already been opened.
180 def connected?
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
181 !@connections.empty?
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
182 end
183
a293278 @lifo Merge docrails
lifo authored
184 # Disconnects all connections in the pool, and clears the pool.
029952e @nicksieger Extract a base class for connection pools, start to flesh out reserve…
nicksieger authored
185 def disconnect!
186 @reserved_connections.each do |name,conn|
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
187 checkin conn
029952e @nicksieger Extract a base class for connection pools, start to flesh out reserve…
nicksieger authored
188 end
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
189 @reserved_connections = {}
190 @connections.each do |conn|
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
191 conn.disconnect!
192 end
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
193 @connections = []
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
194 end
195
8f1b141 @smartinez87 Fixed punctuation errors.
smartinez87 authored
196 # Clears the cache which maps classes.
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
197 def clear_reloadable_connections!
029952e @nicksieger Extract a base class for connection pools, start to flesh out reserve…
nicksieger authored
198 @reserved_connections.each do |name, conn|
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
199 checkin conn
029952e @nicksieger Extract a base class for connection pools, start to flesh out reserve…
nicksieger authored
200 end
201 @reserved_connections = {}
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
202 @connections.each do |conn|
203 conn.disconnect! if conn.requires_reloading?
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
204 end
62c4e4d @ebeigarts Fix connection reloading in development mode. [#4929 state:resolved]
ebeigarts authored
205 @connections.delete_if do |conn|
206 conn.requires_reloading?
207 end
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
208 end
209
817a07b @nicksieger More doco and class/method renames. Now have a strategy for integrati…
nicksieger authored
210 # Verify active connections and remove and disconnect connections
211 # associated with stale threads.
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
212 def verify_active_connections! #:nodoc:
d07a6b1 @nicksieger Make clear_active_connections! also return stale connections back to …
nicksieger authored
213 clear_stale_cached_connections!
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
214 @connections.each do |connection|
7ba2872 @nicksieger Deprecate verification_timeout and verify before reset
nicksieger authored
215 connection.verify!
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
216 end
217 end
218
d07a6b1 @nicksieger Make clear_active_connections! also return stale connections back to …
nicksieger authored
219 # Return any checked-out connections back to the pool by threads that
220 # are no longer alive.
221 def clear_stale_cached_connections!
42be67e @tenderlove unfactoring clear_stale_cached_connections!
tenderlove authored
222 keys = @reserved_connections.keys - Thread.list.find_all { |t|
223 t.alive?
224 }.map { |thread| thread.object_id }
225 keys.each do |key|
226 checkin @reserved_connections[key]
227 @reserved_connections.delete(key)
d07a6b1 @nicksieger Make clear_active_connections! also return stale connections back to …
nicksieger authored
228 end
229 end
230
a293278 @lifo Merge docrails
lifo authored
231 # Check-out a database connection from the pool, indicating that you want
232 # to use it. You should call #checkin when you no longer need this.
233 #
234 # This is done by either returning an existing connection, or by creating
235 # a new connection. If the maximum number of connections for this pool has
236 # already been reached, but the pool is empty (i.e. they're all being used),
237 # then this method will wait until a thread has checked in a connection.
238 # The wait time is bounded however: if no connection can be checked out
239 # within the timeout specified for this pool, then a ConnectionTimeoutError
240 # exception will be raised.
241 #
242 # Returns: an AbstractAdapter object.
243 #
244 # Raises:
245 # - ConnectionTimeoutError: no connection can be obtained from the pool
246 # within the timeout period.
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
247 def checkout
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
248 # Checkout an available connection
249 @connection_mutex.synchronize do
21eb18a @alk Fix race in ConnectionPool#checkout
alk authored
250 loop do
251 conn = if @checked_out.size < @connections.size
252 checkout_existing_connection
253 elsif @connections.size < @size
254 checkout_new_connection
255 end
256 return conn if conn
2a04110 fix ruby 1.9 deadlock problem, fixes #5736 add connection pool tests
Hemant Kumar authored
257
258 @queue.wait(@timeout)
259
260 if(@checked_out.size < @connections.size)
21eb18a @alk Fix race in ConnectionPool#checkout
alk authored
261 next
262 else
8343611 @alk made ConnectionPool#checkout more robust by trying to loot dead threa…
alk authored
263 clear_stale_cached_connections!
264 if @size == @checked_out.size
dd77733 @jeremy Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
265 raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it."
8343611 @alk made ConnectionPool#checkout more robust by trying to loot dead threa…
alk authored
266 end
21eb18a @alk Fix race in ConnectionPool#checkout
alk authored
267 end
2a04110 fix ruby 1.9 deadlock problem, fixes #5736 add connection pool tests
Hemant Kumar authored
268
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
269 end
270 end
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
271 end
272
a293278 @lifo Merge docrails
lifo authored
273 # Check-in a database connection back into the pool, indicating that you
274 # no longer need this connection.
275 #
276 # +conn+: an AbstractAdapter object, which was obtained by earlier by
277 # calling +checkout+ on this pool.
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
278 def checkin(conn)
279 @connection_mutex.synchronize do
57bc25c @jfirebaugh Use run_callbacks; the generated _run_<name>_callbacks method is not …
jfirebaugh authored
280 conn.run_callbacks :checkin do
471a394 @nicksieger Modify connection pool callbacks to be compatible w/ new style
nicksieger authored
281 @checked_out.delete conn
282 @queue.signal
283 end
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
284 end
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
285 end
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
286
113cc4e @nicksieger Remove some synchronization that's probably overkill, assuming one do…
nicksieger authored
287 synchronize :clear_reloadable_connections!, :verify_active_connections!,
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
288 :connected?, :disconnect!, :with => :@connection_mutex
289
290 private
fe575dd @nicksieger Nearing the finish line. Initial fixed-size connection pool implement…
nicksieger authored
291 def new_connection
a3f12f5 @nicksieger Default connection allow_concurrency to false (for PostgreSQL)
nicksieger authored
292 ActiveRecord::Base.send(spec.adapter_method, spec.config)
fe575dd @nicksieger Nearing the finish line. Initial fixed-size connection pool implement…
nicksieger authored
293 end
294
d07a6b1 @nicksieger Make clear_active_connections! also return stale connections back to …
nicksieger authored
295 def current_connection_id #:nodoc:
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
296 Thread.current.object_id
297 end
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
298
fe575dd @nicksieger Nearing the finish line. Initial fixed-size connection pool implement…
nicksieger authored
299 def checkout_new_connection
acccb72 @tenderlove column cache now lives on the connection pool
tenderlove authored
300 raise ConnectionNotEstablished unless @automatic_reconnect
301
fe575dd @nicksieger Nearing the finish line. Initial fixed-size connection pool implement…
nicksieger authored
302 c = new_connection
303 @connections << c
a96b7d4 @nicksieger Add connection reset and verification upon each connection checkout
nicksieger authored
304 checkout_and_verify(c)
fe575dd @nicksieger Nearing the finish line. Initial fixed-size connection pool implement…
nicksieger authored
305 end
306
307 def checkout_existing_connection
d7d2d73 @nicksieger Fix typo: was using brackets instead of parens. Must need more sleep.
nicksieger authored
308 c = (@connections - @checked_out).first
a96b7d4 @nicksieger Add connection reset and verification upon each connection checkout
nicksieger authored
309 checkout_and_verify(c)
310 end
311
312 def checkout_and_verify(c)
471a394 @nicksieger Modify connection pool callbacks to be compatible w/ new style
nicksieger authored
313 c.run_callbacks :checkout do
314 c.verify!
315 @checked_out << c
316 end
fe575dd @nicksieger Nearing the finish line. Initial fixed-size connection pool implement…
nicksieger authored
317 c
318 end
319 end
320
a293278 @lifo Merge docrails
lifo authored
321 # ConnectionHandler is a collection of ConnectionPool objects. It is used
f17159b @fxn edit pass: the names of Rails components have a space, ie, "Active Re…
fxn authored
322 # for keeping separate connection pools for Active Record models that connect
a293278 @lifo Merge docrails
lifo authored
323 # to different databases.
324 #
325 # For example, suppose that you have 5 models, with the following hierarchy:
326 #
327 # |
328 # +-- Book
329 # | |
330 # | +-- ScaryBook
331 # | +-- GoodBook
332 # +-- Author
333 # +-- BankAccount
334 #
335 # Suppose that Book is to connect to a separate database (i.e. one other
336 # than the default database). Then Book, ScaryBook and GoodBook will all use
337 # the same connection pool. Likewise, Author and BankAccount will use the
338 # same connection pool. However, the connection pool used by Author/BankAccount
339 # is not the same as the one used by Book/ScaryBook/GoodBook.
340 #
341 # Normally there is only a single ConnectionHandler instance, accessible via
f17159b @fxn edit pass: the names of Rails components have a space, ie, "Active Re…
fxn authored
342 # ActiveRecord::Base.connection_handler. Active Record models use this to
a293278 @lifo Merge docrails
lifo authored
343 # determine that connection pool that they should use.
ca6d717 @nicksieger Deprecate allow_concurrency and make it have no effect
nicksieger authored
344 class ConnectionHandler
b952470 @tenderlove use an attr_reader for performance
tenderlove authored
345 attr_reader :connection_pools
346
72d959d @nicksieger Split connection handler into single- and multiple-thread versions.
nicksieger authored
347 def initialize(pools = {})
348 @connection_pools = pools
349 end
ff97e9d @nicksieger Connection handling methods extracted out into separate ConnectionHan…
nicksieger authored
350
351 def establish_connection(name, spec)
8e5e02b @nicksieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
352 @connection_pools[name] = ConnectionAdapters::ConnectionPool.new(spec)
ff97e9d @nicksieger Connection handling methods extracted out into separate ConnectionHan…
nicksieger authored
353 end
354
25f9497 @tenderlove adding active_connections? to the connection pool for finding open co…
tenderlove authored
355 # Returns true if there are any active connections among the connection
356 # pools that the ConnectionHandler is managing.
357 def active_connections?
358 connection_pools.values.any? { |pool| pool.active_connection? }
359 end
360
d07a6b1 @nicksieger Make clear_active_connections! also return stale connections back to …
nicksieger authored
361 # Returns any connections in use by the current thread back to the pool,
362 # and also returns connections to the pool cached by threads that are no
363 # longer alive.
ff97e9d @nicksieger Connection handling methods extracted out into separate ConnectionHan…
nicksieger authored
364 def clear_active_connections!
529c271 @nicksieger Simplify dispatcher callbacks to eliminate unnecessary stale thread p…
nicksieger authored
365 @connection_pools.each_value {|pool| pool.release_connection }
ff97e9d @nicksieger Connection handling methods extracted out into separate ConnectionHan…
nicksieger authored
366 end
367
8f1b141 @smartinez87 Fixed punctuation errors.
smartinez87 authored
368 # Clears the cache which maps classes.
ff97e9d @nicksieger Connection handling methods extracted out into separate ConnectionHan…
nicksieger authored
369 def clear_reloadable_connections!
370 @connection_pools.each_value {|pool| pool.clear_reloadable_connections! }
371 end
372
373 def clear_all_connections!
72d959d @nicksieger Split connection handler into single- and multiple-thread versions.
nicksieger authored
374 @connection_pools.each_value {|pool| pool.disconnect! }
ff97e9d @nicksieger Connection handling methods extracted out into separate ConnectionHan…
nicksieger authored
375 end
376
377 # Verify active connections.
378 def verify_active_connections! #:nodoc:
817a07b @nicksieger More doco and class/method renames. Now have a strategy for integrati…
nicksieger authored
379 @connection_pools.each_value {|pool| pool.verify_active_connections! }
ff97e9d @nicksieger Connection handling methods extracted out into separate ConnectionHan…
nicksieger authored
380 end
381
382 # Locate the connection of the nearest super class. This can be an
383 # active or defined connection: if it is the latter, it will be
384 # opened and set as the active connection for the class it was defined
385 # for (not necessarily the current class).
386 def retrieve_connection(klass) #:nodoc:
387 pool = retrieve_connection_pool(klass)
388 (pool && pool.connection) or raise ConnectionNotEstablished
389 end
390
82fcd9d @nicksieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
391 # Returns true if a connection that's accessible to this class has
392 # already been opened.
ff97e9d @nicksieger Connection handling methods extracted out into separate ConnectionHan…
nicksieger authored
393 def connected?(klass)
0832bc6 @lifo Make sure ActiveRecord::Base.connected? doesn't raise an exception fo…
lifo authored
394 conn = retrieve_connection_pool(klass)
a4458f5 @tenderlove removing useless ternary
tenderlove authored
395 conn && conn.connected?
ff97e9d @nicksieger Connection handling methods extracted out into separate ConnectionHan…
nicksieger authored
396 end
397
398 # Remove the connection for this class. This will close the active
399 # connection and the defined connection (if they exist). The result
400 # can be used as an argument for establish_connection, for easily
401 # re-establishing the connection.
402 def remove_connection(klass)
403 pool = @connection_pools[klass.name]
04ef434 @tenderlove only test for existence of +pool+ once
tenderlove authored
404 return nil unless pool
405
acccb72 @tenderlove column cache now lives on the connection pool
tenderlove authored
406 pool.automatic_reconnect = false
04ef434 @tenderlove only test for existence of +pool+ once
tenderlove authored
407 pool.disconnect!
408 pool.spec.config
ff97e9d @nicksieger Connection handling methods extracted out into separate ConnectionHan…
nicksieger authored
409 end
410
fe575dd @nicksieger Nearing the finish line. Initial fixed-size connection pool implement…
nicksieger authored
411 def retrieve_connection_pool(klass)
3007545 @nicksieger Minor tweak to retrieve_connection_pool -- recurse instead of loop
nicksieger authored
412 pool = @connection_pools[klass.name]
413 return pool if pool
414 return nil if ActiveRecord::Base == klass
415 retrieve_connection_pool klass.superclass
fe575dd @nicksieger Nearing the finish line. Initial fixed-size connection pool implement…
nicksieger authored
416 end
72d959d @nicksieger Split connection handler into single- and multiple-thread versions.
nicksieger authored
417 end
1b22071 @josh Ensure ActiveRecord session store's connections are checked in after …
josh authored
418
419 class ConnectionManagement
e524609 @tenderlove proxy body responses so we close database connections after body is f…
tenderlove authored
420 class Proxy # :nodoc:
421 attr_reader :body, :testing
422
423 def initialize(body, testing = false)
424 @body = body
425 @testing = testing
426 end
427
428 def each(&block)
429 body.each(&block)
430 end
431
432 def close
433 body.close if body.respond_to?(:close)
434
435 # Don't return connection (and perform implicit rollback) if
436 # this request is a part of integration test
437 ActiveRecord::Base.clear_active_connections! unless testing
438 end
439 end
440
1b22071 @josh Ensure ActiveRecord session store's connections are checked in after …
josh authored
441 def initialize(app)
442 @app = app
443 end
444
445 def call(env)
c7b7c6a @tenderlove make sure that active connections are not cleared during test when an…
tenderlove authored
446 testing = env.key?('rack.test')
447
e524609 @tenderlove proxy body responses so we close database connections after body is f…
tenderlove authored
448 status, headers, body = @app.call(env)
449
c7b7c6a @tenderlove make sure that active connections are not cleared during test when an…
tenderlove authored
450 [status, headers, Proxy.new(body, testing)]
3b2a032 @tenderlove clearing active connections in the ConnectionManagement middleware if…
tenderlove authored
451 rescue
c7b7c6a @tenderlove make sure that active connections are not cleared during test when an…
tenderlove authored
452 ActiveRecord::Base.clear_active_connections! unless testing
3b2a032 @tenderlove clearing active connections in the ConnectionManagement middleware if…
tenderlove authored
453 raise
1b22071 @josh Ensure ActiveRecord session store's connections are checked in after …
josh authored
454 end
455 end
6edaa26 @nicksieger Initial conversion to connection pool
nicksieger authored
456 end
21eb18a @alk Fix race in ConnectionPool#checkout
alk authored
457 end
Something went wrong with that request. Please try again.