#!/usr/bin/env python
#
# This file is released under the terms of the Artistic License.
# Please see the file LICENSE, included in this package, for details.
#
# Copyright (C) 2006      Open Source Development Labs, Inc.
#               2006-2010 Mark Wong
#

# Because of the massive number of arguments we could have, use long-style only
# options.

import sys
from optparse import OptionParser
from os import listdir, system
from os.path import isdir, isfile, realpath
from subprocess import PIPE, Popen
from re import match

parser = OptionParser(usage = 'usage: %prog --dbms <dbms> --i <dir> --o <dir> [options]')
parser.add_option('--dbms', help = 'dbms used <pgsql>')
parser.add_option('--dbname', help = 'dbname, for use with pgsql')
parser.add_option('--devices',
		help = 'comma delimited devices to plot (iostat)')
parser.add_option('--i', help = 'dbt2 results directory')
parser.add_option('--o', help = 'output directory')
options, args = parser.parse_args()

if not options.dbms:
    parser.error('--dbms flag required')
else:
    # Validate supported dbms.

    dbms = options.dbms
    if dbms == 'pgsql':
        if not options.dbname:
            parser.error('"--dbms pgsql" requires --dbname to be used')
        else:
            dbname = options.dbname
    elif dbms == 'mysql' or dbms == 'drizzle' or dbms == 'sqlite' or dbms == 'nuodb':
        # No special scripts yet to run for these databases but this is needed
        # in order for the report script to run.
       pass
    else:
        parser.error('unrecognized dbms')
        sys.exit(1)

if not options.i:
    parser.error('--i flag required')

if not options.o:
    parser.error('--o flag required')

indir = realpath(options.i)
outdir = realpath(options.o)
mixfile = '%s/mix.log' % indir

device_arg = ''
if options.devices:
    device_arg = options.devices

de = 'd'
no = 'n'
os = 'o'
pa = 'p'
sl = 's'

transaction_name = dict()
transaction_name[de] = 'Delivery'
transaction_name[no] = 'New Order'
transaction_name[os] = 'Order Status'
transaction_name[pa] = 'Payment'
transaction_name[sl] = 'Stock Level'

print 'Generating mpstat, iostat, and vmstat charts for driver systems...'
for dir in listdir('%s/driver' % indir):
    if isdir('%s/driver/%s' % (indir, dir)):
        mpstatfile = '%s/driver/%s/mpstat.out' % (indir, dir)
        if isfile(mpstatfile):
            system('dbt-plot-mpstat %s %s/driver/%s/mpstat' % (mpstatfile,
                   outdir, dir))

        iostatfile = '%s/driver/%s/iostatx.out' % (indir, dir)
        if isfile(iostatfile):
            system('dbt-plot-iostat %s %s/driver/%s/iostat %s' % \
                    (iostatfile, outdir, dir, device_arg))

        vmstatfile = '%s/driver/%s/vmstat.out' % (indir, dir)
        if isfile(vmstatfile):
            system('dbt-plot-vmstat %s %s/driver/%s/vmstat' % (vmstatfile,
                   outdir, dir))

print 'Moving on to database system stats...'
print 'Generating transaction distribution charts...'
count = 0
for key in [de, no, os, pa, sl]:
    system('dbt-plot-transaction-distribution "%s" %s %s %s/txn min 5 %d' % \
            (transaction_name[key], key, mixfile, outdir, int(count) + 1))
    count += 1

print 'Generating mpstat charts...'
mpstatfile = '%s/db/mpstat.out' % indir
if isfile(mpstatfile):
    system('dbt-plot-mpstat %s %s/db/mpstat' % (mpstatfile, outdir))

print 'Generating iostat charts...'
iostatfile = '%s/db/iostatx.out' % indir
if isfile(iostatfile):
    system('dbt-plot-iostat %s %s/db/iostat %s' % \
            (iostatfile, outdir, device_arg))

print 'Generating vmstat charts...'
vmstatfile = '%s/db/vmstat.out' % indir
if isfile(vmstatfile):
    system('dbt-plot-vmstat %s %s/db/vmstat' % (vmstatfile, outdir))

print 'Generating transaction rate charts...'
system('dbt2-plot-transaction-rate %s %s/txn' % (mixfile, outdir))

print 'Generating database statistics charts...'
if dbms == 'pgsql':
    system('dbt-pgsql-plot-database-stats ' \
            '%s/db/pg_stat_databases.out %s %s/db' % (indir, dbname, outdir))

    # This relies on the scripts for PostgreSQL to generate these
    # table-list.txt and index-list.txt files.
    f = None
    try:
        f = open('%s/db/table-list.txt' % indir)
    except:
        print 'Cannot open table list to generate database table stats, ' \
                'continuing...'

    if f is not None:
        for table in f:
            system('dbt-pgsql-plot-table-stats %s/db/pg_stat_tables.out ' \
                    '%s %s/db/tables' % (indir, table.strip(), outdir))
        f.close()

    f = None
    try:
        f = open('%s/db/index-list.txt' % indir)
    except:
        print 'Cannot open index list to generate database index stats, ' \
                'continuing...'

    if f is not None:
        for index in f:
            system('dbt-pgsql-plot-index-stats %s/db/pg_stat_indexes.out ' \
                    '%s %s/db/indexes' % (indir, index.strip(), outdir))
        f.close()

reportfile = '%s/index.html' % outdir
try:
    h = open(reportfile, 'w')
except:
    print 'Cannot open file: %s' % reportfile
    sys.exit(3)

h.write('<html>\n')
h.write('<head>\n')
h.write('<title>Database Test 2 Report</title>\n')
h.write('</head>\n')
h.write('<body>\n')
h.write('<h1>Database Test 2 Report</h1>\n')

h.write('<p>\n')

cmd = 'head -n 1 %s/readme.txt' % indir
p = Popen(cmd.split(), stdout=PIPE)
h.write(p.communicate()[0])

h.write('</p>\n')

h.write('<table>\n')

h.write('<tr>\n')
h.write('<td>\n')
h.write('<table>\n')
h.write('<caption>Results Summary</caption>\n')

h.write('<tr>\n')
h.write('<td align="right">New Order Transactions per Minute (notpm):</td>\n')

cmd = 'grep NOTPM %s/report.txt' % indir
p = Popen(cmd.split(), stdout=PIPE)
h.write('<td>%s</td>\n' % p.communicate()[0].split()[0])

h.write('</tr>\n')

h.write('<tr>\n')
h.write('<td align="right">Scale Factor:</td>\n')

cmd = 'grep Factor %s/readme.txt' % indir
p = Popen(cmd.split(), stdout=PIPE)
h.write('<td>%s</td>\n' % p.communicate()[0].split()[3])

h.write('</tr>\n')

h.write('<tr>\n')
h.write('<td align="right">Test Duration (min.):</td>\n')

cmd = 'grep Duration %s/readme.txt' % indir
p = Popen(cmd.split(), stdout=PIPE)
h.write('<td>%0.1f</td>\n' % (float(p.communicate()[0].split()[2]) / 60.0))

h.write('</tr>\n')

h.write('</table>\n')
h.write('</td>\n')
h.write('<td>\n')
chart = 'txn/tn-transaction-rate.png'
h.write('<a href="%s"><img width="128" src="%s" height="96" />\n' % \
        (chart, chart))
h.write('</td>\n')
h.write('</tr>\n')

h.write('</table>\n')

h.write('<table border="1">\n')
h.write('<caption>Transaction Summary</caption>\n')

h.write('<tr>\n')
h.write('<th colspan="3">Transaction</th>\n')
h.write('<th colspan="2">Response Time (seconds)</th>\n')
h.write('<th colspan="2">Rollbacks</th>\n')
h.write('<th colspan="2">Charts</th>\n')
h.write('</tr>\n')

h.write('<tr>\n')
h.write('<th>Name</th>\n')
h.write('<th>Mix %</th>\n')
h.write('<th>Total</th>\n')
h.write('<th>Average (s)</th>\n')
h.write('<th>90th %</th>\n')
h.write('<th>Total</th>\n')
h.write('<th>%</th>\n')
h.write('<th>Response Time</th>\n')
h.write('<th>Time Distribution</th>\n')
h.write('</tr>\n')

count = 0
short_name = ['d', 'n', 'o', 'p', 's']
c_name = 1
c_mix = 2
c_avg = 3
c_90 = 4
c_total = 5
c_rollback = 6
c_rper = 7
for transaction in ['Delivery', 'New', 'Status', 'Payment', 'Stock']:
    cmd = 'grep %s %s/report.txt' % (transaction, indir)
    p = Popen(cmd.split(), stdout=PIPE)

    m = match(r'(\D+?) +(\d+.\d+) +(\d+.\d+)\D+(\d+.\d+) +(\d+) +(\d+)' \
               ' +(\d+.\d+)', p.communicate()[0])

    h.write('<tr>\n')
    h.write('<td>%s</td>\n' % m.group(c_name))
    h.write('<td>%s</td>\n' % m.group(c_mix))
    h.write('<td>%s</td>\n' % m.group(c_total))
    h.write('<td>%s</td>\n' % m.group(c_avg))
    h.write('<td>%s</td>\n' % m.group(c_90))
    h.write('<td>%s</td>\n' % m.group(c_rollback))
    h.write('<td>%s</td>\n' % m.group(c_rper))
    chart = 'txn/t%s-transaction-rate.png' % short_name[count]
    h.write('<td align="center">\n')
    h.write('<a href="%s"><img width="128" src="%s" height="96" />\n' % \
            (chart, chart))
    h.write('</td>\n')
    chart = 'txn/t%s-distribution.png' % short_name[count]
    h.write('<td align="center">\n')
    h.write('<a href="%s"><img width="128" src="%s" height="96" />\n' % \
            (chart, chart))
    h.write('</td>\n')
    h.write('</tr>\n')
    count += 1

h.write('</table>\n')

h.write('<table>\n')
h.write('<caption>System Summary</caption>\n')

h.write('<tr>\n')
h.write('<td align="right">Operating System:</td>\n')

file = '%s/db/readme.txt' % indir
cmd = 'head -n 2 %s' % file
p = Popen(cmd.split(), stdout=PIPE)
c = p.communicate()[0].split('\n')
c1 = c[0].split()
c2 = c[1]
settings = 'db/proc.txt'
system('cp -p %s/db/proc.out %s/%s' % (indir, outdir, settings))
h.write('<td>%s %s %s</td>\n' % (c1[0], c1[2], c1[11]))
h.write('<td><a href="%s">Settings</a></td>\n' % settings)

h.write('</tr>\n')

h.write('<tr>\n')
h.write('<td align="right">Database Management System:</td>\n')
h.write('<td>%s</td>\n' % c2)

file1 = 'db/param.out'
if isfile('%s/%s' % (indir, file1)):
    file2 = 'db/param.txt'
    system('cp -p %s/%s %s/%s' % (indir, file1, outdir, file2))
    h.write('<td><a href="%s">Settings</a></td>\n' % file2)

file1 = 'db/plan0.out'
if isfile('%s/%s' % (indir, file1)):
    file2 = 'db/plan0.txt'
    system('cp -p %s/%s %s/%s' % (indir, file1, outdir, file2))
    h.write('<td><a href="%s">Query Plans</a></td>\n' % file2)

h.write('</tr>\n')

h.write('<tr>\n')

file = '%s/readme.txt' % indir
cmd = 'head -n 2 %s' % file
p = Popen(cmd.split(), stdout=PIPE)
c = p.communicate()[0].split('\n')

h.write('<td align="right">Notes:</td>\n')
h.write('<td>%s</td>\n' % c[1])

h.write('</tr>\n')

h.write('<tr>\n')
h.write('<td align="right">Driver Charts:</td>\n')
h.write('<td><a href="driver">View Directories</a></td>\n')
h.write('</tr>\n')

h.write('<tr>\n')
h.write('<td align="right">Database Charts:</td>\n')
h.write('<td><a href="db">View Directories</a></td>\n')
h.write('</tr>\n')

h.write('</table>\n')

h.write('</body>\n')
h.write('</html>\n')
