@Override public Map<ThreadIdentifier, EventSequenceNumberHolder> getState() { Map<ThreadIdentifier, EventSequenceNumberHolder> result = new HashMap<>(recordedEvents.size()); for (Map.Entry<ThreadIdentifier, EventSequenceNumberHolder> entry : recordedEvents.entrySet()) { EventSequenceNumberHolder holder = entry.getValue(); // don't transfer version tags - adds too much bulk just so we can do client tag recovery result.put(entry.getKey(), new EventSequenceNumberHolder(holder.getLastSequenceNumber(), null)); } return result; }
boolean removed; if (logger.isDebugEnabled()) { logger.debug("recording {} {}", threadID.expensiveToString(), evh.toString()); if (oldEvh != null) { synchronized (oldEvh) { if (oldEvh.isRemoved()) { break; oldEvh.setEndOfLifeTimestamp(0); if (oldEvh.getLastSequenceNumber() < evh.getLastSequenceNumber()) { oldEvh.setLastSequenceNumber(evh.getLastSequenceNumber()); oldEvh.setVersionTag(evh.getVersionTag()); evh.setEndOfLifeTimestamp(0);
private void removeExpiredSequenceTracker(EventTracker tracker, long now, long expirationTime) { for (Iterator<Map.Entry<ThreadIdentifier, EventSequenceNumberHolder>> entryIterator = tracker.getRecordedEvents().entrySet().iterator(); entryIterator.hasNext();) { Map.Entry<ThreadIdentifier, EventSequenceNumberHolder> entry = entryIterator.next(); EventSequenceNumberHolder evh = entry.getValue(); if (evh.expire(now, expirationTime)) { if (traceEnabled) { logger.trace("{} sweeper: removing {}", tracker.getName(), entry.getKey()); } entryIterator.remove(); } } }
@Override public boolean hasSeenEvent(EventID eventID, InternalCacheEvent tagHolder) { if (eventID == null) { return false; } EventSequenceNumberHolder evh = getSequenceHolderForEvent(eventID); if (evh == null) { return false; } synchronized (evh) { if (evh.isRemoved() || evh.getLastSequenceNumber() < eventID.getSequenceID()) { return false; } // log at fine because partitioned regions can send event multiple times // during normal operation during bucket region initialization if (logger.isTraceEnabled(LogMarker.DISTRIBUTION_BRIDGE_SERVER_VERBOSE)) { logger.trace(LogMarker.DISTRIBUTION_BRIDGE_SERVER_VERBOSE, "Cache encountered replay of event with ID {}. Highest recorded for this source is {}", eventID, evh.getLastSequenceNumber()); } // bug #44956 - recover version tag for duplicate event if (evh.getLastSequenceNumber() == eventID.getSequenceID() && tagHolder != null && evh.getVersionTag() != null) { ((EntryEventImpl) tagHolder).setVersionTag(evh.getVersionTag()); } return true; } }
@Test public void returnsMapContainingSequenceIdHoldersCurrentlyPresent() { EventSequenceNumberHolder sequenceIdHolder = new EventSequenceNumberHolder(0L, null); ThreadIdentifier threadId = new ThreadIdentifier(new byte[0], 0L); eventTracker.recordSequenceNumber(threadId, sequenceIdHolder); Map<ThreadIdentifier, EventSequenceNumberHolder> state = eventTracker.getState(); assertEquals(1, state.size()); EventSequenceNumberHolder returnedHolder = state.get(threadId); assertNotNull(returnedHolder); // the version tag is stripped out on purpose, so passed in object and returned one are not // equal to each other assertNull(returnedHolder.getVersionTag()); assertEquals(sequenceIdHolder.getLastSequenceNumber(), returnedHolder.getLastSequenceNumber()); }
@Test public void removesExpiredSequenceIdHolder() { DistributedEventTracker tracker = constructTestTracker(); task.addTracker(tracker); EventSequenceNumberHolder sequenceIdHolder = new EventSequenceNumberHolder(0L, null); tracker.recordSequenceNumber(new ThreadIdentifier(new byte[0], 0L), sequenceIdHolder); sequenceIdHolder.setEndOfLifeTimestamp(System.currentTimeMillis() - TIME_TO_LIVE); task.run2(); assertEquals(0, tracker.getRecordedEvents().size()); }
eventState.put(key, value); } else { EventSequenceNumberHolder value = new EventSequenceNumberHolder(); InternalDataSerializer.invokeFromData(value, dip); eventState.put(key, value); if (value.getVersionTag() != null) { value.getVersionTag().replaceNullIDs(senderId);
@Override public VersionTag findVersionTagForSequence(EventID eventID) { EventSequenceNumberHolder evh = getSequenceHolderForEvent(eventID); if (evh == null) { if (logger.isDebugEnabled()) { logger.debug("search for version tag failed as no event is recorded for {}", createThreadIDFromEvent(eventID).expensiveToString()); } return null; } synchronized (evh) { if (logger.isDebugEnabled()) { logger.debug("search for version tag located last event for {}: {}", createThreadIDFromEvent(eventID).expensiveToString(), evh); } if (evh.getLastSequenceNumber() != eventID.getSequenceID()) { return null; } // log at fine because partitioned regions can send event multiple times // during normal operation during bucket region initialization if (logger.isTraceEnabled(LogMarker.DISTRIBUTION_BRIDGE_SERVER_VERBOSE) && evh.getVersionTag() == null) { logger.trace(LogMarker.DISTRIBUTION_BRIDGE_SERVER_VERBOSE, "Could not recover version tag. Found event holder with no version tag for {}", eventID); } return evh.getVersionTag(); } }
private EventSequenceNumberHolder recordSequence(EventID eventID) { EventSequenceNumberHolder sequenceIdHolder = new EventSequenceNumberHolder(eventID.getSequenceID(), null); ThreadIdentifier threadIdentifier = new ThreadIdentifier(new byte[0], eventID.getThreadID()); eventTracker.recordSequenceNumber(threadIdentifier, sequenceIdHolder); return sequenceIdHolder; } }
@Test public void hasNotSeenEventIDWhosSequenceIDIsMarkedRemoved() { EventID eventID = new EventID(new byte[0], 0L, 0L); EventSequenceNumberHolder sequenceIdHolder = new EventSequenceNumberHolder(eventID.getSequenceID(), null); sequenceIdHolder.setRemoved(true); ThreadIdentifier threadId = new ThreadIdentifier(new byte[0], 0L); eventTracker.recordSequenceNumber(threadId, sequenceIdHolder); assertFalse(eventTracker.hasSeenEvent(eventID)); }
@Override public void recordBulkOpStart(EventID eventID, ThreadIdentifier tid) { if (logger.isDebugEnabled()) { logger.debug("recording bulkOp start for {}", tid.expensiveToString()); } EventSequenceNumberHolder evh = recordedEvents.get(tid); if (evh == null) { return; } synchronized (evh) { // only remove it when a new bulk op occurs if (eventID.getSequenceID() > evh.getLastSequenceNumber()) { this.recordedBulkOpVersionTags.remove(tid); } } }
@Test public void returnsCorrectTagForEvent() { EventID eventID = new EventID(new byte[0], 0L, 0L); EventSequenceNumberHolder sequenceIdHolder = recordSequence(eventID); assertEquals(sequenceIdHolder.getVersionTag(), eventTracker.findVersionTagForSequence(eventID)); }
@Test public void doesNotRemoveNonExpiredSequenceIdHolder() { DistributedEventTracker tracker = constructTestTracker(); task.addTracker(tracker); EventSequenceNumberHolder sequenceIdHolder = new EventSequenceNumberHolder(0L, null); tracker.recordSequenceNumber(new ThreadIdentifier(new byte[0], 0L), sequenceIdHolder); sequenceIdHolder.setEndOfLifeTimestamp(System.currentTimeMillis() + 10000); task.run2(); assertEquals(1, tracker.getRecordedEvents().size()); }
@Test public void doesNotRemoveNewSequenceIdHolder() { DistributedEventTracker tracker = constructTestTracker(); task.addTracker(tracker); EventSequenceNumberHolder sequenceIdHolder = new EventSequenceNumberHolder(0L, null); tracker.recordSequenceNumber(new ThreadIdentifier(new byte[0], 0L), sequenceIdHolder); task.run2(); assertEquals(1, tracker.getRecordedEvents().size()); }
@Test public void entryInRecordedStateStoredWhenNotInCurrentState() { EventSequenceNumberHolder sequenceIdHolder = new EventSequenceNumberHolder(0L, null); ThreadIdentifier threadId = new ThreadIdentifier(new byte[0], 0L); Map<ThreadIdentifier, EventSequenceNumberHolder> state = Collections.singletonMap(threadId, sequenceIdHolder); eventTracker.recordState(null, state); Map<ThreadIdentifier, EventSequenceNumberHolder> storedState = eventTracker.getState(); assertEquals(storedState.get(threadId).getLastSequenceNumber(), sequenceIdHolder.getLastSequenceNumber()); }
@Override public void recordEvent(InternalCacheEvent event) { EventID eventID = event.getEventId(); if (ignoreEvent(event, eventID)) { return; // not tracked } LocalRegion lr = (LocalRegion) event.getRegion(); ThreadIdentifier membershipID = createThreadIDFromEvent(eventID); VersionTag tag = null; if (lr.getServerProxy() == null) { tag = event.getVersionTag(); RegionVersionVector v = ((LocalRegion) event.getRegion()).getVersionVector(); canonicalizeIDs(tag, v); } EventSequenceNumberHolder newEvh = new EventSequenceNumberHolder(eventID.getSequenceID(), tag); if (logger.isTraceEnabled()) { logger.trace("region event tracker recording {}", event); } recordSequenceNumber(membershipID, newEvh); // If this is a bulkOp, and concurrency checks are enabled, we need to // save the version tag in case we retry. // Make recordBulkOp version tag after recordSequenceNumber, so that recordBulkOpStart // in a retry bulk op would not incorrectly remove the saved version tag in // recordedBulkOpVersionTags if (lr.getConcurrencyChecksEnabled() && (event.getOperation().isPutAll() || event.getOperation().isRemoveAll()) && lr.getServerProxy() == null) { recordBulkOpEvent(event, membershipID); } }
@Test public void entryInRecordedStateNotStoredIfAlreadyInCurrentState() { EventSequenceNumberHolder originalSequenceIdHolder = new EventSequenceNumberHolder(0L, null); ThreadIdentifier threadId = new ThreadIdentifier(new byte[0], 0L); Map<ThreadIdentifier, EventSequenceNumberHolder> state = Collections.singletonMap(threadId, originalSequenceIdHolder); eventTracker.recordState(null, state); EventSequenceNumberHolder newSequenceIdHolder = new EventSequenceNumberHolder(1L, null); Map<ThreadIdentifier, EventSequenceNumberHolder> newState = Collections.singletonMap(threadId, newSequenceIdHolder); eventTracker.recordState(null, newState); Map<ThreadIdentifier, EventSequenceNumberHolder> storedState = eventTracker.getState(); assertEquals(storedState.get(threadId).getLastSequenceNumber(), originalSequenceIdHolder.getLastSequenceNumber()); }