summaryrefslogtreecommitdiff
path: root/scripts/tracetool/backend/__init__.py
blob: f0314ee3763805aea218b8f5cfb88b9881a6dccf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Backend management.


Creating new backends
---------------------

A new backend named 'foo-bar' corresponds to Python module
'tracetool/backend/foo_bar.py'.

A backend module should provide a docstring, whose first non-empty line will be
considered its short description.

All backends must generate their contents through the 'tracetool.out' routine.


Backend attributes
------------------

========= ====================================================================
Attribute Description
========= ====================================================================
PUBLIC    If exists and is set to 'True', the backend is considered "public".
========= ====================================================================


Backend functions
-----------------

======== =======================================================================
Function Description
======== =======================================================================
<format> Called to generate the format- and backend-specific code for each of
         the specified events. If the function does not exist, the backend is
         considered not compatible with the given format.
======== =======================================================================
"""

__author__     = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__  = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__    = "GPL version 2 or (at your option) any later version"

__maintainer__ = "Stefan Hajnoczi"
__email__      = "stefanha@linux.vnet.ibm.com"


import os

import tracetool


def get_list(only_public = False):
    """Get a list of (name, description) pairs."""
    res = [("nop", "Tracing disabled.")]
    modnames = []
    for filename in os.listdir(tracetool.backend.__path__[0]):
        if filename.endswith('.py') and filename != '__init__.py':
            modnames.append(filename.rsplit('.', 1)[0])
    for modname in modnames:
        module = tracetool.try_import("tracetool.backend." + modname)

        # just in case; should never fail unless non-module files are put there
        if not module[0]:
            continue
        module = module[1]

        public = getattr(module, "PUBLIC", False)
        if only_public and not public:
            continue

        doc = module.__doc__
        if doc is None:
            doc = ""
        doc = doc.strip().split("\n")[0]

        name = modname.replace("_", "-")
        res.append((name, doc))
    return res


def exists(name):
    """Return whether the given backend exists."""
    if len(name) == 0:
        return False
    if name == "nop":
        return True
    name = name.replace("-", "_")
    return tracetool.try_import("tracetool.backend." + name)[1]


def compatible(backend, format):
    """Whether a backend is compatible with the given format."""
    if not exists(backend):
        raise ValueError("unknown backend: %s" % backend)

    backend = backend.replace("-", "_")
    format = format.replace("-", "_")

    if backend == "nop":
        return True
    else:
        func = tracetool.try_import("tracetool.backend." + backend,
                                    format, None)[1]
        return func is not None


def _empty(events):
    pass

def generate(backend, format, events):
    """Generate the per-event output for the given (backend, format) pair."""
    if not compatible(backend, format):
        raise ValueError("backend '%s' not compatible with format '%s'" %
                         (backend, format))

    backend = backend.replace("-", "_")
    format = format.replace("-", "_")

    if backend == "nop":
        func = tracetool.try_import("tracetool.format." + format,
                                    "nop", _empty)[1]
    else:
        func = tracetool.try_import("tracetool.backend." + backend,
                                    format, None)[1]

    func(events)