use of org.knime.core.node.Node in project knime-core by knime.
the class LearnerTest method setUp.
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
NodeFactory nodeFactory = new LogRegLearnerNodeFactory();
Node node = new Node(nodeFactory);
m_exec = new ExecutionContext(new DefaultNodeProgressMonitor(), node, SingleNodeContainer.MemoryPolicy.CacheOnDisc, new HashMap<Integer, ContainerTable>());
}
use of org.knime.core.node.Node in project knime-core by knime.
the class JoinerTest method setUp.
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
NodeFactory<NodeModel> dummyFactory = (NodeFactory) new VirtualParallelizedChunkPortObjectInNodeFactory(new PortType[0]);
m_exec = new ExecutionContext(new DefaultNodeProgressMonitor(), new Node(dummyFactory), SingleNodeContainer.MemoryPolicy.CacheOnDisc, new HashMap<Integer, ContainerTable>());
}
use of org.knime.core.node.Node in project knime-core by knime.
the class WorkflowManager method doAfterExecution.
/**
* Cleanup a node after execution. This will also permit the argument node to change its state in
* {@link NodeContainer#performStateTransitionEXECUTED(NodeContainerExecutionStatus)}. This method also takes care
* of restarting loops, if there are any to be continued.
*
* <p>
* As in {@link #doBeforeExecution(NodeContainer)} the argument node is usually a {@link SingleNodeContainer} but
* can also be a remotely executed <code>WorkflowManager</code>.
*
* @param nc node which just finished execution
* @param status indicates if node execution was finished successfully (note that this does not imply State=EXECUTED
* e.g. for loop ends)
*/
void doAfterExecution(final NodeContainer nc, final NodeContainerExecutionStatus status) {
assert isLocalWFM() : "doAfterExecute not allowed for remotely executing workflows";
assert !nc.getID().equals(this.getID());
boolean success = status.isSuccess();
try (WorkflowLock lock = lock()) {
nc.getNodeTimer().endExec(success);
String st = success ? " - success" : " - failure";
LOGGER.debug(nc.getNameWithID() + " doAfterExecute" + st);
if (!success) {
disableNodeForExecution(nc.getID());
}
// switch state from POSTEXECUTE to new state: EXECUTED resp. CONFIGURED
// in case of success (w/out resp. with loop) or IDLE in case of an error.
nc.performStateTransitionEXECUTED(status);
boolean canConfigureSuccessors = true;
// remember previous message in case loop restart fails...
NodeMessage latestNodeMessage = nc.getNodeMessage();
if (nc instanceof NativeNodeContainer) {
NativeNodeContainer nnc = (NativeNodeContainer) nc;
if (success) {
Node node = nnc.getNode();
// process start of bundle of parallel chunks
if (node.getNodeModel() instanceof LoopStartParallelizeNode && !node.isInactive()) {
try {
parallelizeLoop(nc.getID());
} catch (Exception e) {
if (!(e instanceof IllegalLoopException)) {
// handle unexpected exceptions properly (i.e.
// clean up loop) but report them as error!
LOGGER.error("Error in parallelizeLoop: " + e, e);
} else {
// can happen during regular use
// (e.g. wrong end node)
LOGGER.debug("parallelizeLoop failed: " + e, e);
}
// make sure the start node is reset and
// and appropriate message is set.
latestNodeMessage = new NodeMessage(NodeMessage.Type.ERROR, "Parallel Branch Start Failure: " + e.getMessage());
LOGGER.error(latestNodeMessage.getMessage(), e);
success = false;
canConfigureSuccessors = false;
disableNodeForExecution(nc.getID());
resetAndConfigureNode(nc.getID());
}
}
// process loop context for "real" nodes:
if (nnc.isModelCompatibleTo(LoopStartNode.class)) {
// if this was BEGIN, it's not anymore (until we do not restart it explicitly!)
node.setLoopEndNode(null);
}
if (nnc.isModelCompatibleTo(LoopEndNode.class)) {
// make sure entire loop body is executed. Trigger execution of rest if not.
// (note that we do not worry about waiting for executing dangling branches, for those
// we only need to wait when the loop is about to be restarted!)
ArrayList<NodeAndInports> loopBodyNodes = new ArrayList<NodeAndInports>();
try {
NodeID endID = nnc.getID();
NodeID startID = m_workflow.getMatchingLoopStart(endID);
loopBodyNodes = m_workflow.findAllNodesConnectedToLoopBody(startID, endID);
} catch (IllegalLoopException ile) {
// loop is incorrectly wired. We cannot restart potentially dangling branches
latestNodeMessage = new NodeMessage(NodeMessage.Type.ERROR, "Loop Body wired incorrectly (" + ile.getMessage() + ").");
LOGGER.error(latestNodeMessage.getMessage(), ile);
success = false;
}
// check if any of those nodes can still be executed (configured but not yet executing)
for (NodeAndInports nai : loopBodyNodes) {
NodeID id = nai.getID();
NodeContainer currNode = m_workflow.getNode(id);
if (!currNode.getInternalState().equals(EXECUTED)) {
// after this first simple & light-weight test we test true executability:
if (this.canExecuteNodeDirectly(id)) {
// Fixes Bug 2292 (dangling branches were not executed in 1-iteration loops)
if (currNode instanceof WorkflowManager) {
// FIXME: also here we need to execute...?
} else {
assert currNode instanceof SingleNodeContainer;
this.markAndQueueNodeAndPredecessors(id, -1);
}
}
}
}
}
if (success && node.getLoopContext() != null) {
// we are supposed to execute this loop again.
assert nnc.isModelCompatibleTo(LoopEndNode.class);
FlowLoopContext slc = node.getLoopContext();
// then check if the loop is properly configured:
if (m_workflow.getNode(slc.getHeadNode()) == null) {
// obviously not: origin of loop is not in this WFM!
assert false : "Inconsistent loops should be caught earlier.";
// nothing else to do: NC returns to being configured
if (!InternalNodeContainerState.CONFIGURED_MARKEDFOREXEC.equals(nnc.getInternalState())) {
nnc.markForExecution(false);
}
latestNodeMessage = new NodeMessage(NodeMessage.Type.ERROR, "Loop nodes are not in the same workflow!");
LOGGER.error(latestNodeMessage.getMessage());
success = false;
} else {
try {
slc.setTailNode(nc.getID());
if (!nnc.getNode().getPauseLoopExecution()) {
restartLoop(slc);
} else {
// do nothing - leave successors marked. Cancel execution to stop paused loop.
}
} catch (IllegalLoopException ile) {
LOGGER.error(ile.getMessage(), ile);
latestNodeMessage = new NodeMessage(NodeMessage.Type.ERROR, ile.getMessage());
success = false;
}
// make sure we do not accidentally configure the remainder of this node
// since we are not yet done with the loop
canConfigureSuccessors = false;
}
}
if (!success) {
// make sure any marks are removed (only for loop ends!)
disableNodeForExecution(nnc.getID());
nnc.getNode().clearLoopContext();
}
}
}
// note this is NOT the else of the if above - success can be modified...
if (!success && nc instanceof SingleNodeContainer) {
// clean up node interna and status (but keep org. message!)
// switch from IDLE to CONFIGURED if possible!
configureSingleNodeContainer((SingleNodeContainer) nc, /*keepNodeMessage=*/
true);
nc.setNodeMessage(latestNodeMessage);
}
// now handle non success for all types of nodes:
if (!success) {
// clean loops which were waiting for this one to be executed.
for (FlowLoopContext flc : nc.getWaitingLoops()) {
disableNodeForExecution(flc.getTailNode());
}
nc.clearWaitingLoopList();
}
if (nc.getWaitingLoops().size() >= 1) {
// finish! Let's try to restart them:
for (FlowLoopContext slc : nc.getWaitingLoops()) {
try {
restartLoop(slc);
} catch (IllegalLoopException ile) {
// set error message in LoopEnd node not this one!
NodeMessage nm = new NodeMessage(NodeMessage.Type.ERROR, ile.getMessage());
getNodeContainer(slc.getTailNode()).setNodeMessage(nm);
}
}
nc.clearWaitingLoopList();
}
if (canConfigureSuccessors) {
// may be SingleNodeContainer or WFM contained within this
// one but then it can be treated like a SNC
getExecutionController().checkHaltingCriteria(nc.getID());
configureNodeAndPortSuccessors(nc.getID(), null, false, true, false);
}
lock.queueCheckForNodeStateChangeNotification(true);
}
}
use of org.knime.core.node.Node in project knime-core by knime.
the class WorkflowManager method getExternalNodeDataHandles.
/**
* Implementation of {@link #getInputNodes()} and {@link #getExternalOutputs()}.
*
* @param nodeModelClass either {@link InputNode}.class or {@link OutputNode}.class.
* @param retriever resolves the data object from the input or output.
* @return List of nodes with their parameter names unified.
*/
// package scope for tests
<T> List<ExternalNodeDataHandle> getExternalNodeDataHandles(final Class<T> nodeModelClass, final Function<T, ExternalNodeData> retriever) {
List<ExternalNodeDataHandle> result = new ArrayList<>();
try (WorkflowLock lock = lock()) {
Map<NodeID, T> externalNodeDataMap = findNodes(nodeModelClass, NodeModelFilter.all(), true, true);
// get all "parameter names" from all nodes in the workflow in order to see if there are name conflicts;
// occurrence map like {"string-input" -> 1, "foo" -> 1, "bar" -> 3}
Map<String, Long> parameterNamesToCountMap = externalNodeDataMap.values().stream().map(retriever).map(extNodeData -> extNodeData.getID()).collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
parameterNamesToCountMap.values().removeAll(Collections.singleton(Long.valueOf(1L)));
Set<String> nonUniqueParameterNames = parameterNamesToCountMap.keySet();
if (!nonUniqueParameterNames.isEmpty()) {
LOGGER.warnWithFormat("Workflow contains nodes with duplicate parameter name " + "(will be made unique by appending node IDs): %s", ConvenienceMethods.getShortStringFrom(nonUniqueParameterNames, 5));
}
// create result list, make keys unique where needed but also retain the fully qualified parameter name
for (Map.Entry<NodeID, T> entry : externalNodeDataMap.entrySet()) {
NodeID nodeID = entry.getKey();
ExternalNodeData nodeData = retriever.apply(entry.getValue());
String parameterNameShort = nodeData.getID();
// this ID = 0:3, nodeID = 0:3:5:0:2:2 => nodeIDRelativePath = 5:0:2:2
String nodeIDRelativePath = StringUtils.removeStart(nodeID.toString(), getID().toString() + ":");
// nodeIDRelativePath = 5:0:2:2 --> 5:2:2 (':0' are internals of a subnode)
nodeIDRelativePath = StringUtils.remove(nodeIDRelativePath, ":0");
String parameterNameFullyQualified = (parameterNameShort.isEmpty() ? "" : parameterNameShort + "-") + nodeIDRelativePath;
if (nonUniqueParameterNames.contains(parameterNameShort)) {
parameterNameShort = parameterNameFullyQualified;
}
result.add(new ExternalNodeDataHandle(parameterNameShort, parameterNameFullyQualified, (NativeNodeContainer) findNodeContainer(nodeID), nodeData));
}
return result;
}
}
use of org.knime.core.node.Node in project knime-core by knime.
the class CopyNativeNodeContainerPersistor method getNode.
/**
* {@inheritDoc}
*/
@Override
public Node getNode() {
Node node = new Node(m_nodeFactory);
// we don't load any settings into the node instance here as this method is called
// from the constructor of SingleNodeContainer - it doesn't have a context set and therefore
// cannot resolve URLs etc (knime://knime.workflow/some-path)
// Settings are loaded in loadNodeContainer
m_lastCreatedNode = node;
return node;
}
Aggregations