use of org.apache.flink.cep.nfa.sharedbuffer.EventId in project flink by apache.
the class NFA method computeNextStates.
/**
* Computes the next computation states based on the given computation state, the current event,
* its timestamp and the internal state machine. The algorithm is:
*
* <ol>
* <li>Decide on valid transitions and number of branching paths. See {@link OutgoingEdges}
* <li>Perform transitions:
* <ol>
* <li>IGNORE (links in {@link SharedBuffer} will still point to the previous event)
* <ul>
* <li>do not perform for Start State - special case
* <li>if stays in the same state increase the current stage for future use with
* number of outgoing edges
* <li>if after PROCEED increase current stage and add new stage (as we change the
* state)
* <li>lock the entry in {@link SharedBuffer} as it is needed in the created
* branch
* </ul>
* <li>TAKE (links in {@link SharedBuffer} will point to the current event)
* <ul>
* <li>add entry to the shared buffer with version of the current computation
* state
* <li>add stage and then increase with number of takes for the future computation
* states
* <li>peek to the next state if it has PROCEED path to a Final State, if true
* create Final ComputationState to emit results
* </ul>
* </ol>
* <li>Handle the Start State, as it always have to remain
* <li>Release the corresponding entries in {@link SharedBuffer}.
* </ol>
*
* @param sharedBufferAccessor The accessor to shared buffer that we need to change
* @param computationState Current computation state
* @param event Current event which is processed
* @param timerService timer service which provides access to time related features
* @return Collection of computation states which result from the current one
* @throws Exception Thrown if the system cannot access the state.
*/
private Collection<ComputationState> computeNextStates(final SharedBufferAccessor<T> sharedBufferAccessor, final ComputationState computationState, final EventWrapper event, final TimerService timerService) throws Exception {
final ConditionContext context = new ConditionContext(sharedBufferAccessor, computationState, timerService, event.getTimestamp());
final OutgoingEdges<T> outgoingEdges = createDecisionGraph(context, computationState, event.getEvent());
// Create the computing version based on the previously computed edges
// We need to defer the creation of computation states until we know how many edges start
// at this computation state so that we can assign proper version
final List<StateTransition<T>> edges = outgoingEdges.getEdges();
int takeBranchesToVisit = Math.max(0, outgoingEdges.getTotalTakeBranches() - 1);
int ignoreBranchesToVisit = outgoingEdges.getTotalIgnoreBranches();
int totalTakeToSkip = Math.max(0, outgoingEdges.getTotalTakeBranches() - 1);
final List<ComputationState> resultingComputationStates = new ArrayList<>();
for (StateTransition<T> edge : edges) {
switch(edge.getAction()) {
case IGNORE:
{
if (!isStartState(computationState)) {
final DeweyNumber version;
if (isEquivalentState(edge.getTargetState(), getState(computationState))) {
// Stay in the same state (it can be either looping one or
// singleton)
final int toIncrease = calculateIncreasingSelfState(outgoingEdges.getTotalIgnoreBranches(), outgoingEdges.getTotalTakeBranches());
version = computationState.getVersion().increase(toIncrease);
} else {
// IGNORE after PROCEED
version = computationState.getVersion().increase(totalTakeToSkip + ignoreBranchesToVisit).addStage();
ignoreBranchesToVisit--;
}
addComputationState(sharedBufferAccessor, resultingComputationStates, edge.getTargetState(), computationState.getPreviousBufferEntry(), version, computationState.getStartTimestamp(), computationState.getStartEventID());
}
}
break;
case TAKE:
final State<T> nextState = edge.getTargetState();
final State<T> currentState = edge.getSourceState();
final NodeId previousEntry = computationState.getPreviousBufferEntry();
final DeweyNumber currentVersion = computationState.getVersion().increase(takeBranchesToVisit);
final DeweyNumber nextVersion = new DeweyNumber(currentVersion).addStage();
takeBranchesToVisit--;
final NodeId newEntry = sharedBufferAccessor.put(currentState.getName(), event.getEventId(), previousEntry, currentVersion);
final long startTimestamp;
final EventId startEventId;
if (isStartState(computationState)) {
startTimestamp = event.getTimestamp();
startEventId = event.getEventId();
} else {
startTimestamp = computationState.getStartTimestamp();
startEventId = computationState.getStartEventID();
}
addComputationState(sharedBufferAccessor, resultingComputationStates, nextState, newEntry, nextVersion, startTimestamp, startEventId);
// check if newly created state is optional (have a PROCEED path to Final state)
final State<T> finalState = findFinalStateAfterProceed(context, nextState, event.getEvent());
if (finalState != null) {
addComputationState(sharedBufferAccessor, resultingComputationStates, finalState, newEntry, nextVersion, startTimestamp, startEventId);
}
break;
}
}
if (isStartState(computationState)) {
int totalBranches = calculateIncreasingSelfState(outgoingEdges.getTotalIgnoreBranches(), outgoingEdges.getTotalTakeBranches());
DeweyNumber startVersion = computationState.getVersion().increase(totalBranches);
ComputationState startState = ComputationState.createStartState(computationState.getCurrentStateName(), startVersion);
resultingComputationStates.add(startState);
}
if (computationState.getPreviousBufferEntry() != null) {
// release the shared entry referenced by the current computation state.
sharedBufferAccessor.releaseNode(computationState.getPreviousBufferEntry(), computationState.getVersion());
}
return resultingComputationStates;
}
Aggregations