#!/usr/bin/env python
#
# Pretty-printer for simple trace backend binary trace files
#
# Copyright IBM, Corp. 2010
#
# This work is licensed under the terms of the GNU GPL, version 2.  See
# the COPYING file in the top-level directory.
#
# For help see docs/tracing.txt

import struct
import re
import inspect

header_event_id = 0xffffffffffffffff
header_magic    = 0xf2b177cb0aa429b4
header_version  = 0
dropped_event_id = 0xfffffffffffffffe

trace_fmt = '=QQQQQQQQ'
trace_len = struct.calcsize(trace_fmt)
event_re  = re.compile(r'(disable\s+)?([a-zA-Z0-9_]+)\(([^)]*)\).*')

def parse_events(fobj):
    """Parse a trace-events file into {event_num: (name, arg1, ...)}."""

    def get_argnames(args):
        """Extract argument names from a parameter list."""
        return tuple(arg.split()[-1].lstrip('*') for arg in args.split(','))

    events = {dropped_event_id: ('dropped', 'count')}
    event_num = 0
    for line in fobj:
        m = event_re.match(line.strip())
        if m is None:
            continue

        disable, name, args = m.groups()
        events[event_num] = (name,) + get_argnames(args)
        event_num += 1
    return events

def read_record(fobj):
    """Deserialize a trace record from a file into a tuple (event_num, timestamp, arg1, ..., arg6)."""
    s = fobj.read(trace_len)
    if len(s) != trace_len:
        return None
    return struct.unpack(trace_fmt, s)

def read_trace_file(fobj):
    """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, arg1, ..., arg6)."""
    header = read_record(fobj)
    if header is None or \
       header[0] != header_event_id or \
       header[1] != header_magic or \
       header[2] != header_version:
        raise ValueError('not a trace file or incompatible version')

    while True:
        rec = read_record(fobj)
        if rec is None:
            break

        yield rec

class Analyzer(object):
    """A trace file analyzer which processes trace records.

    An analyzer can be passed to run() or process().  The begin() method is
    invoked, then each trace record is processed, and finally the end() method
    is invoked.

    If a method matching a trace event name exists, it is invoked to process
    that trace record.  Otherwise the catchall() method is invoked."""

    def begin(self):
        """Called at the start of the trace."""
        pass

    def catchall(self, event, rec):
        """Called if no specific method for processing a trace event has been found."""
        pass

    def end(self):
        """Called at the end of the trace."""
        pass

def process(events, log, analyzer):
    """Invoke an analyzer on each event in a log."""
    if isinstance(events, str):
        events = parse_events(open(events, 'r'))
    if isinstance(log, str):
        log = open(log, 'rb')

    def build_fn(analyzer, event):
        fn = getattr(analyzer, event[0], None)
        if fn is None:
            return analyzer.catchall

        event_argcount = len(event) - 1
        fn_argcount = len(inspect.getargspec(fn)[0]) - 1
        if fn_argcount == event_argcount + 1:
            # Include timestamp as first argument
            return lambda _, rec: fn(*rec[1:2 + fn_argcount])
        else:
            # Just arguments, no timestamp
            return lambda _, rec: fn(*rec[2:2 + fn_argcount])

    analyzer.begin()
    fn_cache = {}
    for rec in read_trace_file(log):
        event_num = rec[0]
        event = events[event_num]
        if event_num not in fn_cache:
            fn_cache[event_num] = build_fn(analyzer, event)
        fn_cache[event_num](event, rec)
    analyzer.end()

def run(analyzer):
    """Execute an analyzer on a trace file given on the command-line.

    This function is useful as a driver for simple analysis scripts.  More
    advanced scripts will want to call process() instead."""
    import sys

    if len(sys.argv) != 3:
        sys.stderr.write('usage: %s <trace-events> <trace-file>\n' % sys.argv[0])
        sys.exit(1)

    events = parse_events(open(sys.argv[1], 'r'))
    process(events, sys.argv[2], analyzer)

if __name__ == '__main__':
    class Formatter(Analyzer):
        def __init__(self):
            self.last_timestamp = None

        def catchall(self, event, rec):
            timestamp = rec[1]
            if self.last_timestamp is None:
                self.last_timestamp = timestamp
            delta_ns = timestamp - self.last_timestamp
            self.last_timestamp = timestamp

            fields = [event[0], '%0.3f' % (delta_ns / 1000.0)]
            for i in xrange(1, len(event)):
                fields.append('%s=0x%x' % (event[i], rec[i + 1]))
            print ' '.join(fields)

    run(Formatter())
