1# -*- coding: utf-8 -*- 2 3""" 4Backend management. 5 6 7Creating new backends 8--------------------- 9 10A new backend named 'foo-bar' corresponds to Python module 11'tracetool/backend/foo_bar.py'. 12 13A backend module should provide a docstring, whose first non-empty line will be 14considered its short description. 15 16All backends must generate their contents through the 'tracetool.out' routine. 17 18 19Backend attributes 20------------------ 21 22========= ==================================================================== 23Attribute Description 24========= ==================================================================== 25PUBLIC If exists and is set to 'True', the backend is considered "public". 26========= ==================================================================== 27 28 29Backend functions 30----------------- 31 32All the following functions are optional, and no output will be generated if 33they do not exist. 34 35=============================== ============================================== 36Function Description 37=============================== ============================================== 38generate_<format>_begin(events) Generate backend- and format-specific file 39 header contents. 40generate_<format>_end(events) Generate backend- and format-specific file 41 footer contents. 42generate_<format>(event) Generate backend- and format-specific contents 43 for the given event. 44=============================== ============================================== 45 46""" 47 48__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" 49__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>" 50__license__ = "GPL version 2 or (at your option) any later version" 51 52__maintainer__ = "Stefan Hajnoczi" 53__email__ = "stefanha@redhat.com" 54 55 56import os 57 58import tracetool 59 60 61def get_list(only_public = False): 62 """Get a list of (name, description) pairs.""" 63 res = [("nop", "Tracing disabled.")] 64 modnames = [] 65 for filename in os.listdir(tracetool.backend.__path__[0]): 66 if filename.endswith('.py') and filename != '__init__.py': 67 modnames.append(filename.rsplit('.', 1)[0]) 68 for modname in sorted(modnames): 69 module = tracetool.try_import("tracetool.backend." + modname) 70 71 # just in case; should never fail unless non-module files are put there 72 if not module[0]: 73 continue 74 module = module[1] 75 76 public = getattr(module, "PUBLIC", False) 77 if only_public and not public: 78 continue 79 80 doc = module.__doc__ 81 if doc is None: 82 doc = "" 83 doc = doc.strip().split("\n")[0] 84 85 name = modname.replace("_", "-") 86 res.append((name, doc)) 87 return res 88 89 90def exists(name): 91 """Return whether the given backend exists.""" 92 if len(name) == 0: 93 return False 94 if name == "nop": 95 return True 96 name = name.replace("-", "_") 97 return tracetool.try_import("tracetool.backend." + name)[1] 98 99 100class Wrapper: 101 def __init__(self, backends, format): 102 self._backends = [backend.replace("-", "_") for backend in backends] 103 self._format = format.replace("-", "_") 104 for backend in self._backends: 105 assert exists(backend) 106 assert tracetool.format.exists(self._format) 107 108 def _run_function(self, name, *args, **kwargs): 109 for backend in self._backends: 110 func = tracetool.try_import("tracetool.backend." + backend, 111 name % self._format, None)[1] 112 if func is not None: 113 func(*args, **kwargs) 114 115 def generate_begin(self, events, group): 116 self._run_function("generate_%s_begin", events, group) 117 118 def generate(self, event, group): 119 self._run_function("generate_%s", event, group) 120 121 def generate_backend_dstate(self, event, group): 122 self._run_function("generate_%s_backend_dstate", event, group) 123 124 def generate_end(self, events, group): 125 self._run_function("generate_%s_end", events, group) 126