3073 lines · 96.5 KB · Python
RawDownload
					" INNER JOIN call_paths ON calls.call_path_id = call_paths.id"					" INNER JOIN symbols ON call_paths.symbol_id = symbols.id"					" INNER JOIN dsos ON symbols.dso_id = dsos.id"					" WHERE parent_call_path_id = " + str(self.call_path_id) +					" AND comm_id = " + str(self.comm_id) +					" AND thread_id = " + str(self.thread_id) +					" GROUP BY call_path_id, name, short_name"					" ORDER BY call_path_id")		while query.next():			child_item = CallGraphLevelThreeItem(self.glb, self.child_count, self.comm_id, self.thread_id, query.value(0), query.value(1), query.value(2), query.value(3), int(query.value(4)), int(query.value(5)), self)			self.child_items.append(child_item)			self.child_count += 1 # Context-sensitive call graph data model level three item class CallGraphLevelThreeItem(CallGraphLevelTwoPlusItemBase): 	def __init__(self, glb, row, comm_id, thread_id, call_path_id, name, dso, count, time, branch_count, parent_item):		super(CallGraphLevelThreeItem, self).__init__(glb, row, comm_id, thread_id, call_path_id, time, branch_count, parent_item)		dso = dsoname(dso)		self.data = [ name, dso, str(count), str(time), PercentToOneDP(time, parent_item.time), str(branch_count), PercentToOneDP(branch_count, parent_item.branch_count) ]		self.dbid = call_path_id # Context-sensitive call graph data model level two item class CallGraphLevelTwoItem(CallGraphLevelTwoPlusItemBase): 	def __init__(self, glb, row, comm_id, thread_id, pid, tid, parent_item):		super(CallGraphLevelTwoItem, self).__init__(glb, row, comm_id, thread_id, 1, 0, 0, parent_item)		self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", ""]		self.dbid = thread_id 	def Select(self):		super(CallGraphLevelTwoItem, self).Select()		for child_item in self.child_items:			self.time += child_item.time			self.branch_count += child_item.branch_count		for child_item in self.child_items:			child_item.data[4] = PercentToOneDP(child_item.time, self.time)			child_item.data[6] = PercentToOneDP(child_item.branch_count, self.branch_count) # Context-sensitive call graph data model level one item class CallGraphLevelOneItem(CallGraphLevelItemBase): 	def __init__(self, glb, row, comm_id, comm, parent_item):		super(CallGraphLevelOneItem, self).__init__(glb, row, parent_item)		self.data = [comm, "", "", "", "", "", ""]		self.dbid = comm_id 	def Select(self):		self.query_done = True;		query = QSqlQuery(self.glb.db)		QueryExec(query, "SELECT thread_id, pid, tid"					" FROM comm_threads"					" INNER JOIN threads ON thread_id = threads.id"					" WHERE comm_id = " + str(self.dbid))		while query.next():			child_item = CallGraphLevelTwoItem(self.glb, self.child_count, self.dbid, query.value(0), query.value(1), query.value(2), self)			self.child_items.append(child_item)			self.child_count += 1 # Context-sensitive call graph data model root item class CallGraphRootItem(CallGraphLevelItemBase): 	def __init__(self, glb):		super(CallGraphRootItem, self).__init__(glb, 0, None)		self.dbid = 0		self.query_done = True;		query = QSqlQuery(glb.db)		QueryExec(query, "SELECT id, comm FROM comms")		while query.next():			if not query.value(0):				continue			child_item = CallGraphLevelOneItem(glb, self.child_count, query.value(0), query.value(1), self)			self.child_items.append(child_item)			self.child_count += 1 # Context-sensitive call graph data model base class CallGraphModelBase(TreeModel): 	def __init__(self, glb, parent=None):		super(CallGraphModelBase, self).__init__(glb, parent) 	def FindSelect(self, value, pattern, query):		if pattern:			# postgresql and sqlite pattern patching differences:			#   postgresql LIKE is case sensitive but sqlite LIKE is not			#   postgresql LIKE allows % and _ to be escaped with \ but sqlite LIKE does not			#   postgresql supports ILIKE which is case insensitive			#   sqlite supports GLOB (text only) which uses * and ? and is case sensitive			if not self.glb.dbref.is_sqlite3:				# Escape % and _				s = value.replace("%", "\%")				s = s.replace("_", "\_")				# Translate * and ? into SQL LIKE pattern characters % and _				trans = string.maketrans("*?", "%_")				match = " LIKE '" + str(s).translate(trans) + "'"			else:				match = " GLOB '" + str(value) + "'"		else:			match = " = '" + str(value) + "'"		self.DoFindSelect(query, match) 	def Found(self, query, found):		if found:			return self.FindPath(query)		return [] 	def FindValue(self, value, pattern, query, last_value, last_pattern):		if last_value == value and pattern == last_pattern:			found = query.first()		else:			self.FindSelect(value, pattern, query)			found = query.next()		return self.Found(query, found) 	def FindNext(self, query):		found = query.next()		if not found:			found = query.first()		return self.Found(query, found) 	def FindPrev(self, query):		found = query.previous()		if not found:			found = query.last()		return self.Found(query, found) 	def FindThread(self, c):		if c.direction == 0 or c.value != c.last_value or c.pattern != c.last_pattern:			ids = self.FindValue(c.value, c.pattern, c.query, c.last_value, c.last_pattern)		elif c.direction > 0:			ids = self.FindNext(c.query)		else:			ids = self.FindPrev(c.query)		return (True, ids) 	def Find(self, value, direction, pattern, context, callback):		class Context():			def __init__(self, *x):				self.value, self.direction, self.pattern, self.query, self.last_value, self.last_pattern = x			def Update(self, *x):				self.value, self.direction, self.pattern, self.last_value, self.last_pattern = x + (self.value, self.pattern)		if len(context):			context[0].Update(value, direction, pattern)		else:			context.append(Context(value, direction, pattern, QSqlQuery(self.glb.db), None, None))		# Use a thread so the UI is not blocked during the SELECT		thread = Thread(self.FindThread, context[0])		thread.done.connect(lambda ids, t=thread, c=callback: self.FindDone(t, c, ids), Qt.QueuedConnection)		thread.start() 	def FindDone(self, thread, callback, ids):		callback(ids) # Context-sensitive call graph data model class CallGraphModel(CallGraphModelBase): 	def __init__(self, glb, parent=None):		super(CallGraphModel, self).__init__(glb, parent) 	def GetRoot(self):		return CallGraphRootItem(self.glb) 	def columnCount(self, parent=None):		return 7 	def columnHeader(self, column):		headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]		return headers[column] 	def columnAlignment(self, column):		alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ]		return alignment[column] 	def DoFindSelect(self, query, match):		QueryExec(query, "SELECT call_path_id, comm_id, thread_id"						" FROM calls"						" INNER JOIN call_paths ON calls.call_path_id = call_paths.id"						" INNER JOIN symbols ON call_paths.symbol_id = symbols.id"						" WHERE symbols.name" + match +						" GROUP BY comm_id, thread_id, call_path_id"						" ORDER BY comm_id, thread_id, call_path_id") 	def FindPath(self, query):		# Turn the query result into a list of ids that the tree view can walk		# to open the tree at the right place.		ids = []		parent_id = query.value(0)		while parent_id:			ids.insert(0, parent_id)			q2 = QSqlQuery(self.glb.db)			QueryExec(q2, "SELECT parent_id"					" FROM call_paths"					" WHERE id = " + str(parent_id))			if not q2.next():				break			parent_id = q2.value(0)		# The call path root is not used		if ids[0] == 1:			del ids[0]		ids.insert(0, query.value(2))		ids.insert(0, query.value(1))		return ids # Call tree data model level 2+ item base class CallTreeLevelTwoPlusItemBase(CallGraphLevelItemBase): 	def __init__(self, glb, row, comm_id, thread_id, calls_id, time, branch_count, parent_item):		super(CallTreeLevelTwoPlusItemBase, self).__init__(glb, row, parent_item)		self.comm_id = comm_id		self.thread_id = thread_id		self.calls_id = calls_id		self.branch_count = branch_count		self.time = time 	def Select(self):		self.query_done = True;		if self.calls_id == 0:			comm_thread = " AND comm_id = " + str(self.comm_id) + " AND thread_id = " + str(self.thread_id)		else:			comm_thread = ""		query = QSqlQuery(self.glb.db)		QueryExec(query, "SELECT calls.id, name, short_name, call_time, return_time - call_time, branch_count"					" FROM calls"					" INNER JOIN call_paths ON calls.call_path_id = call_paths.id"					" INNER JOIN symbols ON call_paths.symbol_id = symbols.id"					" INNER JOIN dsos ON symbols.dso_id = dsos.id"					" WHERE calls.parent_id = " + str(self.calls_id) + comm_thread +					" ORDER BY call_time, calls.id")		while query.next():			child_item = CallTreeLevelThreeItem(self.glb, self.child_count, self.comm_id, self.thread_id, query.value(0), query.value(1), query.value(2), query.value(3), int(query.value(4)), int(query.value(5)), self)			self.child_items.append(child_item)			self.child_count += 1 # Call tree data model level three item class CallTreeLevelThreeItem(CallTreeLevelTwoPlusItemBase): 	def __init__(self, glb, row, comm_id, thread_id, calls_id, name, dso, count, time, branch_count, parent_item):		super(CallTreeLevelThreeItem, self).__init__(glb, row, comm_id, thread_id, calls_id, time, branch_count, parent_item)		dso = dsoname(dso)		self.data = [ name, dso, str(count), str(time), PercentToOneDP(time, parent_item.time), str(branch_count), PercentToOneDP(branch_count, parent_item.branch_count) ]		self.dbid = calls_id # Call tree data model level two item class CallTreeLevelTwoItem(CallTreeLevelTwoPlusItemBase): 	def __init__(self, glb, row, comm_id, thread_id, pid, tid, parent_item):		super(CallTreeLevelTwoItem, self).__init__(glb, row, comm_id, thread_id, 0, 0, 0, parent_item)		self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", ""]		self.dbid = thread_id 	def Select(self):		super(CallTreeLevelTwoItem, self).Select()		for child_item in self.child_items:			self.time += child_item.time			self.branch_count += child_item.branch_count		for child_item in self.child_items:			child_item.data[4] = PercentToOneDP(child_item.time, self.time)			child_item.data[6] = PercentToOneDP(child_item.branch_count, self.branch_count) # Call tree data model level one item class CallTreeLevelOneItem(CallGraphLevelItemBase): 	def __init__(self, glb, row, comm_id, comm, parent_item):		super(CallTreeLevelOneItem, self).__init__(glb, row, parent_item)		self.data = [comm, "", "", "", "", "", ""]		self.dbid = comm_id 	def Select(self):		self.query_done = True;		query = QSqlQuery(self.glb.db)		QueryExec(query, "SELECT thread_id, pid, tid"					" FROM comm_threads"					" INNER JOIN threads ON thread_id = threads.id"					" WHERE comm_id = " + str(self.dbid))		while query.next():			child_item = CallTreeLevelTwoItem(self.glb, self.child_count, self.dbid, query.value(0), query.value(1), query.value(2), self)			self.child_items.append(child_item)			self.child_count += 1 # Call tree data model root item class CallTreeRootItem(CallGraphLevelItemBase): 	def __init__(self, glb):		super(CallTreeRootItem, self).__init__(glb, 0, None)		self.dbid = 0		self.query_done = True;		query = QSqlQuery(glb.db)		QueryExec(query, "SELECT id, comm FROM comms")		while query.next():			if not query.value(0):				continue			child_item = CallTreeLevelOneItem(glb, self.child_count, query.value(0), query.value(1), self)			self.child_items.append(child_item)			self.child_count += 1 # Call Tree data model class CallTreeModel(CallGraphModelBase): 	def __init__(self, glb, parent=None):		super(CallTreeModel, self).__init__(glb, parent) 	def GetRoot(self):		return CallTreeRootItem(self.glb) 	def columnCount(self, parent=None):		return 7 	def columnHeader(self, column):		headers = ["Call Path", "Object", "Call Time", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]		return headers[column] 	def columnAlignment(self, column):		alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ]		return alignment[column] 	def DoFindSelect(self, query, match):		QueryExec(query, "SELECT calls.id, comm_id, thread_id"						" FROM calls"						" INNER JOIN call_paths ON calls.call_path_id = call_paths.id"						" INNER JOIN symbols ON call_paths.symbol_id = symbols.id"						" WHERE symbols.name" + match +						" ORDER BY comm_id, thread_id, call_time, calls.id") 	def FindPath(self, query):		# Turn the query result into a list of ids that the tree view can walk		# to open the tree at the right place.		ids = []		parent_id = query.value(0)		while parent_id:			ids.insert(0, parent_id)			q2 = QSqlQuery(self.glb.db)			QueryExec(q2, "SELECT parent_id"					" FROM calls"					" WHERE id = " + str(parent_id))			if not q2.next():				break			parent_id = q2.value(0)		ids.insert(0, query.value(2))		ids.insert(0, query.value(1))		return ids # Vertical widget layout class VBox(): 	def __init__(self, w1, w2, w3=None):		self.vbox = QWidget()		self.vbox.setLayout(QVBoxLayout()); 		self.vbox.layout().setContentsMargins(0, 0, 0, 0) 		self.vbox.layout().addWidget(w1)		self.vbox.layout().addWidget(w2)		if w3:			self.vbox.layout().addWidget(w3) 	def Widget(self):		return self.vbox # Tree window base class TreeWindowBase(QMdiSubWindow): 	def __init__(self, parent=None):		super(TreeWindowBase, self).__init__(parent) 		self.model = None		self.view = None		self.find_bar = None 	def DisplayFound(self, ids):		if not len(ids):			return False		parent = QModelIndex()		for dbid in ids:			found = False			n = self.model.rowCount(parent)			for row in xrange(n):				child = self.model.index(row, 0, parent)				if child.internalPointer().dbid == dbid:					found = True					self.view.setCurrentIndex(child)					parent = child					break			if not found:				break		return found 	def Find(self, value, direction, pattern, context):		self.view.setFocus()		self.find_bar.Busy()		self.model.Find(value, direction, pattern, context, self.FindDone) 	def FindDone(self, ids):		found = True		if not self.DisplayFound(ids):			found = False		self.find_bar.Idle()		if not found:			self.find_bar.NotFound()  # Context-sensitive call graph window class CallGraphWindow(TreeWindowBase): 	def __init__(self, glb, parent=None):		super(CallGraphWindow, self).__init__(parent) 		self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x)) 		self.view = QTreeView()		self.view.setModel(self.model) 		for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)):			self.view.setColumnWidth(c, w) 		self.find_bar = FindBar(self, self) 		self.vbox = VBox(self.view, self.find_bar.Widget()) 		self.setWidget(self.vbox.Widget()) 		AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph") # Call tree window class CallTreeWindow(TreeWindowBase): 	def __init__(self, glb, parent=None):		super(CallTreeWindow, self).__init__(parent) 		self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x)) 		self.view = QTreeView()		self.view.setModel(self.model) 		for c, w in ((0, 230), (1, 100), (2, 100), (3, 70), (4, 70), (5, 100)):			self.view.setColumnWidth(c, w) 		self.find_bar = FindBar(self, self) 		self.vbox = VBox(self.view, self.find_bar.Widget()) 		self.setWidget(self.vbox.Widget()) 		AddSubWindow(glb.mainwindow.mdi_area, self, "Call Tree") # Child data item  finder class ChildDataItemFinder(): 	def __init__(self, root):		self.root = root		self.value, self.direction, self.pattern, self.last_value, self.last_pattern = (None,) * 5		self.rows = []		self.pos = 0 	def FindSelect(self):		self.rows = []		if self.pattern:			pattern = re.compile(self.value)			for child in self.root.child_items:				for column_data in child.data:					if re.search(pattern, str(column_data)) is not None:						self.rows.append(child.row)						break		else:			for child in self.root.child_items:				for column_data in child.data:					if self.value in str(column_data):						self.rows.append(child.row)						break 	def FindValue(self):		self.pos = 0		if self.last_value != self.value or self.pattern != self.last_pattern:			self.FindSelect()		if not len(self.rows):			return -1		return self.rows[self.pos] 	def FindThread(self):		if self.direction == 0 or self.value != self.last_value or self.pattern != self.last_pattern:			row = self.FindValue()		elif len(self.rows):			if self.direction > 0:				self.pos += 1

Lines 501–1000 of 3073. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t