Map<String, List<T>> timedOutPattern = sharedBufferAccessor.materializeMatch(extractCurrentMatches( sharedBufferAccessor, computationState)); sharedBufferAccessor.releaseNode(computationState.getPreviousBufferEntry()); sharedBufferAccessor.advanceTime(timestamp);
sharedBufferAccessor.releaseNode(newComputationState.getPreviousBufferEntry()); } else { sharedBufferAccessor.releaseNode(state.getPreviousBufferEntry()); for (ComputationState match : potentialMatches) { Map<String, List<T>> materializedMatch = sharedBufferAccessor.materializeMatch( sharedBufferAccessor.extractPatterns( match.getPreviousBufferEntry(), match.getVersion()).get(0) sharedBufferAccessor.releaseNode(match.getPreviousBufferEntry());
@Test public void testClearingSharedBufferWithMultipleEdgesBetweenEntries() throws Exception { SharedBuffer<Event> sharedBuffer = TestSharedBuffer.createTestBuffer(Event.createTypeSerializer()); int numberEvents = 8; Event[] events = new Event[numberEvents]; EventId[] eventIds = new EventId[numberEvents]; final long timestamp = 1L; for (int i = 0; i < numberEvents; i++) { events[i] = new Event(i + 1, "e" + (i + 1), i); eventIds[i] = sharedBuffer.registerEvent(events[i], timestamp); } try (SharedBufferAccessor<Event> sharedBufferAccessor = sharedBuffer.getAccessor()) { NodeId start = sharedBufferAccessor.put("start", eventIds[1], null, DeweyNumber.fromString("1")); NodeId b0 = sharedBufferAccessor.put("branching", eventIds[2], start, DeweyNumber.fromString("1.0")); NodeId b1 = sharedBufferAccessor.put("branching", eventIds[3], start, DeweyNumber.fromString("1.1")); NodeId b00 = sharedBufferAccessor.put("branching", eventIds[3], b0, DeweyNumber.fromString("1.0.0")); sharedBufferAccessor.put("branching", eventIds[4], b00, DeweyNumber.fromString("1.0.0.0")); NodeId b10 = sharedBufferAccessor.put("branching", eventIds[4], b1, DeweyNumber.fromString("1.1.0")); //simulate IGNORE (next event can point to events[2]) sharedBufferAccessor.lockNode(b0); sharedBufferAccessor.releaseNode(b10); for (EventId eventId : eventIds) { sharedBufferAccessor.releaseEvent(eventId); } } //There should be still events[1] and events[2] in the buffer assertFalse(sharedBuffer.isEmpty()); }
/** * Removes the {@code SharedBufferNode}, when the ref is decreased to zero, and also * decrease the ref of the edge on this node. * * @param node id of the entry * @param sharedBufferNode the node body to be removed * @throws Exception Thrown if the system cannot access the state. */ private void removeNode(NodeId node, SharedBufferNode sharedBufferNode) throws Exception { sharedBuffer.removeEntry(node); EventId eventId = node.getEventId(); releaseEvent(eventId); for (SharedBufferEdge sharedBufferEdge : sharedBufferNode.getEdges()) { releaseNode(sharedBufferEdge.getTarget()); } }
NodeId a = sharedBufferAccessor.put("a", eventIds[0], null, DeweyNumber.fromString("1")); NodeId b = sharedBufferAccessor.put("b", eventIds[1], a, DeweyNumber.fromString("1.0")); NodeId aa = sharedBufferAccessor.put("aa", eventIds[2], b, DeweyNumber.fromString("1.0.0")); NodeId bb = sharedBufferAccessor.put("bb", eventIds[3], aa, DeweyNumber.fromString("1.0.0.0")); NodeId c = sharedBufferAccessor.put("c", eventIds[4], bb, DeweyNumber.fromString("1.0.0.0.0")); Map<String, List<Event>> patternsResult = sharedBufferAccessor.materializeMatch(sharedBufferAccessor.extractPatterns(c, DeweyNumber.fromString("1.0.0.0.0")).get(0)); sharedBufferAccessor.releaseEvent(eventId);
for (int i = 0; i < numberEvents; i++) { events[i] = new Event(i + 1, "e" + (i + 1), i); eventIds[i] = sharedBufferAccessor.registerEvent(events[i], timestamp); NodeId start = sharedBufferAccessor.put("start", eventIds[1], null, DeweyNumber.fromString("1")); NodeId b0 = sharedBufferAccessor.put("branching", eventIds[2], start, DeweyNumber.fromString("1.0")); NodeId b1 = sharedBufferAccessor.put("branching", eventIds[3], start, DeweyNumber.fromString("1.1")); NodeId b00 = sharedBufferAccessor.put("branching", eventIds[3], b0, DeweyNumber.fromString("1.0.0")); sharedBufferAccessor.put("branching", eventIds[4], b00, DeweyNumber.fromString("1.0.0.0")); sharedBufferAccessor.lockNode(b0); sharedBufferAccessor.releaseEvent(eventId);
takeBranchesToVisit--; final NodeId newEntry = sharedBufferAccessor.put( currentState.getName(), event.getEventId(), sharedBufferAccessor.releaseNode(computationState.getPreviousBufferEntry());
/** * Stores given value (value + timestamp) under the given state. It assigns a preceding element * relation to the previous entry. * * @param stateName name of the state that the event should be assigned to * @param eventId unique id of event assigned by this SharedBuffer * @param previousNodeId id of previous entry (might be null if start of new run) * @param version Version of the previous relation * @return assigned id of this element */ public NodeId put( final String stateName, final EventId eventId, @Nullable final NodeId previousNodeId, final DeweyNumber version) { if (previousNodeId != null) { lockNode(previousNodeId); } NodeId currentNodeId = new NodeId(eventId, getOriginalNameFromInternal(stateName)); Lockable<SharedBufferNode> currentNode = sharedBuffer.getEntry(currentNodeId); if (currentNode == null) { currentNode = new Lockable<>(new SharedBufferNode(), 0); lockEvent(eventId); } currentNode.getElement().addEdge(new SharedBufferEdge( previousNodeId, version)); sharedBuffer.upsertEntry(currentNodeId, currentNode); return currentNodeId; }
private void addComputationState( SharedBufferAccessor<T> sharedBufferAccessor, List<ComputationState> computationStates, State<T> currentState, NodeId previousEntry, DeweyNumber version, long startTimestamp, EventId startEventId) throws Exception { ComputationState computationState = ComputationState.createState( currentState.getName(), previousEntry, version, startTimestamp, startEventId); computationStates.add(computationState); sharedBufferAccessor.lockNode(previousEntry); }
/** * Prunes matches/partial matches based on the chosen strategy. * * @param matchesToPrune current partial matches * @param matchedResult already completed matches * @param sharedBufferAccessor accessor to corresponding shared buffer * @throws Exception thrown if could not access the state */ public void prune( Collection<ComputationState> matchesToPrune, Collection<Map<String, List<EventId>>> matchedResult, SharedBufferAccessor<?> sharedBufferAccessor) throws Exception { EventId pruningId = getPruningId(matchedResult); if (pruningId != null) { List<ComputationState> discardStates = new ArrayList<>(); for (ComputationState computationState : matchesToPrune) { if (computationState.getStartEventID() != null && shouldPrune(computationState.getStartEventID(), pruningId)) { sharedBufferAccessor.releaseNode(computationState.getPreviousBufferEntry()); discardStates.add(computationState); } } matchesToPrune.removeAll(discardStates); } }
/** * Extracts all the sequences of events from the start to the given computation state. An event * sequence is returned as a map which contains the events and the names of the states to which * the events were mapped. * * @param sharedBufferAccessor The accessor to {@link SharedBuffer} from which to extract the matches * @param computationState The end computation state of the extracted event sequences * @return Collection of event sequences which end in the given computation state * @throws Exception Thrown if the system cannot access the state. */ private Map<String, List<EventId>> extractCurrentMatches( final SharedBufferAccessor<T> sharedBufferAccessor, final ComputationState computationState) throws Exception { if (computationState.getPreviousBufferEntry() == null) { return new HashMap<>(); } List<Map<String, List<EventId>>> paths = sharedBufferAccessor.extractPatterns( computationState.getPreviousBufferEntry(), computationState.getVersion()); if (paths.isEmpty()) { return new HashMap<>(); } // for a given computation state, we cannot have more than one matching patterns. Preconditions.checkState(paths.size() == 1); return paths.get(0); }
@Override public Iterable<T> getEventsForPattern(final String key) throws Exception { Preconditions.checkNotNull(key); // the (partially) matched pattern is computed lazily when this method is called. // this is to avoid any overheads when using a simple, non-iterative condition. if (matchedEvents == null) { this.matchedEvents = sharedBufferAccessor.materializeMatch(nfa.extractCurrentMatches(sharedBufferAccessor, computationState)); } return new Iterable<T>() { @Override public Iterator<T> iterator() { List<T> elements = matchedEvents.get(key); return elements == null ? Collections.EMPTY_LIST.<T>iterator() : elements.iterator(); } }; } }
@Test public void testSharedBufferClearing() throws Exception { Pattern<Event, ?> pattern = Pattern.<Event>begin("start").followedBy("end"); Event a = new Event(40, "a", 1.0); Event b = new Event(41, "b", 2.0); NFA<Event> nfa = compile(pattern, false); TestTimerService timerService = new TestTimerService(); try (SharedBufferAccessor<Event> accessor = Mockito.spy(sharedBuffer.getAccessor())) { nfa.process(accessor, nfa.createInitialNFAState(), a, 1, AfterMatchSkipStrategy.noSkip(), timerService); nfa.process(accessor, nfa.createInitialNFAState(), b, 2, AfterMatchSkipStrategy.noSkip(), timerService); Mockito.verify(accessor, Mockito.never()).advanceTime(anyLong()); nfa.advanceTime(accessor, nfa.createInitialNFAState(), 2); Mockito.verify(accessor, Mockito.times(1)).advanceTime(2); } } }
/** * Construct an accessor to deal with this sharedBuffer. * * @return an accessor to deal with this sharedBuffer. */ public SharedBufferAccessor<V> getAccessor() { return new SharedBufferAccessor<>(this); }
/** * Decreases the reference counter for the given entry so that it can be * removed once the reference counter reaches 0. * * @param node id of the entry * @throws Exception Thrown if the system cannot access the state. */ public void releaseNode(final NodeId node) throws Exception { Lockable<SharedBufferNode> sharedBufferNode = sharedBuffer.getEntry(node); if (sharedBufferNode != null) { if (sharedBufferNode.release()) { removeNode(node, sharedBufferNode.getElement()); } else { sharedBuffer.upsertEntry(node, sharedBufferNode); } } }
NodeId a10 = sharedBufferAccessor.put("a1", eventIds[0], null, DeweyNumber.fromString("1")); NodeId aLoop0 = sharedBufferAccessor.put("a[]", eventIds[1], a10, DeweyNumber.fromString("1.0")); NodeId a11 = sharedBufferAccessor.put("a1", eventIds[2], null, DeweyNumber.fromString("2")); NodeId aLoop1 = sharedBufferAccessor.put("a[]", eventIds[2], aLoop0, DeweyNumber.fromString("1.0")); NodeId aLoop2 = sharedBufferAccessor.put("a[]", eventIds[3], aLoop1, DeweyNumber.fromString("1.0")); NodeId aSecondLoop0 = sharedBufferAccessor.put("a[]", eventIds[3], a11, DeweyNumber.fromString("2.0")); NodeId aLoop3 = sharedBufferAccessor.put("a[]", eventIds[4], aLoop2, DeweyNumber.fromString("1.0")); NodeId b0 = sharedBufferAccessor.put("b", eventIds[5], aLoop3, DeweyNumber.fromString("1.0.0")); NodeId aLoop4 = sharedBufferAccessor.put("a[]", eventIds[5], aLoop3, DeweyNumber.fromString("1.1")); NodeId b1 = sharedBufferAccessor.put("b", eventIds[5], aSecondLoop0, DeweyNumber.fromString("2.0.0")); NodeId aLoop5 = sharedBufferAccessor.put("a[]", eventIds[6], aLoop4, DeweyNumber.fromString("1.1")); NodeId b3 = sharedBufferAccessor.put("b", eventIds[7], aLoop5, DeweyNumber.fromString("1.1.0")); List<Map<String, List<EventId>>> patterns3 = sharedBufferAccessor.extractPatterns(b3, DeweyNumber.fromString("1.1.0")); assertEquals(1L, patterns3.size()); assertEquals(expectedPattern3, sharedBufferAccessor.materializeMatch(patterns3.get(0))); sharedBufferAccessor.releaseNode(b3); List<Map<String, List<EventId>>> patterns4 = sharedBufferAccessor.extractPatterns(b3, DeweyNumber.fromString("1.1.0")); assertEquals(0L, patterns4.size()); assertTrue(patterns4.isEmpty()); List<Map<String, List<EventId>>> patterns1 = sharedBufferAccessor.extractPatterns(b1, DeweyNumber.fromString("2.0.0")); assertEquals(1L, patterns1.size()); assertEquals(expectedPattern1, sharedBufferAccessor.materializeMatch(patterns1.get(0)));
/** * Removes the {@code SharedBufferNode}, when the ref is decreased to zero, and also * decrease the ref of the edge on this node. * * @param node id of the entry * @param sharedBufferNode the node body to be removed * @throws Exception Thrown if the system cannot access the state. */ private void removeNode(NodeId node, SharedBufferNode sharedBufferNode) throws Exception { sharedBuffer.removeEntry(node); EventId eventId = node.getEventId(); releaseEvent(eventId); for (SharedBufferEdge sharedBufferEdge : sharedBufferNode.getEdges()) { releaseNode(sharedBufferEdge.getTarget()); } }
takeBranchesToVisit--; final NodeId newEntry = sharedBufferAccessor.put( currentState.getName(), event.getEventId(), sharedBufferAccessor.releaseNode(computationState.getPreviousBufferEntry());
/** * Stores given value (value + timestamp) under the given state. It assigns a preceding element * relation to the previous entry. * * @param stateName name of the state that the event should be assigned to * @param eventId unique id of event assigned by this SharedBuffer * @param previousNodeId id of previous entry (might be null if start of new run) * @param version Version of the previous relation * @return assigned id of this element */ public NodeId put( final String stateName, final EventId eventId, @Nullable final NodeId previousNodeId, final DeweyNumber version) { if (previousNodeId != null) { lockNode(previousNodeId); } NodeId currentNodeId = new NodeId(eventId, getOriginalNameFromInternal(stateName)); Lockable<SharedBufferNode> currentNode = sharedBuffer.getEntry(currentNodeId); if (currentNode == null) { currentNode = new Lockable<>(new SharedBufferNode(), 0); lockEvent(eventId); } currentNode.getElement().addEdge(new SharedBufferEdge( previousNodeId, version)); sharedBuffer.upsertEntry(currentNodeId, currentNode); return currentNodeId; }
private void addComputationState( SharedBufferAccessor<T> sharedBufferAccessor, List<ComputationState> computationStates, State<T> currentState, NodeId previousEntry, DeweyNumber version, long startTimestamp, EventId startEventId) throws Exception { ComputationState computationState = ComputationState.createState( currentState.getName(), previousEntry, version, startTimestamp, startEventId); computationStates.add(computationState); sharedBufferAccessor.lockNode(previousEntry); }