5030 lines · 153.7 KB · Python
RawDownload
		return self.child_items[row] 	def getParentItem(self):		return self.parent_item 	def getRow(self):		return self.row 	def childCount(self):		if not self.query_done:			self.Select()			if not self.child_count:				return -1		return self.child_count 	def hasChildren(self):		if not self.query_done:			return True		return self.child_count > 0 	def getData(self, column):		return self.data[column] # Context-sensitive call graph data model level 2+ item base class CallGraphLevelTwoPlusItemBase(CallGraphLevelItemBase): 	def __init__(self, glb, params, row, comm_id, thread_id, call_path_id, time, insn_cnt, cyc_cnt, branch_count, parent_item):		super(CallGraphLevelTwoPlusItemBase, self).__init__(glb, params, row, parent_item)		self.comm_id = comm_id		self.thread_id = thread_id		self.call_path_id = call_path_id		self.insn_cnt = insn_cnt		self.cyc_cnt = cyc_cnt		self.branch_count = branch_count		self.time = time 	def Select(self):		self.query_done = True		query = QSqlQuery(self.glb.db)		if self.params.have_ipc:			ipc_str = ", SUM(insn_count), SUM(cyc_count)"		else:			ipc_str = ""		QueryExec(query, "SELECT call_path_id, name, short_name, COUNT(calls.id), SUM(return_time - call_time)" + ipc_str + ", SUM(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 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():			if self.params.have_ipc:				insn_cnt = int(query.value(5))				cyc_cnt = int(query.value(6))				branch_count = int(query.value(7))			else:				insn_cnt = 0				cyc_cnt = 0				branch_count = int(query.value(5))			child_item = CallGraphLevelThreeItem(self.glb, self.params, 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)), insn_cnt, cyc_cnt, branch_count, 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, params, row, comm_id, thread_id, call_path_id, name, dso, count, time, insn_cnt, cyc_cnt, branch_count, parent_item):		super(CallGraphLevelThreeItem, self).__init__(glb, params, row, comm_id, thread_id, call_path_id, time, insn_cnt, cyc_cnt, branch_count, parent_item)		dso = dsoname(dso)		if self.params.have_ipc:			insn_pcnt = PercentToOneDP(insn_cnt, parent_item.insn_cnt)			cyc_pcnt = PercentToOneDP(cyc_cnt, parent_item.cyc_cnt)			br_pcnt = PercentToOneDP(branch_count, parent_item.branch_count)			ipc = CalcIPC(cyc_cnt, insn_cnt)			self.data = [ name, dso, str(count), str(time), PercentToOneDP(time, parent_item.time), str(insn_cnt), insn_pcnt, str(cyc_cnt), cyc_pcnt, ipc, str(branch_count), br_pcnt ]		else:			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, params, row, comm_id, thread_id, pid, tid, parent_item):		super(CallGraphLevelTwoItem, self).__init__(glb, params, row, comm_id, thread_id, 1, 0, 0, 0, 0, parent_item)		if self.params.have_ipc:			self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", "", "", "", "", "", ""]		else:			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.insn_cnt += child_item.insn_cnt			self.cyc_cnt += child_item.cyc_cnt			self.branch_count += child_item.branch_count		for child_item in self.child_items:			child_item.data[4] = PercentToOneDP(child_item.time, self.time)			if self.params.have_ipc:				child_item.data[6] = PercentToOneDP(child_item.insn_cnt, self.insn_cnt)				child_item.data[8] = PercentToOneDP(child_item.cyc_cnt, self.cyc_cnt)				child_item.data[11] = PercentToOneDP(child_item.branch_count, self.branch_count)			else:				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, params, row, comm_id, comm, parent_item):		super(CallGraphLevelOneItem, self).__init__(glb, params, row, parent_item)		if self.params.have_ipc:			self.data = [comm, "", "", "", "", "", "", "", "", "", "", ""]		else:			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.params, 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, params):		super(CallGraphRootItem, self).__init__(glb, params, 0, None)		self.dbid = 0		self.query_done = True		if_has_calls = ""		if IsSelectable(glb.db, "comms", columns = "has_calls"):			if_has_calls = " WHERE has_calls = " + glb.dbref.TRUE		query = QSqlQuery(glb.db)		QueryExec(query, "SELECT id, comm FROM comms" + if_has_calls)		while query.next():			if not query.value(0):				continue			child_item = CallGraphLevelOneItem(glb, params, self.child_count, query.value(0), query.value(1), self)			self.child_items.append(child_item)			self.child_count += 1 # Call graph model parameters class CallGraphModelParams(): 	def __init__(self, glb, parent=None):		self.have_ipc = IsSelectable(glb.db, "calls", columns = "insn_count, cyc_count") # Context-sensitive call graph data model base class CallGraphModelBase(TreeModel): 	def __init__(self, glb, parent=None):		super(CallGraphModelBase, self).__init__(glb, CallGraphModelParams(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 _				if sys.version_info[0] == 3:					trans = str.maketrans("*?", "%_")				else:					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, self.params) 	def columnCount(self, parent=None):		if self.params.have_ipc:			return 12		else:			return 7 	def columnHeader(self, column):		if self.params.have_ipc:			headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Insn Cnt", "Insn Cnt (%)", "Cyc Cnt", "Cyc Cnt (%)", "IPC", "Branch Count ", "Branch Count (%) "]		else:			headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]		return headers[column] 	def columnAlignment(self, column):		if self.params.have_ipc:			alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ]		else:			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 calls.id <> 0"						" AND 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, params, row, comm_id, thread_id, calls_id, call_time, time, insn_cnt, cyc_cnt, branch_count, parent_item):		super(CallTreeLevelTwoPlusItemBase, self).__init__(glb, params, row, parent_item)		self.comm_id = comm_id		self.thread_id = thread_id		self.calls_id = calls_id		self.call_time = call_time		self.time = time		self.insn_cnt = insn_cnt		self.cyc_cnt = cyc_cnt		self.branch_count = branch_count 	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 = ""		if self.params.have_ipc:			ipc_str = ", insn_count, cyc_count"		else:			ipc_str = ""		query = QSqlQuery(self.glb.db)		QueryExec(query, "SELECT calls.id, name, short_name, call_time, return_time - call_time" + ipc_str + ", 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():			if self.params.have_ipc:				insn_cnt = int(query.value(5))				cyc_cnt = int(query.value(6))				branch_count = int(query.value(7))			else:				insn_cnt = 0				cyc_cnt = 0				branch_count = int(query.value(5))			child_item = CallTreeLevelThreeItem(self.glb, self.params, 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)), insn_cnt, cyc_cnt, branch_count, 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, params, row, comm_id, thread_id, calls_id, name, dso, call_time, time, insn_cnt, cyc_cnt, branch_count, parent_item):		super(CallTreeLevelThreeItem, self).__init__(glb, params, row, comm_id, thread_id, calls_id, call_time, time, insn_cnt, cyc_cnt, branch_count, parent_item)		dso = dsoname(dso)		if self.params.have_ipc:			insn_pcnt = PercentToOneDP(insn_cnt, parent_item.insn_cnt)			cyc_pcnt = PercentToOneDP(cyc_cnt, parent_item.cyc_cnt)			br_pcnt = PercentToOneDP(branch_count, parent_item.branch_count)			ipc = CalcIPC(cyc_cnt, insn_cnt)			self.data = [ name, dso, str(call_time), str(time), PercentToOneDP(time, parent_item.time), str(insn_cnt), insn_pcnt, str(cyc_cnt), cyc_pcnt, ipc, str(branch_count), br_pcnt ]		else:			self.data = [ name, dso, str(call_time), 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, params, row, comm_id, thread_id, pid, tid, parent_item):		super(CallTreeLevelTwoItem, self).__init__(glb, params, row, comm_id, thread_id, 0, 0, 0, 0, 0, 0, parent_item)		if self.params.have_ipc:			self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", "", "", "", "", "", ""]		else:			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.insn_cnt += child_item.insn_cnt			self.cyc_cnt += child_item.cyc_cnt			self.branch_count += child_item.branch_count		for child_item in self.child_items:			child_item.data[4] = PercentToOneDP(child_item.time, self.time)			if self.params.have_ipc:				child_item.data[6] = PercentToOneDP(child_item.insn_cnt, self.insn_cnt)				child_item.data[8] = PercentToOneDP(child_item.cyc_cnt, self.cyc_cnt)				child_item.data[11] = PercentToOneDP(child_item.branch_count, self.branch_count)			else:				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, params, row, comm_id, comm, parent_item):		super(CallTreeLevelOneItem, self).__init__(glb, params, row, parent_item)		if self.params.have_ipc:			self.data = [comm, "", "", "", "", "", "", "", "", "", "", ""]		else:			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.params, 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, params):		super(CallTreeRootItem, self).__init__(glb, params, 0, None)		self.dbid = 0		self.query_done = True		if_has_calls = ""		if IsSelectable(glb.db, "comms", columns = "has_calls"):			if_has_calls = " WHERE has_calls = " + glb.dbref.TRUE		query = QSqlQuery(glb.db)		QueryExec(query, "SELECT id, comm FROM comms" + if_has_calls)		while query.next():			if not query.value(0):				continue			child_item = CallTreeLevelOneItem(glb, params, 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, self.params) 	def columnCount(self, parent=None):		if self.params.have_ipc:			return 12		else:			return 7 	def columnHeader(self, column):		if self.params.have_ipc:			headers = ["Call Path", "Object", "Call Time", "Time (ns) ", "Time (%) ", "Insn Cnt", "Insn Cnt (%)", "Cyc Cnt", "Cyc Cnt (%)", "IPC", "Branch Count ", "Branch Count (%) "]		else:			headers = ["Call Path", "Object", "Call Time", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]		return headers[column] 	def columnAlignment(self, column):		if self.params.have_ipc:			alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ]		else:			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 calls.id <> 0"						" AND 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 layout 

Lines 501–1000 of 5030. Previous lines