FastRestore:addPrefix:Transform must clear both orignal and transformed range

Otherwise, anything left in the range can interfer with the result.
This commit is contained in:
Meng Xu 2020-06-21 22:18:07 -07:00
parent 9318ec033d
commit 3d6f69c8e2
4 changed files with 26 additions and 7 deletions

View File

@ -257,6 +257,8 @@ struct RestoreAsset {
return ss.str();
}
bool hasPrefix() const { return addPrefix.size() > 0 || removePrefix.size() > 0; }
// RestoreAsset and VersionBatch both use endVersion as exclusive in version range
bool isInVersionRange(Version commitVersion) const {
return commitVersion >= beginVersion && commitVersion < endVersion;
@ -264,11 +266,24 @@ struct RestoreAsset {
// Is mutation's begin and end keys are in RestoreAsset's range
bool isInKeyRange(MutationRef mutation) const {
if (isRangeMutation(mutation)) {
// Range mutation's right side is exclusive
return mutation.param1 >= range.begin && mutation.param2 <= range.end;
if (hasPrefix()) {
Key begin = range.begin; // Avoid creating new keys if we do not have addPrefix or removePrefix
Key end = range.end;
begin = begin.removePrefix(removePrefix).withPrefix(addPrefix);
end = end.removePrefix(removePrefix).withPrefix(addPrefix);
if (isRangeMutation(mutation)) {
// Range mutation's right side is exclusive
return mutation.param1 >= begin && mutation.param2 <= end;
} else {
return mutation.param1 >= begin && mutation.param1 < end;
}
} else {
return mutation.param1 >= range.begin && mutation.param1 < range.end;
if (isRangeMutation(mutation)) {
// Range mutation's right side is exclusive
return mutation.param1 >= range.begin && mutation.param2 <= range.end;
} else {
return mutation.param1 >= range.begin && mutation.param1 < range.end;
}
}
}
};

View File

@ -147,7 +147,8 @@ ACTOR static Future<Void> handleSendMutationVectorRequest(RestoreSendVersionedMu
isAtomicOp((MutationRef::Type)versionedMutation.mutation.type) ? 1 : 0;
// Sanity check
ASSERT_WE_THINK(req.asset.isInVersionRange(versionedMutation.version.version));
ASSERT_WE_THINK(req.asset.isInKeyRange(versionedMutation.mutation));
ASSERT_WE_THINK(req.asset.isInKeyRange(
versionedMutation.mutation)); // mutation is already applied removePrefix and addPrefix
// Note: Log and range mutations may be delivered out of order. Can we handle it?
batchData->addMutation(versionedMutation.mutation, versionedMutation.version);

View File

@ -793,7 +793,7 @@ void _parseSerializedMutation(KeyRangeMap<Version>* pRangeVersions,
(!isRangeMutation(mutation) && mutation.param1 < asset.range.begin)) {
continue;
}
// Only apply mutation within the asset.range
// Only apply mutation within the asset.range and apply removePrefix and addPrefix
if (isRangeMutation(mutation)) {
mutation.param1 = mutation.param1 >= asset.range.begin ? mutation.param1 : asset.range.begin;
mutation.param2 = mutation.param2 < asset.range.end ? mutation.param2 : asset.range.end;

View File

@ -381,7 +381,10 @@ struct BackupAndParallelRestoreCorrectnessWorkload : TestWorkload {
tr->setOption(FDBTransactionOptions::LOCK_AWARE);
for (auto& range : restoreRanges) {
TraceEvent("TransformDatabaseContents").detail("Clear", range);
tr->clear(range); // Careful when we restore only a sub key range!
tr->clear(range); // Clear the range.removePrefix().withPrefix()
KeyRange newRange = range;
newRange = newRange.removePrefix(removePrefix).withPrefix(addPrefix); // Clear dest. range
tr->clear(newRange);
}
return Void();
}));