use of org.apache.geode.internal.cache.persistence.PersistenceAdvisor in project geode by apache.
the class InitialImageOperation method getFromOne.
/**
* Fetch an initial image from a single recipient
*
* @param recipientSet list of candidates to fetch from
* @param targetReinitialized true if candidate should wait until initialized before responding
* @param advice
* @param recoveredRVV recovered rvv
* @return true if succeeded to get image
* @throws org.apache.geode.cache.TimeoutException
*/
GIIStatus getFromOne(Set recipientSet, boolean targetReinitialized, CacheDistributionAdvisor.InitialImageAdvice advice, boolean recoveredFromDisk, RegionVersionVector recoveredRVV) throws org.apache.geode.cache.TimeoutException {
final boolean isDebugEnabled = logger.isDebugEnabled();
if (VMOTION_DURING_GII) {
/**
* TODO (ashetkar): recipientSet may contain more than one member. Ensure only the gii-source
* member is vMotioned. The test hook may need to be placed at another point.
*/
VMotionObserverHolder.getInstance().vMotionDuringGII(recipientSet, this.region);
}
// Make sure that candidates are regarded in random order
ArrayList recipients = new ArrayList(recipientSet);
if (this.region.isUsedForSerialGatewaySenderQueue()) {
AbstractGatewaySender sender = this.region.getSerialGatewaySender();
if (sender != null) {
InternalDistributedMember primary = sender.getSenderAdvisor().advisePrimaryGatewaySender();
if (primary != null) {
recipients.remove(primary);
recipients.add(0, primary);
}
}
} else {
if (recipients.size() > 1) {
Collections.shuffle(recipients);
}
}
long giiStart = this.region.getCachePerfStats().startGetInitialImage();
InternalDistributedMember provider = null;
for (Iterator itr = recipients.iterator(); !this.gotImage && itr.hasNext(); ) {
// if we got a partial image from the previous recipient, then clear it
InternalDistributedMember recipient = (InternalDistributedMember) itr.next();
provider = recipient;
// GII is happening and is not part of the GII result.
if (region instanceof HARegion) {
try {
// if (!r.isPrimaryQueue()) {
if (!this.requestFilterInfo(recipient)) {
if (isDebugEnabled) {
logger.debug("Failed to receive interest and CQ information from {}", recipient);
}
}
// }
} catch (Exception ex) {
if (!itr.hasNext()) {
if (isDebugEnabled) {
logger.info("Failed while getting interest and CQ information from {}", recipient, ex);
}
}
continue;
}
}
PersistenceAdvisor persistenceAdvisor = this.region.getPersistenceAdvisor();
if (persistenceAdvisor != null) {
try {
persistenceAdvisor.updateMembershipView(recipient, targetReinitialized);
persistenceAdvisor.setInitializing(this.region.getPersistentID());
} catch (ReplyException e) {
if (isDebugEnabled) {
logger.debug("Failed to get membership view", e);
}
continue;
}
}
final DistributionManager dm = (DistributionManager) this.region.getDistributionManager();
boolean allowDeltaGII = true;
if (FORCE_FULL_GII || recipient.getVersionObject().compareTo(Version.GFE_80) < 0) {
allowDeltaGII = false;
}
Set keysOfUnfinishedOps = null;
RegionVersionVector received_rvv = null;
RegionVersionVector remote_rvv = null;
if (this.region.concurrencyChecksEnabled && recipient.getVersionObject().compareTo(Version.GFE_80) >= 0) {
if (internalBeforeRequestRVV != null && internalBeforeRequestRVV.getRegionName().equals(this.region.getName())) {
internalBeforeRequestRVV.run();
}
// Request the RVV from the provider and discover any operations on this
// member that have not been performed on the provider.
//
// It is important that this happens *before* the state flush. An operation
// maybe unfinished because a member crashed during distribution, or because
// it is in flight right now. If it is in flight right now, we need to make
// sure the provider receives the latest value for the operation before the
// GII really starts.
received_rvv = getRVVFromProvider(dm, recipient, targetReinitialized);
if (received_rvv == null) {
continue;
}
// remote_rvv will be filled with the versions of unfinished keys
// then if recoveredRVV is still newer than the filled remote_rvv, do fullGII
remote_rvv = received_rvv.getCloneForTransmission();
keysOfUnfinishedOps = processReceivedRVV(remote_rvv, recoveredRVV);
if (internalAfterCalculatedUnfinishedOps != null && internalAfterCalculatedUnfinishedOps.getRegionName().equals(this.region.getName())) {
internalAfterCalculatedUnfinishedOps.run();
}
if (keysOfUnfinishedOps == null) {
// if got rvv, keysOfUnfinishedOps at least will be empty
continue;
}
}
Boolean inhibitFlush = (Boolean) inhibitStateFlush.get();
if (!inhibitFlush.booleanValue() && !this.region.doesNotDistribute()) {
if (region instanceof BucketRegionQueue) {
// get the corresponding userPRs and do state flush on all of them
// TODO we should be able to do this state flush with a single
// message, but that will require changing the messaging layer,
// which has implications for a rolling upgrade.
Collection<BucketRegion> userPRBuckets = ((BucketRegionQueue) (this.region)).getCorrespondingUserPRBuckets();
if (isDebugEnabled) {
logger.debug("The parent buckets of this shadowPR region are {}", userPRBuckets);
}
for (BucketRegion parentBucket : userPRBuckets) {
if (isDebugEnabled) {
logger.debug("Going to do state flush operation on the parent bucket.");
}
final StateFlushOperation sf;
sf = new StateFlushOperation(parentBucket);
final Set<InternalDistributedMember> r = new HashSet<InternalDistributedMember>();
r.addAll(advice.replicates);
r.addAll(advice.preloaded);
r.addAll(advice.others);
r.addAll(advice.empties);
r.addAll(advice.uninitialized);
int processorType = targetReinitialized ? DistributionManager.WAITING_POOL_EXECUTOR : DistributionManager.HIGH_PRIORITY_EXECUTOR;
try {
boolean success = sf.flush(r, recipient, processorType, true);
if (!success) {
continue;
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
region.getCancelCriterion().checkCancelInProgress(ie);
return GIIStatus.NO_GII;
}
if (isDebugEnabled) {
logger.debug("Completed state flush operation on the parent bucket.");
}
}
}
final StateFlushOperation sf;
sf = new StateFlushOperation(this.region);
final Set<InternalDistributedMember> r = new HashSet<InternalDistributedMember>();
r.addAll(advice.replicates);
r.addAll(advice.preloaded);
r.addAll(advice.others);
r.addAll(advice.empties);
r.addAll(advice.uninitialized);
int processorType = targetReinitialized ? DistributionManager.WAITING_POOL_EXECUTOR : DistributionManager.HIGH_PRIORITY_EXECUTOR;
try {
boolean success = sf.flush(r, recipient, processorType, false);
if (!success) {
continue;
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
region.getCancelCriterion().checkCancelInProgress(ie);
this.region.getCachePerfStats().endNoGIIDone(giiStart);
return GIIStatus.NO_GII;
}
}
RequestImageMessage m = new RequestImageMessage();
m.regionPath = this.region.getFullPath();
m.keysOnly = false;
m.targetReinitialized = targetReinitialized;
m.setRecipient(recipient);
if (this.region.concurrencyChecksEnabled) {
if (allowDeltaGII && recoveredFromDisk) {
if (!this.region.getDiskRegion().getRVVTrusted()) {
if (isDebugEnabled) {
logger.debug("Region {} recovered without EndGII flag, do full GII", this.region.getFullPath());
}
m.versionVector = null;
} else if (keysOfUnfinishedOps.size() > MAXIMUM_UNFINISHED_OPERATIONS) {
if (isDebugEnabled) {
logger.debug("Region {} has {} unfinished operations, which exceeded threshold {}, do full GII instead", this.region.getFullPath(), keysOfUnfinishedOps.size(), MAXIMUM_UNFINISHED_OPERATIONS);
}
m.versionVector = null;
} else {
if (recoveredRVV.isNewerThanOrCanFillExceptionsFor(remote_rvv)) {
m.versionVector = null;
if (isDebugEnabled) {
logger.debug("Region {}: after filled versions of unfinished keys, recovered rvv is still newer than remote rvv:{}. recovered rvv is {}. Do full GII", this.region.getFullPath(), remote_rvv, recoveredRVV);
}
} else {
m.versionVector = recoveredRVV;
m.unfinishedKeys = keysOfUnfinishedOps;
if (isDebugEnabled) {
logger.debug("Region {} recovered with EndGII flag, rvv is {}. recovered rvv is {}. Do delta GII", this.region.getFullPath(), m.versionVector, recoveredRVV);
}
}
}
m.checkTombstoneVersions = true;
}
if (received_rvv != null) {
// pack the original RVV, then save the received one
if (internalBeforeSavedReceivedRVV != null && internalBeforeSavedReceivedRVV.getRegionName().equals(this.region.getName())) {
internalBeforeSavedReceivedRVV.run();
}
saveReceivedRVV(received_rvv);
if (internalAfterSavedReceivedRVV != null && internalAfterSavedReceivedRVV.getRegionName().equals(this.region.getName())) {
internalAfterSavedReceivedRVV.run();
}
}
}
ImageProcessor processor = new ImageProcessor(this.region.getSystem(), recipient);
dm.acquireGIIPermitUninterruptibly();
try {
m.processorId = processor.getProcessorId();
if (region.isUsedForPartitionedRegionBucket() && region.getDistributionConfig().getAckSevereAlertThreshold() > 0) {
processor.enableSevereAlertProcessing();
m.severeAlertEnabled = true;
}
// do not remove the following log statement
logger.info(LocalizedMessage.create(LocalizedStrings.InitialImageOperation_REGION_0_REQUESTING_INITIAL_IMAGE_FROM_1, new Object[] { this.region.getName(), recipient }));
dm.putOutgoing(m);
this.region.cache.getCancelCriterion().checkCancelInProgress(null);
if (internalAfterSentRequestImage != null && internalAfterSentRequestImage.getRegionName().equals(this.region.getName())) {
internalAfterSentRequestImage.run();
}
try {
processor.waitForRepliesUninterruptibly();
// review unfinished keys and remove untouched entries
if (this.region.getDataPolicy().withPersistence() && keysOfUnfinishedOps != null && !keysOfUnfinishedOps.isEmpty()) {
final DiskRegion dr = this.region.getDiskRegion();
assert dr != null;
for (Object key : keysOfUnfinishedOps) {
RegionEntry re = this.entries.getEntry(key);
if (re == null) {
continue;
}
if (logger.isTraceEnabled(LogMarker.GII)) {
logger.trace(LogMarker.GII, "Processing unfinished operation:entry={}", re);
}
DiskEntry de = (DiskEntry) re;
synchronized (de) {
DiskId id = de.getDiskId();
if (id != null && EntryBits.isRecoveredFromDisk(id.getUserBits())) {
this.region.destroyRecoveredEntry(key);
if (isDebugEnabled) {
logger.debug("Deleted unfinished keys:key={}", key);
}
}
}
}
}
continue;
} catch (InternalGemFireException ex) {
Throwable cause = ex.getCause();
if (cause instanceof org.apache.geode.cache.TimeoutException) {
throw (org.apache.geode.cache.TimeoutException) cause;
}
throw ex;
} catch (ReplyException e) {
if (!region.isDestroyed()) {
e.handleAsUnexpected();
}
} finally {
ImageState imgState = region.getImageState();
if (imgState.getClearRegionFlag()) {
// Asif : Since the operation has been completed clear flag
imgState.setClearRegionFlag(false, null);
}
// source
if (this.gcVersions != null) {
region.getGemFireCache().getTombstoneService().gcTombstones(region, this.gcVersions, false);
}
if (this.gotImage) {
RegionLogger.logGII(this.region.getFullPath(), recipient, region.getDistributionManager().getDistributionManagerId(), region.getPersistentID());
}
if (this.gotImage) {
// TODO add localizedString
logger.info("{} is done getting image from {}. isDeltaGII is {}", this.region.getName(), recipient, this.isDeltaGII);
} else {
// TODO add localizedString
logger.info("{} failed to get image from {}", this.region.getName(), recipient);
}
if (this.region.dataPolicy.withPersistence()) {
logger.info(LocalizedMessage.create(LocalizedStrings.InitialImageOperation_REGION_0_INITIALIZED_PERSISTENT_REGION_WITH_ID_1_FROM_2, new Object[] { this.region.getName(), this.region.getPersistentID(), recipient }));
}
// detection is enabled
if (!this.gotImage) {
this.region.cleanUpAfterFailedGII(recoveredFromDisk);
} else if (received_rvv != null) {
checkForUnrecordedOperations(recipient);
}
}
} finally {
dm.releaseGIIPermit();
processor.cleanup();
}
}
if (this.gotImage) {
this.region.recordEventStateFromImageProvider(provider);
this.region.getCachePerfStats().endGetInitialImage(giiStart);
if (this.isDeltaGII) {
this.region.getCachePerfStats().incDeltaGIICompleted();
}
} else {
this.region.getCachePerfStats().endNoGIIDone(giiStart);
}
return reportGIIStatus();
}
Aggregations