1import os, time, re, pwd
2from autotest_lib.client.bin import test, utils
3from autotest_lib.client.common_lib import error
4
5
6class sysbench(test.test):
7    version = 1
8
9    def initialize(self):
10        self.job.require_gcc()
11        self.results = []
12
13    # http://osdn.dl.sourceforge.net/sourceforge/sysbench/sysbench-0.4.8.tar.gz
14    def setup(self, tarball = 'sysbench-0.4.8.tar.bz2'):
15        tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir)
16        utils.extract_tarball_to_dir(tarball, self.srcdir)
17        self.job.setup_dep(['pgsql', 'mysql'])
18
19        os.chdir(self.srcdir)
20
21        pgsql_dir = os.path.join(self.autodir, 'deps/pgsql/pgsql')
22        mysql_dir = os.path.join(self.autodir, 'deps/mysql/mysql')
23
24        # configure wants to get at pg_config, so add its path
25        utils.system(
26            'PATH=%s/bin:$PATH ./configure --with-mysql=%s --with-pgsql'
27            % (pgsql_dir, mysql_dir))
28        utils.make('-j %d' % utils.count_cpus())
29
30
31    def run_once(self, db_type = 'pgsql', build = 1, \
32                    num_threads = utils.count_cpus(), max_time = 60, \
33                    read_only = 0, args = ''):
34        plib = os.path.join(self.autodir, 'deps/pgsql/pgsql/lib')
35        mlib = os.path.join(self.autodir, 'deps/mysql/mysql/lib/mysql')
36        ld_path = utils.prepend_path(plib,
37            utils.environ('LD_LIBRARY_PATH'))
38        ld_path = utils.prepend_path(mlib, ld_path)
39        os.environ['LD_LIBRARY_PATH'] = ld_path
40
41        # The databases don't want to run as root so run them as nobody
42        self.dbuser = 'nobody'
43        self.dbuid = pwd.getpwnam(self.dbuser)[2]
44        self.sudo = 'sudo -u ' + self.dbuser + ' '
45
46        # Check for nobody user
47        try:
48            utils.system(self.sudo + '/bin/true')
49        except:
50            raise error.TestError('Unable to run as nobody')
51
52        if (db_type == 'pgsql'):
53            self.execute_pgsql(build, num_threads, max_time, read_only, args)
54        elif (db_type == 'mysql'):
55            self.execute_mysql(build, num_threads, max_time, read_only, args)
56
57
58    def execute_pgsql(self, build, num_threads, max_time, read_only, args):
59        bin = os.path.join(self.autodir, 'deps/pgsql/pgsql/bin')
60        data = os.path.join(self.autodir, 'deps/pgsql/pgsql/data')
61        log = os.path.join(self.debugdir, 'pgsql.log')
62
63        if build == 1:
64            utils.system('rm -rf ' + data)
65            os.mkdir(data)
66            os.chown(data, self.dbuid, 0)
67            utils.system(self.sudo + bin + '/initdb -D ' + data)
68
69        # Database must be able to write its output into debugdir
70        os.chown(self.debugdir, self.dbuid, 0)
71        utils.system(self.sudo + bin + '/pg_ctl -D %s -l %s start' %(data, log))
72
73        # Wait for database to start
74        time.sleep(5)
75
76        try:
77            base_cmd = self.srcdir + '/sysbench/sysbench --test=oltp ' \
78                       '--db-driver=pgsql --pgsql-user=' + self.dbuser
79
80            if build == 1:
81                utils.system(self.sudo + bin + '/createdb sbtest')
82                cmd = base_cmd +' prepare'
83                utils.system(cmd)
84
85            cmd = base_cmd + \
86                    ' --num-threads=' + str(num_threads) + \
87                    ' --max-time=' + str(max_time) + \
88                    ' --max-requests=0'
89
90            if read_only:
91                cmd = cmd + ' --oltp-read-only=on'
92
93            self.results.append(utils.system_output(cmd + ' run',
94                                                    retain_output=True))
95
96        except:
97            utils.system(self.sudo + bin + '/pg_ctl -D ' + data + ' stop')
98            raise
99
100        utils.system(self.sudo + bin + '/pg_ctl -D ' + data + ' stop')
101
102
103    def execute_mysql(self, build, num_threads, max_time, read_only, args):
104        bin = os.path.join(self.autodir, 'deps/mysql/mysql/bin')
105        data = os.path.join(self.autodir, 'deps/mysql/mysql/var')
106        log = os.path.join(self.debugdir, 'mysql.log')
107
108        if build == 1:
109            utils.system('rm -rf ' + data)
110            os.mkdir(data)
111            os.chown(data, self.dbuid, 0)
112            utils.system(bin + '/mysql_install_db --user=' + self.dbuser)
113
114        utils.system(bin + '/mysqld_safe --log-error=' + log + \
115                ' --user=' + self.dbuser + ' &')
116
117        # Wait for database to start
118        time.sleep(5)
119
120        try:
121            base_cmd = self.srcdir + '/sysbench/sysbench --test=oltp ' \
122                                     '--db-driver=mysql --mysql-user=root'
123
124            if build == 1:
125                utils.system('echo "create database sbtest" | ' + \
126                        bin + '/mysql -u root')
127                cmd = base_cmd +' prepare'
128                utils.system(cmd)
129
130            cmd = base_cmd + \
131                    ' --num-threads=' + str(num_threads) + \
132                    ' --max-time=' + str(max_time) + \
133                    ' --max-requests=0'
134
135            if read_only:
136                cmd = cmd + ' --oltp-read-only=on'
137
138            self.results.append(utils.system_output(cmd + ' run',
139                                                    retain_output=True))
140
141        except:
142            utils.system(bin + '/mysqladmin shutdown')
143            raise
144
145        utils.system(bin + '/mysqladmin shutdown')
146
147
148    def postprocess(self):
149        self.__format_results("\n".join(self.results))
150
151    def __format_results(self, results):
152        threads = 0
153        tps = 0
154
155        out = open(self.resultsdir + '/keyval', 'w')
156        for line in results.split('\n'):
157            threads_re = re.search('Number of threads: (\d+)', line)
158            if threads_re:
159                threads = threads_re.group(1)
160
161            tps_re = re.search('transactions:\s+\d+\s+\((\S+) per sec.\)', line)
162            if tps_re:
163                tps = tps_re.group(1)
164                break
165
166        out.write('threads=%s\ntps=%s' % (threads, tps))
167        out.close()
168