Files @ 870c5c6c334f
Branch filter:

Location: Morevna/src/morevna.py

Laman
reacquiring old locks
import sys
import os.path
import logging as log
from argparse import ArgumentParser

from util import spawn_daemon, split_host
import config as conf
import stats
from hashtree import HashTree
from client import Client, Connection as ClientConnection, FailedConnection, DeniedConnection, IncompatibleException
from server import Miniserver


def _check_file(f):
	if not os.path.isfile(f):
		print("invalid file specified:", f, file=sys.stderr)
		sys.exit(1)


def build_tree(args):
	_check_file(args.datafile)
	if os.path.isfile(args.treefile):
		tree_mod = os.stat(args.treefile).st_mtime
		data_mod = os.stat(args.datafile).st_mtime
		if data_mod<tree_mod and not args.force:
			print("tree file is up to date")
			return

	tree = HashTree.from_file(args.datafile)
	tree.save(args.treefile)


def push(args):
	_check_file(args.datafile)
	if args.tree:
		_check_file(args.tree)
	if args.host: conf.hosts = [args.host]
	if args.port: conf.port = args.port

	c = Client(args.datafile, args.tree)
	for h in conf.hosts:
		host = split_host(h, conf.port)
		stats.reset()
		try:
			with ClientConnection(*host) as con:
				c.set_connection(con)
				c.init("push")
				blocks_to_transfer = c.negotiate()
				c.send_data(blocks_to_transfer)
			print()
			print(stats.report())
			print()
		except FailedConnection: pass
		except DeniedConnection as e:
			print("Server {0}:{1} denied connection.".format(*host))
			print(e)
		except IncompatibleException as e: print(e)


def pull(args):
	_check_file(args.datafile)
	if args.tree:
		_check_file(args.tree)
	if args.host: conf.hosts = [args.host]
	if args.port: conf.port = args.port

	c = Client(args.datafile, args.tree)
	host = split_host(conf.hosts[0], conf.port)
	try:
		with ClientConnection(*host) as con:
			c.set_connection(con)
			c.init("pull")
			blocks_to_transfer = c.negotiate()
			c.pull_data(blocks_to_transfer, args.force)
		print()
		print(stats.report())
	except FailedConnection: pass
	except DeniedConnection as e:
		print("Server {0}:{1} denied connection.".format(*host))
		print(e)


def serve(args):
	_check_file(args.datafile)
	if args.tree:
		_check_file(args.tree)
	if args.host: conf.hosts.insert(0, args.host)
	if args.port: conf.port = args.port

	try:
		s = Miniserver(args.datafile, args.tree)
		spawn_daemon(s.serve)
	except Exception as e:
		log.exception("exception: %s", e)
		print("Failed to start:\n  ", e)


parser = ArgumentParser()
subparsers = parser.add_subparsers()

p_build = subparsers.add_parser("build")
p_build.add_argument("-f", "--force", action="store_true", help="force tree rebuild")
p_build.add_argument("treefile", help="stored hash tree location")
p_build.add_argument("datafile")
p_build.set_defaults(func=build_tree)

p_update = subparsers.add_parser("push")
p_update.add_argument("-p", "--port", type=int)
p_update.add_argument("--host")
p_update.add_argument("-t", "--tree", help="stored hash tree location")
p_update.add_argument("datafile")
p_update.set_defaults(func=push)

p_update = subparsers.add_parser("pull")
p_update.add_argument("-p", "--port", type=int)
p_update.add_argument("--host")
p_update.add_argument("-t", "--tree", help="stored hash tree location")
p_update.add_argument("-f", "--force", action="store_true", help="ignore lock file")
p_update.add_argument("datafile")
p_update.set_defaults(func=pull)

p_serve = subparsers.add_parser("serve")
p_serve.add_argument("-p", "--port", type=int)
p_serve.add_argument("--host")
p_serve.add_argument("-t", "--tree", help="stored hash tree location")
p_serve.add_argument("datafile")
p_serve.set_defaults(func=serve)

args = parser.parse_args()
try: args.func(args)
except AttributeError:
	parser.print_help()