Browse Source

Fix jobs not starting after a backup is no longer blocked

Nathaniel van Diepen 4 years ago
parent
commit
12465b5905
1 changed files with 40 additions and 8 deletions
  1. 40 8
      backup.py

+ 40 - 8
backup.py

@@ -1,6 +1,7 @@
 import contextlib
 import os
 import platform
+import psutil
 import shlex
 import subprocess
 import sys
@@ -67,15 +68,34 @@ class Job(object):
     def initPool():
         if Job.pool:
             maxthreads = Job.maxthreads
-            if len(Job.pool) < maxthreads:
-                maxthreads = len(Job.pool)
+            queued = Job.queued()
+            running = len(Job.running())
+            if maxthreads > running:
+                if len(queued) < maxthreads - running:
+                    maxthreads = len(queued)
 
-            for i in range(0, maxthreads):
-                Job.pool.pop(0).start()
+                if maxthreads:
+                    for i in range(0, maxthreads):
+                        print(queued[i])
+                        queued[i].start()
 
     @staticmethod
     def finished():
-        return not [x.state for x in Job.pool]
+        return [x for x in Job.pool if x.state in (Job.FAILED, Job.SUCCESSFUL)]
+
+    @staticmethod
+    def pending():
+        return [x for x in Job.pool
+                if x.state not in (Job.FAILED, Job.SUCCESSFUL)]
+
+    @staticmethod
+    def running():
+        return [x for x in Job.pool
+                if x.state is Job.RUNNING]
+
+    @staticmethod
+    def queued():
+        return [x for x in Job.pending() if x.state is Job.QUEUED]
 
     def __init__(self, backup, config):
         self._config = config
@@ -96,7 +116,10 @@ class Job(object):
             self.setState(Job.QUEUED)
 
         elif self._state is Job.RUNNING:
-            code = self._process.poll()
+            code = self._process.poll() or self._process.returncode
+            if code is None and not psutil.pid_exists(self._process.pid):
+                code = -1
+
             if code is not None:
                 self.setState(Job.FAILED if code else Job.SUCCESSFUL)
                 Job.initPool()
@@ -234,6 +257,8 @@ class Job(object):
             self.log('{0} -> {1}'.format(
                     self.getState(self._state), self.getState(state)))
             self._state = state
+            if state in (Job.SUCCESSFUL, Job.FAILED):
+                self.logfile.close()
 
     def getState(self, state=None):
         return {
@@ -372,6 +397,8 @@ class Backup(object):
                 for job in self.ready:
                     job.queue()
 
+                Job.initPool()
+
         elif self._status is Backup.QUEUED and self not in Backup._queue:
             self.setStatus(Backup.READY)
 
@@ -405,8 +432,9 @@ class Backup(object):
     def jobs(self):
         if not hasattr(self, '_jobs'):
             self._jobs = []
-            for job in self.config['jobs']:
-                self._jobs.append(Job(self, job))
+            if 'jobs' in self.config:
+                for job in self.config['jobs']:
+                    self._jobs.append(Job(self, job))
 
         return self._jobs
 
@@ -427,6 +455,8 @@ class Backup(object):
             self.log('{0} -> {1}'.format(
                 self.getStatus(self._status), self.getStatus(status)))
             self._status = status
+            if status in (Backup.SUCCESSFUL, Backup.FAILED):
+                self.logfile.close()
 
     def getStatus(self, status=None):
         return {
@@ -448,6 +478,8 @@ class Backup(object):
             for job in self.ready:
                 job.queue()
 
+            Job.initPool()
+
 
 def config():
     if hasattr(config, '_handle'):