#
# 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.%09d 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 tep_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 tep_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, tep_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,
                                          tep_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)



