import time, os
from autotest_lib.client.bin import test, os_dep, utils
from autotest_lib.client.common_lib import error
class btreplay(test.test):
version = 1
# http://brick.kernel.dk/snaps/blktrace-git-latest.tar.gz
def setup(self, tarball = 'blktrace-git-latest.tar.gz'):
tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir)
utils.extract_tarball_to_dir(tarball, self.srcdir)
self.job.setup_dep(['libaio'])
libs = '-L' + self.autodir + '/deps/libaio/lib -laio'
cflags = '-I ' + self.autodir + '/deps/libaio/include'
var_libs = 'LIBS="' + libs + '"'
var_cflags = 'CFLAGS="' + cflags + '"'
self.make_flags = var_libs + ' ' + var_cflags
os.chdir(self.srcdir)
utils.system('patch -p1 < ../Makefile.patch')
utils.system(self.make_flags + ' make')
def initialize(self):
self.job.require_gcc()
self.ldlib = 'LD_LIBRARY_PATH=%s/deps/libaio/lib'%(self.autodir)
self.results = []
def run_once(self, dev="", devices="", extra_args='', tmpdir=None):
# @dev: The device against which the trace will be replayed.
# e.g. "sdb" or "md_d1"
# @devices: A space-separated list of the underlying devices
# which make up dev, e.g. "sdb sdc". You only need to set
# devices if dev is an MD, LVM, or similar device;
# otherwise leave it as an empty string.
if not tmpdir:
tmpdir = self.tmpdir
os.chdir(self.srcdir)
alldevs = "-d /dev/" + dev
alldnames = dev
for d in devices.split():
alldevs += " -d /dev/" + d
alldnames += " " + d
# convert the trace (assumed to be in this test's base
# directory) into btreplay's required format
#
# TODO: The test currently halts here as there is no trace in the
# test's base directory.
cmd = "./btreplay/btrecord -d .. -D %s %s" % (tmpdir, dev)
self.results.append(utils.system_output(cmd, retain_output=True))
# time a replay that omits "thinktime" between requests
# (by use of the -N flag)
cmd = self.ldlib + " /usr/bin/time ./btreplay/btreplay -d "+\
tmpdir+" -N -W "+dev+" "+extra_args+" 2>&1"
self.results.append(utils.system_output(cmd, retain_output=True))
# trace a replay that reproduces inter-request delays, and
# analyse the trace with btt to determine the average request
# completion latency
utils.system("./blktrace -D %s %s >/dev/null &" % (tmpdir, alldevs))
cmd = self.ldlib + " ./btreplay/btreplay -d %s -W %s %s" %\
(tmpdir, dev, extra_args)
self.results.append(utils.system_output(cmd, retain_output=True))
utils.system("killall -INT blktrace")
# wait until blktrace is really done
slept = 0.0
while utils.system("ps -C blktrace > /dev/null",
ignore_status=True) == 0:
time.sleep(0.1)
slept += 0.1
if slept > 30.0:
utils.system("killall -9 blktrace")
raise error.TestError("blktrace failed to exit in 30 seconds")
utils.system("./blkparse -q -D %s -d %s/trace.bin -O %s >/dev/null" %
(tmpdir, tmpdir, alldnames))
cmd = "./btt/btt -i %s/trace.bin" % tmpdir
self.results.append(utils.system_output(cmd, retain_output=True))
def postprocess(self):
for n in range(len(self.results)):
if self.results[n].strip() == "==================== All Devices ====================":
words = self.results[n-2].split()
s = words[1].strip('sytem').split(':')
e = words[2].strip('elapsd').split(':')
break
systime = 0.0
for n in range(len(s)):
i = (len(s)-1) - n
systime += float(s[i]) * (60**n)
elapsed = 0.0
for n in range(len(e)):
i = (len(e)-1) - n
elapsed += float(e[i]) * (60**n)
q2c = 0.0
for line in self.results:
words = line.split()
if len(words) < 3:
continue
if words[0] == 'Q2C':
q2c = float(words[2])
break
self.write_perf_keyval({'time':elapsed, 'systime':systime,
'avg_q2c_latency':q2c})