Check RestorableFileSet's key ranges in simulation
Ranges written in the manifest file should match with actual file content.
This commit is contained in:
parent
0e54f1ed31
commit
9bfc5bbea8
|
@ -934,5 +934,10 @@ struct StringRefReader {
|
|||
Error failure_error;
|
||||
};
|
||||
|
||||
namespace fileBackup {
|
||||
ACTOR Future<Standalone<VectorRef<KeyValueRef>>> decodeRangeFileBlock(Reference<IAsyncFile> file, int64_t offset,
|
||||
int len);
|
||||
}
|
||||
|
||||
#include "flow/unactorcompiler.h"
|
||||
#endif
|
||||
|
|
|
@ -1331,6 +1331,29 @@ public:
|
|||
return end;
|
||||
}
|
||||
|
||||
ACTOR static Future<KeyRange> getSnapshotFileKeyRange_impl(Reference<BackupContainerFileSystem> bc,
|
||||
RangeFile file) {
|
||||
state Reference<IAsyncFile> inFile = wait(bc->readFile(file.fileName));
|
||||
state bool beginKeySet = false;
|
||||
state Key beginKey;
|
||||
state Key endKey;
|
||||
state int64_t j = 0;
|
||||
for (; j < file.fileSize; j += file.blockSize) {
|
||||
int64_t len = std::min<int64_t>(file.blockSize, file.fileSize - j);
|
||||
Standalone<VectorRef<KeyValueRef>> blockData = wait(fileBackup::decodeRangeFileBlock(inFile, j, len));
|
||||
if (!beginKeySet) {
|
||||
beginKey = blockData.front().key;
|
||||
}
|
||||
endKey = blockData.back().key;
|
||||
}
|
||||
return KeyRange(KeyRangeRef(beginKey, endKey));
|
||||
}
|
||||
|
||||
Future<KeyRange> getSnapshotFileKeyRange(const RangeFile& file) final {
|
||||
ASSERT(g_network->isSimulated());
|
||||
return getSnapshotFileKeyRange_impl(Reference<BackupContainerFileSystem>::addRef(this), file);
|
||||
}
|
||||
|
||||
ACTOR static Future<Optional<RestorableFileSet>> getRestoreSet_impl(Reference<BackupContainerFileSystem> bc, Version targetVersion) {
|
||||
// Find the most recent keyrange snapshot to end at or before targetVersion
|
||||
state Optional<KeyspaceSnapshotFile> snapshot;
|
||||
|
@ -1349,6 +1372,17 @@ public:
|
|||
wait(bc->readKeyspaceSnapshot(snapshot.get()));
|
||||
restorable.ranges = std::move(results.first);
|
||||
restorable.keyRanges = std::move(results.second);
|
||||
if (g_network->isSimulated()) {
|
||||
// Sanity check key ranges
|
||||
state std::map<std::string, KeyRange>::iterator rit;
|
||||
for (rit = restorable.keyRanges.begin(); rit != restorable.keyRanges.end(); rit++) {
|
||||
auto it = std::find_if(restorable.ranges.begin(), restorable.ranges.end(),
|
||||
[file = rit->first](const RangeFile f) { return f.fileName == file; });
|
||||
ASSERT(it != restorable.ranges.end());
|
||||
KeyRange result = wait(bc->getSnapshotFileKeyRange(*it));
|
||||
ASSERT(rit->second.begin <= result.begin && rit->second.end >= result.end);
|
||||
}
|
||||
}
|
||||
|
||||
// No logs needed if there is a complete key space snapshot at the target version.
|
||||
if (snapshot.get().beginVersion == snapshot.get().endVersion &&
|
||||
|
|
|
@ -108,6 +108,12 @@ struct RangeFile {
|
|||
std::string fileName;
|
||||
int64_t fileSize;
|
||||
|
||||
RangeFile() {}
|
||||
RangeFile(Version v, uint32_t bSize, std::string name, int64_t size)
|
||||
: version(v), blockSize(bSize), fileName(name), fileSize(size) {}
|
||||
RangeFile(const RangeFile& f)
|
||||
: version(f.version), blockSize(f.blockSize), fileName(f.fileName), fileSize(f.fileSize) {}
|
||||
|
||||
// Order by version, break ties with name
|
||||
bool operator< (const RangeFile &rhs) const {
|
||||
return version == rhs.version ? fileName < rhs.fileName : version < rhs.version;
|
||||
|
@ -246,6 +252,10 @@ public:
|
|||
// Open a file for read by name
|
||||
virtual Future<Reference<IAsyncFile>> readFile(std::string name) = 0;
|
||||
|
||||
// Returns the key ranges in the snapshot file. This is an expensive function
|
||||
// and should only be used in simulation for sanity check.
|
||||
virtual Future<KeyRange> getSnapshotFileKeyRange(const RangeFile& file) = 0;
|
||||
|
||||
struct ExpireProgress {
|
||||
std::string step;
|
||||
int total;
|
||||
|
|
|
@ -717,22 +717,10 @@ ACTOR static Future<Version> collectBackupFiles(Reference<IBackupContainer> bc,
|
|||
ACTOR static Future<Void> insertRangeVersion(KeyRangeMap<Version>* pRangeVersions, RestoreFileFR* file,
|
||||
Reference<IBackupContainer> bc) {
|
||||
TraceEvent("FastRestoreMasterDecodeRangeVersion").detail("File", file->toString());
|
||||
state Reference<IAsyncFile> inFile = wait(bc->readFile(file->fileName));
|
||||
state bool beginKeySet = false;
|
||||
state Key beginKey;
|
||||
state Key endKey;
|
||||
state int64_t j = 0;
|
||||
for (; j < file->fileSize; j += file->blockSize) {
|
||||
int64_t len = std::min<int64_t>(file->blockSize, file->fileSize - j);
|
||||
Standalone<VectorRef<KeyValueRef>> blockData = wait(parallelFileRestore::decodeRangeFileBlock(inFile, j, len));
|
||||
if (!beginKeySet) {
|
||||
beginKey = blockData.front().key;
|
||||
}
|
||||
endKey = blockData.back().key;
|
||||
}
|
||||
RangeFile rangeFile(file->version, file->blockSize, file->fileName, file->fileSize);
|
||||
|
||||
// First and last key are the range for this file: endKey is exclusive
|
||||
KeyRange fileRange = KeyRangeRef(beginKey.contents(), endKey.contents());
|
||||
KeyRange fileRange = wait(bc->getSnapshotFileKeyRange(rangeFile));
|
||||
TraceEvent("FastRestoreMasterInsertRangeVersion")
|
||||
.detail("DecodedRangeFile", file->fileName)
|
||||
.detail("KeyRange", fileRange)
|
||||
|
|
Loading…
Reference in New Issue