data_objects 0.10.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|