RegionVersionVector implements DataSerializableFixedID, MembershipListener { public void recordGCVersion(T mbr, long regionVersion) { if (mbr == null) { mbr = this.myId; } recordVersion(mbr, regionVersion); if (mbr == null || mbr.equals(this.myId)) { boolean succeeded; do { long v = localGCVersion.get(); if (v > regionVersion) { break; } succeeded = localGCVersion.compareAndSet(v, regionVersion); } while (!succeeded); } else { synchronized (this.memberToGCVersion) { Long holder = this.memberToGCVersion.get(mbr); if (holder != null) { this.memberToGCVersion.put(mbr, Math.max(regionVersion, holder)); } else { this.memberToGCVersion.put(mbr, regionVersion); } } } } 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 testRecordGCVersion() { DiskStoreID id0 = new DiskStoreID(0, 0); DiskStoreID id1 = new DiskStoreID(0, 1); DiskRegionVersionVector rvv0 = new DiskRegionVersionVector(id0); rvv0.getNextVersion(); rvv0.getNextVersion(); rvv0.getNextVersion(); rvv0.recordVersion(id1, 1); rvv0.recordVersion(id1, 3); rvv0.recordVersion(id1, 5); { Map<DiskStoreID, RegionVersionHolder<DiskStoreID>> memberToVersion = rvv0.getMemberToVersion(); RegionVersionHolder<DiskStoreID> holder1 = memberToVersion.get(id1); assertFalse(holder1.contains(2)); assertFalse(holder1.contains(4)); } rvv0.recordGCVersion(id0, 2); rvv0.recordGCVersion(id1, 3); { Map<DiskStoreID, RegionVersionHolder<DiskStoreID>> memberToVersion = rvv0.getMemberToVersion(); RegionVersionHolder<DiskStoreID> holder0 = memberToVersion.get(id0); assertTrue(holder0.getExceptionForTest().isEmpty()); } rvv0.pruneOldExceptions(); Map<DiskStoreID, RegionVersionHolder<DiskStoreID>> memberToVersion = rvv0.getMemberToVersion(); RegionVersionHolder<DiskStoreID> holder0 = memberToVersion.get(id0); RegionVersionHolder<DiskStoreID> holder1 = memberToVersion.get(id1); assertTrue(holder0.getExceptionForTest().isEmpty()); assertTrue(holder1.contains(2)); assertFalse(holder1.contains(4)); }
@Test public void recordLargeGCVersionShouldRecordSuccessfully() { DiskStoreID id0 = new DiskStoreID(0, 0); DiskStoreID id1 = new DiskStoreID(0, 1); DiskRegionVersionVector rvv0 = new DiskRegionVersionVector(id0); rvv0.recordGCVersion(id1, ((long) Integer.MAX_VALUE) - 10L); }