[Rigo] implement resume support on Repositories Update

This commit is contained in:
Fabio Erculiani
2012-03-13 23:35:50 +01:00
parent 5d42022464
commit 7d262a71e2

View File

@@ -195,6 +195,14 @@ class RigoServiceController(GObject.Object):
if our_signals:
sig_match = our_signals.pop(0)
sig_match.remove()
else:
# somebody already consumed this signal
if const_debug_enabled():
const_debug_write(
__name__,
"_repositories_updated_signal: "
"already consumed")
return
self._scale_down() # do we really need this? not really i think
self._release_local_resources()
@@ -203,7 +211,9 @@ class RigoServiceController(GObject.Object):
self.emit("repositories-updated")
if const_debug_enabled():
const_debug_write(__name__, "RigoServiceController: unlock-ui")
const_debug_write(
__name__,
"_repositories_updated_signal: repositories-updated")
def _output_signal(self, text, header, footer, back, importance, level,
count_c, count_t, percent):
@@ -348,7 +358,6 @@ class RigoServiceController(GObject.Object):
in exclusive mode. Scale up privileges, and ask for
root password if not done yet.
"""
# FIXME, complete, need to be nice and not block, etc
# FIXME, ask for password.
acquired_sem = Semaphore(0)
@@ -428,7 +437,8 @@ class RigoServiceController(GObject.Object):
self._update_repositories_unlocked(
repositories, force)
def _update_repositories_unlocked(self, repositories, force):
def _update_repositories_unlocked(self, repositories, force,
execute_method=True):
"""
Internal method handling the actual Repositories Update
execution.
@@ -457,13 +467,23 @@ class RigoServiceController(GObject.Object):
# 1 -- ACTIVITY CRIT :: ON
self._activity_rwsem.writer_acquire()
# connect our signal
sig_match = self._entropy_bus.connect_to_signal(
self._REPOSITORIES_UPDATED_SIGNAL,
self._repositories_updated_signal,
dbus_interface=self.DBUS_INTERFACE)
signal_sem = Semaphore(1)
def _repositories_updated_signal(result, message):
if not signal_sem.acquire(False):
# already called, no need to call again
return
# this is done in order to have it called
# only once by two different code paths
self._repositories_updated_signal(result, message)
with self._registered_signals_mutex:
# connect our signal
sig_match = self._entropy_bus.connect_to_signal(
self._REPOSITORIES_UPDATED_SIGNAL,
_repositories_updated_signal,
dbus_interface=self.DBUS_INTERFACE)
# and register it as a signal generated by us
obj = self._registered_signals.setdefault(
self._REPOSITORIES_UPDATED_SIGNAL, [])
@@ -477,10 +497,43 @@ class RigoServiceController(GObject.Object):
self._terminal.reset()
self._release_local_resources()
iface = dbus.Interface(
self._entropy_bus,
dbus_interface=self.DBUS_INTERFACE)
iface.update_repositories(repositories, force)
if execute_method:
dbus.Interface(
self._entropy_bus,
dbus_interface=self.DBUS_INTERFACE
).update_repositories(repositories, force)
else:
# check if we need to cope with races
self._update_repositories_signal_check(
sig_match, signal_sem)
def _update_repositories_signal_check(self, sig_match, signal_sem):
"""
Called via _update_repositories_unlocked() in order to handle
the possible race between RigoDaemon signal and the fact that
we just lost it.
"""
activity = self.activity()
if activity == ActivityStates.UPDATING_REPOSITORIES:
return
# lost the signal or not, we're going to force
# the callback.
if not signal_sem.acquire(False):
# already called, no need to call again
const_debug_write(
__name__,
"_update_repositories_signal_check: abort")
return
const_debug_write(
__name__,
"_update_repositories_signal_check: accepting")
# Run in the main loop, to avoid calling a signal
# callback in random threads.
GLib.idle_add(self._repositories_updated_signal,
0, "")
def update_repositories(self, repositories, force):
"""
@@ -570,7 +623,6 @@ class WorkViewController(GObject.Object):
self._box.pack_start(box, True, True, 0)
self._service.set_terminal(self._terminal)
self._service.set_work_controller(self)
self.deactivate_progress_bar()
self.deactivate_app_box()
@@ -2123,6 +2175,7 @@ class Rigo(Gtk.Application):
self._work_view_c = WorkViewController(
self._service, self._work_view)
self._service.set_work_controller(self._work_view_c)
def is_ui_locked(self):
"""
@@ -2317,8 +2370,11 @@ class Rigo(Gtk.Application):
acquired = not self._entropy.wait_resources(
max_lock_count=1,
shared=True)
is_exclusive = False
if not acquired:
# check whether RigoDaemon is running in excluive mode
# and ignore non-atomicity here (failing with error
# is acceptable)
if not self._service.is_exclusive():
self._show_ok_dialog(
None,
@@ -2327,6 +2383,7 @@ class Rigo(Gtk.Application):
entropy.tools.kill_threads()
Gtk.main_quit()
return
is_exclusive = True
# otherwise we can go ahead and handle our state later
# check RigoDaemon, don't worry about races between Rigo Clients
@@ -2335,11 +2392,21 @@ class Rigo(Gtk.Application):
# based rwsem).
activity = self._service.activity()
if activity != ActivityStates.AVAILABLE:
msg = ""
show_dialog = True
if activity == ActivityStates.NOT_AVAILABLE:
msg = _("Background Service is currently not available")
elif activity == ActivityStates.UPDATING_REPOSITORIES:
# FIXME, jump to WORK_VIEW and show the progress.
msg = _("Background Service is updating repositories")
show_dialog = False
task = ParallelTask(
self._service._update_repositories_unlocked,
[], False, execute_method=False)
task.daemon = True
task.name = "UpdateRepositoriesUnlocked"
task.start()
elif activity == ActivityStates.INSTALLING_APPLICATION:
# FIXME, jump to WORK_VIEW and show the progress.
msg = _("Background Service is installing Applications")
@@ -2351,6 +2418,18 @@ class Rigo(Gtk.Application):
else:
msg = _("Background Service is incompatible with Rigo")
if show_dialog:
self._show_ok_dialog(
None,
escape_markup(_("Rigo")),
escape_markup(msg))
entropy.tools.kill_threads()
Gtk.main_quit()
return
elif is_exclusive:
msg = _("Background Service is currently unavailable")
# no lock acquired, cannot continue the initialization
self._show_ok_dialog(
None,
escape_markup(_("Rigo")),