#!/usr/bin/python import os import re import sys import time # TODO: # 1. Examine testsuite status logdir = "log" def ifthen(cond, val1, val2, val0=None): if cond: return val1 if cond == None: return val0 return val2 def age_string(age): if age<60: return "%d s" % age if age<3600: return "%d m" % (age/60.0) if age<86400: return "%d h" % (age/3600.0) return "%d d" % (age/86400.0) def start_time(lines): timepat = re.compile(r"^DISTRIBUTE: \[(\d+-\d+-\d+ \d+:\d+:\d+)\]") for line in lines: match = timepat.search(line) if match: try: return time.mktime(time.strptime(match.group(1), "%Y-%m-%d %H:%M:%S")) except: return 0 return 0 def end_time(lines): timepat = re.compile(r"^DISTRIBUTE: \[(\d+-\d+-\d+ \d+:\d+:\d+)\]") for line in reversed(lines): match = timepat.search(line) if match: try: return time.mktime(time.strptime(match.group(1), "%Y-%m-%d %H:%M:%S")) except: return 0 return 0 def build_state(lines, configuration): builtpat = re.compile(r"^ *%s +\[built .*\]" % configuration) incompletepat = re.compile(r"^ *%s +\[incomplete\]" % configuration) for line in reversed(lines): if builtpat.search(line): return True if incompletepat.search(line): return False return None def run_state(lines): successpat = re.compile(r"^DISTRIBUTE: Simulation finished successfully") failpat = re.compile(r"^DISTRIBUTE: Simulation aborted") for line in reversed(lines): if successpat.search(line): return True if failpat.search(line): return False return None def distribute_state(lines): donepat = re.compile(r"^DISTRIBUTE: Done") abortedpat = re.compile(r"^DISTRIBUTE: Aborted") for line in reversed(lines): if donepat.search(line): return True if abortedpat.search(line): return False return None def error_state(lines): crashpat = re.compile(r"^Traceback") errorpat = re.compile(r"^Aborting Simfactory") for line in reversed(lines): if crashpat.search(line): return True # A crash (severe error) if errorpat.search(line): return False # A fatal error return None # No error # Show all tasks have completed while True: print files = os.listdir(logdir) files = filter(lambda file: re.match(r".*\.out$", file), files) outputs = [] num_done = num_aborted = num_working = 0 for file in files: (machine, ext) = os.path.splitext(file) path = os.path.join(logdir, file) f = open(path, "r") lines = f.readlines() # Consider only last 100k lines to speed things up lines = lines[:100] + lines[-100000:] f.close() #duration = end_time(lines[-10]) - start_time(lines[:10]) duration = os.path.getmtime(path) - start_time(lines[:10]) age = time.time() - os.path.getmtime(path) size = os.path.getsize(path) good_conf = (build_state(lines, "sim-debug" ) and build_state(lines, "sim" ) and build_state(lines, "sim-aligned")) good_sim = run_state(lines) error = error_state(lines) done = distribute_state(lines[-1:]) if done: num_done += 1 elif done == None: num_working += 1 else: num_aborted += 1 output = (machine, age, duration, size, good_conf, good_sim, error, done) outputs.append(output) sys.stdout.write(".") sys.stdout.flush() sys.stdout.write("\r" + " "*len(files) + "\r") sys.stdout.flush() print ("%s: %d machines (%d working, %d done, %d aborted)" % (time.strftime("%Y-%m-%d %H:%M:%S"), len(files), num_working, num_done, num_aborted)) print (" %-12s %5s %5s %10s %s" % ("Machine", "age", "dur'n", "size", "state")) print " ============================================================================" # sort by age outputs.sort(key=lambda output: output[1]) for output in outputs: (machine, age, duration, size, good_conf, good_sim, error, done) = output age_str = age_string(age) duration_str = age_string(duration) good_conf_str = ifthen(good_conf, " [conf]", "", "") good_sim_str = ifthen(good_sim, " [success]", " [failure]", "") error_str = ifthen(error, " [CRASH]", " [ERROR]", "") done_str = ifthen(done, " [done]", " [aborted]", " working...") state_str = "".join([good_conf_str, good_sim_str, error_str, done_str]) print (" %-12s %5s %5s %10d %s" % (machine[:12], age_str, duration_str, size, state_str)) time.sleep(60)