import os, re
from autotest_lib.client.bin import test, utils
import postprocessing


class iozone(test.test):
    """
    This autotest module runs the IOzone filesystem benchmark. The benchmark
    generates and measures a variety of file operations. Iozone has been ported
    to many machines and runs under many operating systems.

    Iozone is useful for performing a broad filesystem analysis of a vendor's
    computer platform. The benchmark tests file I/O performance for the
    following operations:

    Read, write, re-read, re-write, read backwards, read strided, fread, fwrite,
    random read, pread ,mmap, aio_read, aio_write

    @author: Ying Tao (yingtao@cn.ibm.com)
    @see: http://www.iozone.org
    """
    version = 3

    def initialize(self):
        self.job.require_gcc()


    def setup(self, tarball='iozone3_347.tar'):
        """
        Builds the given version of IOzone from a tarball.
        @param tarball: Tarball with IOzone
        @see: http://www.iozone.org/src/current/iozone3_347.tar
        """
        tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir)
        utils.extract_tarball_to_dir(tarball, self.srcdir)
        os.chdir(os.path.join(self.srcdir, 'src/current'))
        utils.system('patch -p3 < ../../../makefile.patch')

        ctarget = os.getenv('CTARGET_default')

        if (ctarget == 'armv7a-cros-linux-gnueabi'):
            utils.make('linux-arm')
        elif (ctarget == 'i686-pc-linux-gnu'):
            utils.make('linux')
        elif (ctarget == 'x86_64-cros-linux-gnu'):
            utils.make('linux-AMD64')
        else:
            utils.make('linux')

    def run_once(self, dir=None, args=None):
        """
        Runs IOzone with appropriate parameters, record raw results in a per
        iteration raw output file as well as in the results attribute

        @param dir: IOzone file generation dir.
        @param args: Arguments to the iozone program.
        """
        if not dir:
            dir = self.tmpdir
        os.chdir(dir)
        if not args:
            args = '-a'

        cmd = os.path.join(self.srcdir, 'src', 'current', 'iozone')
        self.results = utils.system_output('%s %s' % (cmd, args))
        self.auto_mode = ("-a" in args)

        self.results_path = os.path.join(self.resultsdir,
                                         'raw_output_%s' % self.iteration)
        self.analysisdir = os.path.join(self.resultsdir,
                                        'analysis_%s' % self.iteration)

        utils.open_write_close(self.results_path, self.results)


    def __get_section_name(self, desc):
        return desc.strip().replace(' ', '_')


    def generate_keyval(self):
        keylist = {}

        if self.auto_mode:
            labels = ('write', 'rewrite', 'read', 'reread', 'randread',
                      'randwrite', 'bkwdread', 'recordrewrite',
                      'strideread', 'fwrite', 'frewrite', 'fread', 'freread')
            for line in self.results.splitlines():
                fields = line.split()
                if len(fields) != 15:
                    continue
                try:
                    fields = tuple([int(i) for i in fields])
                except ValueError:
                    continue
                for l, v in zip(labels, fields[2:]):
                    key_name = "%d-%d-%s" % (fields[0], fields[1], l)
                    keylist[key_name] = v
        else:
            child_regexp  = re.compile('Children see throughput for[\s]+'
                            '([\d]+)\s+([-\w]+[-\w\s]*)\=[\s]+([\d\.]*) KB/sec')
            parent_regexp = re.compile('Parent sees throughput for[\s]+'
                            '([\d]+)\s+([-\w]+[-\w\s]*)\=[\s]+([\d\.]*) KB/sec')

            KBsec_regexp  = re.compile('\=[\s]+([\d\.]*) KB/sec')
            KBval_regexp  = re.compile('\=[\s]+([\d\.]*) KB')

            section = None
            w_count = 0

            for line in self.results.splitlines():
                line = line.strip()

                # Check for the beginning of a new result section
                match = child_regexp.search(line)
                if match:
                    # Extract the section name and the worker count
                    w_count = int(match.group(1))
                    section = self.__get_section_name(match.group(2))

                    # Output the appropriate keyval pair
                    key_name = '%s-%d-kids' % (section, w_count)
                    keylist[key_name] = match.group(3)
                    continue

                # Check for any other interesting lines
                if '=' in line:
                    # Is it something we recognize? First check for parent.
                    match = parent_regexp.search(line)
                    if match:
                        # The section name and the worker count better match
                        p_count = int(match.group(1))
                        p_secnt = self.__get_section_name(match.group(2))
                        if p_secnt != section or p_count != w_count:
                            continue

                        # Set the base name for the keyval
                        basekey = 'parent'
                    else:
                        # Check for the various 'throughput' values
                        if line[3:26] == ' throughput per thread ':
                            basekey = line[0:3]
                            match_x = KBsec_regexp
                        else:
                            # The only other thing we expect is 'Min xfer'
                            if not line.startswith('Min xfer '):
                                continue
                            basekey = 'MinXfer'
                            match_x = KBval_regexp

                        match = match_x.search(line)
                        if match:
                            result = match.group(1)
                            key_name = "%s-%d-%s" % (section, w_count, basekey)
                            keylist[key_name] = result

        self.write_perf_keyval(keylist)


    def postprocess_iteration(self):
        self.generate_keyval()
        if self.auto_mode:
            a = postprocessing.IOzoneAnalyzer(list_files=[self.results_path],
                                              output_dir=self.analysisdir)
            a.analyze()
            p = postprocessing.IOzonePlotter(results_file=self.results_path,
                                             output_dir=self.analysisdir)
            p.plot_all()
