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')
        utils.system('patch -p3 < ../../../clang_fortify.patch')

        ctarget = os.getenv('CTARGET_default')

        if (ctarget == 'armv7a-cros-linux-gnueabihf'):
            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):
        """
        Generates a keylist.
        """
        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()