#
# 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 = pevent_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 pevent_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 pevent_data_pid(self._pevent, self._record)

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

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

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

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

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 =  pevent_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 pevent_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)

    def read_event(self, cpu):
        rec = tracecmd_read_data(self._handle, cpu)
        if rec:
            type = pevent_data_type(self._pevent, rec)
            format = pevent_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 = pevent_data_type(self._pevent, rec)
        format = pevent_data_event_from_type(self._pevent, type)
        # rec ownership goes over to Event instance
        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 = pevent_data_type(self._pevent, rec)
        format = pevent_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)



