diff --git a/secondary.py b/secondary.py index 3b1bf39741aa32cbe976f168c0605953d9b01b6d..c7494bd3a547de9d5ba5ce16032f34545536b2ae 100644 --- a/secondary.py +++ b/secondary.py @@ -7,9 +7,11 @@ import loghandler import os import socket import subprocess +import threading import time import shutil import sys +import tar_stream def cond_unlink(path, log): try: @@ -43,10 +45,10 @@ class Status: class Backup: - def __init__(self, primary_star, mount, path, status, log): - self.primary_star = primary_star - self.primary_in = primary_star.makefile('wb') - self.primary_out = primary_star.makefile('rb') + def __init__(self, primary_tar, mount, path, status, log): + self.primary_tar = primary_tar + self.primary_in = primary_tar.makefile('wb') + self.primary_out = primary_tar.makefile('rb') self.mount = mount self.path = path self.status = status @@ -55,20 +57,25 @@ class Backup: self.trash_root = os.path.join(mount, 'TRASH').encode('utf-8') self.trash = os.path.join(self.trash_root, str(int(time.time())).encode('utf-8')) - extract_cmd = [ '/bin/star', '-x', '-no-fifo', - '-nowarn', '-no-statistics' ] - self.extract = subprocess.Popen(extract_cmd, - cwd=os.path.join(mount, path), - stdin=self.primary_out) - atexit.register(cond_kill, self.extract) - - # Make sure that the generated star archive is not empty + self.extractor = threading.Thread(daemon=True, target=self.run) + self.extractor.start() + # Make sure that the generated tar archive is not empty self.primary_in.write(b'.\0') + pass + + def run(self): + cwd = os.path.join(self.mount, self.path) + reader = tar_stream.TarReader(self.primary_out) + for e in reader: + self.make_room(e.size) + e.tarfile.extract(e, path=cwd) + pass def close(self): self.primary_in.flush() - self.primary_star.shutdown(socket.SHUT_WR) - self.status.extract_OK = self.extract.wait() + self.primary_tar.shutdown(socket.SHUT_WR) + self.extractor.join() + pass def check(self, src, dst): if src.name != dst.name: @@ -104,7 +111,7 @@ class Backup: self.status.unchanged += 1 def make_room(self, size): - for p in sorted(os.listdir(self.trash_root)): + while True: stat = os.statvfs(self.dst_root) free = stat.f_frsize * stat.f_bavail need = size + stat.f_frsize @@ -112,7 +119,8 @@ class Backup: break self.log.MESSAGE("Need to free:", need - free, (need, free), self.trash_root) - d = os.path.join(self.trash_root, p) + oldest = sorted(os.listdir(self.trash_root))[0] + d = os.path.join(self.trash_root, oldest) if os.path.isdir(d): self.log.MESSAGE('Removing dir', d) shutil.rmtree(d) @@ -123,11 +131,6 @@ class Backup: def add(self, src): self.log.DEBUG('Add:', src.name) - if len(src.size) == 0: - size = 0 - else: - size = int(src.size) - self.make_room(size) parent = os.path.dirname(src.name) while len(parent) != 0: # Make sure directories get the correct modes @@ -184,11 +187,11 @@ def do_backup(hash_name, options, socket_path, mount, path): atexit.register(cond_kill, p) dst = hashtoc.HashTOC(p.stdout, rename={hash_name:'sum'}) - # Connect to server star socket - primary_star = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - primary_star.connect(socket_path) + # Connect to server tar socket + primary_tar = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + primary_tar.connect(socket_path) - backup = Backup(primary_star=primary_star, + backup = Backup(primary_tar=primary_tar, mount=mount, path=path, status=status, log=log) while True: if src.name == None and dst.name == None: