Store number of entries at beginning of integrity file, so loading can be faster using unordered_map::reserve()

This commit is contained in:
Sebastian Messmer 2016-06-21 23:54:03 -07:00
parent adb10343d2
commit de692c1ee4
2 changed files with 23 additions and 12 deletions

View File

@ -59,33 +59,33 @@ void KnownBlockVersions::_loadStateFile() {
_checkHeader(&file);
file.read((char*)&_myClientId, sizeof(_myClientId));
ASSERT(file.good(), "Error reading file");
uint64_t numEntries;
file.read((char*)&numEntries, sizeof(numEntries));
ASSERT(file.good(), "Error reading file");
_knownVersions.clear();
optional<pair<Key, uint64_t>> entry = _readEntry(&file);
while(none != entry) {
_knownVersions.insert(*entry);
entry = _readEntry(&file);
_knownVersions.reserve(static_cast<uint64_t>(1.2 * numEntries)); // Reserve for factor 1.2 more, so the file system doesn't immediately have to resize it on the first new block.
for (uint64_t i = 0 ; i < numEntries; ++i) {
auto entry = _readEntry(&file);
_knownVersions.insert(entry);
}
ASSERT(file.eof(), "Didn't read until end of file");
_checkIsEof(&file);
};
void KnownBlockVersions::_checkHeader(std::ifstream *file) {
char actualHeader[HEADER.size()];
file->read(actualHeader, HEADER.size());
ASSERT(file->good(), "Error reading file");
if (HEADER != string(actualHeader, HEADER.size())) {
throw std::runtime_error("Invalid local state: Invalid integrity file header.");
}
}
optional<pair<Key, uint64_t>> KnownBlockVersions::_readEntry(std::ifstream *file) {
ASSERT(file->good(), "Error reading file");
pair<Key, uint64_t> KnownBlockVersions::_readEntry(std::ifstream *file) {
pair<Key, uint64_t> result(Key::Null(), 0);
file->read((char*)result.first.data(), result.first.BINARY_LENGTH);
if (file->eof()) {
// Couldn't read another entry. File end.
return none;
}
ASSERT(file->good(), "Error reading file");
file->read((char*)&result.second, sizeof(result.second));
ASSERT(file->good(), "Error reading file");
@ -93,10 +93,20 @@ optional<pair<Key, uint64_t>> KnownBlockVersions::_readEntry(std::ifstream *file
return result;
};
void KnownBlockVersions::_checkIsEof(std::ifstream *file) {
char dummy;
file->read(&dummy, sizeof(dummy));
if (!file->eof()) {
throw std::runtime_error("There are more entries in the file than advertised");
}
}
void KnownBlockVersions::_saveStateFile() const {
std::ofstream file(_stateFilePath.native().c_str());
file.write(HEADER.c_str(), HEADER.size());
file.write((char*)&_myClientId, sizeof(_myClientId));
uint64_t numEntries = _knownVersions.size();
file.write((char*)&numEntries, sizeof(numEntries));
for (const auto &entry : _knownVersions) {
file.write((char*)entry.first.data(), entry.first.BINARY_LENGTH);
file.write((char*)&entry.second, sizeof(entry.second));

View File

@ -33,7 +33,8 @@ namespace blockstore {
void _loadStateFile();
static void _checkHeader(std::ifstream *file);
static boost::optional<std::pair<Key, uint64_t>> _readEntry(std::ifstream *file);
static std::pair<Key, uint64_t> _readEntry(std::ifstream *file);
static void _checkIsEof(std::ifstream *file);
void _saveStateFile() const;
DISALLOW_COPY_AND_ASSIGN(KnownBlockVersions);