private void compareVersions(Map<String, VersionTag<VersionSource<?>>> versions, InternalDistributedMember defaultID, List<InternalDistributedMember> vmIds, List<RegionVersionVector<VersionSource<?>>> versionVectors) { for (Map.Entry<String, VersionTag<VersionSource<?>>> entry : versions.entrySet()) { VersionTag<VersionSource<?>> tag = entry.getValue(); tag.replaceNullIDs(defaultID); for (int i = 0; i < vmIds.size(); i++) { assertThat(versionVectors.get(i).contains(tag.getMemberID(), tag.getRegionVersion())) .describedAs( vmIds.get(i) + " should contain " + tag) .isTrue(); } } }
@Override public String toString() { if (this.isLiveVector) { return "RegionVersionVector{rv" + this.localVersion + " gc" + this.localGCVersion + "}@" + System.identityHashCode(this); } else { return fullToString(); } }
/** initializes a new version vector for this region */ private RegionVersionVector createVersionVector() { RegionVersionVector regionVersionVector = RegionVersionVector.create(getVersionMember(), this); if (this.getDataPolicy().withPersistence()) { // copy the versions that we have recovered from disk into // the version vector. RegionVersionVector diskVector = diskRegion.getRegionVersionVector(); regionVersionVector.recordVersions(diskVector.getCloneForTransmission()); } else if (!this.getDataPolicy().withStorage()) { // version vectors are currently only necessary in empty regions for // tracking canonical member IDs regionVersionVector.turnOffRecordingForEmptyRegion(); } if (serverRegionProxy != null) { regionVersionVector.setIsClientVector(); } cache.getDistributionManager().addMembershipListener(regionVersionVector); return regionVersionVector; }
/** * Update the on disk GC version for the given member, only if the disk has actually recorded all * of the updates including that member. * * @param diskRVV the RVV for what has been persisted * @param inMemoryRVV the RVV of what is in memory * @param member The member we're trying to update */ private void updateDiskGCRVV(RegionVersionVector diskRVV, RegionVersionVector inMemoryRVV, VersionSource member) { long diskVersion = diskRVV.getVersionForMember(member); long memoryGCVersion = inMemoryRVV.getGCVersion(member); // If the GC version is less than what we have on disk, go ahead // and record it. if (memoryGCVersion <= diskVersion) { diskRVV.recordGCVersion(member, memoryGCVersion); } }
/** * return the next local version number */ private long getNextVersion(boolean checkLocked) { if (checkLocked && this.locked) { // this should never be the case. If version generation is locked and we get here // then the path to this point is not protected by getting the version generation // lock from the RVV but it should be if (logger.isDebugEnabled()) { logger.debug("Generating a version tag when version generation is locked by {}", this.lockOwner); } } long new_version = localVersion.incrementAndGet(); // since there could be special exception, we have to use recordVersion() recordVersion(getOwnerId(), new_version); return new_version; }
/** * For test purposes, see if two RVVs have seen the same events and GC version vectors * * @return true if the RVVs are the same. */ public boolean sameAs(RegionVersionVector<T> other) { // Compare the version version vectors Map<T, RegionVersionHolder<T>> myMemberToVersion = getMemberToVersion(); Map<T, RegionVersionHolder<T>> otherMemberToVersion = other.getMemberToVersion(); if (!myMemberToVersion.keySet().equals(otherMemberToVersion.keySet())) { return false; } for (Iterator<T> it = myMemberToVersion.keySet().iterator(); it.hasNext();) { T key = it.next(); if (!myMemberToVersion.get(key).sameAs(otherMemberToVersion.get(key))) { return false; } } Map<T, Long> myGCVersion = getMemberToGCVersion(); Map<T, Long> otherGCVersion = other.getMemberToGCVersion(); if (!myGCVersion.equals(otherGCVersion)) { return false; } return true; }
rv1.recordVersion(server2, 1); rv1.recordVersion(server2, 5); rv1.recordVersion(server2, 8); System.out.println("for test (a) formed this RVV: " + rv1.fullToString()); assertEquals(8, rv1.getVersionForMember(server2)); assertEquals(2, rv1.getExceptionCount(server2)); rv1.recordVersion(server2, 3); System.out.println("for test (a) RVV is now: " + rv1.fullToString()); assertEquals(8, rv1.getVersionForMember(server2)); assertEquals(2, rv1.getExceptionCount(server2)); rv1.recordVersion(server2, 4); rv1.recordVersion(server2, 2); System.out.println("for test (a) RVV is now: " + rv1.fullToString()); assertEquals(1, rv1.getExceptionCount(server2)); rv1.recordVersion(server2, 6); rv1.recordVersion(server2, 7); System.out.println("for test (a) RVV is now: " + rv1.fullToString()); assertEquals(0, rv1.getExceptionCount(server2)); rv1.recordVersion(server2, 1); rv1.recordVersion(server2, 5); rv1.recordVersion(server2, 8); rv1.recordVersion(server2, 10); System.out.println("for test (b) formed this RVV: " + rv1.fullToString()); assertTrue(rv1.contains(server2, 1)); assertTrue(rv1.contains(server2, 5)); assertTrue(rv1.contains(server2, 8)); assertTrue(rv1.contains(server2, 10));
rv1.updateLocalVersion(10); rv1.recordVersion(server2, 1); rv1.recordVersion(server2, 5); rv1.recordVersion(server2, 8); rv1.recordVersion(server3, 1); rv1.recordVersion(server3, 3); RegionVersionVector singletonRVV = rv1.getCloneForTransmission(server2); assertTrue(singletonRVV.isForSynchronization()); assertEquals(singletonRVV.getOwnerId(), server1); assertTrue(singletonRVV.getMemberToVersion().containsKey(server2)); assertFalse(singletonRVV.getMemberToVersion().containsKey(server3)); assertTrue(singletonRVV.contains(server1, 1)); assertTrue(singletonRVV.contains(server1, 11)); assertTrue(singletonRVV.contains(server3, 1)); assertTrue(singletonRVV.contains(server3, 11)); assertTrue(singletonRVV.contains(server2, 1)); assertTrue(singletonRVV.contains(server2, 5)); assertTrue(singletonRVV.contains(server2, 8)); assertFalse(singletonRVV.contains(server2, 2)); assertFalse(singletonRVV.contains(server2, 3)); assertFalse(singletonRVV.contains(server2, 4)); assertFalse(singletonRVV.contains(server2, 6)); assertFalse(singletonRVV.contains(server2, 7)); assertFalse(singletonRVV.contains(server2, 9));
if (this.versionVector.isForSynchronization() && !rgn.getConcurrencyChecksEnabled()) { if (isGiiDebugEnabled) { logger.trace(LogMarker.INITIAL_IMAGE_VERBOSE, rgn.getVersionVector().fullToString()); if (!rgn.getVersionVector().isNewerThanOrCanFillExceptionsFor(this.versionVector)) { "version vector reports that I have nothing that the requester hasn't already seen"); replyNoData(dm, true, rgn.getVersionVector().getMemberToGCVersion()); sendFailureMessage = false; return; dm.getMembershipManager().waitForDeparture(this.lostMemberID); RegionVersionHolder rvh = rgn.getVersionVector().getHolderForMember(this.lostMemberVersionID); if (rvh != null) { holderToSync = rvh.clone(); this.versionVector.getHolderForMember(this.lostMemberVersionID); if (holderToSync.isNewerThanOrCanFillExceptionsFor(holderOfRequest)) { logger.trace(LogMarker.INITIAL_IMAGE_VERBOSE, RegionVersionVector rvv = rgn.getVersionVector().getCloneForTransmission(); RegionStateMessage.send(dm, getSender(), this.processorId, rvv, false);
for (Map.Entry<T, RegionVersionHolder<T>> entry : otherVector.getMemberToVersion() .entrySet()) { T mbr = entry.getKey(); RegionVersionHolder<T> otherHolder = entry.getValue(); initializeVersionHolder(mbr, otherHolder); otherVector.syncLocalVersion(); initializeVersionHolder(otherVector.getOwnerId(), otherVector.localExceptions); if (otherVector.getCurrentVersion() > 0 && !this.memberToVersion.containsKey(otherVector.getOwnerId())) { recordVersion(otherVector.getOwnerId(), otherVector.getCurrentVersion()); && !mbr.equals(otherVector.getOwnerId())) { RegionVersionHolder holder = this.memberToVersion.get(mbr); initializeVersionHolder(mbr, new RegionVersionHolder(0)); && !myId.equals(otherVector.getOwnerId())) { initializeVersionHolder(myId, new RegionVersionHolder(0)); for (Map.Entry<T, Long> entry : otherVector.getMemberToGCVersion().entrySet()) { T member = entry.getKey(); Long value = entry.getValue();
logger.trace(LogMarker.RVV_VERBOSE, "waiting for my version vector to dominate{}mine={}{} other={}", getLineSeparator(), getLineSeparator(), this.versionVector.fullToString(), rvv); boolean result = this.versionVector.waitToDominate(rvv, this); if (!result) { if (isRvvDebugEnabled) { logger.trace(LogMarker.RVV_VERBOSE, "incrementing clearTimeouts for {} rvv={}", getName(), this.versionVector.fullToString()); tag.setRegionVersion(myVector.getNextVersionWhileLocked()); if (isRvvDebugEnabled) { logger.trace(LogMarker.RVV_VERBOSE, "generated version tag for clear: {}", tag); myVector.recordVersion(tag.getMemberID(), tag); myVector.removeOldVersions(); myVector.removeOldMembers(remainingIDs);
m.versionVector = this.region.getVersionVector().getCloneForTransmission(lostMemberVersionID); m.lostMemberVersionID = lostMemberVersionID; m.lostMemberID = lostMember; } else { m.versionVector = this.region.getVersionVector().getCloneForTransmission(); target, lostMember); long hisVersion = this.region.getVersionVector().getVersionForMember(lostMemberVersionID); this.region.getVersionVector().removeExceptionsFor(target, hisVersion); RegionVersionHolder holder = this.region.getVersionVector().getHolderForMember(lostMemberVersionID); if (this.rcvd_holderToSync != null && this.rcvd_holderToSync.isNewerThanOrCanFillExceptionsFor(holder)) { "synchronizeWith detected mismatch region version holder for lost member {}. Old is {}, new is {}", lostMemberVersionID, holder, this.rcvd_holderToSync); this.region.getVersionVector().initializeVersionHolder(lostMemberVersionID, this.rcvd_holderToSync);
@Test public void usesOldVersionIfGreaterThanNewVersion() throws Exception { VersionSource<InternalDistributedMember> ownerId = mock(VersionSource.class); long oldVersion = 2; long newVersion = 1; RegionVersionVector rvv = new TestableRegionVersionVector(ownerId, oldVersion); rvv.updateLocalVersion(newVersion); assertThat(rvv.getVersionForMember(ownerId)).isEqualTo(oldVersion); }
&& localRVV.isNewerThanOrCanFillExceptionsFor(remoteRVV)) { id = myId; if (!remoteRVV.contains(id, stamp.getRegionVersion())) { remoteRVV.recordVersion(id, stamp.getRegionVersion());
void cmnClearRegion(RegionEventImpl regionEvent, boolean cacheWrite, boolean useRVV) { RegionVersionVector rvv = null; if (useRVV && this.getDataPolicy().withReplication() && this.getConcurrencyChecksEnabled()) { rvv = this.versionVector.getCloneForTransmission(); } clearRegionLocally(regionEvent, cacheWrite, rvv); }
/** * Since version vectors aren't java.io.Serializable we use DataSerializer to return a serialized * form of the vector */ private static byte[] getCCRegionVersionVector() throws Exception { Object id = getMemberId(); int vm = VM.getCurrentVMNum(); logger.info( "vm" + vm + " with id " + id + " copying " + CCRegion.getVersionVector().fullToString()); RegionVersionVector vector = CCRegion.getVersionVector().getCloneForTransmission(); logger.info("clone is " + vector); HeapDataOutputStream dos = new HeapDataOutputStream(3000, Version.CURRENT); DataSerializer.writeObject(vector, dos); byte[] bytes = dos.toByteArray(); logger.info("serialized size is " + bytes.length); return bytes; }
logger.trace(LogMarker.PERSIST_WRITES_VERBOSE, "serializeRVVs: isGCRVV={} drId={} rvv={} oplog#{}", gcRVV, diskRegionID, rvv.fullToString(), getOplogId()); Map<VersionSource, Long> memberToVersion = rvv.getMemberToGCVersion(); InternalDataSerializer.writeUnsignedVL(memberToVersion.size(), out); for (Entry<VersionSource, Long> memberEntry : memberToVersion.entrySet()) { Map<VersionSource, RegionVersionHolder> memberToVersion = rvv.getMemberToVersion(); InternalDataSerializer.writeUnsignedVL(memberToVersion.size(), out); for (Map.Entry<VersionSource, RegionVersionHolder> memberEntry : memberToVersion
rvv.recordVersion(rvv.getOwnerId(), nextRegionVersion); if (logger.isDebugEnabled()) { logger.debug("recorded region version {}; region={}", nextRegionVersion, tag.setRegionVersion(region.getVersionVector().getNextVersion());
public boolean goWithFullGII(DistributedRegion rgn, RegionVersionVector requesterRVV) { if (getSender().getVersionObject().compareTo(Version.GFE_80) < 0) { // pre-8.0 could not handle a delta-GII return true; } if (!rgn.getDataPolicy().withPersistence()) { // non-persistent regions always do full GII if (logger.isDebugEnabled()) { logger.debug("Region {} is not a persistent region, do full GII", rgn.getFullPath()); } return true; } if (!rgn.getVersionVector().isRVVGCDominatedBy(requesterRVV)) { if (logger.isDebugEnabled()) { logger.debug("Region {}'s local RVVGC is not dominated by remote RVV={}, do full GII", rgn.getFullPath(), requesterRVV); } return true; } return false; }
protected void saveReceivedRVV(RegionVersionVector rvv) { assert rvv != null; // Make sure the RVV is at least as current as // the provider's was when the GII began. This ensures that a // concurrent clear() doesn't prevent the new region's RVV from being // initialized and that any vector entries that are no longer represented // by stamps in the region are not lost if (logger.isTraceEnabled(LogMarker.INITIAL_IMAGE_VERBOSE)) { logger.trace(LogMarker.INITIAL_IMAGE_VERBOSE, "Applying received version vector {} to {}", rvv.fullToString(), region.getName()); } // TODO - RVV - Our current RVV might reflect some operations // that are concurrent updates. We want to keep those updates. However // it might also reflect things that we recovered from disk that we are going // to remove. We'll need to remove those from the RVV somehow. region.getVersionVector().recordVersions(rvv); if (region.getDataPolicy().withPersistence()) { region.getDiskRegion().writeRVV(region, false); region.getDiskRegion().writeRVVGC(region); } if (logger.isTraceEnabled(LogMarker.INITIAL_IMAGE_VERBOSE)) { logger.trace(LogMarker.INITIAL_IMAGE_VERBOSE, "version vector is now {}", region.getVersionVector().fullToString()); } }