Class FlowNodeCounter
This counter is composed of two sub-counters:
- a global counter which counts how many times a subflow node was entered and exited
- a local counter - scoped to each (sub)flow, counts how many times nodes in the current flow have been reached
The counter can be used to detect potential infinite loops or infinite recursion. Each time a flow node is reached,
it should be registered in this counter using register(NodeID)
. When a flow node is entered, this counter
must be notified using onFlowEnter(NodeID)
, and when a flow node is exited, the counter should be notified
using onFlowExit(NodeID)
. When the flow associated with a flow node is started, the counter should be
notified using onFlowStart()
. When a flow ends the counter should be notified using onFlowEnd()
.
Note that entering a flow node is not the same as starting the associated flow. For instance, if a flow node has a repeat expression which evaluates to zero, the flow node is entered and exited, but the associated flow is never started.
The global counter detects infinite flow recursion. The global count for a flow is incremented when a flow is started, and decremented when the flow ends.
The local counter detects infinite iterations. The local count for a flow node is incremented every time that node is reached and registered. The local counter is never decremented, however when entering a subflow the local counter enters a new, empty scope. Therefore, a flow node inside a repeated subflow will not cause a false-positive, as every time the subflow repeats, the flow node inside it is counted in a different scope.
- Since:
- 11.1
- Author:
- Petru Galanton
-
Field Summary
Fields -
Constructor Summary
ConstructorsConstructorDescriptionCreates a new instance, with the system default maximum loop count.FlowNodeCounter
(int maxLoopCount) Creates a new instance with the specified maximum loop count. -
Method Summary
Modifier and TypeMethodDescriptionint
getGlobalCount
(NodeID nodeId) Returns the global count for the node with the given id.int
getLocalCount
(NodeID nodeId) Returns the local count for the node with the given id.int
Returns the number of stacked local scopes.int
Returns the number of nodes counted in the local counter in the current scope.int
Returns the maximum loop (and recursion) count.void
Notifies this counter that a flow associated with a flow node has ended.int
onFlowEnter
(NodeID nodeId) Notifies this counter that a flow node was entered.int
onFlowExit
(NodeID nodeId) Notifies this counter that a flow node was exited.void
Notifies this counter that a flow associated with a flow node was started.int
Registers the current node reached in a flow execution in the local counter, increasing its count by one.
-
Field Details
-
DEFAULT_MAX_LOOP_COUNT
public static final int DEFAULT_MAX_LOOP_COUNT- See Also:
-
MAX_LOOP_COUNT_PROPERTY
- See Also:
-
-
Constructor Details
-
FlowNodeCounter
public FlowNodeCounter()Creates a new instance, with the system default maximum loop count. -
FlowNodeCounter
public FlowNodeCounter(int maxLoopCount) Creates a new instance with the specified maximum loop count.- Parameters:
maxLoopCount
-
-
-
Method Details
-
getMaxLoopCount
public int getMaxLoopCount()Returns the maximum loop (and recursion) count. Exceeding this limit causesregister(NodeID)
to throw an InfiniteLoopException, andonFlowEnter(NodeID)
to throw an InfiniteRecursionException.- Returns:
- the maximum loop/recursion count.
-
register
Registers the current node reached in a flow execution in the local counter, increasing its count by one. If the count for the node with the given ID exceeds the maximum loop count an InfiniteLoopException is thrown.- Parameters:
nodeId
- the ID of the current node in the flow execution- Returns:
- the new local count for the current node
- Throws:
InfiniteLoopException
- if the local count for the current node exceeds the limit
-
onFlowEnter
Notifies this counter that a flow node was entered. The count for the current node is incremented in the global counter by one. If the count exceeds the limit an InfiniteRecursionException is thrown. NOTE: flow nodes must still be registered usingregister(NodeID)
.- Parameters:
nodeId
- the ID of the current node (which should be a flow node)- Returns:
- the new global count for the current node
- Throws:
InfiniteRecursionException
- if the global count for the current node exceeds the limit
-
onFlowExit
Notifies this counter that a flow node was exited. The count for the current node is decremented in the global counter by one.- Parameters:
nodeId
- the id of the current flow node, which should previously have been registered withonFlowEnter(NodeID)
.- Returns:
- the new global count for the current node
-
onFlowStart
public void onFlowStart()Notifies this counter that a flow associated with a flow node was started. Causes the local counter to start a new scope. -
onFlowEnd
public void onFlowEnd()Notifies this counter that a flow associated with a flow node has ended. Causes the local counter to revert to the previous scope. -
getGlobalCount
Returns the global count for the node with the given id. If the node has never been registered in this counter, zero is returned.- Parameters:
nodeId
- the id of a flow node- Returns:
- the global count for the given node
-
getLocalCount
Returns the local count for the node with the given id. If the node has never been registered in this counter, zero is returned.- Parameters:
nodeId
- the id of a flow node- Returns:
- the local count for the given node
-
getLocalCounterDepth
public int getLocalCounterDepth()Returns the number of stacked local scopes.- Returns:
- the number of stacked local scopes.
-
getLocalCounterSize
public int getLocalCounterSize()Returns the number of nodes counted in the local counter in the current scope.- Returns:
- the number of nodes counted in the local counter
-