mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-05-10 07:36:52 +02:00
Update TaskManager when node is removed
This commit is contained in:
parent
6d83985b39
commit
34a90563c8
3 changed files with 66 additions and 16 deletions
|
@ -1,5 +1,5 @@
|
||||||
from PySide2 import QtCore
|
from PySide2 import QtCore
|
||||||
|
import shiboken2
|
||||||
|
|
||||||
class QObjectListModel(QtCore.QAbstractListModel):
|
class QObjectListModel(QtCore.QAbstractListModel):
|
||||||
"""
|
"""
|
||||||
|
@ -272,7 +272,7 @@ class QObjectListModel(QtCore.QAbstractListModel):
|
||||||
|
|
||||||
def _dereferenceItem(self, item):
|
def _dereferenceItem(self, item):
|
||||||
# Ask for object deletion if parented to the model
|
# 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
|
# delay deletion until the next event loop
|
||||||
# This avoids warnings when the QML engine tries to evaluate (but should not)
|
# This avoids warnings when the QML engine tries to evaluate (but should not)
|
||||||
# an object that has already been deleted
|
# an object that has already been deleted
|
||||||
|
|
|
@ -6,6 +6,9 @@ import meshroom
|
||||||
from meshroom.common import BaseObject, DictModel, Property
|
from meshroom.common import BaseObject, DictModel, Property
|
||||||
|
|
||||||
class State(Enum):
|
class State(Enum):
|
||||||
|
"""
|
||||||
|
State of the Thread that is computing nodes
|
||||||
|
"""
|
||||||
IDLE = 0
|
IDLE = 0
|
||||||
RUNNING = 1
|
RUNNING = 1
|
||||||
STOPPED = 2
|
STOPPED = 2
|
||||||
|
@ -13,6 +16,9 @@ class State(Enum):
|
||||||
ERROR = 4
|
ERROR = 4
|
||||||
|
|
||||||
class TaskThread(Thread):
|
class TaskThread(Thread):
|
||||||
|
"""
|
||||||
|
A thread with a pile of nodes to compute
|
||||||
|
"""
|
||||||
def __init__(self, manager):
|
def __init__(self, manager):
|
||||||
Thread.__init__(self, target=self.run)
|
Thread.__init__(self, target=self.run)
|
||||||
self._state = State.IDLE
|
self._state = State.IDLE
|
||||||
|
@ -45,7 +51,7 @@ class TaskThread(Thread):
|
||||||
if chunk.isStopped():
|
if chunk.isStopped():
|
||||||
self._state = State.STOPPED
|
self._state = State.STOPPED
|
||||||
self._manager._graph.clearSubmittedNodes()
|
self._manager._graph.clearSubmittedNodes()
|
||||||
self._manager._nodesToProcess.clear()
|
self._manager._nodesToProcess = []
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logging.error("Error on node computation: {}".format(e))
|
logging.error("Error on node computation: {}".format(e))
|
||||||
|
@ -60,21 +66,33 @@ class TaskThread(Thread):
|
||||||
pass
|
pass
|
||||||
nodeD.clearSubmittedChunks()
|
nodeD.clearSubmittedChunks()
|
||||||
|
|
||||||
self._manager._nodesToProcess.clear()
|
self._manager._nodesToProcess = []
|
||||||
self._state = State.DEAD
|
self._state = State.DEAD
|
||||||
self._manager._uigraph.computeStatusChanged.emit()
|
self._manager._uigraph.computeStatusChanged.emit()
|
||||||
|
|
||||||
|
|
||||||
class TaskManager(BaseObject):
|
class TaskManager(BaseObject):
|
||||||
|
"""
|
||||||
|
Manage the nodes that have to be computed locally or on a renderfarm
|
||||||
|
"""
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super(TaskManager, self).__init__(parent)
|
super(TaskManager, self).__init__(parent)
|
||||||
self._nodes = DictModel(keyAttrName='name', parent=self)
|
self._nodes = DictModel(keyAttrName='_name', parent=self)
|
||||||
self._nodesToProcess = DictModel(keyAttrName='name', parent=self)
|
self._nodesToProcess = []
|
||||||
self._nodesExtern = DictModel(keyAttrName='name', parent=self)
|
self._nodesExtern = []
|
||||||
self._graph = None
|
self._graph = None
|
||||||
self._thread = TaskThread(self)
|
self._thread = TaskThread(self)
|
||||||
|
|
||||||
def compute(self, graph=None, toNodes=None, uigraph=None, forceCompute=False, forceStatus=False):
|
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._graph = graph
|
||||||
self._uigraph = uigraph
|
self._uigraph = uigraph
|
||||||
|
|
||||||
|
@ -93,7 +111,7 @@ class TaskManager(BaseObject):
|
||||||
if not externEmpty:
|
if not externEmpty:
|
||||||
self._nodes.update(self._nodesExtern)
|
self._nodes.update(self._nodesExtern)
|
||||||
else:
|
else:
|
||||||
self._nodesExtern.clear()
|
self._nodesExtern = []
|
||||||
|
|
||||||
if forceCompute:
|
if forceCompute:
|
||||||
nodes, edges = graph.dfsOnFinish(startNodes=toNodes)
|
nodes, edges = graph.dfsOnFinish(startNodes=toNodes)
|
||||||
|
@ -104,16 +122,14 @@ class TaskManager(BaseObject):
|
||||||
if not node.isAlreadySubmittedOrFinished():
|
if not node.isAlreadySubmittedOrFinished():
|
||||||
nodes.append(node)
|
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:
|
for node in nodes:
|
||||||
|
node.destroyed.connect(lambda obj=None, name=node.name: self.onNodeDestroyed(obj, name))
|
||||||
node.beginSequence(forceCompute)
|
node.beginSequence(forceCompute)
|
||||||
|
|
||||||
try:
|
self._nodes.update(nodes)
|
||||||
self._nodes.update(nodes)
|
self._nodesToProcess .extend(nodes)
|
||||||
except:
|
|
||||||
print("nodes already added to Task Manager")
|
|
||||||
self._nodesToProcess.update(nodes)
|
|
||||||
|
|
||||||
if self._thread._state == State.IDLE:
|
if self._thread._state == State.IDLE:
|
||||||
self._thread.start()
|
self._thread.start()
|
||||||
|
@ -121,7 +137,34 @@ class TaskManager(BaseObject):
|
||||||
self._thread = TaskThread(self)
|
self._thread = TaskThread(self)
|
||||||
self._thread.start()
|
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):
|
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):
|
if self._thread._state in (State.IDLE, State.DEAD, State.ERROR, State.STOPPED):
|
||||||
self._nodes.clear()
|
self._nodes.clear()
|
||||||
|
|
||||||
|
@ -134,7 +177,7 @@ class TaskManager(BaseObject):
|
||||||
if not externEmpty:
|
if not externEmpty:
|
||||||
self._nodes.update(self._nodesExtern)
|
self._nodes.update(self._nodesExtern)
|
||||||
else:
|
else:
|
||||||
self._nodesExtern.clear()
|
self._nodesExtern = []
|
||||||
|
|
||||||
nodesToProcess, edgesToProcess = graph.dfsToProcess(startNodes=toNodes)
|
nodesToProcess, edgesToProcess = graph.dfsToProcess(startNodes=toNodes)
|
||||||
flowEdges = graph.flowEdges(startNodes=toNodes)
|
flowEdges = graph.flowEdges(startNodes=toNodes)
|
||||||
|
@ -148,15 +191,21 @@ class TaskManager(BaseObject):
|
||||||
res = sub.submit(nodesToProcess, edgesToProcess, graph.filepath)
|
res = sub.submit(nodesToProcess, edgesToProcess, graph.filepath)
|
||||||
if res:
|
if res:
|
||||||
for node in nodesToProcess:
|
for node in nodesToProcess:
|
||||||
|
node.destroyed.connect(lambda obj=None, name=node.name: self.onNodeDestroyed(obj, name))
|
||||||
node.submit() # update node status
|
node.submit() # update node status
|
||||||
self._nodes.update(nodesToProcess)
|
self._nodes.update(nodesToProcess)
|
||||||
self._nodesExtern.update(nodesToProcess)
|
self._nodesExtern.extend(nodesToProcess)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("Error on submit : {}".format(e))
|
logging.error("Error on submit : {}".format(e))
|
||||||
|
|
||||||
nodes = Property(BaseObject, lambda self: self._nodes, constant=True)
|
nodes = Property(BaseObject, lambda self: self._nodes, constant=True)
|
||||||
|
|
||||||
def getAlreadySubmittedChunks(nodes):
|
def getAlreadySubmittedChunks(nodes):
|
||||||
|
"""
|
||||||
|
Check if nodes already have been submitted
|
||||||
|
:param nodes:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
out = []
|
out = []
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
for chunk in node.chunks:
|
for chunk in node.chunks:
|
||||||
|
|
|
@ -307,6 +307,7 @@ class UIGraph(QObject):
|
||||||
if self._graph:
|
if self._graph:
|
||||||
self.clearNodeHover()
|
self.clearNodeHover()
|
||||||
self.clearNodeSelection()
|
self.clearNodeSelection()
|
||||||
|
self._taskManager.clear()
|
||||||
self._graph.deleteLater()
|
self._graph.deleteLater()
|
||||||
self._graph = None
|
self._graph = None
|
||||||
self._sortedDFSChunks.clear()
|
self._sortedDFSChunks.clear()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue