#
# 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 cached_property
from collections.abc import Mapping
from itertools import chain
from ctracecmd import *

"""
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...
"""

class Event(Mapping):
    """
    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):
        tracecmd_free_record(self._record)

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

    def __iter__(self):
        yield from chain(self.common_keys, self.keys)

    def __len__(self):
        return len(self.common_keys) + len(self.keys)

    @cached_property
    def common_keys(self):
        return py_format_get_keys(self._format, True)

    @cached_property
    def keys(self):
        return py_format_get_keys(self._format, False)

    @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 tep_event_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_open(filename, 0)
        self._pevent = tracecmd_get_tep(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_find_event(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_find_event(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_find_event(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_find_event(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(f"Trace contains data for {t.cpus} cpus, long has {t.long_size} bytes")

    print("Peek the first event on CPU0")
    print("\t%s" % (t.peek_event(0)))

    print("Events by 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)

    t = Trace("trace.dat")

    print("Events by time")
    ev = t.read_next_event()
    while ev:
        print("\t%s" % (ev))
        ev = t.read_next_event()
