--- a/backup.py Fri Jan 19 15:41:45 2018 +0000 +++ b/backup.py Fri Jan 19 16:00:36 2018 +0000 @@ -4,6 +4,7 @@ import config import logging +import time from instance import BorgInstance from queue import Queue from threading import Thread, Lock @@ -52,17 +53,19 @@ self.config=config self.lastrun=None + self.lastrun_success=None self.borg_instance=None + self.current_operation=None self.thread=None self.lock=Lock() def __block_when_running(self): - self.lock.acquire() - not_running=self.borg_instance is None and self.thread is None - self.lock.release() + with self.lock: + not_running=self.borg_instance is None and self.thread is None assert(not_running) def __listener(self): + success=True for status in iter(self.borg_instance.read, None): t=status['type'] if t=='progress_percent': @@ -70,6 +73,7 @@ elif t=='archive_progress': pass elif t=='progress_message': + # handle errors pass elif t=='progress_percent': pass @@ -78,18 +82,24 @@ elif t=='log_message': pass elif t=='exception': + success=False pass elif t=='unparsed_error': + success=False pass # What to do? print(status) logging.info('Borg subprocess finished; terminating listener thread') - self.lock.acquire() - self.borg_instance=None - self.thread=None - self.lock.release() + with self.lock: + if self.current_operation=='create': + self.lastrun=self.time_started + self.lastrun_success=success + self.borg_instance=None + self.thread=None + self.current_operation=None + self.time_started=None def __launch(self, queue, operation, archive_or_repository, *args): @@ -102,6 +112,8 @@ self.thread=t self.borg_instance=inst self.queue=queue + self.current_operation=operation + self.time_started=time.monotonic() t.start() @@ -122,16 +134,27 @@ # TODO: Decide exact (manual) abort mechanism. Perhaps two stages def abort(self): - self.lock.acquire() - if self.borg_instance: - self.borg_instance.terminate() - if self.thread: - self.thread.terminate() - self.lock.release() + with self.lock: + if self.borg_instance: + self.borg_instance.terminate() + if self.thread: + self.thread.terminate() def join(self): if self.thread: self.thread.join() + def next_action(): + # TODO pruning as well + now=time.monotonic() + if not self.lastrun: + return 'create', now+self.retry_interval + elif not self.lastrun_success: + return 'create', self.lastrun+self.retry_interval + else: + if self.backup_interval==0: + return 'none', 0 + else: + return 'create', self.lastrun+self.backup_interval