#!/usr/bin/python

# Copyright 2008 VIFF Development Team.
#
# This file is part of VIFF, the Virtual Ideal Functionality Framework.
#
# VIFF is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License (LGPL) as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# VIFF is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
# Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with VIFF. If not, see <http://www.gnu.org/licenses/>.

import os
import sys
import time
import random
from subprocess import Popen, call
from optparse import OptionParser

parser = OptionParser("%prog [-n PLAYERS] [-t THRESHOLD] [-p PORT] "
                      "-f HOSTS | HOST...")
parser.add_option("-n", type="int", help="number of players")
parser.add_option("-t", type="int", help="corruption threshold")
parser.add_option("-p", type="int", help="port number")
parser.add_option("-f", "--file", help="read hosts from file")
parser.add_option("--skip-prss", action="store_true",
                  help="do not run test with PRSS")

parser.set_defaults(n=4, t=1, p=random.randint(3000, 10000), skip_prss=False)

options, args = parser.parse_args()

if options.file:
    fp = open(options.file)
    hosts = [line.strip() for line in fp.readlines()
             if line and not line.startswith("#")]
    fp.close()
else:
    hosts = args

if len(hosts) < options.n:
    parser.error("please supply a hostname for each player")

hosts = hosts[:options.n]

def cleanup():
    print "Cleanup..."
    for host in hosts:
        call(["ssh", host, "hostname; pkill -9 benchmark.py; ps -U $LOGNAME"])
    print "Cleanup done."
    sys.exit(-1)


runs = [("mul-passive", ["--passive"]),
        ("mul-active-hyper", ["--active", "--hyper"])]

if not options.skip_prss:
    runs.append(("mul-active-prss", ["--active", "--prss"]))

try:
    print "Benchmarking %d players" % options.n
    call(["./generate-certificates.py", "-n", str(options.n)])

    call(["./generate-config-files.py",
          "-n", str(options.n), "-t", str(options.t)] \
             + (options.skip_prss and ["--skip-prss"] or []) \
             + ["%s:%d" % (host, options.p) for host in hosts])

    processes = []

    for label, flags in runs:
        print
        print "Flags: %s" % ", ".join(flags)
        benchmark = "./benchmark.py -m '2**32' -c 1000 %s" % " ".join(flags)
        for id, host in zip(range(options.n, 0, -1), reversed(hosts)):
            cmdline = ["ssh", "-xa", host]
            time.sleep(1)
            data = "data-%d-%d-%s.txt" % (options.n, id, label)
            cmdline.append("cd %s; (uptime; %s player-%d.ini) &> %s"
                           % (os.getcwd(), benchmark, id, data))

            print "Connecting to %s" % host
            p = Popen(cmdline)
            processes.append(p)
        print "Waiting...",
        sys.stdout.flush()
        for p in processes:
            p.wait()
        print "done."

except KeyboardInterrupt:
    print "Caught Control-C!"
    cleanup()

