[Rigo] implement resume support on Repositories Update
This commit is contained in:
109
rigo/rigo_app.py
109
rigo/rigo_app.py
@@ -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")),
|
||||
|
||||
Reference in New Issue
Block a user