import os from datetime import datetime import socket import logging as log import config as conf from networkers import NetworkReader, NetworkWriter from hashtree import HashTree lock_file = os.path.join(conf.directory, "dirty.lock") class FailedConnection(Exception): pass class LockedException(Exception): pass class IncompatibleException(Exception): pass class BaseConnection: # abstract def __init__(self): self._socket = None self.incoming = None self.outcoming = None def create_networkers(self): fr = self._socket.makefile(mode="rb") fw = self._socket.makefile(mode="wb") self.incoming = NetworkReader(fr) self.outcoming = NetworkWriter(fw) def __enter__(self): return self.incoming, self.outcoming def __exit__(self, exc_type, exc_val, exc_tb): try: self._socket.shutdown(socket.SHUT_RDWR) self._socket.close() except OSError: log.warning("broken connection") class NetNode: def __init__(self, filename, tree_file=""): self._incoming = None self._outcoming = None self._filename = filename self._tree_file = tree_file if tree_file: self._tree = HashTree.load(tree_file) else: self._tree = HashTree.from_file(filename) self._new_leaves = dict() def is_locked(self): return os.path.isfile(lock_file) def _lock(self): try: f = open(lock_file, "x") f.close() except FileExistsError: stat = os.stat(lock_file) dt = datetime.now().timestamp()-stat.st_mtime if dt<5*60: raise LockedException() log.warning("Found an old lock file ({0}s), ignoring it.".format(round(dt))) self._refresh_lock() def _refresh_lock(self): os.utime(lock_file) def _unlock(self): os.remove(lock_file) def _update_tree(self): log.info("updating hash tree...") self._tree.batch_update(self._new_leaves.items()) self._tree.save(self._tree_file) self._new_leaves = dict() log.info("tree updated")