History

perf scripts python: exported-sql-viewer.py: Create new dialog data item classes

Create new dialog data item classes to replace SQLTableDialogDataItem. This separates out different dialog data items and makes it easier to add new ones. SQLTableDialogDataItem is removed in a separate patch because it makes the diff more readable.

Adrian Hunter committed 7 years ago

Commit 1c3ca1b1 parent 947cc381 file · +272 −13Browse files

Showing the changes to tools/perf/scripts/python (1 of 1 file). Show all

Unified · Split

tools/perf/scripts/python/exported-sql-viewer.py+272−13
@@ -1702,6 +1702,265 @@ class SQLTableDialogDataItem(): · 1701 unmodified lines
17021702 return False
17031703 return True
17041704
1705+# Line edit data item
1706+
1707+class LineEditDataItem(object):
1708+
1709+ def __init__(self, glb, label, placeholder_text, parent, id = ""):
1710+ self.glb = glb
1711+ self.label = label
1712+ self.placeholder_text = placeholder_text
1713+ self.parent = parent
1714+ self.id = id
1715+
1716+ self.value = ""
1717+
1718+ self.widget = QLineEdit()
1719+ self.widget.editingFinished.connect(self.Validate)
1720+ self.widget.textChanged.connect(self.Invalidate)
1721+ self.red = False
1722+ self.error = ""
1723+ self.validated = True
1724+
1725+ if placeholder_text:
1726+ self.widget.setPlaceholderText(placeholder_text)
1727+
1728+ def TurnTextRed(self):
1729+ if not self.red:
1730+ palette = QPalette()
1731+ palette.setColor(QPalette.Text,Qt.red)
1732+ self.widget.setPalette(palette)
1733+ self.red = True
1734+
1735+ def TurnTextNormal(self):
1736+ if self.red:
1737+ palette = QPalette()
1738+ self.widget.setPalette(palette)
1739+ self.red = False
1740+
1741+ def InvalidValue(self, value):
1742+ self.value = ""
1743+ self.TurnTextRed()
1744+ self.error = self.label + " invalid value '" + value + "'"
1745+ self.parent.ShowMessage(self.error)
1746+
1747+ def Invalidate(self):
1748+ self.validated = False
1749+
1750+ def DoValidate(self, input_string):
1751+ self.value = input_string.strip()
1752+
1753+ def Validate(self):
1754+ self.validated = True
1755+ self.error = ""
1756+ self.TurnTextNormal()
1757+ self.parent.ClearMessage()
1758+ input_string = self.widget.text()
1759+ if not len(input_string.strip()):
1760+ self.value = ""
1761+ return
1762+ self.DoValidate(input_string)
1763+
1764+ def IsValid(self):
1765+ if not self.validated:
1766+ self.Validate()
1767+ if len(self.error):
1768+ self.parent.ShowMessage(self.error)
1769+ return False
1770+ return True
1771+
1772+ def IsNumber(self, value):
1773+ try:
1774+ x = int(value)
1775+ except:
1776+ x = 0
1777+ return str(x) == value
1778+
1779+# Non-negative integer ranges dialog data item
1780+
1781+class NonNegativeIntegerRangesDataItem(LineEditDataItem):
1782+
1783+ def __init__(self, glb, label, placeholder_text, column_name, parent):
1784+ super(NonNegativeIntegerRangesDataItem, self).__init__(glb, label, placeholder_text, parent)
1785+
1786+ self.column_name = column_name
1787+
1788+ def DoValidate(self, input_string):
1789+ singles = []
1790+ ranges = []
1791+ for value in [x.strip() for x in input_string.split(",")]:
1792+ if "-" in value:
1793+ vrange = value.split("-")
1794+ if len(vrange) != 2 or not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]):
1795+ return self.InvalidValue(value)
1796+ ranges.append(vrange)
1797+ else:
1798+ if not self.IsNumber(value):
1799+ return self.InvalidValue(value)
1800+ singles.append(value)
1801+ ranges = [("(" + self.column_name + " >= " + r[0] + " AND " + self.column_name + " <= " + r[1] + ")") for r in ranges]
1802+ if len(singles):
1803+ ranges.append(self.column_name + " IN (" + ",".join(singles) + ")")
1804+ self.value = " OR ".join(ranges)
1805+
1806+# Dialog data item converted and validated using a SQL table
1807+
1808+class SQLTableDataItem(LineEditDataItem):
1809+
1810+ def __init__(self, glb, label, placeholder_text, table_name, match_column, column_name1, column_name2, parent):
1811+ super(SQLTableDataItem, self).__init__(glb, label, placeholder_text, parent)
1812+
1813+ self.table_name = table_name
1814+ self.match_column = match_column
1815+ self.column_name1 = column_name1
1816+ self.column_name2 = column_name2
1817+
1818+ def ValueToIds(self, value):
1819+ ids = []
1820+ query = QSqlQuery(self.glb.db)
1821+ stmt = "SELECT id FROM " + self.table_name + " WHERE " + self.match_column + " = '" + value + "'"
1822+ ret = query.exec_(stmt)
1823+ if ret:
1824+ while query.next():
1825+ ids.append(str(query.value(0)))
1826+ return ids
1827+
1828+ def DoValidate(self, input_string):
1829+ all_ids = []
1830+ for value in [x.strip() for x in input_string.split(",")]:
1831+ ids = self.ValueToIds(value)
1832+ if len(ids):
1833+ all_ids.extend(ids)
1834+ else:
1835+ return self.InvalidValue(value)
1836+ self.value = self.column_name1 + " IN (" + ",".join(all_ids) + ")"
1837+ if self.column_name2:
1838+ self.value = "( " + self.value + " OR " + self.column_name2 + " IN (" + ",".join(all_ids) + ") )"
1839+
1840+# Sample time ranges dialog data item converted and validated using 'samples' SQL table
1841+
1842+class SampleTimeRangesDataItem(LineEditDataItem):
1843+
1844+ def __init__(self, glb, label, placeholder_text, column_name, parent):
1845+ self.column_name = column_name
1846+
1847+ self.last_id = 0
1848+ self.first_time = 0
1849+ self.last_time = 2 ** 64
1850+
1851+ query = QSqlQuery(glb.db)
1852+ QueryExec(query, "SELECT id, time FROM samples ORDER BY id DESC LIMIT 1")
1853+ if query.next():
1854+ self.last_id = int(query.value(0))
1855+ self.last_time = int(query.value(1))
1856+ QueryExec(query, "SELECT time FROM samples WHERE time != 0 ORDER BY id LIMIT 1")
1857+ if query.next():
1858+ self.first_time = int(query.value(0))
1859+ if placeholder_text:
1860+ placeholder_text += ", between " + str(self.first_time) + " and " + str(self.last_time)
1861+
1862+ super(SampleTimeRangesDataItem, self).__init__(glb, label, placeholder_text, parent)
1863+
1864+ def IdBetween(self, query, lower_id, higher_id, order):
1865+ QueryExec(query, "SELECT id FROM samples WHERE id > " + str(lower_id) + " AND id < " + str(higher_id) + " ORDER BY id " + order + " LIMIT 1")
1866+ if query.next():
1867+ return True, int(query.value(0))
1868+ else:
1869+ return False, 0
1870+
1871+ def BinarySearchTime(self, lower_id, higher_id, target_time, get_floor):
1872+ query = QSqlQuery(self.glb.db)
1873+ while True:
1874+ next_id = int((lower_id + higher_id) / 2)
1875+ QueryExec(query, "SELECT time FROM samples WHERE id = " + str(next_id))
1876+ if not query.next():
1877+ ok, dbid = self.IdBetween(query, lower_id, next_id, "DESC")
1878+ if not ok:
1879+ ok, dbid = self.IdBetween(query, next_id, higher_id, "")
1880+ if not ok:
1881+ return str(higher_id)
1882+ next_id = dbid
1883+ QueryExec(query, "SELECT time FROM samples WHERE id = " + str(next_id))
1884+ next_time = int(query.value(0))
1885+ if get_floor:
1886+ if target_time > next_time:
1887+ lower_id = next_id
1888+ else:
1889+ higher_id = next_id
1890+ if higher_id <= lower_id + 1:
1891+ return str(higher_id)
1892+ else:
1893+ if target_time >= next_time:
1894+ lower_id = next_id
1895+ else:
1896+ higher_id = next_id
1897+ if higher_id <= lower_id + 1:
1898+ return str(lower_id)
1899+
1900+ def ConvertRelativeTime(self, val):
1901+ mult = 1
1902+ suffix = val[-2:]
1903+ if suffix == "ms":
1904+ mult = 1000000
1905+ elif suffix == "us":
1906+ mult = 1000
1907+ elif suffix == "ns":
1908+ mult = 1
1909+ else:
1910+ return val
1911+ val = val[:-2].strip()
1912+ if not self.IsNumber(val):
1913+ return val
1914+ val = int(val) * mult
1915+ if val >= 0:
1916+ val += self.first_time
1917+ else:
1918+ val += self.last_time
1919+ return str(val)
1920+
1921+ def ConvertTimeRange(self, vrange):
1922+ if vrange[0] == "":
1923+ vrange[0] = str(self.first_time)
1924+ if vrange[1] == "":
1925+ vrange[1] = str(self.last_time)
1926+ vrange[0] = self.ConvertRelativeTime(vrange[0])
1927+ vrange[1] = self.ConvertRelativeTime(vrange[1])
1928+ if not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]):
1929+ return False
1930+ beg_range = max(int(vrange[0]), self.first_time)
1931+ end_range = min(int(vrange[1]), self.last_time)
1932+ if beg_range > self.last_time or end_range < self.first_time:
1933+ return False
1934+ vrange[0] = self.BinarySearchTime(0, self.last_id, beg_range, True)
1935+ vrange[1] = self.BinarySearchTime(1, self.last_id + 1, end_range, False)
1936+ return True
1937+
1938+ def AddTimeRange(self, value, ranges):
1939+ n = value.count("-")
1940+ if n == 1:
1941+ pass
1942+ elif n == 2:
1943+ if value.split("-")[1].strip() == "":
1944+ n = 1
1945+ elif n == 3:
1946+ n = 2
1947+ else:
1948+ return False
1949+ pos = findnth(value, "-", n)
1950+ vrange = [value[:pos].strip() ,value[pos+1:].strip()]
1951+ if self.ConvertTimeRange(vrange):
1952+ ranges.append(vrange)
1953+ return True
1954+ return False
1955+
1956+ def DoValidate(self, input_string):
1957+ ranges = []
1958+ for value in [x.strip() for x in input_string.split(",")]:
1959+ if not self.AddTimeRange(value, ranges):
1960+ return self.InvalidValue(value)
1961+ ranges = [("(" + self.column_name + " >= " + r[0] + " AND " + self.column_name + " <= " + r[1] + ")") for r in ranges]
1962+ self.value = " OR ".join(ranges)
1963+
17051964 # Report Dialog Base
17061965
17071966 class ReportDialogBase(QDialog):
@@ -1716,7 +1975,7 @@ class ReportDialogBase(QDialog): · 8 unmodified lines
17161975 self.setWindowTitle(title)
17171976 self.setMinimumWidth(600)
17181977
1719− self.data_items = [SQLTableDialogDataItem(glb, *x, parent=self) for x in items]
1978+ self.data_items = [x(glb, self) for x in items]
17201979
17211980 self.partial = partial
17221981
@@ -1751,7 +2010,9 @@ class ReportDialogBase(QDialog): · 28 unmodified lines
17512010
17522011 def Ok(self):
17532012 vars = self.report_vars
1754− vars.name = self.data_items[0].value
2013+ for d in self.data_items:
2014+ if d.id == "REPORTNAME":
2015+ vars.name = d.value
17552016 if not vars.name:
17562017 self.ShowMessage("Report name is required")
17572018 return
@@ -1785,17 +2046,15 @@ class SelectedBranchDialog(ReportDialogBase): · 27 unmodified lines
17852046
17862047 def __init__(self, glb, parent=None):
17872048 title = "Selected Branches"
1788− items = (
1789− ("Report name:", "Enter a name to appear in the window title bar", "", "", "", ""),
1790− ("Time ranges:", "Enter time ranges", "<timeranges>", "", "samples.id", ""),
1791− ("CPUs:", "Enter CPUs or ranges e.g. 0,5-6", "<ranges>", "", "cpu", ""),
1792− ("Commands:", "Only branches with these commands will be included", "comms", "comm", "comm_id", ""),
1793− ("PIDs:", "Only branches with these process IDs will be included", "threads", "pid", "thread_id", ""),
1794− ("TIDs:", "Only branches with these thread IDs will be included", "threads", "tid", "thread_id", ""),
1795− ("DSOs:", "Only branches with these DSOs will be included", "dsos", "short_name", "samples.dso_id", "to_dso_id"),
1796− ("Symbols:", "Only branches with these symbols will be included", "symbols", "name", "symbol_id", "to_symbol_id"),
1797− ("Raw SQL clause: ", "Enter a raw SQL WHERE clause", "", "", "", ""),
1798− )
2049+ items = (lambda g, p: LineEditDataItem(g, "Report name:", "Enter a name to appear in the window title bar", p, "REPORTNAME"),
2050+ lambda g, p: SampleTimeRangesDataItem(g, "Time ranges:", "Enter time ranges", "samples.id", p),
2051+ lambda g, p: NonNegativeIntegerRangesDataItem(g, "CPUs:", "Enter CPUs or ranges e.g. 0,5-6", "cpu", p),
2052+ lambda g, p: SQLTableDataItem(g, "Commands:", "Only branches with these commands will be included", "comms", "comm", "comm_id", "", p),
2053+ lambda g, p: SQLTableDataItem(g, "PIDs:", "Only branches with these process IDs will be included", "threads", "pid", "thread_id", "", p),
2054+ lambda g, p: SQLTableDataItem(g, "TIDs:", "Only branches with these thread IDs will be included", "threads", "tid", "thread_id", "", p),
2055+ lambda g, p: SQLTableDataItem(g, "DSOs:", "Only branches with these DSOs will be included", "dsos", "short_name", "samples.dso_id", "to_dso_id", p),
2056+ lambda g, p: SQLTableDataItem(g, "Symbols:", "Only branches with these symbols will be included", "symbols", "name", "symbol_id", "to_symbol_id", p),
2057+ lambda g, p: LineEditDataItem(g, "Raw SQL clause: ", "Enter a raw SQL WHERE clause", p))
17992058 super(SelectedBranchDialog, self).__init__(glb, title, items, True, parent)
18002059
18012060 # Event list