Cache CRCs alongside conditions

This commit is contained in:
Oliver Hamlet
2018-09-06 21:39:11 +01:00
parent 8f3432945e
commit d63b709ff2
5 changed files with 75 additions and 41 deletions
+18
View File
@@ -67,6 +67,23 @@ std::pair<bool, bool> GameCache::GetCachedCondition(
return pair<bool, bool>(false, false);
}
uint32_t GameCache::GetCachedCrc(const std::string& file) const {
lock_guard<mutex> guard(mutex_);
auto it = crcs_.find(to_lower(file));
if (it != crcs_.end()) {
return it->second;
}
return 0;
}
void GameCache::CacheCrc(const std::string& file, uint32_t crc) {
lock_guard<mutex> guard(mutex_);
crcs_.insert(pair<string, uint32_t>(to_lower(file), crc));
}
std::set<std::shared_ptr<const Plugin>> GameCache::GetPlugins() const {
std::set<std::shared_ptr<const Plugin>> output;
std::transform(
@@ -116,6 +133,7 @@ void GameCache::ClearCachedConditions() {
lock_guard<mutex> guard(mutex_);
conditions_.clear();
crcs_.clear();
}
void GameCache::ClearCachedPlugins() {
+4
View File
@@ -43,6 +43,9 @@ public:
std::pair<bool, bool> GetCachedCondition(const std::string& condition) const;
void CacheCondition(const std::string& condition, bool result);
uint32_t GetCachedCrc(const std::string& file) const;
void CacheCrc(const std::string& file, uint32_t crc);
std::set<std::shared_ptr<const Plugin>> GetPlugins() const;
std::shared_ptr<const Plugin> GetPlugin(const std::string& pluginName) const;
void AddPlugin(const Plugin&& plugin);
@@ -56,6 +59,7 @@ public:
private:
std::unordered_map<std::string, bool> conditions_;
std::unordered_map<std::string, uint32_t> crcs_;
std::unordered_map<std::string, std::shared_ptr<const Plugin>> plugins_;
std::set<boost::filesystem::path> archivePaths_;
+39 -40
View File
@@ -75,25 +75,7 @@ bool ConditionEvaluator::evaluate(const PluginCleaningData& cleaningData,
if (shouldParseOnly() || pluginName.empty())
return false;
// First need to get plugin's CRC.
uint32_t crc = 0;
// Get the CRC from the game plugin cache if possible.
try {
crc = gameCache_->GetPlugin(pluginName)->GetCRC();
} catch (...) {
}
// Otherwise calculate it from the file.
if (crc == 0) {
if (boost::filesystem::exists(dataPath_ / pluginName)) {
crc = GetCrc32(dataPath_ / pluginName);
} else if (boost::filesystem::exists(dataPath_ / (pluginName + ".ghost"))) {
crc = GetCrc32(dataPath_ / (pluginName + ".ghost"));
}
}
return cleaningData.GetCRC() == crc;
return cleaningData.GetCRC() == getCrc(pluginName);
}
PluginMetadata ConditionEvaluator::evaluateAll(
@@ -256,27 +238,7 @@ bool ConditionEvaluator::checksumMatches(const std::string& filePath,
if (shouldParseOnly())
return false;
uint32_t realChecksum = 0;
if (filePath == "LOOT")
realChecksum = GetCrc32(boost::filesystem::absolute("LOOT.exe"));
else {
// CRC could be for a plugin or a file.
// Get the CRC from the game plugin cache if possible.
try {
realChecksum = gameCache_->GetPlugin(filePath)->GetCRC();
} catch (...) {
}
if (realChecksum == 0) {
if (boost::filesystem::exists(dataPath_ / filePath))
realChecksum = GetCrc32(dataPath_ / filePath);
else if (hasPluginFileExtension(filePath, gameType_) &&
boost::filesystem::exists(dataPath_ / (filePath + ".ghost")))
realChecksum = GetCrc32(dataPath_ / (filePath + ".ghost"));
}
}
return checksum == realChecksum;
return checksum == getCrc(filePath);
}
bool ConditionEvaluator::compareVersions(const std::string& filePath,
@@ -468,4 +430,41 @@ Version ConditionEvaluator::getVersion(const std::string& filePath) const {
bool ConditionEvaluator::shouldParseOnly() const {
return gameCache_ == nullptr || loadOrderHandler_ == nullptr;
}
uint32_t ConditionEvaluator::getCrc(const std::string & file) const {
uint32_t crc = gameCache_->GetCachedCrc(file);
if (crc != 0) {
return crc;
}
if (file == "LOOT") {
crc = GetCrc32(boost::filesystem::absolute("LOOT.exe"));
gameCache_->CacheCrc(file, crc);
return crc;
}
// Get the CRC from the game plugin cache if possible.
try {
crc = gameCache_->GetPlugin(file)->GetCRC();
} catch (...) {
}
// Otherwise calculate it from the file.
if (crc == 0) {
if (boost::filesystem::exists(dataPath_ / file)) {
crc = GetCrc32(dataPath_ / file);
}
else if (hasPluginFileExtension(file, gameType_) &&
boost::filesystem::exists(dataPath_ / (file + ".ghost"))) {
crc = GetCrc32(dataPath_ / (file + ".ghost"));
}
}
if (crc != 0) {
gameCache_->CacheCrc(file, crc);
}
return crc;
}
}
+2
View File
@@ -92,6 +92,8 @@ private:
bool shouldParseOnly() const;
uint32_t getCrc(const std::string& file) const;
const GameType gameType_;
const boost::filesystem::path dataPath_;
const std::shared_ptr<GameCache> gameCache_;
+12 -1
View File
@@ -70,6 +70,15 @@ TEST_P(GameCacheTest, gettingANonCachedConditionShouldReturnAFalseFalsePair) {
EXPECT_EQ(std::make_pair(false, false), cache_.GetCachedCondition(condition));
}
TEST_P(GameCacheTest, gettingACachedCrcShouldReturnTheValue) {
cache_.CacheCrc(boost::locale::to_upper(blankEsm), 5);
EXPECT_EQ(5, cache_.GetCachedCrc(blankEsm));
}
TEST_P(GameCacheTest, gettingAnUncachedCrcShouldReturnZero) {
EXPECT_EQ(0, cache_.GetCachedCrc(blankEsm));
}
TEST_P(GameCacheTest, addingAPluginThatDoesNotExistShouldSucceed) {
cache_.AddPlugin(Plugin(game_.Type(),
game_.DataPath(),
@@ -159,13 +168,15 @@ TEST_P(GameCacheTest,
EXPECT_NO_THROW(cache_.ClearCachedConditions());
}
TEST_P(GameCacheTest, clearingCachedConditionsShouldClearAnyCachedConditions) {
TEST_P(GameCacheTest, clearingCachedConditionsShouldClearAnyCachedConditionsAndCrcs) {
EXPECT_NO_THROW(cache_.CacheCondition(condition, true));
cache_.CacheCrc(blankEsm, 5);
EXPECT_NO_THROW(cache_.ClearCachedConditions());
EXPECT_EQ(std::make_pair(false, false),
cache_.GetCachedCondition(conditionLowercase));
EXPECT_EQ(0, cache_.GetCachedCrc(blankEsm));
}
TEST_P(GameCacheTest, clearingCachedPluginsShouldNotThrowIfNoPluginsAreCached) {