5108 lines · 155.9 KB · Python
RawDownload
				self.layout().addLayout(child) # Horizontal layout class VBoxLayout(QVBoxLayout): 	def __init__(self, *children):		super(VBoxLayout, self).__init__() 		self.layout().setContentsMargins(0, 0, 0, 0)		for child in children:			if child.isWidgetType():				self.layout().addWidget(child)			else:				self.layout().addLayout(child) # Vertical layout widget class VBox(): 	def __init__(self, *children):		self.vbox = QWidget()		self.vbox.setLayout(VBoxLayout(*children)) 	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.find_bar = None 		self.view = QTreeView()		self.view.setSelectionMode(QAbstractItemView.ContiguousSelection)		self.view.CopyCellsToClipboard = CopyTreeCellsToClipboard 		self.context_menu = TreeContextMenu(self.view) 	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.setExpanded(parent, 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.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, thread_at_time=None):		super(CallTreeWindow, self).__init__(parent) 		self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x)) 		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") 		if thread_at_time:			self.DisplayThreadAtTime(*thread_at_time) 	def DisplayThreadAtTime(self, comm_id, thread_id, time):		parent = QModelIndex()		for dbid in (comm_id, thread_id):			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.setExpanded(parent, True)					self.view.setCurrentIndex(child)					parent = child					break			if not found:				return		found = False		while True:			n = self.model.rowCount(parent)			if not n:				return			last_child = None			for row in xrange(n):				self.view.setExpanded(parent, True)				child = self.model.index(row, 0, parent)				child_call_time = child.internalPointer().call_time				if child_call_time < time:					last_child = child				elif child_call_time == time:					self.view.setCurrentIndex(child)					return				elif child_call_time > time:					break			if not last_child:				if not found:					child = self.model.index(0, 0, parent)					self.view.setExpanded(parent, True)					self.view.setCurrentIndex(child)				return			found = True			self.view.setExpanded(parent, True)			self.view.setCurrentIndex(last_child)			parent = last_child # ExecComm() gets the comm_id of the command string that was set when the process exec'd i.e. the program name def ExecComm(db, thread_id, time):	query = QSqlQuery(db)	QueryExec(query, "SELECT comm_threads.comm_id, comms.c_time, comms.exec_flag"				" FROM comm_threads"				" INNER JOIN comms ON comms.id = comm_threads.comm_id"				" WHERE comm_threads.thread_id = " + str(thread_id) +				" ORDER BY comms.c_time, comms.id")	first = None	last = None	while query.next():		if first is None:			first = query.value(0)		if query.value(2) and Decimal(query.value(1)) <= Decimal(time):			last = query.value(0)	if not(last is None):		return last	return first # Container for (x, y) data class XY():	def __init__(self, x=0, y=0):		self.x = x		self.y = y 	def __str__(self):		return "XY({}, {})".format(str(self.x), str(self.y)) # Container for sub-range data class Subrange():	def __init__(self, lo=0, hi=0):		self.lo = lo		self.hi = hi 	def __str__(self):		return "Subrange({}, {})".format(str(self.lo), str(self.hi)) # Graph data region base class class GraphDataRegion(object): 	def __init__(self, key, title = "", ordinal = ""):		self.key = key		self.title = title		self.ordinal = ordinal # Function to sort GraphDataRegion def GraphDataRegionOrdinal(data_region):	return data_region.ordinal # Attributes for a graph region class GraphRegionAttribute(): 	def __init__(self, colour):		self.colour = colour # Switch graph data region represents a task class SwitchGraphDataRegion(GraphDataRegion): 	def __init__(self, key, exec_comm_id, pid, tid, comm, thread_id, comm_id):		super(SwitchGraphDataRegion, self).__init__(key) 		self.title = str(pid) + " / " + str(tid) + " " + comm		# Order graph legend within exec comm by pid / tid / time		self.ordinal = str(pid).rjust(16) + str(exec_comm_id).rjust(8) + str(tid).rjust(16)		self.exec_comm_id = exec_comm_id		self.pid = pid		self.tid = tid		self.comm = comm		self.thread_id = thread_id		self.comm_id = comm_id # Graph data point class GraphDataPoint(): 	def __init__(self, data, index, x, y, altx=None, alty=None, hregion=None, vregion=None):		self.data = data		self.index = index		self.x = x		self.y = y		self.altx = altx		self.alty = alty		self.hregion = hregion		self.vregion = vregion # Graph data (single graph) base class class GraphData(object): 	def __init__(self, collection, xbase=Decimal(0), ybase=Decimal(0)):		self.collection = collection		self.points = []		self.xbase = xbase		self.ybase = ybase		self.title = "" 	def AddPoint(self, x, y, altx=None, alty=None, hregion=None, vregion=None):		index = len(self.points) 		x = float(Decimal(x) - self.xbase)		y = float(Decimal(y) - self.ybase) 		self.points.append(GraphDataPoint(self, index, x, y, altx, alty, hregion, vregion)) 	def XToData(self, x):		return Decimal(x) + self.xbase 	def YToData(self, y):		return Decimal(y) + self.ybase # Switch graph data (for one CPU) class SwitchGraphData(GraphData): 	def __init__(self, db, collection, cpu, xbase):		super(SwitchGraphData, self).__init__(collection, xbase) 		self.cpu = cpu		self.title = "CPU " + str(cpu)		self.SelectSwitches(db) 	def SelectComms(self, db, thread_id, last_comm_id, start_time, end_time):		query = QSqlQuery(db)		QueryExec(query, "SELECT id, c_time"					" FROM comms"					" WHERE c_thread_id = " + str(thread_id) +					"   AND exec_flag = " + self.collection.glb.dbref.TRUE +					"   AND c_time >= " + str(start_time) +					"   AND c_time <= " + str(end_time) +					" ORDER BY c_time, id")		while query.next():			comm_id = query.value(0)			if comm_id == last_comm_id:				continue			time = query.value(1)			hregion = self.HRegion(db, thread_id, comm_id, time)			self.AddPoint(time, 1000, None, None, hregion) 	def SelectSwitches(self, db):		last_time = None		last_comm_id = None		last_thread_id = None		query = QSqlQuery(db)		QueryExec(query, "SELECT time, thread_out_id, thread_in_id, comm_out_id, comm_in_id, flags"					" FROM context_switches"					" WHERE machine_id = " + str(self.collection.machine_id) +					"   AND cpu = " + str(self.cpu) +					" ORDER BY time, id")		while query.next():			flags = int(query.value(5))			if flags & 1:				# Schedule-out: detect and add exec's				if last_thread_id == query.value(1) and last_comm_id is not None and last_comm_id != query.value(3):					self.SelectComms(db, last_thread_id, last_comm_id, last_time, query.value(0))				continue			# Schedule-in: add data point			if len(self.points) == 0:				start_time = self.collection.glb.StartTime(self.collection.machine_id)				hregion = self.HRegion(db, query.value(1), query.value(3), start_time)				self.AddPoint(start_time, 1000, None, None, hregion)			time = query.value(0)			comm_id = query.value(4)			thread_id = query.value(2)			hregion = self.HRegion(db, thread_id, comm_id, time)			self.AddPoint(time, 1000, None, None, hregion)			last_time = time			last_comm_id = comm_id			last_thread_id = thread_id 	def NewHRegion(self, db, key, thread_id, comm_id, time):		exec_comm_id = ExecComm(db, thread_id, time)		query = QSqlQuery(db)		QueryExec(query, "SELECT pid, tid FROM threads WHERE id = " + str(thread_id))		if query.next():			pid = query.value(0)			tid = query.value(1)		else:			pid = -1			tid = -1		query = QSqlQuery(db)		QueryExec(query, "SELECT comm FROM comms WHERE id = " + str(comm_id))		if query.next():			comm = query.value(0)		else:			comm = ""		return SwitchGraphDataRegion(key, exec_comm_id, pid, tid, comm, thread_id, comm_id) 	def HRegion(self, db, thread_id, comm_id, time):		key = str(thread_id) + ":" + str(comm_id)		hregion = self.collection.LookupHRegion(key)		if hregion is None:			hregion = self.NewHRegion(db, key, thread_id, comm_id, time)			self.collection.AddHRegion(key, hregion)		return hregion # Graph data collection (multiple related graphs) base class class GraphDataCollection(object): 	def __init__(self, glb):		self.glb = glb		self.data = []		self.hregions = {}		self.xrangelo = None		self.xrangehi = None		self.yrangelo = None		self.yrangehi = None		self.dp = XY(0, 0) 	def AddGraphData(self, data):		self.data.append(data) 	def LookupHRegion(self, key):		if key in self.hregions:			return self.hregions[key]		return None 	def AddHRegion(self, key, hregion):		self.hregions[key] = hregion # Switch graph data collection (SwitchGraphData for each CPU) class SwitchGraphDataCollection(GraphDataCollection): 	def __init__(self, glb, db, machine_id):		super(SwitchGraphDataCollection, self).__init__(glb) 		self.machine_id = machine_id		self.cpus = self.SelectCPUs(db) 		self.xrangelo = glb.StartTime(machine_id)		self.xrangehi = glb.FinishTime(machine_id) 		self.yrangelo = Decimal(0)		self.yrangehi = Decimal(1000) 		for cpu in self.cpus:			self.AddGraphData(SwitchGraphData(db, self, cpu, self.xrangelo)) 	def SelectCPUs(self, db):		cpus = []		query = QSqlQuery(db)		QueryExec(query, "SELECT DISTINCT cpu"					" FROM context_switches"					" WHERE machine_id = " + str(self.machine_id))		while query.next():			cpus.append(int(query.value(0)))		return sorted(cpus) # Switch graph data graphics item displays the graphed data class SwitchGraphDataGraphicsItem(QGraphicsItem): 	def __init__(self, data, graph_width, graph_height, attrs, event_handler, parent=None):		super(SwitchGraphDataGraphicsItem, self).__init__(parent) 		self.data = data		self.graph_width = graph_width		self.graph_height = graph_height		self.attrs = attrs		self.event_handler = event_handler		self.setAcceptHoverEvents(True) 	def boundingRect(self):		return QRectF(0, 0, self.graph_width, self.graph_height) 	def PaintPoint(self, painter, last, x):		if not(last is None or last.hregion.pid == 0 or x < self.attrs.subrange.x.lo):			if last.x < self.attrs.subrange.x.lo:				x0 = self.attrs.subrange.x.lo			else:				x0 = last.x			if x > self.attrs.subrange.x.hi:				x1 = self.attrs.subrange.x.hi			else:				x1 = x - 1			x0 = self.attrs.XToPixel(x0)			x1 = self.attrs.XToPixel(x1) 			y0 = self.attrs.YToPixel(last.y) 			colour = self.attrs.region_attributes[last.hregion.key].colour 			width = x1 - x0 + 1			if width < 2:				painter.setPen(colour)				painter.drawLine(x0, self.graph_height - y0, x0, self.graph_height)			else:				painter.fillRect(x0, self.graph_height - y0, width, self.graph_height - 1, colour) 	def paint(self, painter, option, widget):		last = None		for point in self.data.points:			self.PaintPoint(painter, last, point.x)			if point.x > self.attrs.subrange.x.hi:				break;			last = point		self.PaintPoint(painter, last, self.attrs.subrange.x.hi + 1) 	def BinarySearchPoint(self, target):		lower_pos = 0		higher_pos = len(self.data.points)		while True:			pos = int((lower_pos + higher_pos) / 2)			val = self.data.points[pos].x			if target >= val:				lower_pos = pos			else:				higher_pos = pos			if higher_pos <= lower_pos + 1:				return lower_pos 	def XPixelToData(self, x):		x = self.attrs.PixelToX(x)		if x < self.data.points[0].x:			x = 0			pos = 0			low = True		else:			pos = self.BinarySearchPoint(x)			low = False		return (low, pos, self.data.XToData(x)) 	def EventToData(self, event):		no_data = (None,) * 4		if len(self.data.points) < 1:			return no_data

Lines 1001–1500 of 5108. Previous lines