import sys import os.path import logging as log from argparse import ArgumentParser from util import spawnDaemon, splitHost 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 _checkFile(f): if not os.path.isfile(f): print("invalid file specified:",f,file=sys.stderr) sys.exit(1) def buildTree(args): _checkFile(args.datafile) if os.path.isfile(args.treefile): treeMod=os.stat(args.treefile).st_mtime dataMod=os.stat(args.datafile).st_mtime if dataMod<treeMod and not args.force: print("tree file is up to date") return tree=HashTree.fromFile(args.datafile) tree.save(args.treefile) def push(args): _checkFile(args.datafile) if args.tree: _checkFile(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=splitHost(h,conf.port) stats.reset() try: with ClientConnection(*host) as con: c.setConnection(con) c.init("push") blocksToTransfer=c.negotiate() c.sendData(blocksToTransfer) 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): _checkFile(args.datafile) if args.tree: _checkFile(args.tree) if args.host: conf.hosts=[args.host] if args.port: conf.port=args.port c=Client(args.datafile,args.tree) host=splitHost(conf.hosts[0],conf.port) try: with ClientConnection(*host) as con: c.setConnection(con) c.init("pull") blocksToTransfer=c.negotiate() c.pullData(blocksToTransfer,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): _checkFile(args.datafile) if args.tree: _checkFile(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) spawnDaemon(s.serve) except Exception as e: log.exception("exception: %s",e) print("Failed to start:\n ",e) parser=ArgumentParser() subparsers=parser.add_subparsers() pBuild=subparsers.add_parser("build") pBuild.add_argument("-f","--force",action="store_true",help="force tree rebuild") pBuild.add_argument("treefile", help="stored hash tree location") pBuild.add_argument("datafile") pBuild.set_defaults(func=buildTree) pUpdate=subparsers.add_parser("push") pUpdate.add_argument("-p","--port",type=int) pUpdate.add_argument("--host") pUpdate.add_argument("-t","--tree",help="stored hash tree location") pUpdate.add_argument("datafile") pUpdate.set_defaults(func=push) pUpdate=subparsers.add_parser("pull") pUpdate.add_argument("-p","--port",type=int) pUpdate.add_argument("--host") pUpdate.add_argument("-t","--tree",help="stored hash tree location") pUpdate.add_argument("-f","--force",action="store_true",help="ignore lock file") pUpdate.add_argument("datafile") pUpdate.set_defaults(func=pull) pServe=subparsers.add_parser("serve") pServe.add_argument("-p","--port",type=int) pServe.add_argument("--host") pServe.add_argument("-t","--tree",help="stored hash tree location") pServe.add_argument("datafile") pServe.set_defaults(func=serve) args=parser.parse_args() args.func(args)