1#    Copyright 2015-2017 ARM Limited
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15
16
17"""The idea is to create a wrapper class that
18returns a Type of a Class dynamically created based
19on the input parameters. Similar to a factory design
20pattern
21"""
22from trappy.base import Base
23import re
24from trappy.ftrace import GenericFTrace
25
26
27def default_init(self):
28    """Default Constructor for the
29    Dynamic MetaClass. This is used for
30    the dynamic object creation in
31    :mod:`trappy.dynamic.DynamicTypeFactory`
32    """
33
34    kwords = {}
35
36    try:
37        kwords["parse_raw"] = self.parse_raw
38    except AttributeError:
39        pass
40
41    super(type(self), self).__init__(**kwords)
42
43
44class DynamicTypeFactory(type):
45
46    """Override the type class to create
47    a dynamic type on the fly. This Factory
48    class is used internally by
49    :mod:`trappy.dynamic.register_dynamic_ftrace`
50    """
51
52    def __new__(mcs, name, bases, dct):
53        """Override the new method"""
54        return type.__new__(mcs, name, bases, dct)
55
56    def __init__(cls, name, bases, dct):
57        """Override the constructor"""
58        super(DynamicTypeFactory, cls).__init__(name, bases, dct)
59
60
61def _get_name(name):
62    """Internal Method to Change camelcase to
63    underscores. CamelCase -> camel_case
64    """
65    return re.sub('(?!^)([A-Z]+)', r'_\1', name).lower()
66
67
68def register_dynamic_ftrace(class_name, unique_word, scope="all",
69                            parse_raw=False, pivot=None):
70    """Create a Dynamic FTrace parser and register it with any FTrace parsing classes
71
72    :param class_name: The name of the class to be registered
73        (Should be in CamelCase)
74    :type class_name: str
75
76    :param unique_word: The unique_word to be matched in the
77        trace
78    :type unique_word: str
79
80    :param scope: Registry Scope (Can be used to constrain
81        the parsing of events and group them together)
82    :type scope: str
83
84    :param parse_raw: If, true, raw trace output (-r flag)
85        will be used
86    :type parse_raw: bool
87
88    :param pivot: The data column about which the data can be grouped
89    :type pivot: str
90
91    For example if a new unique word :code:`my_unique_word` has
92    to be registered with TRAPpy:
93    ::
94
95        import trappy
96        custom_class = trappy.register_dynamic_ftrace("MyEvent", "my_unique_word")
97        trace = trappy.FTrace("/path/to/trace_file")
98
99        # New data member created in the ftrace object
100        trace.my_event
101
102    .. note:: The name of the member is :code:`my_event` from **MyEvent**
103
104
105    :return: A class object of type :mod:`trappy.base.Base`
106    """
107
108    kwords = {
109            "__init__": default_init,
110            "unique_word": unique_word,
111            "name": _get_name(class_name),
112            "parse_raw" : parse_raw,
113        }
114
115    if pivot:
116        kwords["pivot"] = pivot
117
118    dyn_class = DynamicTypeFactory(class_name, (Base,), kwords)
119    GenericFTrace.register_parser(dyn_class, scope)
120    return dyn_class
121
122
123def register_ftrace_parser(cls, scope="all"):
124    """Register a new FTrace parser class implementation
125
126    Should be used when the class has complex helper methods and does
127    not expect to use the default constructor.
128
129    :param cls: The class to be registered for
130        enabling the parsing of an event in trace
131    :type cls: :mod:`trappy.base.Base`
132
133    :param scope: scope of this parser class.  The scope can be used
134        to restrict the parsing done on an individual file.  Currently
135        the only scopes available are "sched", "thermal" or "all"
136    :type scope: string
137
138    """
139
140    # Check the argspec of the class
141    GenericFTrace.register_parser(cls, scope)
142
143def unregister_ftrace_parser(ftrace_parser):
144    """Unregister an ftrace parser
145
146    :param ftrace_parser: An ftrace parser class that was registered
147        with register_ftrace_parser() or register_dynamic_ftrace().
148        If done with the latter, the cls parameter is the return value
149        of register_dynamic_ftrace()
150    :type ftrace_parser: class derived from :mod:`trappy.base.Base`
151
152    """
153    GenericFTrace.unregister_parser(ftrace_parser)
154