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); _checkHeader(&file);
file.read((char*)&_myClientId, sizeof(_myClientId)); file.read((char*)&_myClientId, sizeof(_myClientId));
ASSERT(file.good(), "Error reading file"); ASSERT(file.good(), "Error reading file");
uint64_t numEntries;
file.read((char*)&numEntries, sizeof(numEntries));
ASSERT(file.good(), "Error reading file");
_knownVersions.clear(); _knownVersions.clear();
optional<pair<Key, uint64_t>> 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.
while(none != entry) { for (uint64_t i = 0 ; i < numEntries; ++i) {
_knownVersions.insert(*entry); auto entry = _readEntry(&file);
entry = _readEntry(&file); _knownVersions.insert(entry);
} }
ASSERT(file.eof(), "Didn't read until end of file");
_checkIsEof(&file);
}; };
void KnownBlockVersions::_checkHeader(std::ifstream *file) { void KnownBlockVersions::_checkHeader(std::ifstream *file) {
char actualHeader[HEADER.size()]; char actualHeader[HEADER.size()];
file->read(actualHeader, HEADER.size()); file->read(actualHeader, HEADER.size());
ASSERT(file->good(), "Error reading file");
if (HEADER != string(actualHeader, HEADER.size())) { if (HEADER != string(actualHeader, HEADER.size())) {
throw std::runtime_error("Invalid local state: Invalid integrity file header."); throw std::runtime_error("Invalid local state: Invalid integrity file header.");
} }
} }
optional<pair<Key, uint64_t>> KnownBlockVersions::_readEntry(std::ifstream *file) { pair<Key, uint64_t> KnownBlockVersions::_readEntry(std::ifstream *file) {
ASSERT(file->good(), "Error reading file");
pair<Key, uint64_t> result(Key::Null(), 0); pair<Key, uint64_t> result(Key::Null(), 0);
file->read((char*)result.first.data(), result.first.BINARY_LENGTH); 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"); ASSERT(file->good(), "Error reading file");
file->read((char*)&result.second, sizeof(result.second)); file->read((char*)&result.second, sizeof(result.second));
ASSERT(file->good(), "Error reading file"); ASSERT(file->good(), "Error reading file");
@ -93,10 +93,20 @@ optional<pair<Key, uint64_t>> KnownBlockVersions::_readEntry(std::ifstream *file
return result; 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 { void KnownBlockVersions::_saveStateFile() const {
std::ofstream file(_stateFilePath.native().c_str()); std::ofstream file(_stateFilePath.native().c_str());
file.write(HEADER.c_str(), HEADER.size()); file.write(HEADER.c_str(), HEADER.size());
file.write((char*)&_myClientId, sizeof(_myClientId)); file.write((char*)&_myClientId, sizeof(_myClientId));
uint64_t numEntries = _knownVersions.size();
file.write((char*)&numEntries, sizeof(numEntries));
for (const auto &entry : _knownVersions) { for (const auto &entry : _knownVersions) {
file.write((char*)entry.first.data(), entry.first.BINARY_LENGTH); file.write((char*)entry.first.data(), entry.first.BINARY_LENGTH);
file.write((char*)&entry.second, sizeof(entry.second)); file.write((char*)&entry.second, sizeof(entry.second));

View File

@ -33,7 +33,8 @@ namespace blockstore {
void _loadStateFile(); void _loadStateFile();
static void _checkHeader(std::ifstream *file); 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; void _saveStateFile() const;
DISALLOW_COPY_AND_ASSIGN(KnownBlockVersions); DISALLOW_COPY_AND_ASSIGN(KnownBlockVersions);