Speed up of timeouts for wait up

This is identical to the patch for wait down on hosts.  This causes
wait up to return more quickly when a machine comes back on.  This
waits 10 seconds before retrying, the previous approach generally
waited the full length of timeout due to the delay required for ssh
connections to timeout.

Signed-off-by: Ryan Stutsman <stutsman@google.com>



git-svn-id: http://test.kernel.org/svn/autotest/trunk@651 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/tko/create_db b/tko/create_db
index e65dfdf..0c468d9 100644
--- a/tko/create_db
+++ b/tko/create_db
@@ -3,25 +3,24 @@
 -- kernel versions
 CREATE TABLE kversions (
 kversion INTEGER PRIMARY KEY,
-printable VARCHAR(100),			-- Full version with patches
-base VARCHAR(30)			-- Base version without patches
+kversion_hash VARCHAR(35),		-- Hash of base + all patches
+base VARCHAR(30),			-- Base version without patches
+printable VARCHAR(100)			-- Full version with patches
 );
 
 -- main jobs table
 CREATE TABLE jobs (
 job_idx INTEGER PRIMARY KEY,		-- index number
 tag VARCHAR(30),			-- job key
-kversion INTEGER,			-- index to kversion table
-status INTEGER,				-- Numerical status
-reason VARCHAR(100),			-- justification for status
 machine VARCHAR(20)			-- machine name
 );
 
 -- One entry per patch used, anywhere
 CREATE TABLE patches (
-patchref INTEGER PRIMARY KEY,		-- index number
+kversion INTEGER PRIMARY KEY,		-- index number
 name VARCHAR(20),			-- short name
-url VARCHAR(200)			-- full URL
+url VARCHAR(200),			-- full URL
+hash VARCHAR(35)
 );
 
 -- test functional results
@@ -43,9 +42,9 @@
 );
 
 -- test functional results
-CREATE TABLE iteration (
+CREATE TABLE iteration_result(
 test_idx INTEGER,			-- ref to test table
-interation INTEGER,			-- integer
+iteration INTEGER,			-- integer
 attribute VARCHAR(30),			-- attribute name (e.g. 'throughput')
 value FLOAT				-- attribute value (eg 700.1)
 );
diff --git a/tko/db.py b/tko/db.py
index 78c5790..054fab7 100644
--- a/tko/db.py
+++ b/tko/db.py
@@ -1,4 +1,4 @@
-import sqlite
+import sqlite, re
 
 class db:
 	def __init__(self):
@@ -13,13 +13,33 @@
 
 
 	def insert_job(self, tag, job):
+		# is kernel version in tree?
 		command = 'insert into jobs ' + \
-			'(job, version, status, reason, machine, kernel) ' +\
-			'values (%s, %s, %s, %s, %s, %s) '
-		values = (tag, job.kernel, job.status_num, job.reason, \
-			 job.machine, job.kernel)
+			'(tag, machine) ' + \
+			'values (%s, %s) '
+		print command
+		values = (tag, 'UNKNOWN')
 		self.cur.execute(command, values)
-		self.con.commit();
+		self.con.commit()
+		# Select it back from the job table and find the uniq key
+
+
+	def insert_test(self, job, 
+	def lookup_kernel_version(base, patches):
+		command = 'select kversion from kversions where base = %s'
+
+
+	def insert_kernel_version(base, patches):
+		base = re.sub(r'\+.*', '', printable)
+		command = 'select kversion from kversions where printable = %s'
+		self.cur.execute(command, tag)
+		results = self.cur.fetchall()
+		if results:
+			return results[0]
+		command = 'insert into kversions (printable, base) ' + \
+			  'values (%s, %s)'
+		self.cur.execute(command, (printable, base))
+		self.con.commit()
 
 
 	def find_job(self, tag):
diff --git a/tko/parse b/tko/parse
index bb85000..be79bb6 100755
--- a/tko/parse
+++ b/tko/parse
@@ -1,6 +1,9 @@
 #!/usr/bin/python
 import os, re, parse, db, sys
 
+if len(sys.argv) < 2:
+	raise "I need a path to the results directory"
+
 topdir = sys.argv[1]
 jobs_list = os.listdir(topdir)
 
@@ -11,9 +14,11 @@
 	print 'looking for ' + j
 	if db.find_job(j):
 		continue
-	job = parse.parse(os.path.join(topdir, j), 'regression')
+	job = parse.job(os.path.join(topdir, j), 'regression')
 	print 'parsed ' + j
 	if not job.kernel:
 		continue
-	print '%s %s %s %s' % (j, job.kernel, job.status, job.reason)
+	print '%s %s' % (j, job.kernel.base)
+	for test in job.tests:
+		print "\t%s %s %s" % (test.dir, test.status, test.reason)
 	db.insert_job(j, job)
diff --git a/tko/parse.py b/tko/parse.py
index 852a8f8..bb7c58f 100755
--- a/tko/parse.py
+++ b/tko/parse.py
@@ -1,5 +1,5 @@
 #!/usr/bin/python
-import os, re
+import os, re, md5
 
 valid_users = r'(apw|mbligh|andyw|korgtest)'
 build_stock = re.compile('build generic stock (2\.\S+)')	
@@ -33,20 +33,23 @@
 	return short
 
 
-class parse:
-	def __init__(self, topdir, type):
-		self.topdir = topdir
+class job:
+	def __init__(self, dir, type):
+		self.dir = dir
 		self.type = type
-		self.control = os.path.join(topdir, "autobench.dat")
-		self.set_status('NOSTATUS')
-		self.reason = ''
+		self.control = os.path.join(dir, "control")
 		self.machine = ''
 		self.variables = {}
+		self.tests = []
 		self.kernel = None
 
+		print 'FOOFACE ' + self.control
 		if not os.path.exists(self.control):
 			return
-		self.derive_kernel()
+		# HACK. we don't have proper build tags in the status file yet
+		# so we hardcode build/ and do it at the start of the job
+		print 'POOFACE'
+		self.kernel = kernel(os.path.join(dir, 'build'))
 		self.grope_status()
 
 
@@ -67,32 +70,16 @@
 				self.patches_long.append(segment.split(' ')[1])
 		self.patches_short = [shorten_patch(p) for p in self.patches_long]
 		
-		
-	def derive_kernel(self):
-		self.kernel = '2.6.18'
-
 
 	def grope_status(self):
-		status_file = os.path.join(self.topdir, "status")
-		try:
-			line = open(status_file, 'r').readline().rstrip()
-			(status, reason) = line.split(' ', 1)
-		except:
-			return
+		status_file = os.path.join(self.dir, "status")
+		for line in open(status_file, 'r').readlines():
+			(status, testname, reason) = line.rstrip().split(' ', 2)
 
-		for (a, b) in munge_reasons:
-			reason = re.sub(a, b, reason)
+		# for (a, b) in munge_reasons:
+		#	reason = re.sub(a, b, reason)
 
-		if reason.count('run completed unexpectedly'):
-			try:
-				if os.system('head $resultsdir{$job}/debug/test.log.0 | grep "autobench already running, exiting" > /dev/null'):
-					status = 'FAIL'
-					reason = 'autobench already running'
-			except:
-				pass
-
-		self.set_status(status)
-		self.reason = reason
+		self.tests.append(test(testname, status, reason))
 
 
 	def set_status(self, status):
@@ -100,3 +87,65 @@
 			return
 		self.status = status
 		self.status_num = status_num[status]
+
+
+class kernel:
+	def __init__(self, builddir):
+		self.base = None
+		self.patches = []
+
+		log = os.path.join(builddir, 'debug/build_log')
+		patch_hashes = []
+		for line in open(log, 'r'):
+			(type, rest) = line.split(': ', 1)
+			words = rest.split()
+			if type == 'BUILD VERSION':
+				self.base = words[0]
+			if type == 'PATCH':
+				self.patches.append(words[0:])
+				# patch_hashes.append(words[2])
+		self.kversion_hash = self.get_kversion_hash(self.base, patch_hashes)
+
+
+	def get_kversion_hash(self, base, patch_hashes):
+		"""\
+		Calculate a hash representing the unique combination of
+		the kernel base version plus 
+		"""
+		key_string = ','.join([base] + patch_hashes)
+		return md5.new(key_string).hexdigest()
+
+
+class test:
+	def __init__(self, dir, status, reason):
+		self.dir = dir
+		self.status = status
+		self.reason = reason
+		self.keyval = os.path.join(dir, 'results/keyval')
+		self.iterations = []
+
+		if not os.path.exists(self.keyval):
+			self.keyval = None
+			return
+		count = 1
+		lines = []
+		for line in open(self.keyval, 'r').readlines():
+			if not re.search('\S'):			# blank line
+				self.iterations.append(iteration(count, lines))
+				lines = []
+				count += 1
+				next
+			else:
+				lines.append(line)
+		if lines:
+			self.iterations.append(iteration(count, lines))
+
+
+class iteration:
+	def __init__(self, index, lines):
+		self.index = index
+		self.keyval = {}
+
+		for line in lines:
+			(key, value) = line.split('=', 1)
+			self.keyval[key] = value