summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Bartosh <ed.bartosh@linux.intel.com>2016-07-06 12:00:34 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-07-08 09:57:28 +0100
commit78b3fe6d5bf7f239f3060627372f951bfec020c7 (patch)
tree07029fe825aace5a0956fd02b1bbf655019a3fc6
parent2b56c032646897da5cf6a23d178d34df67cddc3c (diff)
downloadpoky-78b3fe6d5bf7f239f3060627372f951bfec020c7.tar.gz
bitbake: eventreplay: rewrite the script
Rewritten toaster-eventreplay to make code working as expected, more compact and readable. [YOCTO #9585] (Bitbake rev: 45370a860b24a761d1b6e08ba752079cc45f54da) Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com> Signed-off-by: Elliot Smith <elliot.smith@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rwxr-xr-xbitbake/bin/toaster-eventreplay207
1 files changed, 82 insertions, 125 deletions
diff --git a/bitbake/bin/toaster-eventreplay b/bitbake/bin/toaster-eventreplay
index 7de3967fe3..80967a0934 100755
--- a/bitbake/bin/toaster-eventreplay
+++ b/bitbake/bin/toaster-eventreplay
@@ -21,11 +21,13 @@
21# with this program; if not, write to the Free Software Foundation, Inc., 21# with this program; if not, write to the Free Software Foundation, Inc.,
22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 23
24"""
25This command takes a filename as a single parameter. The filename is read
26as a build eventlog, and the ToasterUI is used to process events in the file
27and log data in the database
28"""
24 29
25# This command takes a filename as a single parameter. The filename is read 30import os
26# as a build eventlog, and the ToasterUI is used to process events in the file
27# and log data in the database
28
29import sys 31import sys
30import json 32import json
31import pickle 33import pickle
@@ -40,130 +42,85 @@ sys.path.insert(0, join(dirname(dirname(abspath(__file__))), 'lib'))
40import bb.cooker 42import bb.cooker
41from bb.ui import toasterui 43from bb.ui import toasterui
42 44
43class FileReadEventsServerConnection(): 45class EventPlayer:
44 """ Emulates a connection to a bitbake server that feeds 46 """Emulate a connection to a bitbake server."""
45 events coming actually read from a saved log file. 47
46 """ 48 def __init__(self, eventfile, variables):
47 49 self.eventfile = eventfile
48 class MockConnection(): 50 self.variables = variables
49 """ fill-in for the proxy to the server. we just return generic data 51 self.eventmask = []
52
53 def waitEvent(self, _timeout):
54 """Read event from the file."""
55 line = self.eventfile.readline().strip()
56 if not line:
57 return
58 try:
59 event_str = json.loads(line)['vars'].encode('utf-8')
60 event = pickle.loads(codecs.decode(event_str, 'base64'))
61 event_name = "%s.%s" % (event.__module__, event.__class__.__name__)
62 if event_name not in self.eventmask:
63 return
64 return event
65 except ValueError as err:
66 print("Failed loading ", line)
67 raise err
68
69 def runCommand(self, command_line):
70 """Emulate running a command on the server."""
71 name = command_line[0]
72
73 if name == "getVariable":
74 var_name = command_line[1]
75 variable = self.variables.get(var_name)
76 if variable:
77 return variable['v'], None
78 return None, "Missing variable %s" % var_name
79
80 elif name == "getAllKeysWithFlags":
81 dump = {}
82 flaglist = command_line[1]
83 for key, val in self.variables.items():
84 try:
85 if not key.startswith("__"):
86 dump[key] = {
87 'v': val['v'],
88 'history' : val['history'],
89 }
90 for flag in flaglist:
91 dump[key][flag] = val[flag]
92 except Exception as err:
93 print(err)
94 return (dump, None)
95
96 elif name == 'setEventMask':
97 self.eventmask = command_line[-1]
98 return True, None
99
100 else:
101 raise Exception("Command %s not implemented" % command_line[0])
102
103 def getEventHandle(self):
50 """ 104 """
51 def __init__(self, sc): 105 This method is called by toasterui.
52 self._sc = sc 106 The return value is passed to self.runCommand but not used there.
53 self.eventmask = [] 107 """
54 108 pass
55 def runCommand(self, commandArray): 109
56 """ emulates running a command on the server; only read-only commands are accepted """ 110def main(argv):
57 command_name = commandArray[0] 111 with open(argv[-1]) as eventfile:
58 112 # load variables from the first line
59 if command_name == "getVariable": 113 variables = json.loads(eventfile.readline().strip())['allvariables']
60 if commandArray[1] in self._sc._variables: 114
61 return (self._sc._variables[commandArray[1]]['v'], None) 115 params = namedtuple('ConfigParams', ['observe_only'])(True)
62 return (None, "Missing variable") 116 player = EventPlayer(eventfile, variables)
63 117
64 elif command_name == "getAllKeysWithFlags": 118 return toasterui.main(player, player, params)
65 dump = {}
66 flaglist = commandArray[1]
67 for k in self._sc._variables.keys():
68 try:
69 if not k.startswith("__"):
70 v = self._sc._variables[k]['v']
71 dump[k] = {
72 'v' : v ,
73 'history' : self._sc._variables[k]['history'],
74 }
75 for d in flaglist:
76 dump[k][d] = self._sc._variables[k][d]
77 except Exception as e:
78 print(e)
79 return (dump, None)
80
81 elif command_name == 'setEventMask':
82 self.eventmask = commandArray[-1]
83 return True, None
84
85 else:
86 raise Exception("Command %s not implemented" % commandArray[0])
87
88 def terminateServer(self):
89 """ do not do anything """
90 pass
91
92 def getEventHandle(self):
93 pass
94
95
96 class EventReader():
97 def __init__(self, sc):
98 self._sc = sc
99 self.firstraise = 0
100
101 def _create_event(self, line):
102 def _import_class(name):
103 assert len(name) > 0
104 assert "." in name, name
105
106 components = name.strip().split(".")
107 modulename = ".".join(components[:-1])
108 moduleklass = components[-1]
109
110 module = __import__(modulename, fromlist=[str(moduleklass)])
111 return getattr(module, moduleklass)
112
113 # we build a toaster event out of current event log line
114 try:
115 event_data = json.loads(line.strip())
116 event_class = _import_class(event_data['class'])
117 event_str = event_data['vars'].encode('utf-8')
118 event_object = pickle.loads(codecs.decode(event_str, 'base64'))
119 except ValueError as e:
120 print("Failed loading ", line)
121 raise e
122
123 if not isinstance(event_object, event_class):
124 raise Exception("Error loading objects %s class %s ", event_object, event_class)
125
126 return event_object
127
128 def waitEvent(self, timeout):
129
130 nextline = self._sc._eventfile.readline()
131 if len(nextline) == 0:
132 # the build data ended, while toasterui still waits for events.
133 # this happens when the server was abruptly stopped, so we simulate this
134 self.firstraise += 1
135 if self.firstraise == 1:
136 raise KeyboardInterrupt()
137 else:
138 return None
139 else:
140 self._sc.lineno += 1
141 return self._create_event(nextline)
142
143
144 def _readVariables(self, variableline):
145 self._variables = json.loads(variableline.strip())['allvariables']
146
147
148 def __init__(self, file_name):
149 self.connection = FileReadEventsServerConnection.MockConnection(self)
150 self._eventfile = open(file_name, "r")
151
152 # we expect to have the variable dump at the start of the file
153 self.lineno = 1
154 self._readVariables(self._eventfile.readline())
155
156 self.events = FileReadEventsServerConnection.EventReader(self)
157 119
158# run toaster ui on our mock bitbake class 120# run toaster ui on our mock bitbake class
159if __name__ == "__main__": 121if __name__ == "__main__":
160 if len(sys.argv) < 2: 122 if len(sys.argv) != 2:
161 print("Usage: %s event.log " % sys.argv[0]) 123 print("Usage: %s <event file>" % os.path.basename(sys.argv[0]))
162 sys.exit(1) 124 sys.exit(1)
163 125
164 file_name = sys.argv[-1] 126 sys.exit(main(sys.argv))
165 mock_connection = FileReadEventsServerConnection(file_name)
166 configParams = namedtuple('ConfigParams', ['observe_only'])(True)
167
168 # run the main program and set exit code to the returned value
169 sys.exit(toasterui.main(mock_connection.connection, mock_connection.events, configParams))