check for running jobs before shutting down/rebooting
[enigma2.git] / lib / python / Components / Task.py
index 167de21..659660e 100644 (file)
@@ -7,6 +7,7 @@ class Job(object):
        NOT_STARTED, IN_PROGRESS, FINISHED, FAILED = range(4)
        def __init__(self, name):
                self.tasks = [ ]
        NOT_STARTED, IN_PROGRESS, FINISHED, FAILED = range(4)
        def __init__(self, name):
                self.tasks = [ ]
+               self.resident_tasks = [ ]
                self.workspace = "/tmp"
                self.current_task = 0
                self.callback = None
                self.workspace = "/tmp"
                self.current_task = 0
                self.callback = None
@@ -36,6 +37,9 @@ class Job(object):
 
        progress = property(getProgress)
 
 
        progress = property(getProgress)
 
+       def getStatustext(self):
+               return { self.NOT_STARTED: _("Waiting"), self.IN_PROGRESS: _("In Progress"), self.FINISHED: _("Finished"), self.FAILED: _("Failed") }[self.status]
+
        def task_progress_changed_CB(self):
                self.state_changed()
 
        def task_progress_changed_CB(self):
                self.state_changed()
 
@@ -52,28 +56,43 @@ class Job(object):
                self.status = self.IN_PROGRESS
                self.state_changed()
                self.runNext()
                self.status = self.IN_PROGRESS
                self.state_changed()
                self.runNext()
-               sumTaskWeightings = sum([t.weighting for t in self.tasks])
+               sumTaskWeightings = sum([t.weighting for t in self.tasks]) or 1
                self.weightScale = self.end / float(sumTaskWeightings)
 
        def runNext(self):
                if self.current_task == len(self.tasks):
                self.weightScale = self.end / float(sumTaskWeightings)
 
        def runNext(self):
                if self.current_task == len(self.tasks):
-                       cb = self.callback
-                       self.callback = None
-                       self.status = self.FINISHED
-                       self.state_changed()
-                       cb(self, None, [])
+                       if len(self.resident_tasks) == 0:
+                               cb = self.callback
+                               self.callback = None
+                               self.status = self.FINISHED
+                               self.state_changed()
+                               cb(self, None, [])
+                       else:
+                               print "still waiting for %d resident task(s) %s to finish" % (len(self.resident_tasks), str(self.resident_tasks))
                else:
                        self.tasks[self.current_task].run(self.taskCallback, self.task_progress_changed_CB)
                        self.state_changed()
 
                else:
                        self.tasks[self.current_task].run(self.taskCallback, self.task_progress_changed_CB)
                        self.state_changed()
 
-       def taskCallback(self, task, res):
+       def taskCallback(self, task, res, stay_resident = False):
+               cb_idx = self.tasks.index(task)
+               if stay_resident:
+                       if cb_idx not in self.resident_tasks:
+                               self.resident_tasks.append(self.current_task)
+                               print "task going resident:", task
+                       else:
+                               print "task keeps staying resident:", task
+                               return
                if len(res):
                        print ">>> Error:", res
                        self.status = self.FAILED
                        self.state_changed()
                        self.callback(self, task, res)
                if len(res):
                        print ">>> Error:", res
                        self.status = self.FAILED
                        self.state_changed()
                        self.callback(self, task, res)
-               else:
-                       self.state_changed();
+               if cb_idx != self.current_task:
+                       if cb_idx in self.resident_tasks:
+                               print "resident task finished:", task
+                               self.resident_tasks.remove(cb_idx)
+               if res == []:
+                       self.state_changed()
                        self.current_task += 1
                        self.runNext()
 
                        self.current_task += 1
                        self.runNext()
 
@@ -84,6 +103,8 @@ class Job(object):
        def abort(self):
                if self.current_task < len(self.tasks):
                        self.tasks[self.current_task].abort()
        def abort(self):
                if self.current_task < len(self.tasks):
                        self.tasks[self.current_task].abort()
+               for i in self.resident_tasks:
+                       self.tasks[i].abort()
 
        def cancel(self):
                # some Jobs might have a better idea of how to cancel a job
 
        def cancel(self):
                # some Jobs might have a better idea of how to cancel a job
@@ -142,7 +163,8 @@ class Task(object):
                from enigma import eConsoleAppContainer
                self.container = eConsoleAppContainer()
                self.container.appClosed.get().append(self.processFinished)
                from enigma import eConsoleAppContainer
                self.container = eConsoleAppContainer()
                self.container.appClosed.get().append(self.processFinished)
-               self.container.dataAvail.get().append(self.processOutput)
+               self.container.stdoutAvail.get().append(self.processStdout)
+               self.container.stderrAvail.get().append(self.processStderr)
 
                assert self.cmd is not None
                assert len(self.args) >= 1
 
                assert self.cmd is not None
                assert len(self.args) >= 1
@@ -150,7 +172,7 @@ class Task(object):
                if self.cwd is not None:
                        self.container.setCWD(self.cwd)
 
                if self.cwd is not None:
                        self.container.setCWD(self.cwd)
 
-               print "execute:", self.container.execute(self.cmd, self.args), self.cmd, self.args
+               print "execute:", self.container.execute(self.cmd, self.args), self.cmd, " ".join(self.args)
                if self.initial_input:
                        self.writeInput(self.initial_input)
 
                if self.initial_input:
                        self.writeInput(self.initial_input)
 
@@ -159,6 +181,12 @@ class Task(object):
 
        def cleanup(self, failed):
                pass
 
        def cleanup(self, failed):
                pass
+       
+       def processStdout(self, data):
+               self.processOutput(data)
+               
+       def processStderr(self, data):
+               self.processOutput(data)
 
        def processOutput(self, data):
                self.output_line += data
 
        def processOutput(self, data):
                self.output_line += data
@@ -189,7 +217,6 @@ class Task(object):
                        for postcondition in self.postconditions:
                                if not postcondition.check(self):
                                        not_met.append(postcondition)
                        for postcondition in self.postconditions:
                                if not postcondition.check(self):
                                        not_met.append(postcondition)
-
                self.cleanup(not_met)
                self.callback(self, not_met)
 
                self.cleanup(not_met)
                self.callback(self, not_met)
 
@@ -207,7 +234,6 @@ class Task(object):
                        progress = self.end
                if progress < 0:
                        progress = 0
                        progress = self.end
                if progress < 0:
                        progress = 0
-               print "progress now", progress
                self.__progress = progress
                self.task_progress_changed()
 
                self.__progress = progress
                self.task_progress_changed()
 
@@ -221,6 +247,7 @@ class JobManager:
                self.active_jobs = [ ]
                self.failed_jobs = [ ]
                self.job_classes = [ ]
                self.active_jobs = [ ]
                self.failed_jobs = [ ]
                self.job_classes = [ ]
+               self.in_background = False
                self.active_job = None
 
        def AddJob(self, job):
                self.active_job = None
 
        def AddJob(self, job):
@@ -235,10 +262,17 @@ class JobManager:
 
        def jobDone(self, job, task, problems):
                print "job", job, "completed with", problems, "in", task
 
        def jobDone(self, job, task, problems):
                print "job", job, "completed with", problems, "in", task
+               from Tools import Notifications
+               if self.in_background:
+                       from Screens.TaskView import JobView
+                       Notifications.AddNotification(JobView, self.active_job)
                if problems:
                if problems:
-                       from Tools import Notifications
                        from Screens.MessageBox import MessageBox
                        from Screens.MessageBox import MessageBox
-                       Notifications.AddNotificationWithCallback(self.errorCB, MessageBox, _("Error: %s\nRetry?") % (problems[0].getErrorMessage(task)))
+                       if problems[0].RECOVERABLE:
+                               Notifications.AddNotificationWithCallback(self.errorCB, MessageBox, _("Error: %s\nRetry?") % (problems[0].getErrorMessage(task)))
+                       else:
+                               Notifications.AddNotification(MessageBox, _("Error") + (': %s') % (problems[0].getErrorMessage(task)), type = MessageBox.TYPE_ERROR )
+                               self.errorCB(False)
                        return
                        #self.failed_jobs.append(self.active_job)
 
                        return
                        #self.failed_jobs.append(self.active_job)
 
@@ -255,6 +289,12 @@ class JobManager:
                        self.active_job = None
                        self.kick()
 
                        self.active_job = None
                        self.kick()
 
+       def getPendingJobs(self):
+               list = [ ]
+               if self.active_job:
+                       list.append(self.active_job)
+               list += self.active_jobs
+               return list
 # some examples:
 #class PartitionExistsPostcondition:
 #      def __init__(self, device):
 # some examples:
 #class PartitionExistsPostcondition:
 #      def __init__(self, device):
@@ -294,7 +334,7 @@ class Condition:
        RECOVERABLE = False
 
        def getErrorMessage(self, task):
        RECOVERABLE = False
 
        def getErrorMessage(self, task):
-               return _("An error has occured. (%s)") % (self.__class__.__name__)
+               return _("An unknown error occured!") + " (%s @ task %s)" % (self.__class__.__name__, task.__class__.__name__)
 
 class WorkspaceExistsPrecondition(Condition):
        def check(self, task):
 
 class WorkspaceExistsPrecondition(Condition):
        def check(self, task):