]> asedeno.scripts.mit.edu Git - linux.git/blob - tools/perf/scripts/python/export-to-sqlite.py
perf scripts python: export-to-sqlite.py: Export Intel PT power and ptwrite events
[linux.git] / tools / perf / scripts / python / export-to-sqlite.py
1 # export-to-sqlite.py: export perf data to a sqlite3 database
2 # Copyright (c) 2017, Intel Corporation.
3 #
4 # This program is free software; you can redistribute it and/or modify it
5 # under the terms and conditions of the GNU General Public License,
6 # version 2, as published by the Free Software Foundation.
7 #
8 # This program is distributed in the hope it will be useful, but WITHOUT
9 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11 # more details.
12
13 from __future__ import print_function
14
15 import os
16 import sys
17 import struct
18 import datetime
19
20 # To use this script you will need to have installed package python-pyside which
21 # provides LGPL-licensed Python bindings for Qt.  You will also need the package
22 # libqt4-sql-sqlite for Qt sqlite3 support.
23 #
24 # Examples of installing pyside:
25 #
26 # ubuntu:
27 #
28 #       $ sudo apt-get install python-pyside.qtsql libqt4-sql-psql
29 #
30 #       Alternately, to use Python3 and/or pyside 2, one of the following:
31 #
32 #               $ sudo apt-get install python3-pyside.qtsql libqt4-sql-psql
33 #               $ sudo apt-get install python-pyside2.qtsql libqt5sql5-psql
34 #               $ sudo apt-get install python3-pyside2.qtsql libqt5sql5-psql
35 # fedora:
36 #
37 #       $ sudo yum install python-pyside
38 #
39 #       Alternately, to use Python3 and/or pyside 2, one of the following:
40 #               $ sudo yum install python3-pyside
41 #               $ pip install --user PySide2
42 #               $ pip3 install --user PySide2
43 #
44 # An example of using this script with Intel PT:
45 #
46 #       $ perf record -e intel_pt//u ls
47 #       $ perf script -s ~/libexec/perf-core/scripts/python/export-to-sqlite.py pt_example branches calls
48 #       2017-07-31 14:26:07.326913 Creating database...
49 #       2017-07-31 14:26:07.538097 Writing records...
50 #       2017-07-31 14:26:09.889292 Adding indexes
51 #       2017-07-31 14:26:09.958746 Done
52 #
53 # To browse the database, sqlite3 can be used e.g.
54 #
55 #       $ sqlite3 pt_example
56 #       sqlite> .header on
57 #       sqlite> select * from samples_view where id < 10;
58 #       sqlite> .mode column
59 #       sqlite> select * from samples_view where id < 10;
60 #       sqlite> .tables
61 #       sqlite> .schema samples_view
62 #       sqlite> .quit
63 #
64 # An example of using the database is provided by the script
65 # exported-sql-viewer.py.  Refer to that script for details.
66 #
67 # The database structure is practically the same as created by the script
68 # export-to-postgresql.py. Refer to that script for details.  A notable
69 # difference is  the 'transaction' column of the 'samples' table which is
70 # renamed 'transaction_' in sqlite because 'transaction' is a reserved word.
71
72 pyside_version_1 = True
73 if not "pyside-version-1" in sys.argv:
74         try:
75                 from PySide2.QtSql import *
76                 pyside_version_1 = False
77         except:
78                 pass
79
80 if pyside_version_1:
81         from PySide.QtSql import *
82
83 sys.path.append(os.environ['PERF_EXEC_PATH'] + \
84         '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
85
86 # These perf imports are not used at present
87 #from perf_trace_context import *
88 #from Core import *
89
90 perf_db_export_mode = True
91 perf_db_export_calls = False
92 perf_db_export_callchains = False
93
94 def printerr(*args, **keyword_args):
95         print(*args, file=sys.stderr, **keyword_args)
96
97 def printdate(*args, **kw_args):
98         print(datetime.datetime.today(), *args, sep=' ', **kw_args)
99
100 def usage():
101         printerr("Usage is: export-to-sqlite.py <database name> [<columns>] [<calls>] [<callchains>] [<pyside-version-1>]");
102         printerr("where:  columns            'all' or 'branches'");
103         printerr("        calls              'calls' => create calls and call_paths table");
104         printerr("        callchains         'callchains' => create call_paths table");
105         printerr("        pyside-version-1   'pyside-version-1' => use pyside version 1");
106         raise Exception("Too few or bad arguments")
107
108 if (len(sys.argv) < 2):
109         usage()
110
111 dbname = sys.argv[1]
112
113 if (len(sys.argv) >= 3):
114         columns = sys.argv[2]
115 else:
116         columns = "all"
117
118 if columns not in ("all", "branches"):
119         usage()
120
121 branches = (columns == "branches")
122
123 for i in range(3,len(sys.argv)):
124         if (sys.argv[i] == "calls"):
125                 perf_db_export_calls = True
126         elif (sys.argv[i] == "callchains"):
127                 perf_db_export_callchains = True
128         elif (sys.argv[i] == "pyside-version-1"):
129                 pass
130         else:
131                 usage()
132
133 def do_query(q, s):
134         if (q.exec_(s)):
135                 return
136         raise Exception("Query failed: " + q.lastError().text())
137
138 def do_query_(q):
139         if (q.exec_()):
140                 return
141         raise Exception("Query failed: " + q.lastError().text())
142
143 printdate("Creating database ...")
144
145 db_exists = False
146 try:
147         f = open(dbname)
148         f.close()
149         db_exists = True
150 except:
151         pass
152
153 if db_exists:
154         raise Exception(dbname + " already exists")
155
156 db = QSqlDatabase.addDatabase('QSQLITE')
157 db.setDatabaseName(dbname)
158 db.open()
159
160 query = QSqlQuery(db)
161
162 do_query(query, 'PRAGMA journal_mode = OFF')
163 do_query(query, 'BEGIN TRANSACTION')
164
165 do_query(query, 'CREATE TABLE selected_events ('
166                 'id             integer         NOT NULL        PRIMARY KEY,'
167                 'name           varchar(80))')
168 do_query(query, 'CREATE TABLE machines ('
169                 'id             integer         NOT NULL        PRIMARY KEY,'
170                 'pid            integer,'
171                 'root_dir       varchar(4096))')
172 do_query(query, 'CREATE TABLE threads ('
173                 'id             integer         NOT NULL        PRIMARY KEY,'
174                 'machine_id     bigint,'
175                 'process_id     bigint,'
176                 'pid            integer,'
177                 'tid            integer)')
178 do_query(query, 'CREATE TABLE comms ('
179                 'id             integer         NOT NULL        PRIMARY KEY,'
180                 'comm           varchar(16))')
181 do_query(query, 'CREATE TABLE comm_threads ('
182                 'id             integer         NOT NULL        PRIMARY KEY,'
183                 'comm_id        bigint,'
184                 'thread_id      bigint)')
185 do_query(query, 'CREATE TABLE dsos ('
186                 'id             integer         NOT NULL        PRIMARY KEY,'
187                 'machine_id     bigint,'
188                 'short_name     varchar(256),'
189                 'long_name      varchar(4096),'
190                 'build_id       varchar(64))')
191 do_query(query, 'CREATE TABLE symbols ('
192                 'id             integer         NOT NULL        PRIMARY KEY,'
193                 'dso_id         bigint,'
194                 'sym_start      bigint,'
195                 'sym_end        bigint,'
196                 'binding        integer,'
197                 'name           varchar(2048))')
198 do_query(query, 'CREATE TABLE branch_types ('
199                 'id             integer         NOT NULL        PRIMARY KEY,'
200                 'name           varchar(80))')
201
202 if branches:
203         do_query(query, 'CREATE TABLE samples ('
204                 'id             integer         NOT NULL        PRIMARY KEY,'
205                 'evsel_id       bigint,'
206                 'machine_id     bigint,'
207                 'thread_id      bigint,'
208                 'comm_id        bigint,'
209                 'dso_id         bigint,'
210                 'symbol_id      bigint,'
211                 'sym_offset     bigint,'
212                 'ip             bigint,'
213                 'time           bigint,'
214                 'cpu            integer,'
215                 'to_dso_id      bigint,'
216                 'to_symbol_id   bigint,'
217                 'to_sym_offset  bigint,'
218                 'to_ip          bigint,'
219                 'branch_type    integer,'
220                 'in_tx          boolean,'
221                 'call_path_id   bigint,'
222                 'insn_count     bigint,'
223                 'cyc_count      bigint)')
224 else:
225         do_query(query, 'CREATE TABLE samples ('
226                 'id             integer         NOT NULL        PRIMARY KEY,'
227                 'evsel_id       bigint,'
228                 'machine_id     bigint,'
229                 'thread_id      bigint,'
230                 'comm_id        bigint,'
231                 'dso_id         bigint,'
232                 'symbol_id      bigint,'
233                 'sym_offset     bigint,'
234                 'ip             bigint,'
235                 'time           bigint,'
236                 'cpu            integer,'
237                 'to_dso_id      bigint,'
238                 'to_symbol_id   bigint,'
239                 'to_sym_offset  bigint,'
240                 'to_ip          bigint,'
241                 'period         bigint,'
242                 'weight         bigint,'
243                 'transaction_   bigint,'
244                 'data_src       bigint,'
245                 'branch_type    integer,'
246                 'in_tx          boolean,'
247                 'call_path_id   bigint,'
248                 'insn_count     bigint,'
249                 'cyc_count      bigint)')
250
251 if perf_db_export_calls or perf_db_export_callchains:
252         do_query(query, 'CREATE TABLE call_paths ('
253                 'id             integer         NOT NULL        PRIMARY KEY,'
254                 'parent_id      bigint,'
255                 'symbol_id      bigint,'
256                 'ip             bigint)')
257 if perf_db_export_calls:
258         do_query(query, 'CREATE TABLE calls ('
259                 'id             integer         NOT NULL        PRIMARY KEY,'
260                 'thread_id      bigint,'
261                 'comm_id        bigint,'
262                 'call_path_id   bigint,'
263                 'call_time      bigint,'
264                 'return_time    bigint,'
265                 'branch_count   bigint,'
266                 'call_id        bigint,'
267                 'return_id      bigint,'
268                 'parent_call_path_id    bigint,'
269                 'flags          integer,'
270                 'parent_id      bigint,'
271                 'insn_count     bigint,'
272                 'cyc_count      bigint)')
273
274 do_query(query, 'CREATE TABLE ptwrite ('
275                 'id             integer         NOT NULL        PRIMARY KEY,'
276                 'payload        bigint,'
277                 'exact_ip       integer)')
278
279 do_query(query, 'CREATE TABLE cbr ('
280                 'id             integer         NOT NULL        PRIMARY KEY,'
281                 'cbr            integer,'
282                 'mhz            integer,'
283                 'percent        integer)')
284
285 do_query(query, 'CREATE TABLE mwait ('
286                 'id             integer         NOT NULL        PRIMARY KEY,'
287                 'hints          integer,'
288                 'extensions     integer)')
289
290 do_query(query, 'CREATE TABLE pwre ('
291                 'id             integer         NOT NULL        PRIMARY KEY,'
292                 'cstate         integer,'
293                 'subcstate      integer,'
294                 'hw             integer)')
295
296 do_query(query, 'CREATE TABLE exstop ('
297                 'id             integer         NOT NULL        PRIMARY KEY,'
298                 'exact_ip       integer)')
299
300 do_query(query, 'CREATE TABLE pwrx ('
301                 'id             integer         NOT NULL        PRIMARY KEY,'
302                 'deepest_cstate integer,'
303                 'last_cstate    integer,'
304                 'wake_reason    integer)')
305
306 # printf was added to sqlite in version 3.8.3
307 sqlite_has_printf = False
308 try:
309         do_query(query, 'SELECT printf("") FROM machines')
310         sqlite_has_printf = True
311 except:
312         pass
313
314 def emit_to_hex(x):
315         if sqlite_has_printf:
316                 return 'printf("%x", ' + x + ')'
317         else:
318                 return x
319
320 do_query(query, 'CREATE VIEW machines_view AS '
321         'SELECT '
322                 'id,'
323                 'pid,'
324                 'root_dir,'
325                 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest'
326         ' FROM machines')
327
328 do_query(query, 'CREATE VIEW dsos_view AS '
329         'SELECT '
330                 'id,'
331                 'machine_id,'
332                 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
333                 'short_name,'
334                 'long_name,'
335                 'build_id'
336         ' FROM dsos')
337
338 do_query(query, 'CREATE VIEW symbols_view AS '
339         'SELECT '
340                 'id,'
341                 'name,'
342                 '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,'
343                 'dso_id,'
344                 'sym_start,'
345                 'sym_end,'
346                 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding'
347         ' FROM symbols')
348
349 do_query(query, 'CREATE VIEW threads_view AS '
350         'SELECT '
351                 'id,'
352                 'machine_id,'
353                 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
354                 'process_id,'
355                 'pid,'
356                 'tid'
357         ' FROM threads')
358
359 do_query(query, 'CREATE VIEW comm_threads_view AS '
360         'SELECT '
361                 'comm_id,'
362                 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
363                 'thread_id,'
364                 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
365                 '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
366         ' FROM comm_threads')
367
368 if perf_db_export_calls or perf_db_export_callchains:
369         do_query(query, 'CREATE VIEW call_paths_view AS '
370                 'SELECT '
371                         'c.id,'
372                         + emit_to_hex('c.ip') + ' AS ip,'
373                         'c.symbol_id,'
374                         '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,'
375                         '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,'
376                         '(SELECT dso FROM symbols_view  WHERE id = c.symbol_id) AS dso_short_name,'
377                         'c.parent_id,'
378                         + emit_to_hex('p.ip') + ' AS parent_ip,'
379                         'p.symbol_id AS parent_symbol_id,'
380                         '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,'
381                         '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
382                         '(SELECT dso FROM symbols_view  WHERE id = p.symbol_id) AS parent_dso_short_name'
383                 ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
384 if perf_db_export_calls:
385         do_query(query, 'CREATE VIEW calls_view AS '
386                 'SELECT '
387                         'calls.id,'
388                         'thread_id,'
389                         '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
390                         '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
391                         '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
392                         'call_path_id,'
393                         + emit_to_hex('ip') + ' AS ip,'
394                         'symbol_id,'
395                         '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
396                         'call_time,'
397                         'return_time,'
398                         'return_time - call_time AS elapsed_time,'
399                         'branch_count,'
400                         'insn_count,'
401                         'cyc_count,'
402                         'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC,'
403                         'call_id,'
404                         'return_id,'
405                         'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,'
406                         'parent_call_path_id,'
407                         'calls.parent_id'
408                 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
409
410 do_query(query, 'CREATE VIEW samples_view AS '
411         'SELECT '
412                 'id,'
413                 'time,'
414                 'cpu,'
415                 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
416                 '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
417                 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
418                 '(SELECT name FROM selected_events WHERE id = evsel_id) AS event,'
419                 + emit_to_hex('ip') + ' AS ip_hex,'
420                 '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
421                 'sym_offset,'
422                 '(SELECT short_name FROM dsos WHERE id = dso_id) AS dso_short_name,'
423                 + emit_to_hex('to_ip') + ' AS to_ip_hex,'
424                 '(SELECT name FROM symbols WHERE id = to_symbol_id) AS to_symbol,'
425                 'to_sym_offset,'
426                 '(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,'
427                 '(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,'
428                 'in_tx,'
429                 'insn_count,'
430                 'cyc_count,'
431                 'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC'
432         ' FROM samples')
433
434 do_query(query, 'CREATE VIEW ptwrite_view AS '
435         'SELECT '
436                 'ptwrite.id,'
437                 'time,'
438                 'cpu,'
439                 + emit_to_hex('payload') + ' AS payload_hex,'
440                 'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip'
441         ' FROM ptwrite'
442         ' INNER JOIN samples ON samples.id = ptwrite.id')
443
444 do_query(query, 'CREATE VIEW cbr_view AS '
445         'SELECT '
446                 'cbr.id,'
447                 'time,'
448                 'cpu,'
449                 'cbr,'
450                 'mhz,'
451                 'percent'
452         ' FROM cbr'
453         ' INNER JOIN samples ON samples.id = cbr.id')
454
455 do_query(query, 'CREATE VIEW mwait_view AS '
456         'SELECT '
457                 'mwait.id,'
458                 'time,'
459                 'cpu,'
460                 + emit_to_hex('hints') + ' AS hints_hex,'
461                 + emit_to_hex('extensions') + ' AS extensions_hex'
462         ' FROM mwait'
463         ' INNER JOIN samples ON samples.id = mwait.id')
464
465 do_query(query, 'CREATE VIEW pwre_view AS '
466         'SELECT '
467                 'pwre.id,'
468                 'time,'
469                 'cpu,'
470                 'cstate,'
471                 'subcstate,'
472                 'CASE WHEN hw=0 THEN \'False\' ELSE \'True\' END AS hw'
473         ' FROM pwre'
474         ' INNER JOIN samples ON samples.id = pwre.id')
475
476 do_query(query, 'CREATE VIEW exstop_view AS '
477         'SELECT '
478                 'exstop.id,'
479                 'time,'
480                 'cpu,'
481                 'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip'
482         ' FROM exstop'
483         ' INNER JOIN samples ON samples.id = exstop.id')
484
485 do_query(query, 'CREATE VIEW pwrx_view AS '
486         'SELECT '
487                 'pwrx.id,'
488                 'time,'
489                 'cpu,'
490                 'deepest_cstate,'
491                 'last_cstate,'
492                 'CASE     WHEN wake_reason=1 THEN \'Interrupt\''
493                         ' WHEN wake_reason=2 THEN \'Timer Deadline\''
494                         ' WHEN wake_reason=4 THEN \'Monitored Address\''
495                         ' WHEN wake_reason=8 THEN \'HW\''
496                         ' ELSE wake_reason '
497                 'END AS wake_reason'
498         ' FROM pwrx'
499         ' INNER JOIN samples ON samples.id = pwrx.id')
500
501 do_query(query, 'CREATE VIEW power_events_view AS '
502         'SELECT '
503                 'samples.id,'
504                 'time,'
505                 'cpu,'
506                 'selected_events.name AS event,'
507                 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT cbr FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS cbr,'
508                 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT mhz FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS mhz,'
509                 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT percent FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS percent,'
510                 'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('hints') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS hints_hex,'
511                 'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('extensions') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS extensions_hex,'
512                 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT cstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS cstate,'
513                 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT subcstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS subcstate,'
514                 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT hw FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS hw,'
515                 'CASE WHEN selected_events.name=\'exstop\' THEN (SELECT exact_ip FROM exstop WHERE exstop.id = samples.id) ELSE "" END AS exact_ip,'
516                 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT deepest_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS deepest_cstate,'
517                 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT last_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS last_cstate,'
518                 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT '
519                         'CASE     WHEN wake_reason=1 THEN \'Interrupt\''
520                                 ' WHEN wake_reason=2 THEN \'Timer Deadline\''
521                                 ' WHEN wake_reason=4 THEN \'Monitored Address\''
522                                 ' WHEN wake_reason=8 THEN \'HW\''
523                                 ' ELSE wake_reason '
524                         'END'
525                 ' FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS wake_reason'
526         ' FROM samples'
527         ' INNER JOIN selected_events ON selected_events.id = evsel_id'
528         ' WHERE selected_events.name IN (\'cbr\',\'mwait\',\'exstop\',\'pwre\',\'pwrx\')')
529
530 do_query(query, 'END TRANSACTION')
531
532 evsel_query = QSqlQuery(db)
533 evsel_query.prepare("INSERT INTO selected_events VALUES (?, ?)")
534 machine_query = QSqlQuery(db)
535 machine_query.prepare("INSERT INTO machines VALUES (?, ?, ?)")
536 thread_query = QSqlQuery(db)
537 thread_query.prepare("INSERT INTO threads VALUES (?, ?, ?, ?, ?)")
538 comm_query = QSqlQuery(db)
539 comm_query.prepare("INSERT INTO comms VALUES (?, ?)")
540 comm_thread_query = QSqlQuery(db)
541 comm_thread_query.prepare("INSERT INTO comm_threads VALUES (?, ?, ?)")
542 dso_query = QSqlQuery(db)
543 dso_query.prepare("INSERT INTO dsos VALUES (?, ?, ?, ?, ?)")
544 symbol_query = QSqlQuery(db)
545 symbol_query.prepare("INSERT INTO symbols VALUES (?, ?, ?, ?, ?, ?)")
546 branch_type_query = QSqlQuery(db)
547 branch_type_query.prepare("INSERT INTO branch_types VALUES (?, ?)")
548 sample_query = QSqlQuery(db)
549 if branches:
550         sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
551 else:
552         sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
553 if perf_db_export_calls or perf_db_export_callchains:
554         call_path_query = QSqlQuery(db)
555         call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)")
556 if perf_db_export_calls:
557         call_query = QSqlQuery(db)
558         call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
559 ptwrite_query = QSqlQuery(db)
560 ptwrite_query.prepare("INSERT INTO ptwrite VALUES (?, ?, ?)")
561 cbr_query = QSqlQuery(db)
562 cbr_query.prepare("INSERT INTO cbr VALUES (?, ?, ?, ?)")
563 mwait_query = QSqlQuery(db)
564 mwait_query.prepare("INSERT INTO mwait VALUES (?, ?, ?)")
565 pwre_query = QSqlQuery(db)
566 pwre_query.prepare("INSERT INTO pwre VALUES (?, ?, ?, ?)")
567 exstop_query = QSqlQuery(db)
568 exstop_query.prepare("INSERT INTO exstop VALUES (?, ?)")
569 pwrx_query = QSqlQuery(db)
570 pwrx_query.prepare("INSERT INTO pwrx VALUES (?, ?, ?, ?)")
571
572 def trace_begin():
573         printdate("Writing records...")
574         do_query(query, 'BEGIN TRANSACTION')
575         # id == 0 means unknown.  It is easier to create records for them than replace the zeroes with NULLs
576         evsel_table(0, "unknown")
577         machine_table(0, 0, "unknown")
578         thread_table(0, 0, 0, -1, -1)
579         comm_table(0, "unknown")
580         dso_table(0, 0, "unknown", "unknown", "")
581         symbol_table(0, 0, 0, 0, 0, "unknown")
582         sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
583         if perf_db_export_calls or perf_db_export_callchains:
584                 call_path_table(0, 0, 0, 0)
585                 call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
586
587 unhandled_count = 0
588
589 def is_table_empty(table_name):
590         do_query(query, 'SELECT * FROM ' + table_name + ' LIMIT 1');
591         if query.next():
592                 return False
593         return True
594
595 def drop(table_name):
596         do_query(query, 'DROP VIEW ' + table_name + '_view');
597         do_query(query, 'DROP TABLE ' + table_name);
598
599 def trace_end():
600         do_query(query, 'END TRANSACTION')
601
602         printdate("Adding indexes")
603         if perf_db_export_calls:
604                 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
605                 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')
606
607         printdate("Dropping unused tables")
608         if is_table_empty("ptwrite"):
609                 drop("ptwrite")
610         if is_table_empty("mwait") and is_table_empty("pwre") and is_table_empty("exstop") and is_table_empty("pwrx"):
611                 drop("mwait")
612                 drop("pwre")
613                 drop("exstop")
614                 drop("pwrx")
615                 do_query(query, 'DROP VIEW power_events_view');
616                 if is_table_empty("cbr"):
617                         drop("cbr")
618
619         if (unhandled_count):
620                 printdate("Warning: ", unhandled_count, " unhandled events")
621         printdate("Done")
622
623 def trace_unhandled(event_name, context, event_fields_dict):
624         global unhandled_count
625         unhandled_count += 1
626
627 def sched__sched_switch(*x):
628         pass
629
630 def bind_exec(q, n, x):
631         for xx in x[0:n]:
632                 q.addBindValue(str(xx))
633         do_query_(q)
634
635 def evsel_table(*x):
636         bind_exec(evsel_query, 2, x)
637
638 def machine_table(*x):
639         bind_exec(machine_query, 3, x)
640
641 def thread_table(*x):
642         bind_exec(thread_query, 5, x)
643
644 def comm_table(*x):
645         bind_exec(comm_query, 2, x)
646
647 def comm_thread_table(*x):
648         bind_exec(comm_thread_query, 3, x)
649
650 def dso_table(*x):
651         bind_exec(dso_query, 5, x)
652
653 def symbol_table(*x):
654         bind_exec(symbol_query, 6, x)
655
656 def branch_type_table(*x):
657         bind_exec(branch_type_query, 2, x)
658
659 def sample_table(*x):
660         if branches:
661                 for xx in x[0:15]:
662                         sample_query.addBindValue(str(xx))
663                 for xx in x[19:24]:
664                         sample_query.addBindValue(str(xx))
665                 do_query_(sample_query)
666         else:
667                 bind_exec(sample_query, 24, x)
668
669 def call_path_table(*x):
670         bind_exec(call_path_query, 4, x)
671
672 def call_return_table(*x):
673         bind_exec(call_query, 14, x)
674
675 def ptwrite(id, raw_buf):
676         data = struct.unpack_from("<IQ", raw_buf)
677         flags = data[0]
678         payload = data[1]
679         exact_ip = flags & 1
680         ptwrite_query.addBindValue(str(id))
681         ptwrite_query.addBindValue(str(payload))
682         ptwrite_query.addBindValue(str(exact_ip))
683         do_query_(ptwrite_query)
684
685 def cbr(id, raw_buf):
686         data = struct.unpack_from("<BBBBII", raw_buf)
687         cbr = data[0]
688         MHz = (data[4] + 500) / 1000
689         percent = ((cbr * 1000 / data[2]) + 5) / 10
690         cbr_query.addBindValue(str(id))
691         cbr_query.addBindValue(str(cbr))
692         cbr_query.addBindValue(str(MHz))
693         cbr_query.addBindValue(str(percent))
694         do_query_(cbr_query)
695
696 def mwait(id, raw_buf):
697         data = struct.unpack_from("<IQ", raw_buf)
698         payload = data[1]
699         hints = payload & 0xff
700         extensions = (payload >> 32) & 0x3
701         mwait_query.addBindValue(str(id))
702         mwait_query.addBindValue(str(hints))
703         mwait_query.addBindValue(str(extensions))
704         do_query_(mwait_query)
705
706 def pwre(id, raw_buf):
707         data = struct.unpack_from("<IQ", raw_buf)
708         payload = data[1]
709         hw = (payload >> 7) & 1
710         cstate = (payload >> 12) & 0xf
711         subcstate = (payload >> 8) & 0xf
712         pwre_query.addBindValue(str(id))
713         pwre_query.addBindValue(str(cstate))
714         pwre_query.addBindValue(str(subcstate))
715         pwre_query.addBindValue(str(hw))
716         do_query_(pwre_query)
717
718 def exstop(id, raw_buf):
719         data = struct.unpack_from("<I", raw_buf)
720         flags = data[0]
721         exact_ip = flags & 1
722         exstop_query.addBindValue(str(id))
723         exstop_query.addBindValue(str(exact_ip))
724         do_query_(exstop_query)
725
726 def pwrx(id, raw_buf):
727         data = struct.unpack_from("<IQ", raw_buf)
728         payload = data[1]
729         deepest_cstate = payload & 0xf
730         last_cstate = (payload >> 4) & 0xf
731         wake_reason = (payload >> 8) & 0xf
732         pwrx_query.addBindValue(str(id))
733         pwrx_query.addBindValue(str(deepest_cstate))
734         pwrx_query.addBindValue(str(last_cstate))
735         pwrx_query.addBindValue(str(wake_reason))
736         do_query_(pwrx_query)
737
738 def synth_data(id, config, raw_buf, *x):
739         if config == 0:
740                 ptwrite(id, raw_buf)
741         elif config == 1:
742                 mwait(id, raw_buf)
743         elif config == 2:
744                 pwre(id, raw_buf)
745         elif config == 3:
746                 exstop(id, raw_buf)
747         elif config == 4:
748                 pwrx(id, raw_buf)
749         elif config == 5:
750                 cbr(id, raw_buf)