RegionVersionVector implements DataSerializableFixedID, MembershipListener { public synchronized boolean isRVVGCDominatedBy(RegionVersionVector<T> requesterRVV) { if (requesterRVV.singleMember) { Map.Entry<T, RegionVersionHolder<T>> entry = requesterRVV.memberToVersion.entrySet().iterator().next(); Long gcVersion = this.memberToGCVersion.get(entry.getKey()); return isGCVersionDominatedByOtherHolder(gcVersion, entry.getValue()); } boolean isDominatedByRemote = true; long localgcversion = this.localGCVersion.get(); if (localgcversion > 0) { RegionVersionHolder<T> otherHolder = requesterRVV.memberToVersion.get(this.myId); isDominatedByRemote = isGCVersionDominatedByOtherHolder(localgcversion, otherHolder); if (isDominatedByRemote == false) { return false; } } for (Map.Entry<T, Long> entry : this.memberToGCVersion.entrySet()) { T mbr = entry.getKey(); Long gcVersion = entry.getValue(); RegionVersionHolder<T> otherHolder = null; if (mbr.equals(requesterRVV.getOwnerId())) { otherHolder = requesterRVV.localExceptions; } else { otherHolder = requesterRVV.memberToVersion.get(mbr); } isDominatedByRemote = isGCVersionDominatedByOtherHolder(gcVersion, otherHolder); if (isDominatedByRemote == false) { return false; } } return isDominatedByRemote; } protected  RegionVersionVector(T ownerId, ConcurrentHashMap<T, RegionVersionHolder<T>> vector,
      long version, ConcurrentHashMap<T, Long> gcVersions, long gcVersion, boolean singleMember,
      RegionVersionHolder<T> localExceptions);  RegionVersionVector();  RegionVersionVector(T ownerId);  RegionVersionVector(T ownerId, LocalRegion owner); @VisibleForTesting  RegionVersionVector(T ownerId, LocalRegion owner, long version); RegionVersionVector<T> getCloneForTransmission(); RegionVersionVector<T> getCloneForTransmission(T mbr); Map<T, Long> getTombstoneGCVector(); boolean containsTombstoneGCVersions(Map<T, Long> regionGCVersions); long lockForClear(String regionPath, DistributionManager dm,
      InternalDistributedMember locker); void unlockForClear(InternalDistributedMember locker); long getNextVersion(); long getNextVersionWhileLocked(); void lockForCacheModification(LocalRegion owner); void releaseCacheModificationLock(LocalRegion owner); void lockForCacheModification(); void releaseCacheModificationLock(); long getCurrentVersion(); RegionVersionHolder<T> getLocalExceptions(); RegionVersionHolder<T> getHolderForMember(T id); T getOwnerId(); void turnOffRecordingForEmptyRegion(); void setIsClientVector(); void recordVersions(RegionVersionVector<T> otherVector); void initializeVersionHolder(T mbr, RegionVersionHolder<T> otherHolder); void recordVersion(T mbr, VersionTag<T> tag); void recordVersion(T member, long version); @edu.umd.cs.findbugs.annotations.SuppressWarnings( value = "ML_SYNC_ON_FIELD_TO_GUARD_CHANGING_THAT_FIELD", justification = "sync on localExceptions guards concurrent modification but this is a replacement") void initRecoveredVersion(T member, RegionVersionHolder<T> v, boolean latestOplog); long getVersionForMember(T mbr); Set<T> getDepartedMembersSet(); boolean contains(T id, long version); void removeOldMembers(Set<VersionSource<T>> idsToKeep); boolean containsMember(T id); boolean hasHigherTombstoneGCVersions(RegionVersionVector<T> other); boolean isNewerThanOrCanFillExceptionsFor(RegionVersionVector<T> other); synchronized boolean isRVVGCDominatedBy(RegionVersionVector<T> requesterRVV); boolean waitToDominate(RegionVersionVector<T> otherVector, LocalRegion region); boolean dominates(RegionVersionVector<T> other); void removeExceptionsFor(DistributedMember mbr, long version); void removeOldVersions(); int getExceptionCount(T mbr); T getCanonicalId(T id); @Override void toData(DataOutput out,
      SerializationContext context); @Override void fromData(DataInput in,
      DeserializationContext context); void recordGCVersion(T mbr, long regionVersion); void recordGCVersions(RegionVersionVector<T> other); boolean isTombstoneTooOld(T mbr, long gcVersion); long getGCVersion(T mbr); Map<T, RegionVersionHolder<T>> getMemberToVersion(); synchronized Map<T, Long> getMemberToGCVersion(); void pruneOldExceptions(); @Override String toString(); String fullToString(); @Override void memberJoined(DistributionManager distributionManager, InternalDistributedMember id); @Override void memberSuspect(DistributionManager distributionManager, InternalDistributedMember id,
      InternalDistributedMember whoSuspected, String reason); @Override void quorumLost(DistributionManager distributionManager,
      Set<InternalDistributedMember> failures, List<InternalDistributedMember> remaining); @Override void memberDeparted(DistributionManager distributionManager,
      final InternalDistributedMember id, boolean crashed); static RegionVersionVector<?> create(boolean persistent, DataInput in); static RegionVersionVector<?> create(VersionSource<?> versionMember, LocalRegion owner); boolean sameAs(RegionVersionVector<T> other); boolean logicallySameAs(RegionVersionVector<T> other); boolean isForSynchronization(); boolean isDepartedMember(VersionSource<T> mbr); @Override KnownVersion[] getSerializationVersions(); static final boolean DEBUG; static final long MAX_DOMINANCE_WAIT_TIME; static final long DOMINANCE_PAUSE_TIME; }
@Test public void isRvvGcDominatedByRequesterRvvReturnsFalseIfRequesterRvvForLostMemberDominates() throws Exception { InternalDistributedMember lostMember = mock(InternalDistributedMember.class); ConcurrentHashMap<InternalDistributedMember, Long> memberToGcVersion = new ConcurrentHashMap<>(); memberToGcVersion.put(lostMember, new Long(1) ); RegionVersionVector providerRvv = new VMRegionVersionVector(lostMember, null, 0, memberToGcVersion, 0, true, null); ConcurrentHashMap<InternalDistributedMember, RegionVersionHolder<InternalDistributedMember>> memberToRegionVersionHolder = new ConcurrentHashMap<>(); RegionVersionHolder regionVersionHolder = new RegionVersionHolder(lostMember); memberToRegionVersionHolder.put(lostMember, regionVersionHolder); RegionVersionVector requesterRvv = new VMRegionVersionVector(lostMember, memberToRegionVersionHolder, 0, null, 0, true, null); assertThat(providerRvv.isRVVGCDominatedBy(requesterRvv)).isFalse(); }
@Test public void isRvvGcDominatedByRequesterRvvReturnsFalseIfProviderRvvIsNotPresent() throws Exception { final String local = getIPLiteral(); InternalDistributedMember provider = new InternalDistributedMember(local, 101); InternalDistributedMember requester = new InternalDistributedMember(local, 102); RegionVersionVector providerRvv = new VMRegionVersionVector(provider, null, 1, null, 1, false, null); ConcurrentHashMap<InternalDistributedMember, RegionVersionHolder<InternalDistributedMember>> memberToRegionVersionHolder = new ConcurrentHashMap<>(); RegionVersionHolder regionVersionHolder = new RegionVersionHolder(provider); RegionVersionVector requesterRvv = new VMRegionVersionVector(requester, memberToRegionVersionHolder, 0, null, 0, false, null); assertThat(providerRvv.isRVVGCDominatedBy(requesterRvv)).isFalse(); }
@Test public void isRvvGcDominatedByRequesterRvvReturnsFalseIfRequesterRvvDominatesProvider() throws Exception { final String local = getIPLiteral(); InternalDistributedMember provider = new InternalDistributedMember(local, 101); InternalDistributedMember requester = new InternalDistributedMember(local, 102); RegionVersionVector providerRvv = new VMRegionVersionVector(provider, null, 1, null, 1, false, null); ConcurrentHashMap<InternalDistributedMember, RegionVersionHolder<InternalDistributedMember>> memberToRegionVersionHolder = new ConcurrentHashMap<>(); RegionVersionHolder regionVersionHolder = new RegionVersionHolder(provider); memberToRegionVersionHolder.put(provider, regionVersionHolder); RegionVersionVector requesterRvv = new VMRegionVersionVector(requester, memberToRegionVersionHolder, 0, null, 0, false, null); assertThat(providerRvv.isRVVGCDominatedBy(requesterRvv)).isFalse(); }