The FreeBSD guys are doing Linux comparisons with sysbench again. We
should get it automated so we can keep an eye on any regressions.

The following autobench test supports both MySQL and PostgreSQL. We
default to the read/write OLTP workload but the control example uses the
read only workload - its what the FreeBSD comparisons are using.

Signed-off-by: Anton Blanchard <[email protected]>



git-svn-id: http://test.kernel.org/svn/autotest/trunk@868 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/client/tests/sysbench/sysbench.py b/client/tests/sysbench/sysbench.py
new file mode 100644
index 0000000..71cc465
--- /dev/null
+++ b/client/tests/sysbench/sysbench.py
@@ -0,0 +1,181 @@
+import test, time, re, pwd
+from autotest_utils import *
+
+class sysbench(test.test):
+	version = 1
+
+	# http://osdn.dl.sourceforge.net/sourceforge/sysbench/sysbench-0.4.8.tar.gz
+	def setup(self, tarball = 'sysbench-0.4.8.tar.bz2'):
+		tarball = unmap_url(self.bindir, tarball, self.tmpdir)
+		extract_tarball_to_dir(tarball, self.srcdir)
+		self.job.setup_dep(['pgsql', 'mysql'])
+
+		os.chdir(self.srcdir)
+
+		pgsql_dir = os.path.join(self.autodir, 'deps/pgsql/pgsql')
+		mysql_dir = os.path.join(self.autodir, 'deps/mysql/mysql')
+
+		# configure wants to get at pg_config, so add its path
+		system('PATH=%s/bin:$PATH ./configure --with-mysql=%s --with-pgsql' % (pgsql_dir, mysql_dir))
+		system('make -j %d' % count_cpus())
+
+
+	def execute(self, db_type = 'pgsql', build = 1, \
+			num_threads = count_cpus(), max_time = 60, \
+			read_only = 0, args = ''):
+		plib = os.path.join(self.autodir, 'deps/pgsql/pgsql/lib')
+		mlib = os.path.join(self.autodir, 'deps/mysql/mysql/lib/mysql')
+		ld_path = prepend_path(plib, environ('LD_LIBRARY_PATH'))
+		ld_path = prepend_path(mlib, ld_path)
+		os.environ['LD_LIBRARY_PATH'] = ld_path
+
+		# The databases don't want to run as root so run them as nobody 
+		self.dbuser = 'nobody'
+		self.dbuid = pwd.getpwnam(self.dbuser)[2]
+		self.sudo = 'sudo -u ' + self.dbuser + ' '
+
+		# Check for nobody user
+		try:
+			system(self.sudo + '/bin/true')
+		except:
+			raise 'Unable to run as nobody'
+
+		if (db_type == 'pgsql'):
+			self.execute_pgsql(build, num_threads, max_time, \
+				read_only, args)
+		elif (db_type == 'mysql'):
+			self.execute_mysql(build, num_threads, max_time, \
+				read_only, args)
+
+
+	def execute_pgsql(self, build, num_threads, max_time, read_only, args):
+		bin = os.path.join(self.autodir, 'deps/pgsql/pgsql/bin')
+		data = os.path.join(self.autodir, 'deps/pgsql/pgsql/data')
+		log = os.path.join(self.debugdir, 'pgsql.log')
+
+		if build == 1:
+			system('rm -rf ' + data)
+			os.mkdir(data)
+			os.chown(data, self.dbuid, 0)
+			system(self.sudo + bin + '/initdb -D ' + data)
+
+		# Database must be able to write its output into debugdir
+		os.chown(self.debugdir, self.dbuid, 0)
+		system(self.sudo + bin + '/pg_ctl -D ' + data + \
+			' -l ' + log + ' start')
+
+		# Wait for database to start
+		time.sleep(5)
+
+		try:
+			base_cmd = self.srcdir + '/sysbench/sysbench ' + \
+				'--test=oltp --db-driver=pgsql ' + \
+				'--pgsql-user=' + self.dbuser
+
+			if build == 1:
+				system(self.sudo + bin + '/createdb sbtest')
+				cmd = base_cmd +' prepare'
+				system(cmd)
+
+			cmd = base_cmd + \
+				' --num-threads=' + str(num_threads) + \
+				' --max-time=' + str(max_time) + \
+				' --max-requests=0'
+
+			if read_only:
+				cmd = cmd + ' --oltp-read-only=on'
+
+			profilers = self.job.profilers
+                	if not profilers.only():
+				system(cmd + ' run')
+
+			# Do a profiling run if necessary
+			if profilers.present():
+				profilers.start(self)
+				print "Profiling run ..."
+				system(cmd + ' run')
+				profilers.stop(self)
+				profilers.report(self)
+		except:
+			system(self.sudo + bin + '/pg_ctl -D ' + data + ' stop')
+			raise
+
+		system(self.sudo + bin + '/pg_ctl -D ' + data + ' stop')
+
+		self.__format_results(open(self.debugdir + '/stdout').read())
+
+
+	def execute_mysql(self, build, num_threads, max_time, read_only, args):
+		bin = os.path.join(self.autodir, 'deps/mysql/mysql/bin')
+		data = os.path.join(self.autodir, 'deps/mysql/mysql/var')
+		log = os.path.join(self.debugdir, 'mysql.log')
+
+		if build == 1:
+			system('rm -rf ' + data)
+			os.mkdir(data)	
+			os.chown(data, self.dbuid, 0)
+			system(bin + '/mysql_install_db --user=' + self.dbuser)
+
+		system(bin + '/mysqld_safe --log-error=' + log + \
+			' --user=' + self.dbuser + ' &')
+
+		# Wait for database to start
+		time.sleep(5)
+
+		try:
+			base_cmd = self.srcdir + '/sysbench/sysbench ' + \
+				'--test=oltp --db-driver=mysql ' + \
+				'--mysql-user=root'
+
+			if build == 1:
+				system('echo "create database sbtest" | ' + \
+					bin + '/mysql -u root')
+				cmd = base_cmd +' prepare'
+				system(cmd)
+
+			cmd = base_cmd + \
+				' --num-threads=' + str(num_threads) + \
+				' --max-time=' + str(max_time) + \
+				' --max-requests=0'
+
+			if read_only:
+				cmd = cmd + ' --oltp-read-only=on'
+
+			profilers = self.job.profilers
+                	if not profilers.only():
+				system(cmd + ' run')
+
+			# Do a profiling run if necessary
+			if profilers.present():
+				profilers.start(self)
+				print "Profiling run ..."
+				system(cmd + ' run')
+				profilers.stop(self)
+				profilers.report(self)
+		except:
+			system(bin + '/mysqladmin shutdown')
+			raise
+
+		system(bin + '/mysqladmin shutdown')
+
+		self.__format_results(open(self.debugdir + '/stdout').read())
+
+
+	def __format_results(self, results):
+		threads = 0
+		tps = 0
+
+		out = open(self.resultsdir + '/keyval', 'w')
+		for line in results.split('\n'):
+			threads_re = re.search('Number of threads: (\d+)', line)
+			if threads_re:
+				threads = threads_re.group(1)
+
+			tps_re = re.search('transactions:\s+\d+\s+\((\S+) per sec.\)', line)
+			if tps_re:
+				tps = tps_re.group(1)
+				break
+
+		print >> out, 'threads=%s\ntps=%s' % (threads, tps)
+		out.close()
+