Class: CommonPool::ObjectPool

Inherits:
Object
  • Object
show all
Defined in:
lib/common_pool.rb

Overview

First in, first out object pooling implementation.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data_source = nil) {|self.config| ... } ⇒ ObjectPool

Initialize pool instance with default configuration options. Override config as a parameter passed to the block.

Yields:

Raises:

  • (ArgumentError)


112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/common_pool.rb', line 112

def initialize(data_source = nil, &proc)
  raise ArgumentError, "Data source is required." unless data_source      
  self.config = Configuration.new
  self.data_source = data_source
  @active_list          = {}
  @idle_list          = []
  @idle_check_status  = "Not Running"
  @mutex              = Mutex.new
  @cond               = ConditionVariable.new
  
  yield self.config if block_given?
  self.start_check_idle_thread
end

Instance Attribute Details

#active_listObject (readonly)

Returns the value of attribute active_list.



108
109
110
# File 'lib/common_pool.rb', line 108

def active_list
  @active_list
end

#configObject

Returns the value of attribute config.



109
110
111
# File 'lib/common_pool.rb', line 109

def config
  @config
end

#data_sourceObject

Returns the value of attribute data_source.



109
110
111
# File 'lib/common_pool.rb', line 109

def data_source
  @data_source
end

#idle_check_statusObject

Returns the value of attribute idle_check_status.



108
109
110
# File 'lib/common_pool.rb', line 108

def idle_check_status
  @idle_check_status
end

#idle_check_threadObject (readonly)

Returns the value of attribute idle_check_thread.



108
109
110
# File 'lib/common_pool.rb', line 108

def idle_check_thread
  @idle_check_thread
end

#idle_listObject (readonly)

Returns the value of attribute idle_list.



108
109
110
# File 'lib/common_pool.rb', line 108

def idle_list
  @idle_list
end

Instance Method Details

#borrow_objectObject

Borrow object from the pool. If max number of active objects reached, CommonPoolErrror will be thrown.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/common_pool.rb', line 138

def borrow_object
  @mutex.synchronize {
    if !@idle_list.empty?
      result = @idle_list.shift
      
    elsif @active_list.size < @config.max_active
      result = create_with_timestamp
      
    elsif @active_list.size >= @config.max_active
      raise CommonPoolError, "Max number of %d active objects reached." % @config.max_active
      
    else
      begin
        timeout(@config.timeout){ @cond.wait(@mutex) }
      rescue TimeoutError
        raise TimeoutError, "#{@config.timeout} seconds request timeout reached."
      end
      result = @idle_list.shift
    end
    @active_list.store(result[1].__id__, result)
    
    logger.debug("* Get #{result[1]}") if logger
    result[1]
  }
end

#clearObject

Clear object pool, set the idle list and used list to empty.



185
186
187
188
189
190
# File 'lib/common_pool.rb', line 185

def clear()
  @mutex.synchronize {
    @idle_list = []
    @active_list = {}
  }
end

#configure {|self.config| ... } ⇒ Object

Configure pool instance after initialization.

Yields:



127
128
129
130
# File 'lib/common_pool.rb', line 127

def configure(&proc)
  yield self.config 
  self.start_check_idle_thread
end

#invalidate_object(object) ⇒ Object

Invalidate object



176
177
178
179
180
181
182
# File 'lib/common_pool.rb', line 176

def invalidate_object(object)
  @mutex.synchronize {
    logger.debug("* Invalidate #{object}") if logger
    @active_list.delete(object.__id__)
    nil
  }
end

#max_active=(size) ⇒ Object

Reset the max active objects in the pool.



193
194
195
196
197
198
199
200
201
# File 'lib/common_pool.rb', line 193

def max_active=(size)
  @mutex.synchronize {
    if @idle_list.size + @active_list.size > size
      raise ArgumentError, "Cannot change max size to %d. There are objects over the size." % size
    end
    @config.max_active = size
  }
  size
end

#restart_check_idle_threadObject

Restart idle check thread



249
250
251
252
# File 'lib/common_pool.rb', line 249

def restart_check_idle_thread
  stop_idle_check_thread
  start_idle_check_thread
end

#return_object(object) ⇒ Object

Return object back to the pool.



165
166
167
168
169
170
171
172
173
# File 'lib/common_pool.rb', line 165

def return_object(object)
  logger.debug("* Return #{object}") if logger
  return if object.nil?
  if @active_list.delete(object.__id__)
    add_to_idle_list(object)
  else
    logger.debug("Session #{object} not returned, coz has been invalidated from used list.") if logger
  end
end

#startObject

Alias for check_idle_thread.



133
134
135
# File 'lib/common_pool.rb', line 133

def start
  start_check_idle_thread
end

#start_check_idle_threadObject

Start check idle objects thread, will only run if idle_check_interval is greater than 0.



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/common_pool.rb', line 204

def start_check_idle_thread
  @mutex.synchronize {
    return unless @config.idle_check_interval > 0 and @idle_check_thread.nil?
    @idle_check_status = "Checking..."
    
    @idle_check_thread = Thread.new do
      loop do
        thread_id = @idle_check_thread.__id__ if @idle_check_thread
        
        begin
          logger.debug(">> Starting idle objects check (Object ID: #{self.__id__}, Thread ID: #{thread_id})") if logger
          logger.debug("Status: " + self.status_info.map {|k,v| "#{k}=#{v}"}.join(', ')) if logger
          @idle_check_status = "Checking..."
          
          check_idle
          
          @idle_check_status = "Check status: OK. Sleeping now..."
        rescue Exception => e
          @idle_check_status = "Check status: Error - #{e.to_s} \n#{e.backtrace.join("\n")}. Sleeping...\n"
        end
        
        logger.debug(@idle_check_status) if logger
        if @config.idle_check_interval > 0 
          logger.debug(">> Sleeping (Object ID: #{self.__id__}, Thread ID: #{thread_id}) #{@config.idle_check_interval} seconds ...\n\n") if logger
          sleep @config.idle_check_interval
        else
          logger.debug(">> Idle check interval is set 0 or less. Thus idle check thread will only be executed once.") if logger
        end
      end
    end
  }
end

#status_infoObject

Return a hash of active and idle objects size with pool instance configuration options.



255
256
257
258
259
# File 'lib/common_pool.rb', line 255

def status_info
  {:active_objects => @active_list.size,
   :idle_objects => @idle_list.size,
   :idle_check_status => @idle_check_status}.merge(self.config.to_hash)
end

#stop_idle_check_threadObject

Stop idle check thread



238
239
240
241
242
243
244
245
246
# File 'lib/common_pool.rb', line 238

def stop_idle_check_thread
  if @idle_check_thread 
    logger.debug(">> Stopping idle objects check thread ...") if logger
    @idle_check_status = "Stopping..."
    @idle_check_thread.kill
    @idle_check_thread = nil
    @idle_check_status = "Not Running"
  end
end

#valid_idle_object?(object) ⇒ Boolean

Check if an idle object is valid, return false if validation_timeout period reached.

Returns:

  • (Boolean)


262
263
264
265
266
267
268
269
270
271
# File 'lib/common_pool.rb', line 262

def valid_idle_object?(object)
  begin
    timeout(self.config.validation_timeout) do 
      self.data_source.valid?(object)
    end
  rescue TimeoutError => e
    logger.debug("Timeout #{@config.validation_timeout} seconds validating object: #{object}") if logger
    false
  end
end