public static CopyModeResult CreateCopyNoneResult(SharedProgressVectorEntry sharedProgressVectorEntry) { return(new CopyModeResult { SharedProgressVectorEntry = sharedProgressVectorEntry, SourceStartingLsn = LogicalSequenceNumber.InvalidLsn, TargetStartingLsn = LogicalSequenceNumber.InvalidLsn, CopyMode = CopyMode.None }); }
public static CopyModeResult CreatePartialCopyResult( SharedProgressVectorEntry sharedProgressVectorEntry, LogicalSequenceNumber sourceStartingLsn, LogicalSequenceNumber targetStartingLsn) { return(new CopyModeResult { SourceStartingLsn = sourceStartingLsn, TargetStartingLsn = targetStartingLsn, CopyMode = CopyMode.Partial, SharedProgressVectorEntry = sharedProgressVectorEntry }); }
public static CopyModeResult CreateFullCopyResult( SharedProgressVectorEntry sharedProgressVectorEntry, FullCopyReason reason) { Utility.Assert(reason != FullCopyReason.Invalid, "reason!= FullCopyReason.Invalid"); return(new CopyModeResult { SharedProgressVectorEntry = sharedProgressVectorEntry, SourceStartingLsn = LogicalSequenceNumber.InvalidLsn, TargetStartingLsn = LogicalSequenceNumber.InvalidLsn, CopyMode = CopyMode.Full, FullCopyReason = reason }); }
public static CopyModeResult CreateFalseProgressResult( long lastRecoveredAtomicRedoOperationLsnAtTarget, SharedProgressVectorEntry sharedProgressVectorEntry, LogicalSequenceNumber sourceStartingLsn, LogicalSequenceNumber targetStartingLsn) { if (lastRecoveredAtomicRedoOperationLsnAtTarget > sourceStartingLsn.LSN) { // Atomic Redo operations cannot be undone in false progress. // So resort to full copy return(CreateFullCopyResult(sharedProgressVectorEntry, FullCopyReason.AtomicRedoOperationFalseProgressed)); } return(new CopyModeResult { SourceStartingLsn = sourceStartingLsn, TargetStartingLsn = targetStartingLsn, CopyMode = CopyMode.FalseProgress | CopyMode.Partial, SharedProgressVectorEntry = sharedProgressVectorEntry }); }
internal static CopyModeResult FindCopyMode( CopyContextParameters sourceParamaters, CopyContextParameters targetParameters, long lastRecoveredAtomicRedoOperationLsnAtTarget) { var result = FindCopyModePrivate(sourceParamaters, targetParameters, lastRecoveredAtomicRedoOperationLsnAtTarget); if (result.CopyMode.HasFlag(CopyMode.FalseProgress)) { string failureMsg = string.Format( "(sourceStartingLsn is expected to be lesser or equal to targetStartingLsn). Source starting lsn : {0}, target starting lsn :{1} ", result.SourceStartingLsn.LSN, result.TargetStartingLsn.LSN); if (!ValidateIfDebugEnabled( result.SourceStartingLsn <= result.TargetStartingLsn, failureMsg)) { SharedProgressVectorEntry failedValidationResult = new SharedProgressVectorEntry { SourceIndex = result.SharedProgressVectorEntry.SourceIndex, TargetIndex = result.SharedProgressVectorEntry.TargetIndex, SourceProgressVectorEntry = result.SharedProgressVectorEntry.SourceProgressVectorEntry, TargetProgressVectorEntry = result.SharedProgressVectorEntry.TargetProgressVectorEntry, FullCopyReason = FullCopyReason.ValidationFailed, FailedValidationMessage = failureMsg }; return(CopyModeResult.CreateFullCopyResult( failedValidationResult, FullCopyReason.ValidationFailed)); } } return(result); }
internal static SharedProgressVectorEntry FindSharedVector( ProgressVector sourceProgressVector, ProgressVector targetProgressVector) { // Initialize indices var sourceIndex = sourceProgressVector.vectors.Count - 1; var targetIndex = targetProgressVector.vectors.Count - 1; Utility.Assert( targetProgressVector.vectors[targetIndex].Epoch.DataLossNumber <= sourceProgressVector.vectors[sourceIndex].Epoch.DataLossNumber, "targetDataLossNumber ({0}) <= sourceDataLossNumber ({1})", targetProgressVector.vectors[targetIndex].Epoch.DataLossNumber, sourceProgressVector.vectors[sourceIndex].Epoch.DataLossNumber); SharedProgressVectorEntry progrssVectorTrimmedResult = new SharedProgressVectorEntry() { FullCopyReason = FullCopyReason.ProgressVectorTrimmed }; do { bool decrementIndexSuccess = DecrementIndexUntilLeq( ref targetIndex, targetProgressVector, sourceProgressVector.vectors[sourceIndex]); if (!decrementIndexSuccess) { return(progrssVectorTrimmedResult); } decrementIndexSuccess = DecrementIndexUntilLeq( ref sourceIndex, sourceProgressVector, targetProgressVector.vectors[targetIndex]); if (!decrementIndexSuccess) { return(progrssVectorTrimmedResult); } } while (sourceProgressVector.vectors[sourceIndex] != targetProgressVector.vectors[targetIndex]); var sourceProgressVectorEntry = sourceProgressVector.vectors[sourceIndex]; var targetProgressVectorEntry = targetProgressVector.vectors[targetIndex]; // WITHOUT MINI RECONFIG ENABLED, it is not possible for the target to make VALID progress TWICE from the shared epoch // Note that this check is only valid in the absence of dataloss and restore. // E.g /* * Target Replica Copy Context: 131383889527030885 * TargetLogHeadEpoch: 0,0 TargetLogHeadLsn: 0 TargetLogTailEpoch: 131383889406148342,64424509440 TargetLogTailLSN: 73 * SourceLogHeadEpoch: 0,0 SourceLogHeadLsn: 0 SourceLogTailEpoch: 131383889406148342,68719476736 SourceLogTailLSN: 68 * Target ProgressVector: [(131383889406148342,64424509440),73,131383889527030885,2017-05-04T16:32:22] * [(131383889406148342,55834574848),68,131383889527030885,2017-05-04T16:31:54] * [(131383889406148342,51539607552),62,131383889416461059,2017-05-04T16:31:37] * [(131383889406148342,47244640256),56,131383889527030885,2017-05-04T16:31:20] * [(0,0),0,0,2017-05-04T16:29:07] * Source ProgressVector: [(131383889406148342,68719476736),68,131383890970495929,2017-05-04T16:32:33] * [(131383889406148342,60129542144),68,131383890970495929,2017-05-04T16:32:09] * [(131383889406148342,51539607552),62,131383889416461059,2017-05-04T16:31:37] * [(131383889406148342,47244640256),56,131383889527030885,2017-05-04T16:31:20] * [(0,0),0,0,2017-05-04T16:31:33] * LastRecoveredAtomicRedoOperationLsn: 0. * * * Target Replica Copy Context: 131399770096882719 * TargetLogHeadEpoch: 0,0 TargetLogHeadLsn: 0 TargetLogTailEpoch: 131399758616683034,390842023936 TargetLogTailLSN: 374 * SourceLogHeadEpoch: 0,0 SourceLogHeadLsn: 0 SourceLogTailEpoch: 131399758616683034,395136991232 SourceLogTailLSN: 369 * Target ProgressVector: * [(131399758616683034,390842023936),374,131399770096882719,2017-05-23T01:42:03] * [(131399758616683034,382252089344),374,131399770096882719,2017-05-23T01:41:29] * [(131399758616683034,377957122048),369,131399770096882719,2017-05-23T01:41:00] * [(131399758616683034,373662154752),338,131399758632647497,2017-05-23T01:40:31] * Source ProgressVector: * [(131399758616683034,395136991232),369,131399758701866693,2017-05-23T01:42:19] * [(131399758616683034,386547056640),369,131399758701866693,2017-05-23T01:41:44] * [(131399758616683034,373662154752),338,131399758632647497,2017-05-23T01:40:31] * LastRecoveredAtomicRedoOperationLsn: 0 */ string failureMsg; if (targetProgressVector.LastProgressVectorEntry.Epoch.DataLossNumber == sourceProgressVector.LastProgressVectorEntry.Epoch.DataLossNumber && targetIndex < targetProgressVector.vectors.Count - 1 && targetProgressVector.LastProgressVectorEntry.Epoch.DataLossNumber == targetProgressVector.vectors[targetIndex].Epoch.DataLossNumber) { // Target replica could only have repeatedly attempted to become a // primary without ever making progress at the shared dataloss number // We can do "double progress check" only if there has NOT been any other data loss happening on the target after shared point. Having a differnt dataloss numbers in shared vector and target's tail // means that target has been a valid primary and progressed in LSN until hitting a dataloss and then a very old secondary can become primary and invalidate all the progress made by the target. var failureLsn = targetProgressVector.vectors[targetIndex + 1].Lsn; var failureLsnIncremented = 0; for (var n = targetIndex + 2; n <= targetProgressVector.vectors.Count - 1; n++) { var vector = targetProgressVector.vectors[n]; if (vector.Epoch.DataLossNumber != targetProgressVectorEntry.Epoch.DataLossNumber) { break; } if (vector.Lsn != failureLsn) { // Update failureLsn to ensure we don't assert if there are multiple entries for same LSN like in 2nd example above failureLsn = vector.Lsn; failureLsnIncremented++; } } failureMsg = string.Format( "FailureLsn incremented must be <= 1. It is {0}", failureLsnIncremented); if (!ValidateIfDebugEnabled( failureLsnIncremented <= 1, failureMsg)) { return(new SharedProgressVectorEntry { SourceIndex = sourceIndex, TargetIndex = targetIndex, SourceProgressVectorEntry = sourceProgressVectorEntry, TargetProgressVectorEntry = targetProgressVectorEntry, FullCopyReason = FullCopyReason.ValidationFailed, FailedValidationMessage = failureMsg }); } } // Sanity check that source and target progress vectors are always in // agreement upto above determined ProgressVectorEntry shared by both of them var i = sourceIndex; var sourceEntry = sourceProgressVectorEntry; var j = targetIndex; var targetEntry = targetProgressVectorEntry; failureMsg = "sourceEntry == targetEntry"; do { sourceEntry = DecrementIndexUntilLsnIsEqual(ref i, sourceProgressVector, sourceEntry.Lsn.LSN); if (i == 0) { break; } targetEntry = DecrementIndexUntilLsnIsEqual(ref j, targetProgressVector, targetEntry.Lsn.LSN); if (j == 0) { break; } if (!ValidateIfDebugEnabled( sourceEntry == targetEntry, failureMsg)) { return(new SharedProgressVectorEntry { SourceIndex = sourceIndex, TargetIndex = targetIndex, SourceProgressVectorEntry = sourceProgressVectorEntry, TargetProgressVectorEntry = targetProgressVectorEntry, FullCopyReason = FullCopyReason.ValidationFailed, FailedValidationMessage = failureMsg }); } } while (true); Utility.Assert(sourceProgressVectorEntry != null && targetProgressVectorEntry != null, "Source and target expected to be non null"); return(new SharedProgressVectorEntry { SourceIndex = sourceIndex, TargetIndex = targetIndex, SourceProgressVectorEntry = sourceProgressVectorEntry, TargetProgressVectorEntry = targetProgressVectorEntry }); }