Linux-libre 5.4.48-gnu
[librecmc/linux-libre.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                 'c_thread_id    bigint,'
182                 'c_time         bigint,'
183                 'exec_flag      boolean)')
184 do_query(query, 'CREATE TABLE comm_threads ('
185                 'id             integer         NOT NULL        PRIMARY KEY,'
186                 'comm_id        bigint,'
187                 'thread_id      bigint)')
188 do_query(query, 'CREATE TABLE dsos ('
189                 'id             integer         NOT NULL        PRIMARY KEY,'
190                 'machine_id     bigint,'
191                 'short_name     varchar(256),'
192                 'long_name      varchar(4096),'
193                 'build_id       varchar(64))')
194 do_query(query, 'CREATE TABLE symbols ('
195                 'id             integer         NOT NULL        PRIMARY KEY,'
196                 'dso_id         bigint,'
197                 'sym_start      bigint,'
198                 'sym_end        bigint,'
199                 'binding        integer,'
200                 'name           varchar(2048))')
201 do_query(query, 'CREATE TABLE branch_types ('
202                 'id             integer         NOT NULL        PRIMARY KEY,'
203                 'name           varchar(80))')
204
205 if branches:
206         do_query(query, 'CREATE TABLE samples ('
207                 'id             integer         NOT NULL        PRIMARY KEY,'
208                 'evsel_id       bigint,'
209                 'machine_id     bigint,'
210                 'thread_id      bigint,'
211                 'comm_id        bigint,'
212                 'dso_id         bigint,'
213                 'symbol_id      bigint,'
214                 'sym_offset     bigint,'
215                 'ip             bigint,'
216                 'time           bigint,'
217                 'cpu            integer,'
218                 'to_dso_id      bigint,'
219                 'to_symbol_id   bigint,'
220                 'to_sym_offset  bigint,'
221                 'to_ip          bigint,'
222                 'branch_type    integer,'
223                 'in_tx          boolean,'
224                 'call_path_id   bigint,'
225                 'insn_count     bigint,'
226                 'cyc_count      bigint)')
227 else:
228         do_query(query, 'CREATE TABLE samples ('
229                 'id             integer         NOT NULL        PRIMARY KEY,'
230                 'evsel_id       bigint,'
231                 'machine_id     bigint,'
232                 'thread_id      bigint,'
233                 'comm_id        bigint,'
234                 'dso_id         bigint,'
235                 'symbol_id      bigint,'
236                 'sym_offset     bigint,'
237                 'ip             bigint,'
238                 'time           bigint,'
239                 'cpu            integer,'
240                 'to_dso_id      bigint,'
241                 'to_symbol_id   bigint,'
242                 'to_sym_offset  bigint,'
243                 'to_ip          bigint,'
244                 'period         bigint,'
245                 'weight         bigint,'
246                 'transaction_   bigint,'
247                 'data_src       bigint,'
248                 'branch_type    integer,'
249                 'in_tx          boolean,'
250                 'call_path_id   bigint,'
251                 'insn_count     bigint,'
252                 'cyc_count      bigint)')
253
254 if perf_db_export_calls or perf_db_export_callchains:
255         do_query(query, 'CREATE TABLE call_paths ('
256                 'id             integer         NOT NULL        PRIMARY KEY,'
257                 'parent_id      bigint,'
258                 'symbol_id      bigint,'
259                 'ip             bigint)')
260 if perf_db_export_calls:
261         do_query(query, 'CREATE TABLE calls ('
262                 'id             integer         NOT NULL        PRIMARY KEY,'
263                 'thread_id      bigint,'
264                 'comm_id        bigint,'
265                 'call_path_id   bigint,'
266                 'call_time      bigint,'
267                 'return_time    bigint,'
268                 'branch_count   bigint,'
269                 'call_id        bigint,'
270                 'return_id      bigint,'
271                 'parent_call_path_id    bigint,'
272                 'flags          integer,'
273                 'parent_id      bigint,'
274                 'insn_count     bigint,'
275                 'cyc_count      bigint)')
276
277 do_query(query, 'CREATE TABLE ptwrite ('
278                 'id             integer         NOT NULL        PRIMARY KEY,'
279                 'payload        bigint,'
280                 'exact_ip       integer)')
281
282 do_query(query, 'CREATE TABLE cbr ('
283                 'id             integer         NOT NULL        PRIMARY KEY,'
284                 'cbr            integer,'
285                 'mhz            integer,'
286                 'percent        integer)')
287
288 do_query(query, 'CREATE TABLE mwait ('
289                 'id             integer         NOT NULL        PRIMARY KEY,'
290                 'hints          integer,'
291                 'extensions     integer)')
292
293 do_query(query, 'CREATE TABLE pwre ('
294                 'id             integer         NOT NULL        PRIMARY KEY,'
295                 'cstate         integer,'
296                 'subcstate      integer,'
297                 'hw             integer)')
298
299 do_query(query, 'CREATE TABLE exstop ('
300                 'id             integer         NOT NULL        PRIMARY KEY,'
301                 'exact_ip       integer)')
302
303 do_query(query, 'CREATE TABLE pwrx ('
304                 'id             integer         NOT NULL        PRIMARY KEY,'
305                 'deepest_cstate integer,'
306                 'last_cstate    integer,'
307                 'wake_reason    integer)')
308
309 do_query(query, 'CREATE TABLE context_switches ('
310                 'id             integer         NOT NULL        PRIMARY KEY,'
311                 'machine_id     bigint,'
312                 'time           bigint,'
313                 'cpu            integer,'
314                 'thread_out_id  bigint,'
315                 'comm_out_id    bigint,'
316                 'thread_in_id   bigint,'
317                 'comm_in_id     bigint,'
318                 'flags          integer)')
319
320 # printf was added to sqlite in version 3.8.3
321 sqlite_has_printf = False
322 try:
323         do_query(query, 'SELECT printf("") FROM machines')
324         sqlite_has_printf = True
325 except:
326         pass
327
328 def emit_to_hex(x):
329         if sqlite_has_printf:
330                 return 'printf("%x", ' + x + ')'
331         else:
332                 return x
333
334 do_query(query, 'CREATE VIEW machines_view AS '
335         'SELECT '
336                 'id,'
337                 'pid,'
338                 'root_dir,'
339                 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest'
340         ' FROM machines')
341
342 do_query(query, 'CREATE VIEW dsos_view AS '
343         'SELECT '
344                 'id,'
345                 'machine_id,'
346                 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
347                 'short_name,'
348                 'long_name,'
349                 'build_id'
350         ' FROM dsos')
351
352 do_query(query, 'CREATE VIEW symbols_view AS '
353         'SELECT '
354                 'id,'
355                 'name,'
356                 '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,'
357                 'dso_id,'
358                 'sym_start,'
359                 'sym_end,'
360                 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding'
361         ' FROM symbols')
362
363 do_query(query, 'CREATE VIEW threads_view AS '
364         'SELECT '
365                 'id,'
366                 'machine_id,'
367                 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
368                 'process_id,'
369                 'pid,'
370                 'tid'
371         ' FROM threads')
372
373 do_query(query, 'CREATE VIEW comm_threads_view AS '
374         'SELECT '
375                 'comm_id,'
376                 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
377                 'thread_id,'
378                 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
379                 '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
380         ' FROM comm_threads')
381
382 if perf_db_export_calls or perf_db_export_callchains:
383         do_query(query, 'CREATE VIEW call_paths_view AS '
384                 'SELECT '
385                         'c.id,'
386                         + emit_to_hex('c.ip') + ' AS ip,'
387                         'c.symbol_id,'
388                         '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,'
389                         '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,'
390                         '(SELECT dso FROM symbols_view  WHERE id = c.symbol_id) AS dso_short_name,'
391                         'c.parent_id,'
392                         + emit_to_hex('p.ip') + ' AS parent_ip,'
393                         'p.symbol_id AS parent_symbol_id,'
394                         '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,'
395                         '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
396                         '(SELECT dso FROM symbols_view  WHERE id = p.symbol_id) AS parent_dso_short_name'
397                 ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
398 if perf_db_export_calls:
399         do_query(query, 'CREATE VIEW calls_view AS '
400                 'SELECT '
401                         'calls.id,'
402                         'thread_id,'
403                         '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
404                         '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
405                         '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
406                         'call_path_id,'
407                         + emit_to_hex('ip') + ' AS ip,'
408                         'symbol_id,'
409                         '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
410                         'call_time,'
411                         'return_time,'
412                         'return_time - call_time AS elapsed_time,'
413                         'branch_count,'
414                         'insn_count,'
415                         'cyc_count,'
416                         'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC,'
417                         'call_id,'
418                         'return_id,'
419                         '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,'
420                         'parent_call_path_id,'
421                         'calls.parent_id'
422                 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
423
424 do_query(query, 'CREATE VIEW samples_view AS '
425         'SELECT '
426                 'id,'
427                 'time,'
428                 'cpu,'
429                 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
430                 '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
431                 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
432                 '(SELECT name FROM selected_events WHERE id = evsel_id) AS event,'
433                 + emit_to_hex('ip') + ' AS ip_hex,'
434                 '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
435                 'sym_offset,'
436                 '(SELECT short_name FROM dsos WHERE id = dso_id) AS dso_short_name,'
437                 + emit_to_hex('to_ip') + ' AS to_ip_hex,'
438                 '(SELECT name FROM symbols WHERE id = to_symbol_id) AS to_symbol,'
439                 'to_sym_offset,'
440                 '(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,'
441                 '(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,'
442                 'in_tx,'
443                 'insn_count,'
444                 'cyc_count,'
445                 'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC'
446         ' FROM samples')
447
448 do_query(query, 'CREATE VIEW ptwrite_view AS '
449         'SELECT '
450                 'ptwrite.id,'
451                 'time,'
452                 'cpu,'
453                 + emit_to_hex('payload') + ' AS payload_hex,'
454                 'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip'
455         ' FROM ptwrite'
456         ' INNER JOIN samples ON samples.id = ptwrite.id')
457
458 do_query(query, 'CREATE VIEW cbr_view AS '
459         'SELECT '
460                 'cbr.id,'
461                 'time,'
462                 'cpu,'
463                 'cbr,'
464                 'mhz,'
465                 'percent'
466         ' FROM cbr'
467         ' INNER JOIN samples ON samples.id = cbr.id')
468
469 do_query(query, 'CREATE VIEW mwait_view AS '
470         'SELECT '
471                 'mwait.id,'
472                 'time,'
473                 'cpu,'
474                 + emit_to_hex('hints') + ' AS hints_hex,'
475                 + emit_to_hex('extensions') + ' AS extensions_hex'
476         ' FROM mwait'
477         ' INNER JOIN samples ON samples.id = mwait.id')
478
479 do_query(query, 'CREATE VIEW pwre_view AS '
480         'SELECT '
481                 'pwre.id,'
482                 'time,'
483                 'cpu,'
484                 'cstate,'
485                 'subcstate,'
486                 'CASE WHEN hw=0 THEN \'False\' ELSE \'True\' END AS hw'
487         ' FROM pwre'
488         ' INNER JOIN samples ON samples.id = pwre.id')
489
490 do_query(query, 'CREATE VIEW exstop_view AS '
491         'SELECT '
492                 'exstop.id,'
493                 'time,'
494                 'cpu,'
495                 'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip'
496         ' FROM exstop'
497         ' INNER JOIN samples ON samples.id = exstop.id')
498
499 do_query(query, 'CREATE VIEW pwrx_view AS '
500         'SELECT '
501                 'pwrx.id,'
502                 'time,'
503                 'cpu,'
504                 'deepest_cstate,'
505                 'last_cstate,'
506                 'CASE     WHEN wake_reason=1 THEN \'Interrupt\''
507                         ' WHEN wake_reason=2 THEN \'Timer Deadline\''
508                         ' WHEN wake_reason=4 THEN \'Monitored Address\''
509                         ' WHEN wake_reason=8 THEN \'HW\''
510                         ' ELSE wake_reason '
511                 'END AS wake_reason'
512         ' FROM pwrx'
513         ' INNER JOIN samples ON samples.id = pwrx.id')
514
515 do_query(query, 'CREATE VIEW power_events_view AS '
516         'SELECT '
517                 'samples.id,'
518                 'time,'
519                 'cpu,'
520                 'selected_events.name AS event,'
521                 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT cbr FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS cbr,'
522                 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT mhz FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS mhz,'
523                 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT percent FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS percent,'
524                 'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('hints') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS hints_hex,'
525                 'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('extensions') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS extensions_hex,'
526                 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT cstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS cstate,'
527                 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT subcstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS subcstate,'
528                 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT hw FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS hw,'
529                 'CASE WHEN selected_events.name=\'exstop\' THEN (SELECT exact_ip FROM exstop WHERE exstop.id = samples.id) ELSE "" END AS exact_ip,'
530                 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT deepest_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS deepest_cstate,'
531                 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT last_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS last_cstate,'
532                 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT '
533                         'CASE     WHEN wake_reason=1 THEN \'Interrupt\''
534                                 ' WHEN wake_reason=2 THEN \'Timer Deadline\''
535                                 ' WHEN wake_reason=4 THEN \'Monitored Address\''
536                                 ' WHEN wake_reason=8 THEN \'HW\''
537                                 ' ELSE wake_reason '
538                         'END'
539                 ' FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS wake_reason'
540         ' FROM samples'
541         ' INNER JOIN selected_events ON selected_events.id = evsel_id'
542         ' WHERE selected_events.name IN (\'cbr\',\'mwait\',\'exstop\',\'pwre\',\'pwrx\')')
543
544 do_query(query, 'CREATE VIEW context_switches_view AS '
545         'SELECT '
546                 'context_switches.id,'
547                 'context_switches.machine_id,'
548                 'context_switches.time,'
549                 'context_switches.cpu,'
550                 'th_out.pid AS pid_out,'
551                 'th_out.tid AS tid_out,'
552                 'comm_out.comm AS comm_out,'
553                 'th_in.pid AS pid_in,'
554                 'th_in.tid AS tid_in,'
555                 'comm_in.comm AS comm_in,'
556                 'CASE     WHEN context_switches.flags = 0 THEN \'in\''
557                         ' WHEN context_switches.flags = 1 THEN \'out\''
558                         ' WHEN context_switches.flags = 3 THEN \'out preempt\''
559                         ' ELSE context_switches.flags '
560                 'END AS flags'
561         ' FROM context_switches'
562         ' INNER JOIN threads AS th_out ON th_out.id   = context_switches.thread_out_id'
563         ' INNER JOIN threads AS th_in  ON th_in.id    = context_switches.thread_in_id'
564         ' INNER JOIN comms AS comm_out ON comm_out.id = context_switches.comm_out_id'
565         ' INNER JOIN comms AS comm_in  ON comm_in.id  = context_switches.comm_in_id')
566
567 do_query(query, 'END TRANSACTION')
568
569 evsel_query = QSqlQuery(db)
570 evsel_query.prepare("INSERT INTO selected_events VALUES (?, ?)")
571 machine_query = QSqlQuery(db)
572 machine_query.prepare("INSERT INTO machines VALUES (?, ?, ?)")
573 thread_query = QSqlQuery(db)
574 thread_query.prepare("INSERT INTO threads VALUES (?, ?, ?, ?, ?)")
575 comm_query = QSqlQuery(db)
576 comm_query.prepare("INSERT INTO comms VALUES (?, ?, ?, ?, ?)")
577 comm_thread_query = QSqlQuery(db)
578 comm_thread_query.prepare("INSERT INTO comm_threads VALUES (?, ?, ?)")
579 dso_query = QSqlQuery(db)
580 dso_query.prepare("INSERT INTO dsos VALUES (?, ?, ?, ?, ?)")
581 symbol_query = QSqlQuery(db)
582 symbol_query.prepare("INSERT INTO symbols VALUES (?, ?, ?, ?, ?, ?)")
583 branch_type_query = QSqlQuery(db)
584 branch_type_query.prepare("INSERT INTO branch_types VALUES (?, ?)")
585 sample_query = QSqlQuery(db)
586 if branches:
587         sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
588 else:
589         sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
590 if perf_db_export_calls or perf_db_export_callchains:
591         call_path_query = QSqlQuery(db)
592         call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)")
593 if perf_db_export_calls:
594         call_query = QSqlQuery(db)
595         call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
596 ptwrite_query = QSqlQuery(db)
597 ptwrite_query.prepare("INSERT INTO ptwrite VALUES (?, ?, ?)")
598 cbr_query = QSqlQuery(db)
599 cbr_query.prepare("INSERT INTO cbr VALUES (?, ?, ?, ?)")
600 mwait_query = QSqlQuery(db)
601 mwait_query.prepare("INSERT INTO mwait VALUES (?, ?, ?)")
602 pwre_query = QSqlQuery(db)
603 pwre_query.prepare("INSERT INTO pwre VALUES (?, ?, ?, ?)")
604 exstop_query = QSqlQuery(db)
605 exstop_query.prepare("INSERT INTO exstop VALUES (?, ?)")
606 pwrx_query = QSqlQuery(db)
607 pwrx_query.prepare("INSERT INTO pwrx VALUES (?, ?, ?, ?)")
608 context_switch_query = QSqlQuery(db)
609 context_switch_query.prepare("INSERT INTO context_switches VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")
610
611 def trace_begin():
612         printdate("Writing records...")
613         do_query(query, 'BEGIN TRANSACTION')
614         # id == 0 means unknown.  It is easier to create records for them than replace the zeroes with NULLs
615         evsel_table(0, "unknown")
616         machine_table(0, 0, "unknown")
617         thread_table(0, 0, 0, -1, -1)
618         comm_table(0, "unknown", 0, 0, 0)
619         dso_table(0, 0, "unknown", "unknown", "")
620         symbol_table(0, 0, 0, 0, 0, "unknown")
621         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)
622         if perf_db_export_calls or perf_db_export_callchains:
623                 call_path_table(0, 0, 0, 0)
624                 call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
625
626 unhandled_count = 0
627
628 def is_table_empty(table_name):
629         do_query(query, 'SELECT * FROM ' + table_name + ' LIMIT 1');
630         if query.next():
631                 return False
632         return True
633
634 def drop(table_name):
635         do_query(query, 'DROP VIEW ' + table_name + '_view');
636         do_query(query, 'DROP TABLE ' + table_name);
637
638 def trace_end():
639         do_query(query, 'END TRANSACTION')
640
641         printdate("Adding indexes")
642         if perf_db_export_calls:
643                 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
644                 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')
645                 do_query(query, 'ALTER TABLE comms ADD has_calls boolean')
646                 do_query(query, 'UPDATE comms SET has_calls = 1 WHERE comms.id IN (SELECT DISTINCT comm_id FROM calls)')
647
648         printdate("Dropping unused tables")
649         if is_table_empty("ptwrite"):
650                 drop("ptwrite")
651         if is_table_empty("mwait") and is_table_empty("pwre") and is_table_empty("exstop") and is_table_empty("pwrx"):
652                 do_query(query, 'DROP VIEW power_events_view');
653                 drop("mwait")
654                 drop("pwre")
655                 drop("exstop")
656                 drop("pwrx")
657                 if is_table_empty("cbr"):
658                         drop("cbr")
659         if is_table_empty("context_switches"):
660                 drop("context_switches")
661
662         if (unhandled_count):
663                 printdate("Warning: ", unhandled_count, " unhandled events")
664         printdate("Done")
665
666 def trace_unhandled(event_name, context, event_fields_dict):
667         global unhandled_count
668         unhandled_count += 1
669
670 def sched__sched_switch(*x):
671         pass
672
673 def bind_exec(q, n, x):
674         for xx in x[0:n]:
675                 q.addBindValue(str(xx))
676         do_query_(q)
677
678 def evsel_table(*x):
679         bind_exec(evsel_query, 2, x)
680
681 def machine_table(*x):
682         bind_exec(machine_query, 3, x)
683
684 def thread_table(*x):
685         bind_exec(thread_query, 5, x)
686
687 def comm_table(*x):
688         bind_exec(comm_query, 5, x)
689
690 def comm_thread_table(*x):
691         bind_exec(comm_thread_query, 3, x)
692
693 def dso_table(*x):
694         bind_exec(dso_query, 5, x)
695
696 def symbol_table(*x):
697         bind_exec(symbol_query, 6, x)
698
699 def branch_type_table(*x):
700         bind_exec(branch_type_query, 2, x)
701
702 def sample_table(*x):
703         if branches:
704                 for xx in x[0:15]:
705                         sample_query.addBindValue(str(xx))
706                 for xx in x[19:24]:
707                         sample_query.addBindValue(str(xx))
708                 do_query_(sample_query)
709         else:
710                 bind_exec(sample_query, 24, x)
711
712 def call_path_table(*x):
713         bind_exec(call_path_query, 4, x)
714
715 def call_return_table(*x):
716         bind_exec(call_query, 14, x)
717
718 def ptwrite(id, raw_buf):
719         data = struct.unpack_from("<IQ", raw_buf)
720         flags = data[0]
721         payload = data[1]
722         exact_ip = flags & 1
723         ptwrite_query.addBindValue(str(id))
724         ptwrite_query.addBindValue(str(payload))
725         ptwrite_query.addBindValue(str(exact_ip))
726         do_query_(ptwrite_query)
727
728 def cbr(id, raw_buf):
729         data = struct.unpack_from("<BBBBII", raw_buf)
730         cbr = data[0]
731         MHz = (data[4] + 500) / 1000
732         percent = ((cbr * 1000 / data[2]) + 5) / 10
733         cbr_query.addBindValue(str(id))
734         cbr_query.addBindValue(str(cbr))
735         cbr_query.addBindValue(str(MHz))
736         cbr_query.addBindValue(str(percent))
737         do_query_(cbr_query)
738
739 def mwait(id, raw_buf):
740         data = struct.unpack_from("<IQ", raw_buf)
741         payload = data[1]
742         hints = payload & 0xff
743         extensions = (payload >> 32) & 0x3
744         mwait_query.addBindValue(str(id))
745         mwait_query.addBindValue(str(hints))
746         mwait_query.addBindValue(str(extensions))
747         do_query_(mwait_query)
748
749 def pwre(id, raw_buf):
750         data = struct.unpack_from("<IQ", raw_buf)
751         payload = data[1]
752         hw = (payload >> 7) & 1
753         cstate = (payload >> 12) & 0xf
754         subcstate = (payload >> 8) & 0xf
755         pwre_query.addBindValue(str(id))
756         pwre_query.addBindValue(str(cstate))
757         pwre_query.addBindValue(str(subcstate))
758         pwre_query.addBindValue(str(hw))
759         do_query_(pwre_query)
760
761 def exstop(id, raw_buf):
762         data = struct.unpack_from("<I", raw_buf)
763         flags = data[0]
764         exact_ip = flags & 1
765         exstop_query.addBindValue(str(id))
766         exstop_query.addBindValue(str(exact_ip))
767         do_query_(exstop_query)
768
769 def pwrx(id, raw_buf):
770         data = struct.unpack_from("<IQ", raw_buf)
771         payload = data[1]
772         deepest_cstate = payload & 0xf
773         last_cstate = (payload >> 4) & 0xf
774         wake_reason = (payload >> 8) & 0xf
775         pwrx_query.addBindValue(str(id))
776         pwrx_query.addBindValue(str(deepest_cstate))
777         pwrx_query.addBindValue(str(last_cstate))
778         pwrx_query.addBindValue(str(wake_reason))
779         do_query_(pwrx_query)
780
781 def synth_data(id, config, raw_buf, *x):
782         if config == 0:
783                 ptwrite(id, raw_buf)
784         elif config == 1:
785                 mwait(id, raw_buf)
786         elif config == 2:
787                 pwre(id, raw_buf)
788         elif config == 3:
789                 exstop(id, raw_buf)
790         elif config == 4:
791                 pwrx(id, raw_buf)
792         elif config == 5:
793                 cbr(id, raw_buf)
794
795 def context_switch_table(*x):
796         bind_exec(context_switch_query, 9, x)