[yast-commit] <rest-service> master : change BackgroundManager module to a singleton object
ref: refs/heads/master commit 94553d8777b6fb544d7d822b3428e227b851e7f9 Author: Ladislav Slezak <lslezak@novell.com> Date: Wed Dec 16 19:57:58 2009 +0100 change BackgroundManager module to a singleton object --- plugins/patches/app/models/patch.rb | 41 ++++++++++++++--------- plugins/status/lib/status.rb | 29 ++++++++++------ webservice/lib/background_manager.rb | 58 ++++++++++++++++++---------------- 3 files changed, 74 insertions(+), 54 deletions(-) diff --git a/plugins/patches/app/models/patch.rb b/plugins/patches/app/models/patch.rb index bee5300..638ecc4 100644 --- a/plugins/patches/app/models/patch.rb +++ b/plugins/patches/app/models/patch.rb @@ -3,10 +3,19 @@ require 'resolvable' # Model for patches available via package kit class Patch < Resolvable - # extend adds the module methods as class methods - # (used instead of include because background processes - # are used in class methods here) - extend BackgroundManager + private + + # just a short cut for accessing the singleton object + def self.bm + BackgroundManager.instance + end + + # create unique id for the background manager + def self.id(what) + "patches_#{what}" + end + + public def to_xml( options = {} ) super :patch_update, options @@ -37,8 +46,6 @@ class Patch < Resolvable result = nil - process_id = what - while !subproc.eof? do begin line = subproc.readline @@ -53,7 +60,7 @@ class Patch < Resolvable elsif received.has_key? 'background_status' s = received['background_status'] - update_progress process_id do |bs| + bm.update_progress id(what) do |bs| bs.status = s['status'] bs.progress = s['progress'] bs.subprogress = s['subprogress'] @@ -84,34 +91,36 @@ class Patch < Resolvable # background reading doesn't work correctly if class reloading is active # (static class members are lost between requests) - if background && !background_enabled? + if background && !bm.background_enabled? Rails.logger.info "Class reloading is active, cannot use background thread (set config.cache_classes = true)" background = false end if background - if process_finished? what - Rails.logger.debug "Request #{what} is done" - return get_value what + proc_id = id(what) + if bm.process_finished? proc_id + Rails.logger.debug "Request #{proc_id} is done" + return bm.get_value proc_id end - running = get_progress what + running = bm.get_progress proc_id if running - Rails.logger.debug "Request #{what} is already running: #{running.inspect}" + Rails.logger.debug "Request #{proc_id} is already running: #{running.inspect}" return [running] end - add_process what + + bm.add_process proc_id Rails.logger.info "Starting background thread for reading patches..." # run the patch query in a separate thread Thread.new do res = subprocess_find what Rails.logger.info "*** Patches thread: Found #{res.size} applicable patches" - finish_process(what, res) + bm.finish_process(proc_id, res) end - return [ get_progress(what) ] + return [ bm.get_progress(proc_id) ] else return do_find(what) end diff --git a/plugins/status/lib/status.rb b/plugins/status/lib/status.rb index cfbf3d9..9ad67e0 100644 --- a/plugins/status/lib/status.rb +++ b/plugins/status/lib/status.rb @@ -31,7 +31,14 @@ class Status :metrics, :limits - include BackgroundManager + private + + # just a short cut for accessing the singleton object + def bm + BackgroundManager.instance + end + + public def to_xml(options = {}) if @data.class == Hash && @data.size == 1 && @data[:progress].class == BackgroundStatus @@ -173,14 +180,14 @@ class Status end def create_unique_key(start, stop, data) - start.to_i.to_s + '_' + stop.to_i.to_s + '_' + data.to_s + 'status_' + start.to_i.to_s + '_' + stop.to_i.to_s + '_' + data.to_s end # this is a wrapper to collect_data def collect_data(start=nil, stop=nil, data = %w{cpu memory disk}, background = false) # background reading doesn't work correctly if class reloading is active # (static class members are lost between requests) - if background && !background_enabled? + if background && !bm.background_enabled? Rails.logger.info "Class reloading is active, cannot use background thread (set config.cache_classes = true)" background = false end @@ -188,32 +195,32 @@ class Status if background key = create_unique_key(start, stop, data) - if process_finished? key + if bm.process_finished? key Rails.logger.debug "Request #{key} is done" - @data = get_value key + @data = bm.get_value key @data.delete :progress return @data end - running = get_progress key + running = bm.get_progress key if running Rails.logger.debug "Request #{key} is already running: #{running.inspect}" @data = {:progress => running} return @data end - add_process(key) + bm.add_process(key) # read the status in a separate thread Thread.new do Rails.logger.info '*** Background thread for reading status started...' res = collect_status_data(start, stop, data, true) - finish_process(key, res) + bm.finish_process(key, res) Rails.logger.info '*** Finishing background status thread' end # return current progress - @data = {:progress => get_progress(key)} + @data = {:progress => bm.get_progress(key)} return @data else collect_status_data(start, stop, data) @@ -234,7 +241,7 @@ class Status metrics.each_pair do |m, n| if progress - update_progress key do |stat| + bm.update_progress key do |stat| stat.status = m.to_s stat.progress = 100 * current_step / total_steps Rails.logger.debug "*** Reading status: #{stat.status}: #{stat.progress}%" @@ -253,7 +260,7 @@ class Status total_steps = data.size if progress data.each do |d| if progress - update_progress key do |stat| + bm.update_progress key do |stat| stat.status = d.to_s stat.progress = 100 * current_step / total_steps Rails.logger.debug "*** Reading status: #{stat.status}: #{stat.progress}%" diff --git a/webservice/lib/background_manager.rb b/webservice/lib/background_manager.rb index 722d078..fead92d 100644 --- a/webservice/lib/background_manager.rb +++ b/webservice/lib/background_manager.rb @@ -1,68 +1,72 @@ -# this is a helper module for managing background processes with progress +# this is a singleton class for managing background processes with progress # for long running tasks -module BackgroundManager - # class variables - they keep the information between requests - # DO NOT USE THEM DIRECTLY, USE THE THREAD SAFE METHODS BELOW! - # - # currently running requests in background (current states) - @@running = Hash.new - # finished requests (actual results) - @@done = Hash.new - # a mutex which guards access to the shared class variables above - @@mutex = Mutex.new +class BackgroundManager + + include Singleton + + # instance variables - they keep the information between requests + + def initialize + # currently running requests in background (current states) + @running = Hash.new + # finished requests (actual results) + @done = Hash.new + # a mutex which guards access to the shared class variables above + @mutex = Mutex.new + end # define a new background process # id is unique ID def add_process(id) - @@mutex.synchronize do - @@running[id] = BackgroundStatus.new unless @@running.has_key?(id) + @mutex.synchronize do + @running[id] = BackgroundStatus.new unless @running.has_key?(id) end end # is the process running? def process_running?(id) - @@mutex.synchronize do - return @@running.has_key? id + @mutex.synchronize do + return @running.has_key? id end end # is the process finished? def process_finished?(id) - @@mutex.synchronize do - return @@done.has_key? id + @mutex.synchronize do + return @done.has_key? id end end # remove the progress status and remember the real final value def finish_process(id, value) - @@mutex.synchronize do - @@running.delete(id) - @@done[id] = value + @mutex.synchronize do + @running.delete(id) + @done[id] = value end end # get the current progress # returns a copy, use update_progress() for updating the progress def get_progress(id) - @@mutex.synchronize do - ret = @@running[id] + @mutex.synchronize do + ret = @running[id] ret.nil? ? nil : ret.dup end end # get the final value, the value is removed from the internal structure def get_value(id) - @@mutex.synchronize do - return @@done.delete id + @mutex.synchronize do + return @done.delete id end end # update the progress def update_progress(id, &block) - @@mutex.synchronize do - bs = @@running[id] + @mutex.synchronize do + bs = @running[id] yield bs if bs && block_given? end @@ -71,7 +75,7 @@ module BackgroundManager # is background processing possible? # if cache_classes is disabled it is not possible # because all classes are reloaded between requests - # and the static attributes keeping the progress are lost + # and the attributes keeping the progress are lost def background_enabled? return Rails.configuration.cache_classes end -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org
participants (1)
-
Ladislav Slezak