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")