#
# Copyright (C) International Business Machines  Corp., 2009
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# 2009-Dec-17:	Initial version by Darren Hart <dvhltc@us.ibm.com>
#

from functools import update_wrapper
from ctracecmd import *
from UserDict import DictMixin

"""
Python interface to the tracecmd library for parsing ftrace traces

Python tracecmd applications should be written to this interface. It will be
updated as the tracecmd C API changes and try to minimze the impact to python
applications. The ctracecmd Python module is automatically generated using SWIG
and it is recommended applications not use it directly.

TODO: consider a complete class hierarchy of ftrace events...
"""

def cached_property(func, name=None):
    if name is None:
        name = func.__name__
    def _get(self):
        try:
            return self.__cached_properties[name]
        except AttributeError:
            self.__cached_properties = {}
        except KeyError:
            pass
        value = func(self)
        self.__cached_properties[name] = value
        return value
    update_wrapper(_get, func)
    def _del(self):
        self.__cached_properties.pop(name, None)
    return property(_get, None, _del)

class Event(object, DictMixin):
    """
    This class can be used to access event data
    according to an event's record and format.
    """
    def __init__(self, pevent, record, format):
        self._pevent = pevent
        self._record = record
        self._format = format

    def __str__(self):
        return "%d.%d CPU%d %s: pid=%d comm=%s type=%d" % \
               (self.ts/1000000000, self.ts%1000000000, self.cpu, self.name,
                self.num_field("common_pid"), self.comm, self.type)

    def __del__(self):
        free_record(self._record)

    def __getitem__(self, n):
        f = tep_find_field(self._format, n)
        if f is None:
            raise KeyError("no field '%s'" % n)
        return Field(self._record, f)

    def keys(self):
        return py_format_get_keys(self._format)

    @cached_property
    def comm(self):
        return tep_data_comm_from_pid(self._pevent, self.pid)

    @cached_property
    def cpu(self):
        return pevent_record_cpu_get(self._record)

    @cached_property
    def name(self):
        return event_format_name_get(self._format)

    @cached_property
    def pid(self):
        return tep_data_pid(self._pevent, self._record)

    @cached_property
    def ts(self):
        return pevent_record_ts_get(self._record)

    @cached_property
    def type(self):
        return tep_data_type(self._pevent, self._record)

    def num_field(self, name):
        f = tep_find_any_field(self._format, name)
        if f is None:
            return None
        ret, val = tep_read_number_field(f, pevent_record_data_get(self._record))
        if ret:
            return None
        return val

    def str_field(self, name):
        f = tep_find_any_field(self._format, name)
        if f is None:
            return None
        return py_field_get_str(f, self._record)

    def stack_field(self, long_size):
        return py_field_get_stack(self._pevent, self._record, self._format,
                                  long_size)

class TraceSeq(object):
    def __init__(self, trace_seq):
        self._trace_seq = trace_seq

    def puts(self, s):
        return trace_seq_puts(self._trace_seq, s)

class FieldError(Exception):
    pass

class Field(object):
    def __init__(self, record, field):
        self._record = record
        self._field = field

    @cached_property
    def data(self):
        return py_field_get_data(self._field, self._record)

    def __long__(self):
        ret, val =  tep_read_number_field(self._field,
                                             pevent_record_data_get(self._record))
        if ret:
            raise FieldError("Not a number field")
        return val
    __int__ = __long__

    def __str__(self):
        return py_field_get_str(self._field, self._record)

class PEvent(object):
    def __init__(self, pevent):
        self._pevent = pevent

    def _handler(self, cb, s, record, event_fmt):
        return cb(TraceSeq(s), Event(self._pevent, record, event_fmt))

    def register_event_handler(self, subsys, event_name, callback):
        l = lambda s, r, e: self._handler(callback, s, r, e)

        py_pevent_register_event_handler(
                  self._pevent, -1, subsys, event_name, l)

    @cached_property
    def file_endian(self):
        if tep_is_file_bigendian(self._pevent):
            return '>'
        return '<'


class FileFormatError(Exception):
    pass

class Trace(object):
    """
    Trace object represents the trace file it is created with.

    The Trace object aggregates the tracecmd structures and functions that are
    used to manage the trace and extract events from it.
    """
    def __init__(self, filename):
        self._handle = tracecmd_alloc(filename)

        if tracecmd_read_headers(self._handle):
            raise FileFormatError("Invalid headers")

        if tracecmd_init_data(self._handle):
            raise FileFormatError("Failed to init data")

        self._pevent = tracecmd_get_pevent(self._handle)

    @cached_property
    def cpus(self):
        return tracecmd_cpus(self._handle)

    @cached_property
    def long_size(self):
        return tracecmd_long_size(self._handle)

    def read_event(self, cpu):
        rec = tracecmd_read_data(self._handle, cpu)
        if rec:
            type = tep_data_type(self._pevent, rec)
            format = tep_data_event_from_type(self._pevent, type)
            # rec ownership goes over to Event instance
            return Event(self._pevent, rec, format)
        return None

    def read_event_at(self, offset):
        res = tracecmd_read_at(self._handle, offset)
        # SWIG only returns the CPU if the record is None for some reason
        if isinstance(res, int):
            return None
        rec, cpu = res
        type = tep_data_type(self._pevent, rec)
        format = tep_data_event_from_type(self._pevent, type)
        # rec ownership goes over to Event instance
        return Event(self._pevent, rec, format)

    def read_next_event(self):
        res = tracecmd_read_next_data(self._handle)
        if isinstance(res, int):
            return None
        rec, cpu = res
        type = tep_data_type(self._pevent, rec)
        format = tep_data_event_from_type(self._pevent, type)
        return Event(self._pevent, rec, format)

    def peek_event(self, cpu):
        rec = tracecmd_peek_data_ref(self._handle, cpu)
        if rec is None:
            return None
        type = tep_data_type(self._pevent, rec)
        format = tep_data_event_from_type(self._pevent, type)
        # rec ownership goes over to Event instance
        return Event(self._pevent, rec, format)


# Basic builtin test, execute module directly
if __name__ == "__main__":
    t = Trace("trace.dat")
    print "Trace contains data for %d cpus" % (t.cpus)

    for cpu in range(0, t.cpus):
        print "CPU %d" % (cpu)
        ev = t.read_event(cpu)
        while ev:
            print "\t%s" % (ev)
            ev = t.read_event(cpu)



