ref: refs/heads/master commit 458b43dd8d2a3ccd182f7bf23ec9b305ff1b7ba5 Author: Ladislav Slezak <lslezak@novell.com> Date: Wed Nov 11 12:56:56 2009 +0100 - read avaliable patches in a separate thread (in background) - initial commit --- .../patches/app/controllers/patches_controller.rb | 7 ++- plugins/patches/app/models/background_status.rb | 27 +++++++++++ plugins/patches/app/models/patch.rb | 46 +++++++++++++++++-- plugins/patches/app/models/resolvable.rb | 19 +++++++- 4 files changed, 90 insertions(+), 9 deletions(-) diff --git a/plugins/patches/app/controllers/patches_controller.rb b/plugins/patches/app/controllers/patches_controller.rb index a743afb..6468c0c 100644 --- a/plugins/patches/app/controllers/patches_controller.rb +++ b/plugins/patches/app/controllers/patches_controller.rb @@ -27,7 +27,7 @@ class PatchesController < ApplicationController Rails.cache.write('patches:timestamp', Time.now) return # the cache expires after 5 minutes, repository metadata - # or RPM database update invalidates the cache immeditely + # or RPM database update invalidates the cache immediately # (new patches might be applicable) elsif cache_timestamp < 5.minutes.ago || cache_timestamp < Patch.mtime logger.debug "#### Patch cache expired" @@ -42,7 +42,10 @@ class PatchesController < ApplicationController # GET /patch_updates.xml def index # note: permission check was performed in :before_filter - @patches = Patch.find(:available) +# ActionController::Base.benchmark("Patches read") do + @patches = Patch.find(:available, {:background => true}) +# end + respond_to do |format| format.xml { render :xml => @patches.to_xml( :root => "patches", :dasherize => false ) } format.json { render :json => @patches.to_json( :root => "patches", :dasherize => false ) } diff --git a/plugins/patches/app/models/background_status.rb b/plugins/patches/app/models/background_status.rb new file mode 100644 index 0000000..9ee50f0 --- /dev/null +++ b/plugins/patches/app/models/background_status.rb @@ -0,0 +1,27 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +class BackgroundStatus + + attr_writer :status, + :progress, + :subprogress + + def initialize(stat = 'unknown', progress = 0, subprogress = nil) + @status = stat + @progress = progress + @subprogress = subprogress + end + + def to_xml(options = {}) + xml = options[:builder] ||= Builder::XmlMarkup.new(options) + xml.instruct! unless options[:skip_instruct] + + xml.tag! :background_status do + xml.tag!(:status, @status) + xml.tag!(:progress, @progress.to_i, {:type => "integer"} ) + xml.tag!(:subprogress, @subprogress.to_i, {:type => "integer"}) + end + end + +end diff --git a/plugins/patches/app/models/patch.rb b/plugins/patches/app/models/patch.rb index f50cef0..a6deb90 100644 --- a/plugins/patches/app/models/patch.rb +++ b/plugins/patches/app/models/patch.rb @@ -3,16 +3,17 @@ require 'resolvable' # Model for patches available via package kit class Patch < Resolvable + @@running = Hash.new + @@done = Hash.new + def to_xml( options = {} ) super :patch_update, options end - # find patches - # Patch.find(:available) - # Patch.find(212) - def self.find(what) + # find patches using PackageKit + def self.do_find(what, bg_status = nil) patch_updates = Array.new - self.execute("GetUpdates", "NONE", "Package") { |line1,line2,line3| + self.execute("GetUpdates", "NONE", "Package", bg_status) { |line1,line2,line3| columns = line2.split ";" if what == :available || columns[1] == what update = Patch.new(:resolvable_id => columns[1], @@ -28,6 +29,41 @@ class Patch < Resolvable return patch_updates end + # find patches + # Patch.find(:available) + # Patch.find(212) + def self.find(what, opts = {}) + background = opts[:background] + + if background + if @@done.has_key?(what) + Rails.logger.debug "Request #{what} is done" + @@running.delete(what) + return @@done.delete(what) + end + + running = @@running[what] + if running + Rails.logger.debug "Request #{what} is already running: #{running.inspect}" + return [running] + end + + bs = BackgroundStatus.new + @@running[what] = bs + + Rails.logger.info "Starting background thread for reading patches..." + Thread.new do + res = do_find(what, bs) + Rails.logger.info "*** Patches thread: Found #{res.size} applicable patches" + @@done[what] = res + end + + return [bs] + else + return do_find(what) + end + end + # installs this def install self.class.install(id) diff --git a/plugins/patches/app/models/resolvable.rb b/plugins/patches/app/models/resolvable.rb index 7b9acc3..f4e8331 100644 --- a/plugins/patches/app/models/resolvable.rb +++ b/plugins/patches/app/models/resolvable.rb @@ -130,10 +130,11 @@ public # # method: method to execute # args: arguments to method - # signal: signal to intercept (usuallay "Package") + # signal: signal to intercept (usually "Package") + # bg_stat: BackgroundStatus object for reporting progress (optional) # block: block to run on signal # - def self.execute(method, args, signal, &block) + def self.execute(method, args, signal, bg_stat = nil, &block) begin dbusloop = DBus::Main.new transaction_iface, packagekit_iface = self.packagekit_connect @@ -159,6 +160,20 @@ public # quit, bnc#561578 transaction_iface.send(method.to_sym, *args) + if bg_stat + proxy.on_signal("StatusChanged") do |s| + Rails.logger.debug "Background process: StatusChanged: #{s}" + bg_stat.status = s + end + + proxy.on_signal("ProgressChanged") do |p1, p2, p3, p4| + Rails.logger.debug "Background process: ProgressChanged: #{p1}%" + bg_stat.progress = p1 + # 101% means no subprogress available + bg_stat.subprogress = p2 < 101 ? p2 : nil + end + end + dbusloop << DBus::SystemBus.instance dbusloop.run -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org