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

Ticket #2162: connection_pool.rb

File connection_pool.rb, 2.7 kB (added by greg@lapcominc.com, 5 years ago)

new file

Line 
1 require 'monitor'
2
3 module ActiveRecord
4   class ConnectionPool
5     include MonitorMixin
6    
7     def initialize(prc)
8       super()
9       @prc = prc
10       startup
11     end
12    
13     def startup
14       @min_size,@max_size = ActiveRecord::Base.pool_connections_min,ActiveRecord::Base.pool_connections_max
15       @available_connections = []
16       @acquired_connections = []
17       @min_size.times { @available_connections << @prc.call }
18       @cond_var ||= new_cond
19       @use_check = 0
20       @use_thread = Thread.new { reap_connections }
21     end
22    
23     def shutdown
24       synchronize do
25         @cond_var.wait_until { @acquired_connections.size==0 }
26         @available_connections.each do |c|
27           c.close         
28         end
29         @available_connections = nil       
30       end
31       @use_thread.terminate
32     end   
33     private :startup, :shutdown
34    
35     def reset
36       shutdown
37       startup
38     end
39    
40     def current_size
41       return @available_connections.size + @acquired_connections.size
42     end
43    
44     def reap_connections
45       Base.logger.debug("starting reaper thread")
46       loop do
47         sleep(ActiveRecord::Base.pool_connections_reaper_period)
48         synchronize do
49           Base.logger.debug("use_check is #{@use_check}")
50           if @use_check < current_size
51             num_to_free = current_size - @use_check
52             max_to_free = current_size-@min_size
53             num_to_free = max_to_free if num_to_free > max_to_free
54             Base.logger.debug("freeing #{num_to_free} connections")
55             @available_connections[0...num_to_free].each do |conn|
56               conn.close
57               @available_connections.delete(conn)
58             end
59           end
60         end
61         @use_check=0
62       end
63     end
64        
65     def acquire_connection
66       conn = nil
67       synchronize do
68         loop do
69           if @available_connections.size > 0
70             conn = @available_connections.shift
71             break
72           elsif (@max_size > 0 and current_size < @max_size) or @max_size==0
73             conn = @prc.call
74             break
75           else
76             if ActiveRecord::Base.pool_connections_wait
77               @cond_var.wait
78             else
79               raise ActiveRecord::ConnectionNotEstablished
80             end
81           end 
82         end
83         @acquired_connections << conn
84         @use_check=@acquired_connections.size if @acquired_connections.size > @use_check
85         Base.logger.debug("current_size=" + current_size.to_s + " max_size=" + @max_size.to_s)
86       end
87       conn
88     end
89    
90     def release_connection(conn)
91       synchronize do
92         @acquired_connections.delete(conn)
93         @available_connections << conn
94         @cond_var.signal
95       end
96     end
97   end
98 end