2 # -*- coding: utf-8 -*-
5 Machinery for generating tracing-related intermediate files.
8 __author__
= "Lluís Vilanova <vilanova@ac.upc.edu>"
9 __copyright__
= "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
10 __license__
= "GPL version 2 or (at your option) any later version"
12 __maintainer__
= "Stefan Hajnoczi"
13 __email__
= "stefanha@linux.vnet.ibm.com"
19 import tracetool
.format
20 import tracetool
.backend
23 def error_write(*lines
):
24 """Write a set of error lines."""
25 sys
.stderr
.writelines("\n".join(lines
) + "\n")
28 """Write a set of error lines and exit."""
33 def out(*lines
, **kwargs
):
34 """Write a set of output lines.
36 You can use kwargs as a shorthand for mapping variables when formating all
39 lines
= [ l
% kwargs
for l
in lines
]
40 sys
.stdout
.writelines("\n".join(lines
) + "\n")
44 """Event arguments description."""
46 def __init__(self
, args
):
51 List of (type, name) tuples.
57 """Build and Arguments instance from an argument string.
62 String describing the event arguments.
65 for arg
in arg_str
.split(","):
71 arg_type
, identifier
= arg
.rsplit('*', 1)
73 identifier
= identifier
.strip()
75 arg_type
, identifier
= arg
.rsplit(None, 1)
77 res
.append((arg_type
, identifier
))
81 """Iterate over the (type, name) pairs."""
82 return iter(self
._args
)
85 """Number of arguments."""
86 return len(self
._args
)
89 """String suitable for declaring function arguments."""
90 if len(self
._args
) == 0:
93 return ", ".join([ " ".join([t
, n
]) for t
,n
in self
._args
])
96 """Evaluable string representation for this object."""
97 return "Arguments(\"%s\")" % str(self
)
100 """List of argument names."""
101 return [ name
for _
, name
in self
._args
]
104 """List of argument types."""
105 return [ type_
for type_
, _
in self
._args
]
109 """Event description.
116 The event format string.
117 properties : set(str)
118 Properties of the event.
123 _CRE
= re
.compile("((?P<props>.*)\s+)?(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?")
125 _VALID_PROPS
= set(["disable"])
127 def __init__(self
, name
, props
, fmt
, args
):
136 Event printing format.
141 self
.properties
= props
145 unknown_props
= set(self
.properties
) - self
._VALID
_PROPS
146 if len(unknown_props
) > 0:
147 raise ValueError("Unknown properties: %s" % ", ".join(unknown_props
))
151 """Build an Event instance from a string.
156 Line describing the event.
158 m
= Event
._CRE
.match(line_str
)
160 groups
= m
.groupdict('')
162 name
= groups
["name"]
163 props
= groups
["props"].split()
165 args
= Arguments
.build(groups
["args"])
167 return Event(name
, props
, fmt
, args
)
170 """Evaluable string representation for this object."""
171 return "Event('%s %s(%s) %s')" % (" ".join(self
.properties
),
176 def _read_events(fobj
):
181 if line
.lstrip().startswith('#'):
183 res
.append(Event
.build(line
))
187 class TracetoolError (Exception):
188 """Exception for calls to generate."""
192 def try_import(mod_name
, attr_name
= None, attr_default
= None):
193 """Try to import a module and get an attribute from it.
199 attr_name : str, optional
200 Name of an attribute in the module.
201 attr_default : optional
202 Default value if the attribute does not exist in the module.
206 A pair indicating whether the module could be imported and the module or
207 object or attribute value.
210 module
= __import__(mod_name
, globals(), locals(), ["__package__"])
211 if attr_name
is None:
213 return True, getattr(module
, str(attr_name
), attr_default
)
218 def generate(fevents
, format
, backend
,
219 binary
= None, probe_prefix
= None):
220 """Generate the output for the given (format, backend) pair.
225 Event description file.
231 See tracetool.backend.dtrace.BINARY.
232 probe_prefix : str or None
233 See tracetool.backend.dtrace.PROBEPREFIX.
235 # fix strange python error (UnboundLocalError tracetool)
240 raise TracetoolError("format not set")
241 mformat
= format
.replace("-", "_")
242 if not tracetool
.format
.exists(mformat
):
243 raise TracetoolError("unknown format: %s" % format
)
245 backend
= str(backend
)
246 if len(backend
) is 0:
247 raise TracetoolError("backend not set")
248 mbackend
= backend
.replace("-", "_")
249 if not tracetool
.backend
.exists(mbackend
):
250 raise TracetoolError("unknown backend: %s" % backend
)
252 if not tracetool
.backend
.compatible(mbackend
, mformat
):
253 raise TracetoolError("backend '%s' not compatible with format '%s'" %
256 import tracetool
.backend
.dtrace
257 tracetool
.backend
.dtrace
.BINARY
= binary
258 tracetool
.backend
.dtrace
.PROBEPREFIX
= probe_prefix
260 events
= _read_events(fevents
)
263 ( e
.properies
.add("disable") for e
in events
)
265 tracetool
.format
.generate_begin(mformat
, events
)
266 tracetool
.backend
.generate("nop", format
,
269 if "disable" in e
.properties
])
270 tracetool
.backend
.generate(backend
, format
,
273 if "disable" not in e
.properties
])
274 tracetool
.format
.generate_end(mformat
, events
)