gene_pool 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/History.txt +4 -0
- data/LICENSE +20 -0
- data/README.rdoc +37 -0
- data/Rakefile +16 -0
- data/VERSION +1 -0
- data/gene_pool.gemspec +49 -0
- data/lib/gene_pool.rb +134 -0
- data/test/gene_pool_test.rb +232 -0
- metadata +71 -0
data/.gitignore
ADDED
data/History.txt
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Brad Pardee
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
= gene_pool
|
2
|
+
|
3
|
+
* http://github.com/bpardee/gene_pool
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Generic pooling library for connection pools.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* Thread-safe
|
12
|
+
* Pure ruby
|
13
|
+
|
14
|
+
== INSTALL:
|
15
|
+
|
16
|
+
gem install gene_pool
|
17
|
+
|
18
|
+
== EXAMPLE USAGE:
|
19
|
+
|
20
|
+
class MyClient
|
21
|
+
@@gene_pool = GenePool.new(:name => 'MyClient',
|
22
|
+
:pool_size => 10,
|
23
|
+
:warn_timeout => 0.25,
|
24
|
+
:logger => Rails.logger) do
|
25
|
+
TCPSocket.new('myserver', 4321)
|
26
|
+
end
|
27
|
+
|
28
|
+
def send_message
|
29
|
+
@@gene_pool.with_connection do |socket|
|
30
|
+
# use socket here
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
== Copyright
|
36
|
+
|
37
|
+
Copyright (c) 2010 Brad Pardee. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gemspec|
|
7
|
+
gemspec.name = "gene_pool"
|
8
|
+
gemspec.summary = "Generic pooling library for creating a connection pool"
|
9
|
+
gemspec.description = "Generic pooling library for creating a connection pool"
|
10
|
+
gemspec.email = "bradpardee@gmail.com"
|
11
|
+
gemspec.homepage = "http://github.com/bpardee/gene_pool"
|
12
|
+
gemspec.authors = ["Brad Pardee"]
|
13
|
+
end
|
14
|
+
rescue LoadError
|
15
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
16
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/gene_pool.gemspec
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{gene_pool}
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Brad Pardee"]
|
12
|
+
s.date = %q{2010-09-08}
|
13
|
+
s.description = %q{Generic pooling library for creating a connection pool}
|
14
|
+
s.email = %q{bradpardee@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"History.txt",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"gene_pool.gemspec",
|
27
|
+
"lib/gene_pool.rb",
|
28
|
+
"test/gene_pool_test.rb"
|
29
|
+
]
|
30
|
+
s.homepage = %q{http://github.com/bpardee/gene_pool}
|
31
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
32
|
+
s.require_paths = ["lib"]
|
33
|
+
s.rubygems_version = %q{1.3.6}
|
34
|
+
s.summary = %q{Generic pooling library for creating a connection pool}
|
35
|
+
s.test_files = [
|
36
|
+
"test/gene_pool_test.rb"
|
37
|
+
]
|
38
|
+
|
39
|
+
if s.respond_to? :specification_version then
|
40
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
41
|
+
s.specification_version = 3
|
42
|
+
|
43
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
44
|
+
else
|
45
|
+
end
|
46
|
+
else
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
data/lib/gene_pool.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
# Generic connection pool class
|
2
|
+
class GenePool
|
3
|
+
|
4
|
+
attr_reader :name, :pool_size, :warn_timeout, :logger
|
5
|
+
|
6
|
+
def initialize(options={}, &connect_block)
|
7
|
+
@connect_block = connect_block
|
8
|
+
|
9
|
+
@name = options[:name] || 'GenePool'
|
10
|
+
@pool_size = options[:pool_size] || 1
|
11
|
+
@warn_timeout = options[:warn_timeout] || 5.0
|
12
|
+
@logger = options[:logger]
|
13
|
+
|
14
|
+
# Mutex for synchronizing pool access
|
15
|
+
@mutex = Mutex.new
|
16
|
+
|
17
|
+
# Condition variable for waiting for an available connection
|
18
|
+
@queue = ConditionVariable.new
|
19
|
+
|
20
|
+
@connections = []
|
21
|
+
@checked_out = []
|
22
|
+
# Map the original connections object_id within the with_connection method to the final connection.
|
23
|
+
# This could change if the connection is renew'ed.
|
24
|
+
@with_map = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Check out a connection from the pool, creating it if necessary.
|
28
|
+
def checkout
|
29
|
+
start_time = Time.now
|
30
|
+
connection = nil
|
31
|
+
reserved_connection_placeholder = Thread.current
|
32
|
+
begin
|
33
|
+
@mutex.synchronize do
|
34
|
+
until connection do
|
35
|
+
if @checked_out.size < @connections.size
|
36
|
+
connection = (@connections - @checked_out).first
|
37
|
+
@checked_out << connection
|
38
|
+
elsif @connections.size < @pool_size
|
39
|
+
# Perform the actual connection outside the mutex
|
40
|
+
connection = reserved_connection_placeholder
|
41
|
+
@connections << connection
|
42
|
+
@checked_out << connection
|
43
|
+
@logger.debug "#{@name}: Created connection ##{@connections.size} #{connection}:#{connection.object_id} for #{name}" if @logger && @logger.debug?
|
44
|
+
else
|
45
|
+
@logger.info "#{@name}: Waiting for an available connection, all #{@pool_size} connections are checked out." if @logger
|
46
|
+
@queue.wait(@mutex)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
ensure
|
51
|
+
delta = Time.now - start_time
|
52
|
+
if @logger && delta > @warn_timeout
|
53
|
+
@logger.warn "#{@name}: It took #{delta} seconds to obtain a connection. Consider raising the pool size which is " +
|
54
|
+
"currently set to #{@pool_size}."
|
55
|
+
end
|
56
|
+
end
|
57
|
+
if connection == reserved_connection_placeholder
|
58
|
+
connection = renew(reserved_connection_placeholder)
|
59
|
+
end
|
60
|
+
|
61
|
+
@logger.debug "#{@name}: Checkout connection #{connection.object_id} self=#{self}" if @logger && @logger.debug?
|
62
|
+
return connection
|
63
|
+
end
|
64
|
+
|
65
|
+
# Return a connection to the pool.
|
66
|
+
def checkin(connection)
|
67
|
+
@mutex.synchronize do
|
68
|
+
@checked_out.delete(connection)
|
69
|
+
@queue.signal
|
70
|
+
end
|
71
|
+
@logger.debug "#{@name}: Checkin connection #{connection.object_id} self=#{self}" if @logger && @logger.debug?
|
72
|
+
end
|
73
|
+
|
74
|
+
# Create a scope for checking out a connection
|
75
|
+
def with_connection
|
76
|
+
connection = checkout
|
77
|
+
@mutex.synchronize do
|
78
|
+
@with_map[connection.object_id] = connection
|
79
|
+
end
|
80
|
+
begin
|
81
|
+
yield connection
|
82
|
+
ensure
|
83
|
+
@mutex.synchronize do
|
84
|
+
# Update connection for any renew's that have occurred
|
85
|
+
connection = @with_map.delete(connection.object_id)
|
86
|
+
end
|
87
|
+
checkin(connection)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Remove an existing connection from the pool
|
92
|
+
def remove(connection)
|
93
|
+
@mutex.synchronize do
|
94
|
+
@connections.delete(connection)
|
95
|
+
@checked_out.delete(connection)
|
96
|
+
@queue.signal
|
97
|
+
end
|
98
|
+
@logger.debug "#{@name}: Removed connection #{connection.object_id} self=#{self}" if @logger && @logger.debug?
|
99
|
+
end
|
100
|
+
|
101
|
+
# If a connection needs to be renewed for some reason, reassign it here
|
102
|
+
def renew(old_connection)
|
103
|
+
new_connection =
|
104
|
+
begin
|
105
|
+
@connect_block.call
|
106
|
+
rescue Exception
|
107
|
+
remove old_connection
|
108
|
+
raise
|
109
|
+
end
|
110
|
+
@mutex.synchronize do
|
111
|
+
index = @checked_out.index(old_connection)
|
112
|
+
raise Error.new("Can't reassign non-checked out connection for #{@name}") unless index
|
113
|
+
@checked_out[index] = new_connection
|
114
|
+
@connections[@connections.index(old_connection)] = new_connection
|
115
|
+
# If this is part of a with_connection block, then track our new connection
|
116
|
+
with_key = @with_map.index(old_connection)
|
117
|
+
@with_map[with_key] = new_connection if with_key
|
118
|
+
end
|
119
|
+
@logger.debug "#{@name}: Renewed connection old=#{old_connection.object_id} new=#{new_connection}:#{new_connection.object_id}" if @logger && @logger.debug?
|
120
|
+
return new_connection
|
121
|
+
end
|
122
|
+
|
123
|
+
# Perform the given block for each connection, i.e., closing each connection.
|
124
|
+
def each
|
125
|
+
@connections.each { |connection| yield connection }
|
126
|
+
end
|
127
|
+
|
128
|
+
def to_s
|
129
|
+
conn = @connections.map{|c| c.object_id}.join(',')
|
130
|
+
chk = @checked_out.map{|c| c.object_id}.join(',')
|
131
|
+
with = @with_map.keys.map{|k| "#{k}=#{@with_map[k].object_id}"}.join(',')
|
132
|
+
"connections=#{conn} checked_out=#{chk} with_map=#{with}"
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'gene_pool'
|
5
|
+
require 'stringio'
|
6
|
+
require 'logger'
|
7
|
+
require 'timeout'
|
8
|
+
|
9
|
+
# Increase visibility
|
10
|
+
class GenePool
|
11
|
+
attr_reader :connections, :checked_out, :with_map
|
12
|
+
end
|
13
|
+
|
14
|
+
class DummyConnection
|
15
|
+
def initialize(count, sleep_time=nil)
|
16
|
+
sleep sleep_time if sleep_time
|
17
|
+
@count = count
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_i
|
21
|
+
@count
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
@count.to_s
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
class GenePoolTest < Test::Unit::TestCase
|
31
|
+
|
32
|
+
context 'on default setup' do
|
33
|
+
setup do
|
34
|
+
@gene_pool = GenePool.new { Object.new }
|
35
|
+
end
|
36
|
+
|
37
|
+
should 'have default options set' do
|
38
|
+
assert_equal 'GenePool', @gene_pool.name
|
39
|
+
assert_equal 1, @gene_pool.pool_size
|
40
|
+
assert_equal 5.0, @gene_pool.warn_timeout
|
41
|
+
assert_nil @gene_pool.logger
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context '' do
|
46
|
+
setup do
|
47
|
+
#@stringio = StringIO.new
|
48
|
+
#@logger = Logger.new($stdout)
|
49
|
+
#@logger = Logger.new(@stringio)
|
50
|
+
@logger = nil
|
51
|
+
# Override sleep in individual tests
|
52
|
+
@sleep = nil
|
53
|
+
@timeout = 5
|
54
|
+
counter = 0
|
55
|
+
mutex = Mutex.new
|
56
|
+
@gene_pool = GenePool.new(:name => 'TestGenePool',
|
57
|
+
:pool_size => 10,
|
58
|
+
:warn_timeout => 2.0,
|
59
|
+
:logger => @logger) do
|
60
|
+
count = nil
|
61
|
+
mutex.synchronize do
|
62
|
+
count = counter += 1
|
63
|
+
end
|
64
|
+
Timeout.timeout(@timeout) do
|
65
|
+
DummyConnection.new(count, @sleep)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
should 'have options set' do
|
71
|
+
assert_equal 'TestGenePool', @gene_pool.name
|
72
|
+
assert_equal 10, @gene_pool.pool_size
|
73
|
+
assert_equal 2.0, @gene_pool.warn_timeout
|
74
|
+
assert_same @logger, @gene_pool.logger
|
75
|
+
end
|
76
|
+
|
77
|
+
should 'create 1 connection' do
|
78
|
+
(1..3).each do |i|
|
79
|
+
@gene_pool.with_connection do |conn|
|
80
|
+
assert_equal conn.to_i, 1
|
81
|
+
assert_equal 1, @gene_pool.connections.size
|
82
|
+
assert_equal 1, @gene_pool.checked_out.size
|
83
|
+
assert_same conn, @gene_pool.connections[0]
|
84
|
+
assert_same conn, @gene_pool.checked_out[0]
|
85
|
+
end
|
86
|
+
assert_equal 0, @gene_pool.checked_out.size
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
should 'create 2 connections' do
|
91
|
+
conn1 = @gene_pool.checkout
|
92
|
+
(1..3).each do |i|
|
93
|
+
@gene_pool.with_connection do |conn2|
|
94
|
+
assert_equal 1, conn1.to_i
|
95
|
+
assert_equal 2, conn2.to_i
|
96
|
+
assert_equal 2, @gene_pool.connections.size
|
97
|
+
assert_equal 2, @gene_pool.checked_out.size
|
98
|
+
assert_same conn1, @gene_pool.connections[0]
|
99
|
+
assert_same conn1, @gene_pool.checked_out[0]
|
100
|
+
assert_same conn2, @gene_pool.connections[1]
|
101
|
+
assert_same conn2, @gene_pool.checked_out[1]
|
102
|
+
end
|
103
|
+
assert_equal 1, @gene_pool.checked_out.size
|
104
|
+
end
|
105
|
+
@gene_pool.checkin(conn1)
|
106
|
+
assert_equal 0, @gene_pool.checked_out.size
|
107
|
+
end
|
108
|
+
|
109
|
+
should 'be able to reset multiple times' do
|
110
|
+
@gene_pool.with_connection do |conn1|
|
111
|
+
conn2 = @gene_pool.renew(conn1)
|
112
|
+
conn3 = @gene_pool.renew(conn2)
|
113
|
+
assert_equal 1, conn1.to_i
|
114
|
+
assert_equal 2, conn2.to_i
|
115
|
+
assert_equal 3, conn3.to_i
|
116
|
+
assert_equal 1, @gene_pool.connections.size
|
117
|
+
assert_equal 1, @gene_pool.checked_out.size
|
118
|
+
end
|
119
|
+
assert_equal 1, @gene_pool.connections.size
|
120
|
+
assert_equal 0, @gene_pool.checked_out.size
|
121
|
+
end
|
122
|
+
|
123
|
+
should 'be able to remove connection' do
|
124
|
+
@gene_pool.with_connection do |conn|
|
125
|
+
@gene_pool.remove(conn)
|
126
|
+
assert_equal 0, @gene_pool.connections.size
|
127
|
+
assert_equal 0, @gene_pool.checked_out.size
|
128
|
+
end
|
129
|
+
assert_equal 0, @gene_pool.connections.size
|
130
|
+
assert_equal 0, @gene_pool.checked_out.size
|
131
|
+
end
|
132
|
+
|
133
|
+
should 'be able to remove multiple connections' do
|
134
|
+
@gene_pool.with_connection do |conn1|
|
135
|
+
@gene_pool.with_connection do |conn2|
|
136
|
+
@gene_pool.with_connection do |conn3|
|
137
|
+
@gene_pool.remove(conn1)
|
138
|
+
@gene_pool.remove(conn3)
|
139
|
+
assert_equal 1, @gene_pool.connections.size
|
140
|
+
assert_equal 1, @gene_pool.checked_out.size
|
141
|
+
assert_same conn2, @gene_pool.checked_out[0]
|
142
|
+
assert_same conn2, @gene_pool.connections[0]
|
143
|
+
end
|
144
|
+
assert_equal 1, @gene_pool.connections.size
|
145
|
+
assert_equal 1, @gene_pool.checked_out.size
|
146
|
+
end
|
147
|
+
assert_equal 1, @gene_pool.connections.size
|
148
|
+
assert_equal 0, @gene_pool.checked_out.size
|
149
|
+
end
|
150
|
+
assert_equal 1, @gene_pool.connections.size
|
151
|
+
assert_equal 0, @gene_pool.checked_out.size
|
152
|
+
end
|
153
|
+
|
154
|
+
should 'handle aborted connection' do
|
155
|
+
@gene_pool.with_connection do |conn1|
|
156
|
+
@sleep = 2
|
157
|
+
@timeout = 1
|
158
|
+
begin
|
159
|
+
@gene_pool.with_connection { |conn2| }
|
160
|
+
flunk "connection should have timed out"
|
161
|
+
rescue Timeout::Error => e
|
162
|
+
#pass
|
163
|
+
end
|
164
|
+
assert_equal 1, @gene_pool.connections.size
|
165
|
+
assert_equal 1, @gene_pool.checked_out.size
|
166
|
+
end
|
167
|
+
assert_equal 1, @gene_pool.connections.size
|
168
|
+
assert_equal 0, @gene_pool.checked_out.size
|
169
|
+
# Do another test just to be sure nothings hosed
|
170
|
+
@sleep = nil
|
171
|
+
@gene_pool.with_connection do |conn1|
|
172
|
+
assert 1, conn1.to_i
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
should 'not allow more than pool_size connections' do
|
177
|
+
conns = []
|
178
|
+
pool_size = @gene_pool.pool_size
|
179
|
+
(1..pool_size).each do |i|
|
180
|
+
c = @gene_pool.checkout
|
181
|
+
conns << c
|
182
|
+
assert_equal i, c.to_i
|
183
|
+
assert_equal i, @gene_pool.connections.size
|
184
|
+
assert_equal i, @gene_pool.checked_out.size
|
185
|
+
assert_equal conns, @gene_pool.connections
|
186
|
+
end
|
187
|
+
begin
|
188
|
+
Timeout.timeout(1) do
|
189
|
+
@gene_pool.checkout
|
190
|
+
end
|
191
|
+
flunk "connection should have timed out"
|
192
|
+
rescue Timeout::Error => e
|
193
|
+
#pass "successfully timed out connection"
|
194
|
+
end
|
195
|
+
(1..pool_size).each do |i|
|
196
|
+
@gene_pool.checkin(conns[i-1])
|
197
|
+
assert_equal pool_size, @gene_pool.connections.size
|
198
|
+
assert_equal pool_size-i, @gene_pool.checked_out.size
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
should 'handle thread contention' do
|
203
|
+
conns = []
|
204
|
+
pool_size = @gene_pool.pool_size
|
205
|
+
# Do it with new connections and old connections
|
206
|
+
(1..2).each do |n|
|
207
|
+
(1..pool_size).each do |i|
|
208
|
+
Thread.new do
|
209
|
+
c = @gene_pool.checkout
|
210
|
+
conns[i-1] = c
|
211
|
+
end
|
212
|
+
end
|
213
|
+
# Let the threads complete
|
214
|
+
sleep 1
|
215
|
+
assert_equal pool_size, @gene_pool.connections.size
|
216
|
+
assert_equal pool_size, @gene_pool.checked_out.size
|
217
|
+
(1..pool_size).each do |i|
|
218
|
+
Thread.new do
|
219
|
+
@gene_pool.checkin(conns[i-1])
|
220
|
+
end
|
221
|
+
end
|
222
|
+
sleep 1
|
223
|
+
assert_equal pool_size, @gene_pool.connections.size
|
224
|
+
assert_equal 0, @gene_pool.checked_out.size
|
225
|
+
end
|
226
|
+
ival_conns = []
|
227
|
+
@gene_pool.each { |conn| ival_conns << conn.to_i }
|
228
|
+
ival_conns.sort!
|
229
|
+
assert_equal (1..pool_size).to_a, ival_conns
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gene_pool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Brad Pardee
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-09-08 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Generic pooling library for creating a connection pool
|
22
|
+
email: bradpardee@gmail.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
files:
|
31
|
+
- .gitignore
|
32
|
+
- History.txt
|
33
|
+
- LICENSE
|
34
|
+
- README.rdoc
|
35
|
+
- Rakefile
|
36
|
+
- VERSION
|
37
|
+
- gene_pool.gemspec
|
38
|
+
- lib/gene_pool.rb
|
39
|
+
- test/gene_pool_test.rb
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: http://github.com/bpardee/gene_pool
|
42
|
+
licenses: []
|
43
|
+
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options:
|
46
|
+
- --charset=UTF-8
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
version: "0"
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.3.6
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: Generic pooling library for creating a connection pool
|
70
|
+
test_files:
|
71
|
+
- test/gene_pool_test.rb
|