data_objects 0.10.0 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog.markdown +20 -0
- data/LICENSE +1 -29
- data/README.markdown +16 -2
- data/Rakefile +41 -7
- data/lib/data_objects.rb +3 -2
- data/lib/data_objects/byte_array.rb +6 -0
- data/lib/data_objects/connection.rb +21 -9
- data/lib/data_objects/logger.rb +15 -15
- data/lib/data_objects/pooling.rb +250 -0
- data/lib/data_objects/reader.rb +16 -0
- data/lib/data_objects/spec/bacon.rb +9 -0
- data/lib/data_objects/spec/command_spec.rb +54 -47
- data/lib/data_objects/spec/connection_spec.rb +119 -30
- data/lib/data_objects/spec/encoding_spec.rb +64 -6
- data/lib/data_objects/spec/helpers/immediate_red_green_output.rb +59 -0
- data/lib/data_objects/spec/helpers/pending.rb +22 -0
- data/lib/data_objects/spec/helpers/ssl.rb +21 -0
- data/lib/data_objects/spec/reader_spec.rb +47 -24
- data/lib/data_objects/spec/result_spec.rb +10 -19
- data/lib/data_objects/spec/typecast/array_spec.rb +16 -20
- data/lib/data_objects/spec/typecast/bigdecimal_spec.rb +16 -24
- data/lib/data_objects/spec/typecast/boolean_spec.rb +16 -24
- data/lib/data_objects/spec/typecast/byte_array_spec.rb +11 -15
- data/lib/data_objects/spec/typecast/class_spec.rb +7 -11
- data/lib/data_objects/spec/typecast/date_spec.rb +17 -25
- data/lib/data_objects/spec/typecast/datetime_spec.rb +18 -26
- data/lib/data_objects/spec/typecast/float_spec.rb +19 -27
- data/lib/data_objects/spec/typecast/integer_spec.rb +10 -14
- data/lib/data_objects/spec/typecast/nil_spec.rb +18 -30
- data/lib/data_objects/spec/typecast/other_spec.rb +45 -0
- data/lib/data_objects/spec/typecast/range_spec.rb +16 -20
- data/lib/data_objects/spec/typecast/string_spec.rb +72 -13
- data/lib/data_objects/spec/typecast/time_spec.rb +11 -15
- data/lib/data_objects/utilities.rb +18 -0
- data/lib/data_objects/version.rb +1 -2
- data/spec/command_spec.rb +2 -2
- data/spec/connection_spec.rb +7 -5
- data/spec/do_mock2.rb +31 -0
- data/spec/pooling_spec.rb +162 -0
- data/spec/reader_spec.rb +7 -4
- data/spec/result_spec.rb +2 -2
- data/spec/spec_helper.rb +26 -5
- data/spec/transaction_spec.rb +11 -9
- data/tasks/metrics.rake +36 -0
- data/tasks/release.rake +10 -70
- data/tasks/spec.rake +16 -14
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +53 -27
- data/HISTORY.markdown +0 -7
- data/Manifest.txt +0 -44
- data/spec/lib/pending_helpers.rb +0 -11
- data/spec/lib/rspec_immediate_feedback_formatter.rb +0 -53
- data/spec/lib/ssl_helpers.rb +0 -20
- data/tasks/gem.rake +0 -8
- data/tasks/install.rake +0 -13
data/ChangeLog.markdown
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
## 0.10.1 (unreleased, in git)
|
2
|
+
|
3
|
+
* Removal of Extlib dependency: Pooling and Utilities code moved to DataObjects.
|
4
|
+
* Switch to Jeweler for Gem building tasks (this change may be temporary).
|
5
|
+
* Switch to using Bacon for running specs: This should make specs friendlier to
|
6
|
+
new Ruby implementations that are not yet 100% MRI-compatible, and in turn,
|
7
|
+
prepared the road for our own IronRuby and MacRuby support.
|
8
|
+
* Make DataObjects::Reader Enumerable.
|
9
|
+
|
10
|
+
## 0.10.0 2009-09-15
|
11
|
+
|
12
|
+
* No Changes since 0.9.11
|
13
|
+
|
14
|
+
## 0.9.11 2009-01-19
|
15
|
+
* Fixes
|
16
|
+
* Use Extlib `Object.full_const_get` instead of custom code
|
17
|
+
* Remove Field as it was unused
|
18
|
+
|
19
|
+
## 0.9.9 2008-11-27
|
20
|
+
* No Changes since 0.9.8
|
data/LICENSE
CHANGED
@@ -1,32 +1,4 @@
|
|
1
|
-
Copyright (c) 2007
|
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.
|
21
|
-
|
22
|
-
---
|
23
|
-
---
|
24
|
-
|
25
|
-
Some portions of tasks/ext_helper_java.rb are verbatim copies of software
|
26
|
-
licensed under the MIT license. That license is included below:
|
27
|
-
|
28
|
-
Copyright (c) 2006-2008 Nick Sieger <nick@nicksieger.com>
|
29
|
-
Copyright (c) 2006-2008 Ola Bini <ola.bini@gmail.com>
|
1
|
+
Copyright (c) 2007 - 2010 Yehuda Katz, Dirkjan Bussink
|
30
2
|
|
31
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
32
4
|
a copy of this software and associated documentation files (the
|
data/README.markdown
CHANGED
@@ -1,4 +1,18 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# do_derby
|
2
|
+
|
3
|
+
* <http://dataobjects.info>
|
4
|
+
|
5
|
+
## Description
|
3
6
|
|
4
7
|
A unified Ruby API for popular databases.
|
8
|
+
|
9
|
+
## License
|
10
|
+
|
11
|
+
Licensed under the MIT license. Please see the {file:LICENSE} for more information.
|
12
|
+
|
13
|
+
## Contact
|
14
|
+
|
15
|
+
**IRC**: **Join us on IRC in #datamapper on irc.freenode.net!**<br/>
|
16
|
+
**Git**: <http://github.com/datamapper/do><br/>
|
17
|
+
**Author**: Dirkjan Bussink<br/>
|
18
|
+
**License**: MIT License
|
data/Rakefile
CHANGED
@@ -1,15 +1,49 @@
|
|
1
|
+
require 'pathname'
|
1
2
|
require 'rubygems'
|
2
3
|
require 'rake'
|
3
4
|
require 'rake/clean'
|
4
5
|
|
5
|
-
|
6
|
-
require 'lib/data_objects/version'
|
6
|
+
ROOT = Pathname(__FILE__).dirname.expand_path
|
7
7
|
|
8
|
-
ROOT
|
9
|
-
JRUBY = RUBY_PLATFORM =~ /java/
|
10
|
-
WINDOWS = Gem.win_platform?
|
11
|
-
SUDO = WINDOWS ? '' : ('sudo' unless ENV['SUDOLESS'])
|
8
|
+
require ROOT + 'lib/data_objects/version'
|
12
9
|
|
13
|
-
|
10
|
+
JRUBY = RUBY_PLATFORM =~ /java/
|
11
|
+
IRONRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ironruby'
|
12
|
+
WINDOWS = Gem.win_platform? || (JRUBY && ENV_JAVA['os.name'] =~ /windows/i)
|
13
|
+
SUDO = WINDOWS ? '' : ('sudo' unless ENV['SUDOLESS'])
|
14
14
|
|
15
15
|
CLEAN.include(%w[ pkg/ **/*.rbc ])
|
16
|
+
|
17
|
+
begin
|
18
|
+
gem 'jeweler', '~> 1.4'
|
19
|
+
require 'jeweler'
|
20
|
+
|
21
|
+
Jeweler::Tasks.new do |gem|
|
22
|
+
gem.name = 'data_objects'
|
23
|
+
gem.version = DataObjects::VERSION
|
24
|
+
gem.summary = 'DataObjects basic API and shared driver specifications'
|
25
|
+
gem.description = 'Provide a standard and simplified API for communicating with RDBMS from Ruby'
|
26
|
+
gem.platform = Gem::Platform::RUBY
|
27
|
+
gem.files = FileList["lib/**/*.rb", "spec/**/*.rb", "tasks/**/*.rake",
|
28
|
+
"LICENSE", "Rakefile", "*.{markdown,rdoc,txt,yml}"]
|
29
|
+
gem.test_files = FileList['spec/**/*.rb']
|
30
|
+
|
31
|
+
gem.add_dependency 'addressable', '~>2.1'
|
32
|
+
|
33
|
+
gem.add_development_dependency 'bacon', '~>1.1'
|
34
|
+
gem.add_development_dependency 'mocha', '~>0.9'
|
35
|
+
gem.add_development_dependency 'yard', '~>0.5'
|
36
|
+
|
37
|
+
gem.rubyforge_project = 'dorb'
|
38
|
+
|
39
|
+
gem.authors = ['Dirkjan Bussink']
|
40
|
+
gem.email = 'd.bussink@gmail.com'
|
41
|
+
gem.homepage = 'http://github.com/datamapper/do'
|
42
|
+
end
|
43
|
+
|
44
|
+
Jeweler::GemcutterTasks.new
|
45
|
+
|
46
|
+
FileList['tasks/**/*.rake'].each { |task| import task }
|
47
|
+
rescue LoadError
|
48
|
+
puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler'
|
49
|
+
end
|
data/lib/data_objects.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
require 'extlib'
|
2
|
-
|
3
1
|
require 'data_objects/version'
|
2
|
+
require 'data_objects/utilities'
|
4
3
|
require 'data_objects/logger'
|
4
|
+
require 'data_objects/byte_array'
|
5
|
+
require 'data_objects/pooling'
|
5
6
|
require 'data_objects/connection'
|
6
7
|
require 'data_objects/uri'
|
7
8
|
require 'data_objects/transaction'
|
@@ -15,16 +15,18 @@ module DataObjects
|
|
15
15
|
case uri.scheme.to_sym
|
16
16
|
when :java
|
17
17
|
warn 'JNDI URLs (connection strings) are only for use with JRuby' unless RUBY_PLATFORM =~ /java/
|
18
|
-
|
18
|
+
driver_name = uri.query.delete("scheme")
|
19
|
+
conn_uri = uri.to_s.gsub(/\?$/, '')
|
19
20
|
when :jdbc
|
20
21
|
warn 'JDBC URLs (connection strings) are only for use with JRuby' unless RUBY_PLATFORM =~ /java/
|
21
22
|
|
22
|
-
|
23
|
+
path = uri.path.sub(/jdbc:/, '')
|
24
|
+
driver_name = if path.split(':').first == 'sqlite'
|
23
25
|
'sqlite3'
|
24
|
-
elsif
|
26
|
+
elsif path.split(':').first == 'postgresql'
|
25
27
|
'postgres'
|
26
28
|
else
|
27
|
-
|
29
|
+
path.split(':').first
|
28
30
|
end
|
29
31
|
|
30
32
|
conn_uri = uri_s # NOTE: for now, do not reformat this JDBC connection
|
@@ -45,11 +47,24 @@ module DataObjects
|
|
45
47
|
driver_name.capitalize
|
46
48
|
end
|
47
49
|
|
48
|
-
DataObjects.const_get(driver_class)::Connection
|
50
|
+
clazz = DataObjects.const_get(driver_class)::Connection
|
51
|
+
unless clazz.method_defined? :close
|
52
|
+
if (uri.scheme.to_sym == :java)
|
53
|
+
clazz.class_eval do
|
54
|
+
alias close dispose
|
55
|
+
end
|
56
|
+
else
|
57
|
+
clazz.class_eval do
|
58
|
+
include Pooling
|
59
|
+
alias close release
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
clazz.new(conn_uri)
|
49
64
|
end
|
50
65
|
|
51
66
|
# Ensure that all Connection subclasses handle pooling and logging uniformly.
|
52
|
-
# See also
|
67
|
+
# See also DataObjects::Pooling and DataObjects::Logger
|
53
68
|
def self.inherited(target)
|
54
69
|
target.class_eval do
|
55
70
|
|
@@ -60,10 +75,7 @@ module DataObjects
|
|
60
75
|
instance
|
61
76
|
end
|
62
77
|
|
63
|
-
include Extlib::Pooling
|
64
78
|
include Quoting
|
65
|
-
|
66
|
-
alias close release
|
67
79
|
end
|
68
80
|
|
69
81
|
if driver_module_name = target.name.split('::')[-2]
|
data/lib/data_objects/logger.rb
CHANGED
@@ -51,16 +51,16 @@ module DataObjects
|
|
51
51
|
# The name of the log file
|
52
52
|
attr_reader :log
|
53
53
|
|
54
|
-
# @note
|
55
|
-
# Ruby (standard) logger levels:
|
56
|
-
# off: absolutely nothing
|
57
|
-
# fatal: an unhandleable error that results in a program crash
|
58
|
-
# error: a handleable error condition
|
59
|
-
# warn: a warning
|
60
|
-
# info: generic (useful) information about system operation
|
61
|
-
# debug: low-level information for developers
|
62
54
|
#
|
63
|
-
#
|
55
|
+
# Ruby (standard) logger levels:
|
56
|
+
# off: absolutely nothing
|
57
|
+
# fatal: an unhandleable error that results in a program crash
|
58
|
+
# error: a handleable error condition
|
59
|
+
# warn: a warning
|
60
|
+
# info: generic (useful) information about system operation
|
61
|
+
# debug: low-level information for developers
|
62
|
+
#
|
63
|
+
# DataObjects::Logger::LEVELS[:off, :fatal, :error, :warn, :info, :debug]
|
64
64
|
LEVELS =
|
65
65
|
{
|
66
66
|
:off => 99999,
|
@@ -201,12 +201,12 @@ module DataObjects
|
|
201
201
|
|
202
202
|
# Appends a string and log level to logger's buffer.
|
203
203
|
|
204
|
-
#
|
205
|
-
#
|
206
|
-
#
|
207
|
-
#
|
208
|
-
#
|
209
|
-
#
|
204
|
+
#
|
205
|
+
# Note that the string is discarded if the string's log level less than the
|
206
|
+
# logger's log level.
|
207
|
+
#
|
208
|
+
# Note that if the logger is aio capable then the logger will use
|
209
|
+
# non-blocking asynchronous writes.
|
210
210
|
#
|
211
211
|
# @param level<Fixnum> the logging level as an integer
|
212
212
|
# @param string<String> the message string to be logged
|
@@ -0,0 +1,250 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
module DataObjects
|
5
|
+
|
6
|
+
def self.exiting= bool
|
7
|
+
if bool && DataObjects.const_defined?('Pooling')
|
8
|
+
if DataObjects::Pooling.scavenger?
|
9
|
+
DataObjects::Pooling.scavenger.wakeup
|
10
|
+
end
|
11
|
+
end
|
12
|
+
@exiting = true
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.exiting
|
16
|
+
return @exiting if defined?(@exiting)
|
17
|
+
@exiting = false
|
18
|
+
end
|
19
|
+
|
20
|
+
# ==== Notes
|
21
|
+
# Provides pooling support to class it got included in.
|
22
|
+
#
|
23
|
+
# Pooling of objects is a faster way of aquiring instances
|
24
|
+
# of objects compared to regular allocation and initialization
|
25
|
+
# because instances are keeped in memory reused.
|
26
|
+
#
|
27
|
+
# Classes that include Pooling module have re-defined new
|
28
|
+
# method that returns instances acquired from pool.
|
29
|
+
#
|
30
|
+
# Term resource is used for any type of poolable objects
|
31
|
+
# and should NOT be thought as DataMapper Resource or
|
32
|
+
# ActiveResource resource and such.
|
33
|
+
#
|
34
|
+
# In Data Objects connections are pooled so that it is
|
35
|
+
# unnecessary to allocate and initialize connection object
|
36
|
+
# each time connection is needed, like per request in a
|
37
|
+
# web application.
|
38
|
+
#
|
39
|
+
# Pool obviously has to be thread safe because state of
|
40
|
+
# object is reset when it is released.
|
41
|
+
module Pooling
|
42
|
+
|
43
|
+
def self.scavenger?
|
44
|
+
defined?(@scavenger) && !@scavenger.nil? && @scavenger.alive?
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.scavenger
|
48
|
+
unless scavenger?
|
49
|
+
@scavenger = Thread.new do
|
50
|
+
running = true
|
51
|
+
while running do
|
52
|
+
# Sleep before we actually start doing anything.
|
53
|
+
# Otherwise we might clean up something we just made
|
54
|
+
sleep(scavenger_interval)
|
55
|
+
|
56
|
+
lock.synchronize do
|
57
|
+
pools.each do |pool|
|
58
|
+
# This is a useful check, but non-essential, and right now it breaks lots of stuff.
|
59
|
+
# if pool.expired?
|
60
|
+
pool.lock.synchronize do
|
61
|
+
if pool.expired?
|
62
|
+
pool.dispose
|
63
|
+
end
|
64
|
+
end
|
65
|
+
# end
|
66
|
+
end
|
67
|
+
|
68
|
+
# The pool is empty, we stop the scavenger
|
69
|
+
# It wil be restarted if new resources are added again
|
70
|
+
if pools.empty?
|
71
|
+
running = false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end # loop
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
@scavenger.priority = -10
|
79
|
+
@scavenger
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.pools
|
83
|
+
@pools ||= Set.new
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.append_pool(pool)
|
87
|
+
lock.synchronize do
|
88
|
+
pools << pool
|
89
|
+
end
|
90
|
+
DataObjects::Pooling.scavenger
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.lock
|
94
|
+
@lock ||= Mutex.new
|
95
|
+
end
|
96
|
+
|
97
|
+
class InvalidResourceError < StandardError
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.included(target)
|
101
|
+
target.class_eval do
|
102
|
+
class << self
|
103
|
+
alias __new new
|
104
|
+
end
|
105
|
+
|
106
|
+
@__pools = {}
|
107
|
+
@__pool_lock = Mutex.new
|
108
|
+
@__pool_wait = ConditionVariable.new
|
109
|
+
|
110
|
+
def self.__pool_lock
|
111
|
+
@__pool_lock
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.__pool_wait
|
115
|
+
@__pool_wait
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.new(*args)
|
119
|
+
(@__pools[args] ||= __pool_lock.synchronize { Pool.new(self.pool_size, self, args) }).new
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.__pools
|
123
|
+
@__pools
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.pool_size
|
127
|
+
8
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def release
|
133
|
+
@__pool.release(self) unless @__pool.nil?
|
134
|
+
end
|
135
|
+
|
136
|
+
def detach
|
137
|
+
@__pool.delete(self) unless @__pool.nil?
|
138
|
+
end
|
139
|
+
|
140
|
+
class Pool
|
141
|
+
attr_reader :available
|
142
|
+
attr_reader :used
|
143
|
+
|
144
|
+
def initialize(max_size, resource, args)
|
145
|
+
raise ArgumentError.new("+max_size+ should be a Fixnum but was #{max_size.inspect}") unless Fixnum === max_size
|
146
|
+
raise ArgumentError.new("+resource+ should be a Class but was #{resource.inspect}") unless Class === resource
|
147
|
+
|
148
|
+
@max_size = max_size
|
149
|
+
@resource = resource
|
150
|
+
@args = args
|
151
|
+
|
152
|
+
@available = []
|
153
|
+
@used = {}
|
154
|
+
DataObjects::Pooling.append_pool(self)
|
155
|
+
end
|
156
|
+
|
157
|
+
def lock
|
158
|
+
@resource.__pool_lock
|
159
|
+
end
|
160
|
+
|
161
|
+
def wait
|
162
|
+
@resource.__pool_wait
|
163
|
+
end
|
164
|
+
|
165
|
+
def scavenge_interval
|
166
|
+
@resource.scavenge_interval
|
167
|
+
end
|
168
|
+
|
169
|
+
def new
|
170
|
+
instance = nil
|
171
|
+
begin
|
172
|
+
lock.synchronize do
|
173
|
+
if @available.size > 0
|
174
|
+
instance = @available.pop
|
175
|
+
@used[instance.object_id] = instance
|
176
|
+
elsif @used.size < @max_size
|
177
|
+
instance = @resource.__new(*@args)
|
178
|
+
raise InvalidResourceError.new("#{@resource} constructor created a nil object") if instance.nil?
|
179
|
+
raise InvalidResourceError.new("#{instance} is already part of the pool") if @used.include? instance
|
180
|
+
instance.instance_variable_set(:@__pool, self)
|
181
|
+
instance.instance_variable_set(:@__allocated_in_pool, Time.now)
|
182
|
+
@used[instance.object_id] = instance
|
183
|
+
else
|
184
|
+
# Wait for another thread to release an instance.
|
185
|
+
# If we exhaust the pool and don't release the active instance,
|
186
|
+
# we'll wait here forever, so it's *very* important to always
|
187
|
+
# release your services and *never* exhaust the pool within
|
188
|
+
# a single thread.
|
189
|
+
wait.wait(lock)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end until instance
|
193
|
+
instance
|
194
|
+
end
|
195
|
+
|
196
|
+
def release(instance)
|
197
|
+
lock.synchronize do
|
198
|
+
instance.instance_variable_set(:@__allocated_in_pool, Time.now)
|
199
|
+
@used.delete(instance.object_id)
|
200
|
+
@available.push(instance)
|
201
|
+
wait.signal
|
202
|
+
end
|
203
|
+
nil
|
204
|
+
end
|
205
|
+
|
206
|
+
def delete(instance)
|
207
|
+
lock.synchronize do
|
208
|
+
instance.instance_variable_set(:@__pool, nil)
|
209
|
+
@used.delete(instance.object_id)
|
210
|
+
wait.signal
|
211
|
+
end
|
212
|
+
nil
|
213
|
+
end
|
214
|
+
|
215
|
+
def size
|
216
|
+
@used.size + @available.size
|
217
|
+
end
|
218
|
+
alias length size
|
219
|
+
|
220
|
+
def inspect
|
221
|
+
"#<DataObjects::Pooling::Pool<#{@resource.name}> available=#{@available.size} used=#{@used.size} size=#{@max_size}>"
|
222
|
+
end
|
223
|
+
|
224
|
+
def flush!
|
225
|
+
@available.pop.dispose until @available.empty?
|
226
|
+
end
|
227
|
+
|
228
|
+
def dispose
|
229
|
+
flush!
|
230
|
+
@resource.__pools.delete(@args)
|
231
|
+
!DataObjects::Pooling.pools.delete?(self).nil?
|
232
|
+
end
|
233
|
+
|
234
|
+
def expired?
|
235
|
+
@available.each do |instance|
|
236
|
+
if DataObjects.exiting || instance.instance_variable_get(:@__allocated_in_pool) + DataObjects::Pooling.scavenger_interval <= (Time.now + 0.02)
|
237
|
+
instance.dispose
|
238
|
+
@available.delete(instance)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
size == 0
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
|
246
|
+
def self.scavenger_interval
|
247
|
+
60
|
248
|
+
end
|
249
|
+
end # module Pooling
|
250
|
+
end # module DataObjects
|