aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/scripts/python/export-to-postgresql.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/scripts/python/export-to-postgresql.py')
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py77
1 files changed, 54 insertions, 23 deletions
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index 0564dd7377f2..c3eae1d77d36 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -10,6 +10,8 @@
10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11# more details. 11# more details.
12 12
13from __future__ import print_function
14
13import os 15import os
14import sys 16import sys
15import struct 17import struct
@@ -199,6 +201,18 @@ import datetime
199 201
200from PySide.QtSql import * 202from PySide.QtSql import *
201 203
204if sys.version_info < (3, 0):
205 def toserverstr(str):
206 return str
207 def toclientstr(str):
208 return str
209else:
210 # Assume UTF-8 server_encoding and client_encoding
211 def toserverstr(str):
212 return bytes(str, "UTF_8")
213 def toclientstr(str):
214 return bytes(str, "UTF_8")
215
202# Need to access PostgreSQL C library directly to use COPY FROM STDIN 216# Need to access PostgreSQL C library directly to use COPY FROM STDIN
203from ctypes import * 217from ctypes import *
204libpq = CDLL("libpq.so.5") 218libpq = CDLL("libpq.so.5")
@@ -234,12 +248,17 @@ perf_db_export_mode = True
234perf_db_export_calls = False 248perf_db_export_calls = False
235perf_db_export_callchains = False 249perf_db_export_callchains = False
236 250
251def printerr(*args, **kw_args):
252 print(*args, file=sys.stderr, **kw_args)
253
254def printdate(*args, **kw_args):
255 print(datetime.datetime.today(), *args, sep=' ', **kw_args)
237 256
238def usage(): 257def usage():
239 print >> sys.stderr, "Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>]" 258 printerr("Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>]")
240 print >> sys.stderr, "where: columns 'all' or 'branches'" 259 printerr("where: columns 'all' or 'branches'")
241 print >> sys.stderr, " calls 'calls' => create calls and call_paths table" 260 printerr(" calls 'calls' => create calls and call_paths table")
242 print >> sys.stderr, " callchains 'callchains' => create call_paths table" 261 printerr(" callchains 'callchains' => create call_paths table")
243 raise Exception("Too few arguments") 262 raise Exception("Too few arguments")
244 263
245if (len(sys.argv) < 2): 264if (len(sys.argv) < 2):
@@ -273,7 +292,7 @@ def do_query(q, s):
273 return 292 return
274 raise Exception("Query failed: " + q.lastError().text()) 293 raise Exception("Query failed: " + q.lastError().text())
275 294
276print datetime.datetime.today(), "Creating database..." 295printdate("Creating database...")
277 296
278db = QSqlDatabase.addDatabase('QPSQL') 297db = QSqlDatabase.addDatabase('QPSQL')
279query = QSqlQuery(db) 298query = QSqlQuery(db)
@@ -394,7 +413,8 @@ if perf_db_export_calls:
394 'call_id bigint,' 413 'call_id bigint,'
395 'return_id bigint,' 414 'return_id bigint,'
396 'parent_call_path_id bigint,' 415 'parent_call_path_id bigint,'
397 'flags integer)') 416 'flags integer,'
417 'parent_id bigint)')
398 418
399do_query(query, 'CREATE VIEW machines_view AS ' 419do_query(query, 'CREATE VIEW machines_view AS '
400 'SELECT ' 420 'SELECT '
@@ -478,8 +498,9 @@ if perf_db_export_calls:
478 'branch_count,' 498 'branch_count,'
479 'call_id,' 499 'call_id,'
480 'return_id,' 500 'return_id,'
481 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,' 501 '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 CAST ( flags AS VARCHAR(6) ) END AS flags,'
482 'parent_call_path_id' 502 'parent_call_path_id,'
503 'calls.parent_id'
483 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') 504 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
484 505
485do_query(query, 'CREATE VIEW samples_view AS ' 506do_query(query, 'CREATE VIEW samples_view AS '
@@ -504,12 +525,12 @@ do_query(query, 'CREATE VIEW samples_view AS '
504 ' FROM samples') 525 ' FROM samples')
505 526
506 527
507file_header = struct.pack("!11sii", "PGCOPY\n\377\r\n\0", 0, 0) 528file_header = struct.pack("!11sii", b"PGCOPY\n\377\r\n\0", 0, 0)
508file_trailer = "\377\377" 529file_trailer = b"\377\377"
509 530
510def open_output_file(file_name): 531def open_output_file(file_name):
511 path_name = output_dir_name + "/" + file_name 532 path_name = output_dir_name + "/" + file_name
512 file = open(path_name, "w+") 533 file = open(path_name, "wb+")
513 file.write(file_header) 534 file.write(file_header)
514 return file 535 return file
515 536
@@ -524,13 +545,13 @@ def copy_output_file_direct(file, table_name):
524 545
525# Use COPY FROM STDIN because security may prevent postgres from accessing the files directly 546# Use COPY FROM STDIN because security may prevent postgres from accessing the files directly
526def copy_output_file(file, table_name): 547def copy_output_file(file, table_name):
527 conn = PQconnectdb("dbname = " + dbname) 548 conn = PQconnectdb(toclientstr("dbname = " + dbname))
528 if (PQstatus(conn)): 549 if (PQstatus(conn)):
529 raise Exception("COPY FROM STDIN PQconnectdb failed") 550 raise Exception("COPY FROM STDIN PQconnectdb failed")
530 file.write(file_trailer) 551 file.write(file_trailer)
531 file.seek(0) 552 file.seek(0)
532 sql = "COPY " + table_name + " FROM STDIN (FORMAT 'binary')" 553 sql = "COPY " + table_name + " FROM STDIN (FORMAT 'binary')"
533 res = PQexec(conn, sql) 554 res = PQexec(conn, toclientstr(sql))
534 if (PQresultStatus(res) != 4): 555 if (PQresultStatus(res) != 4):
535 raise Exception("COPY FROM STDIN PQexec failed") 556 raise Exception("COPY FROM STDIN PQexec failed")
536 data = file.read(65536) 557 data = file.read(65536)
@@ -564,7 +585,7 @@ if perf_db_export_calls:
564 call_file = open_output_file("call_table.bin") 585 call_file = open_output_file("call_table.bin")
565 586
566def trace_begin(): 587def trace_begin():
567 print datetime.datetime.today(), "Writing to intermediate files..." 588 printdate("Writing to intermediate files...")
568 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs 589 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs
569 evsel_table(0, "unknown") 590 evsel_table(0, "unknown")
570 machine_table(0, 0, "unknown") 591 machine_table(0, 0, "unknown")
@@ -575,11 +596,12 @@ def trace_begin():
575 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 596 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
576 if perf_db_export_calls or perf_db_export_callchains: 597 if perf_db_export_calls or perf_db_export_callchains:
577 call_path_table(0, 0, 0, 0) 598 call_path_table(0, 0, 0, 0)
599 call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
578 600
579unhandled_count = 0 601unhandled_count = 0
580 602
581def trace_end(): 603def trace_end():
582 print datetime.datetime.today(), "Copying to database..." 604 printdate("Copying to database...")
583 copy_output_file(evsel_file, "selected_events") 605 copy_output_file(evsel_file, "selected_events")
584 copy_output_file(machine_file, "machines") 606 copy_output_file(machine_file, "machines")
585 copy_output_file(thread_file, "threads") 607 copy_output_file(thread_file, "threads")
@@ -594,7 +616,7 @@ def trace_end():
594 if perf_db_export_calls: 616 if perf_db_export_calls:
595 copy_output_file(call_file, "calls") 617 copy_output_file(call_file, "calls")
596 618
597 print datetime.datetime.today(), "Removing intermediate files..." 619 printdate("Removing intermediate files...")
598 remove_output_file(evsel_file) 620 remove_output_file(evsel_file)
599 remove_output_file(machine_file) 621 remove_output_file(machine_file)
600 remove_output_file(thread_file) 622 remove_output_file(thread_file)
@@ -609,7 +631,7 @@ def trace_end():
609 if perf_db_export_calls: 631 if perf_db_export_calls:
610 remove_output_file(call_file) 632 remove_output_file(call_file)
611 os.rmdir(output_dir_name) 633 os.rmdir(output_dir_name)
612 print datetime.datetime.today(), "Adding primary keys" 634 printdate("Adding primary keys")
613 do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)') 635 do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)')
614 do_query(query, 'ALTER TABLE machines ADD PRIMARY KEY (id)') 636 do_query(query, 'ALTER TABLE machines ADD PRIMARY KEY (id)')
615 do_query(query, 'ALTER TABLE threads ADD PRIMARY KEY (id)') 637 do_query(query, 'ALTER TABLE threads ADD PRIMARY KEY (id)')
@@ -624,7 +646,7 @@ def trace_end():
624 if perf_db_export_calls: 646 if perf_db_export_calls:
625 do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)') 647 do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)')
626 648
627 print datetime.datetime.today(), "Adding foreign keys" 649 printdate("Adding foreign keys")
628 do_query(query, 'ALTER TABLE threads ' 650 do_query(query, 'ALTER TABLE threads '
629 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),' 651 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),'
630 'ADD CONSTRAINT processfk FOREIGN KEY (process_id) REFERENCES threads (id)') 652 'ADD CONSTRAINT processfk FOREIGN KEY (process_id) REFERENCES threads (id)')
@@ -657,10 +679,11 @@ def trace_end():
657 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),' 679 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),'
658 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)') 680 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)')
659 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') 681 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
682 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')
660 683
661 if (unhandled_count): 684 if (unhandled_count):
662 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" 685 printdate("Warning: ", unhandled_count, " unhandled events")
663 print datetime.datetime.today(), "Done" 686 printdate("Done")
664 687
665def trace_unhandled(event_name, context, event_fields_dict): 688def trace_unhandled(event_name, context, event_fields_dict):
666 global unhandled_count 689 global unhandled_count
@@ -670,12 +693,14 @@ def sched__sched_switch(*x):
670 pass 693 pass
671 694
672def evsel_table(evsel_id, evsel_name, *x): 695def evsel_table(evsel_id, evsel_name, *x):
696 evsel_name = toserverstr(evsel_name)
673 n = len(evsel_name) 697 n = len(evsel_name)
674 fmt = "!hiqi" + str(n) + "s" 698 fmt = "!hiqi" + str(n) + "s"
675 value = struct.pack(fmt, 2, 8, evsel_id, n, evsel_name) 699 value = struct.pack(fmt, 2, 8, evsel_id, n, evsel_name)
676 evsel_file.write(value) 700 evsel_file.write(value)
677 701
678def machine_table(machine_id, pid, root_dir, *x): 702def machine_table(machine_id, pid, root_dir, *x):
703 root_dir = toserverstr(root_dir)
679 n = len(root_dir) 704 n = len(root_dir)
680 fmt = "!hiqiii" + str(n) + "s" 705 fmt = "!hiqiii" + str(n) + "s"
681 value = struct.pack(fmt, 3, 8, machine_id, 4, pid, n, root_dir) 706 value = struct.pack(fmt, 3, 8, machine_id, 4, pid, n, root_dir)
@@ -686,6 +711,7 @@ def thread_table(thread_id, machine_id, process_id, pid, tid, *x):
686 thread_file.write(value) 711 thread_file.write(value)
687 712
688def comm_table(comm_id, comm_str, *x): 713def comm_table(comm_id, comm_str, *x):
714 comm_str = toserverstr(comm_str)
689 n = len(comm_str) 715 n = len(comm_str)
690 fmt = "!hiqi" + str(n) + "s" 716 fmt = "!hiqi" + str(n) + "s"
691 value = struct.pack(fmt, 2, 8, comm_id, n, comm_str) 717 value = struct.pack(fmt, 2, 8, comm_id, n, comm_str)
@@ -697,6 +723,9 @@ def comm_thread_table(comm_thread_id, comm_id, thread_id, *x):
697 comm_thread_file.write(value) 723 comm_thread_file.write(value)
698 724
699def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x): 725def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x):
726 short_name = toserverstr(short_name)
727 long_name = toserverstr(long_name)
728 build_id = toserverstr(build_id)
700 n1 = len(short_name) 729 n1 = len(short_name)
701 n2 = len(long_name) 730 n2 = len(long_name)
702 n3 = len(build_id) 731 n3 = len(build_id)
@@ -705,12 +734,14 @@ def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x):
705 dso_file.write(value) 734 dso_file.write(value)
706 735
707def symbol_table(symbol_id, dso_id, sym_start, sym_end, binding, symbol_name, *x): 736def symbol_table(symbol_id, dso_id, sym_start, sym_end, binding, symbol_name, *x):
737 symbol_name = toserverstr(symbol_name)
708 n = len(symbol_name) 738 n = len(symbol_name)
709 fmt = "!hiqiqiqiqiii" + str(n) + "s" 739 fmt = "!hiqiqiqiqiii" + str(n) + "s"
710 value = struct.pack(fmt, 6, 8, symbol_id, 8, dso_id, 8, sym_start, 8, sym_end, 4, binding, n, symbol_name) 740 value = struct.pack(fmt, 6, 8, symbol_id, 8, dso_id, 8, sym_start, 8, sym_end, 4, binding, n, symbol_name)
711 symbol_file.write(value) 741 symbol_file.write(value)
712 742
713def branch_type_table(branch_type, name, *x): 743def branch_type_table(branch_type, name, *x):
744 name = toserverstr(name)
714 n = len(name) 745 n = len(name)
715 fmt = "!hiii" + str(n) + "s" 746 fmt = "!hiii" + str(n) + "s"
716 value = struct.pack(fmt, 2, 4, branch_type, n, name) 747 value = struct.pack(fmt, 2, 4, branch_type, n, name)
@@ -728,7 +759,7 @@ def call_path_table(cp_id, parent_id, symbol_id, ip, *x):
728 value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip) 759 value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip)
729 call_path_file.write(value) 760 call_path_file.write(value)
730 761
731def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, *x): 762def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, parent_id, *x):
732 fmt = "!hiqiqiqiqiqiqiqiqiqiqii" 763 fmt = "!hiqiqiqiqiqiqiqiqiqiqiiiq"
733 value = struct.pack(fmt, 11, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags) 764 value = struct.pack(fmt, 12, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags, 8, parent_id)
734 call_file.write(value) 765 call_file.write(value)