Update TaskManager when node is removed

This commit is contained in:
Lee Geertsen 2019-09-06 11:02:45 +02:00 committed by Yann Lanthony
parent 6d83985b39
commit 34a90563c8
No known key found for this signature in database
GPG key ID: 519FAE6DF7A70642
3 changed files with 66 additions and 16 deletions

View file

@ -1,5 +1,5 @@
from PySide2 import QtCore
import shiboken2
class QObjectListModel(QtCore.QAbstractListModel):
"""
@ -272,7 +272,7 @@ class QObjectListModel(QtCore.QAbstractListModel):
def _dereferenceItem(self, item):
# Ask for object deletion if parented to the model
if item.parent() == self:
if shiboken2.isValid(item) and item.parent() == self:
# delay deletion until the next event loop
# This avoids warnings when the QML engine tries to evaluate (but should not)
# an object that has already been deleted

View file

@ -6,6 +6,9 @@ import meshroom
from meshroom.common import BaseObject, DictModel, Property
class State(Enum):
"""
State of the Thread that is computing nodes
"""
IDLE = 0
RUNNING = 1
STOPPED = 2
@ -13,6 +16,9 @@ class State(Enum):
ERROR = 4
class TaskThread(Thread):
"""
A thread with a pile of nodes to compute
"""
def __init__(self, manager):
Thread.__init__(self, target=self.run)
self._state = State.IDLE
@ -45,7 +51,7 @@ class TaskThread(Thread):
if chunk.isStopped():
self._state = State.STOPPED
self._manager._graph.clearSubmittedNodes()
self._manager._nodesToProcess.clear()
self._manager._nodesToProcess = []
else:
logging.error("Error on node computation: {}".format(e))
@ -60,21 +66,33 @@ class TaskThread(Thread):
pass
nodeD.clearSubmittedChunks()
self._manager._nodesToProcess.clear()
self._manager._nodesToProcess = []
self._state = State.DEAD
self._manager._uigraph.computeStatusChanged.emit()
class TaskManager(BaseObject):
"""
Manage the nodes that have to be computed locally or on a renderfarm
"""
def __init__(self, parent=None):
super(TaskManager, self).__init__(parent)
self._nodes = DictModel(keyAttrName='name', parent=self)
self._nodesToProcess = DictModel(keyAttrName='name', parent=self)
self._nodesExtern = DictModel(keyAttrName='name', parent=self)
self._nodes = DictModel(keyAttrName='_name', parent=self)
self._nodesToProcess = []
self._nodesExtern = []
self._graph = None
self._thread = TaskThread(self)
def compute(self, graph=None, toNodes=None, uigraph=None, forceCompute=False, forceStatus=False):
"""
Nodes are to be computed locally are sent to a thread
:param graph:
:param toNodes:
:param uigraph:
:param forceCompute:
:param forceStatus:
:return:
"""
self._graph = graph
self._uigraph = uigraph
@ -93,7 +111,7 @@ class TaskManager(BaseObject):
if not externEmpty:
self._nodes.update(self._nodesExtern)
else:
self._nodesExtern.clear()
self._nodesExtern = []
if forceCompute:
nodes, edges = graph.dfsOnFinish(startNodes=toNodes)
@ -104,16 +122,14 @@ class TaskManager(BaseObject):
if not node.isAlreadySubmittedOrFinished():
nodes.append(node)
print('Nodes to execute: ', str([n.name for n in nodes]))
logging.info('Nodes to execute: ', str([n.name for n in nodes]))
for node in nodes:
node.destroyed.connect(lambda obj=None, name=node.name: self.onNodeDestroyed(obj, name))
node.beginSequence(forceCompute)
try:
self._nodes.update(nodes)
except:
print("nodes already added to Task Manager")
self._nodesToProcess.update(nodes)
self._nodes.update(nodes)
self._nodesToProcess .extend(nodes)
if self._thread._state == State.IDLE:
self._thread.start()
@ -121,7 +137,34 @@ class TaskManager(BaseObject):
self._thread = TaskThread(self)
self._thread.start()
def onNodeDestroyed(self, obj, name):
"""
Remove node from the taskmanager when it's destroyed in the graph
:param obj:
:param name:
:return:
"""
self._nodes.pop(name)
def clear(self):
"""
Remove all the nodes from the taskmanager
:return:
"""
self._nodes.clear()
self._nodesExtern = []
self._nodesToProcess = []
def submit(self, graph=None, submitter=None, toNodes=None):
"""
Nodes are send to the renderfarm
:param graph:
:param submitter:
:param toNodes:
:return:
"""
if self._thread._state in (State.IDLE, State.DEAD, State.ERROR, State.STOPPED):
self._nodes.clear()
@ -134,7 +177,7 @@ class TaskManager(BaseObject):
if not externEmpty:
self._nodes.update(self._nodesExtern)
else:
self._nodesExtern.clear()
self._nodesExtern = []
nodesToProcess, edgesToProcess = graph.dfsToProcess(startNodes=toNodes)
flowEdges = graph.flowEdges(startNodes=toNodes)
@ -148,15 +191,21 @@ class TaskManager(BaseObject):
res = sub.submit(nodesToProcess, edgesToProcess, graph.filepath)
if res:
for node in nodesToProcess:
node.destroyed.connect(lambda obj=None, name=node.name: self.onNodeDestroyed(obj, name))
node.submit() # update node status
self._nodes.update(nodesToProcess)
self._nodesExtern.update(nodesToProcess)
self._nodesExtern.extend(nodesToProcess)
except Exception as e:
logging.error("Error on submit : {}".format(e))
nodes = Property(BaseObject, lambda self: self._nodes, constant=True)
def getAlreadySubmittedChunks(nodes):
"""
Check if nodes already have been submitted
:param nodes:
:return:
"""
out = []
for node in nodes:
for chunk in node.chunks:

View file

@ -307,6 +307,7 @@ class UIGraph(QObject):
if self._graph:
self.clearNodeHover()
self.clearNodeSelection()
self._taskManager.clear()
self._graph.deleteLater()
self._graph = None
self._sortedDFSChunks.clear()