From 4fbbac95b86a58d72be37bbdb2ed561a06b84930 Mon Sep 17 00:00:00 2001 From: Christophe Date: Wed, 17 Jul 2024 14:44:38 +0200 Subject: [PATCH] vkconfig3: Add layer manifest validation caching --- vkconfig_core/configurator.cpp | 17 ++++++++++-- vkconfig_core/configurator.h | 2 ++ vkconfig_core/environment.cpp | 27 +++++++++++++++++++ vkconfig_core/environment.h | 1 + vkconfig_core/layer.cpp | 20 ++++++++------ vkconfig_core/layer.h | 6 ++++- vkconfig_core/layer_manager.cpp | 11 ++++---- vkconfig_core/layer_manager.h | 6 +++-- vkconfig_core/path.cpp | 19 ++++++++++--- vkconfig_core/path.h | 2 ++ .../test/test_configuration_built_in.cpp | 6 +++-- vkconfig_core/test/test_layer.cpp | 20 +++++++------- vkconfig_core/test/test_layer_manager.cpp | 23 ++++++++++------ 13 files changed, 119 insertions(+), 41 deletions(-) diff --git a/vkconfig_core/configurator.cpp b/vkconfig_core/configurator.cpp index 9e39aeff1c..0b2ca6edd1 100644 --- a/vkconfig_core/configurator.cpp +++ b/vkconfig_core/configurator.cpp @@ -302,15 +302,28 @@ Configurator& Configurator::Get() { Configurator::Configurator() : environment(), layers(), configurations() {} Configurator::~Configurator() { + this->UpdateLayersValidationCache(); + this->configurations.SaveAllConfigurations(); this->Surrender(); } +void Configurator::UpdateLayersValidationCache() { + this->environment.layers_validated.clear(); + + for (std::size_t i = 0, n = this->layers.Size(); i < n; ++i) { + const Layer& layer = this->layers.selected_layers[i]; + + this->environment.layers_validated.insert( + std::make_pair(layer.manifest_path.AbsolutePath(), layer.validated_last_modified)); + } +} + bool Configurator::Init() { // Load simple app settings, the additional search paths, and the // override app list. - this->layers.LoadAllInstalledLayers(); + this->layers.LoadAllInstalledLayers(environment.layers_validated); if (this->environment.has_crashed) { this->environment.has_crashed = false; @@ -373,7 +386,7 @@ bool Configurator::HasOverride() const { void Configurator::ResetToDefault(bool hard) { this->environment.Reset(Environment::CLEAR); - this->layers.LoadAllInstalledLayers(); + this->layers.LoadAllInstalledLayers(this->environment.layers_validated); this->configurations.Reset(this->layers.selected_layers); } diff --git a/vkconfig_core/configurator.h b/vkconfig_core/configurator.h index 0e50464f6d..bc5fe0117a 100644 --- a/vkconfig_core/configurator.h +++ b/vkconfig_core/configurator.h @@ -77,6 +77,8 @@ class Configurator { void BuildLoaderSettings(const ConfigurationInfo& info, const std::string& executable_path, std::vector& loader_settings_array) const; + void UpdateLayersValidationCache(); + public: Environment environment; LayerManager layers; diff --git a/vkconfig_core/environment.cpp b/vkconfig_core/environment.cpp index 244db47449..23c39abc92 100644 --- a/vkconfig_core/environment.cpp +++ b/vkconfig_core/environment.cpp @@ -37,6 +37,7 @@ #include #include +#include static const char* GetApplicationSuffix() { static const char* TABLE[] = { @@ -163,6 +164,18 @@ bool Environment::Load() { this->loader_message_types_flags |= GetLogBit(token.c_str()); } + // layers json object + const QJsonObject& json_layers_object = json_root_object.value("layers").toObject(); + const QJsonObject& json_layers_validated_object = json_layers_object.value("validated").toObject(); + + const QStringList& json_layers_validated_keys = json_layers_validated_object.keys(); + + for (int i = 0, n = json_layers_validated_keys.length(); i < n; ++i) { + const std::string& manifest_path = json_layers_validated_keys[i].toStdString(); + const std::string& last_modified = json_layers_validated_object.value(manifest_path.c_str()).toString().toStdString(); + layers_validated.insert(std::make_pair(manifest_path, last_modified)); + } + // applications json object const QJsonObject& json_applications_object = json_root_object.value("applications").toObject(); @@ -239,9 +252,17 @@ bool Environment::Load() { bool Environment::Save() const { const Path& vkconfig_init_path = ::Get(Path::INIT); + if (Path(vkconfig_init_path.AbsoluteDir()).Exists()) { + std::cout << Path(vkconfig_init_path).AbsoluteDir() << " exists." << std::endl; + } else { + std::cout << Path(vkconfig_init_path).AbsoluteDir() << " doesn't exist." << std::endl; + } QFile file(vkconfig_init_path.AbsolutePath().c_str()); const bool result = file.open(QIODevice::WriteOnly | QIODevice::Text); + if (result == false) { + std::cout << vkconfig_init_path.AbsolutePath().c_str() << std::endl; + } assert(result); QJsonObject json_root_object; @@ -309,7 +330,13 @@ bool Environment::Save() const { json_root_object.insert("applications", json_applications_object); + QJsonObject json_layers_paths_object; + for (auto it = this->layers_validated.begin(), end = this->layers_validated.end(); it != end; ++it) { + json_layers_paths_object.insert(it->first.c_str(), it->second.c_str()); + } + QJsonObject json_layers_object; + json_layers_object.insert("validated", json_layers_paths_object); json_root_object.insert("layers", json_layers_object); diff --git a/vkconfig_core/environment.h b/vkconfig_core/environment.h index e5856060d9..5122478527 100644 --- a/vkconfig_core/environment.h +++ b/vkconfig_core/environment.h @@ -115,6 +115,7 @@ class Environment { Path path_import; ConfigurationInfo global_configuration; + std::map layers_validated; private: Environment(const Environment&) = delete; diff --git a/vkconfig_core/layer.cpp b/vkconfig_core/layer.cpp index f0790aaaf2..d7c6ff9202 100644 --- a/vkconfig_core/layer.cpp +++ b/vkconfig_core/layer.cpp @@ -134,7 +134,7 @@ SettingMeta* Layer::Instantiate(SettingMetaSet& meta_set, const std::string& key return setting_meta; } -bool Layer::Load(const Path& full_path_to_file, LayerType type) { +bool Layer::Load(const Path& full_path_to_file, const std::map& layers_validated, LayerType type) { this->type = type; // Set layer type, no way to know this from the json file if (full_path_to_file.Empty()) { @@ -182,10 +182,7 @@ bool Layer::Load(const Path& full_path_to_file, LayerType type) { const QJsonObject& json_layer_object = ReadObject(json_root_object, "layer"); - std::string current_last_modified = full_path_to_file.LastModified(); - - QSettings settings; - std::string cached_last_modified = settings.value(full_path_to_file.AbsolutePath().c_str()).toString().toStdString(); + const std::string& last_modified = full_path_to_file.LastModified(); this->key = ReadStringValue(json_layer_object, "name"); @@ -197,11 +194,18 @@ bool Layer::Load(const Path& full_path_to_file, LayerType type) { JsonValidator validator; - const bool should_validate = current_last_modified != cached_last_modified; + std::string cached_last_modified; + auto it = layers_validated.find(this->manifest_path.AbsolutePath()); + if (it != layers_validated.end()) { + cached_last_modified = it->second; + } + const bool should_validate = !this->manifest_path.IsBuiltIn() && last_modified != cached_last_modified; const bool is_valid = should_validate ? validator.Check(json_text) : true; - if (should_validate && is_valid) { - settings.setValue(full_path_to_file.AbsolutePath().c_str(), current_last_modified.c_str()); + if (!is_valid) { + this->validated_last_modified.clear(); + } else { + this->validated_last_modified = last_modified; } const QJsonValue& json_library_path_value = json_layer_object.value("library_path"); diff --git a/vkconfig_core/layer.h b/vkconfig_core/layer.h index 9d049dbb75..871238dbde 100644 --- a/vkconfig_core/layer.h +++ b/vkconfig_core/layer.h @@ -59,6 +59,7 @@ class Layer { Path binary_path; Version api_version; std::string implementation_version; + std::string validated_last_modified; StatusType status; std::string description; std::string introduction; @@ -75,11 +76,14 @@ class Layer { std::vector settings; std::vector presets; - bool Load(const Path& full_path_to_file, LayerType type = LAYER_TYPE_EXPLICIT); + bool Load(const Path& full_path_to_file, const std::map& layers_validated, + LayerType type = LAYER_TYPE_EXPLICIT); private: Layer& operator=(const Layer&) = delete; + bool IsBuiltIn() const; + std::vector > memory; // Settings are deleted when all layers instances are deleted. }; diff --git a/vkconfig_core/layer_manager.cpp b/vkconfig_core/layer_manager.cpp index 52ae1b6bad..6cad7a9673 100644 --- a/vkconfig_core/layer_manager.cpp +++ b/vkconfig_core/layer_manager.cpp @@ -124,8 +124,6 @@ LayerManager::LayerManager(const std::vector &user_defined_paths) { user_defined_paths.end()); this->paths[LAYERS_PATHS_SDK].push_back(::Get(Path::SDK_BIN)); - - this->LoadAllInstalledLayers(); } void LayerManager::Clear() { this->selected_layers.clear(); } @@ -147,7 +145,7 @@ const Layer *LayerManager::Find(const std::string &layer_name) const { } // Find all installed layers on the system. -void LayerManager::LoadAllInstalledLayers() { +void LayerManager::LoadAllInstalledLayers(const std::map &layers_validated) { this->selected_layers.clear(); for (std::size_t group_index = 0, group_count = this->paths.size(); group_index < group_count; ++group_index) { @@ -155,17 +153,18 @@ void LayerManager::LoadAllInstalledLayers() { const std::vector &paths_group = this->paths[group_index]; for (std::size_t i = 0, n = paths_group.size(); i < n; ++i) { - this->LoadLayersFromPath(paths_group[i], layer_type); + this->LoadLayersFromPath(paths_group[i], layers_validated, layer_type); } } } -void LayerManager::LoadLayersFromPath(const Path &layers_path, LayerType type) { +void LayerManager::LoadLayersFromPath(const Path &layers_path, const std::map &layers_validated, + LayerType type) { const std::vector &layers_paths = layers_path.IsDir() ? CollectFilePaths(layers_path) : GetVector(layers_path); for (std::size_t i = 0, n = layers_paths.size(); i < n; ++i) { Layer layer; - if (layer.Load(layers_paths[i], type)) { + if (layer.Load(layers_paths[i], layers_validated, type)) { if (this->IsAvailable(layer)) { continue; } diff --git a/vkconfig_core/layer_manager.h b/vkconfig_core/layer_manager.h index 339a286a65..a4a33ecf4c 100644 --- a/vkconfig_core/layer_manager.h +++ b/vkconfig_core/layer_manager.h @@ -54,8 +54,10 @@ class LayerManager { Layer* Find(const std::string& layer_name); const Layer* Find(const std::string& layer_name) const; - void LoadAllInstalledLayers(); - void LoadLayersFromPath(const Path& layers_path, LayerType type = LAYER_TYPE_EXPLICIT); + void LoadAllInstalledLayers(const std::map& layers_validated); + + void LoadLayersFromPath(const Path& layers_path, const std::map& layers_validated, + LayerType type = LAYER_TYPE_EXPLICIT); std::vector selected_layers; diff --git a/vkconfig_core/path.cpp b/vkconfig_core/path.cpp index 3b136a2064..6221650d15 100644 --- a/vkconfig_core/path.cpp +++ b/vkconfig_core/path.cpp @@ -112,6 +112,8 @@ bool Path::IsFile() const { return QFileInfo(this->data.c_str()).isFile(); } bool Path::IsDir() const { return QFileInfo(this->data.c_str()).isDir(); } +bool Path::IsBuiltIn() const { return this->data.find(":") == 0; } + Path& Path::operator=(const Path& path) { this->data = path.data; return *this; @@ -223,7 +225,6 @@ static const Path GetHomePath() { } Path path(result); - if (!path.Exists()) { path.Create(); } @@ -238,7 +239,12 @@ static const Path GetAppDataPath() { }; static_assert(std::size(TABLE) == ENVIRONMENT_COUNT); - return QDir().homePath().toStdString() + TABLE[VKC_ENV]; + Path path(QDir().homePath().toStdString() + TABLE[VKC_ENV]); + if (!path.Exists()) { + path.Create(); + } + + return path; } static const Path GetInitPath() { @@ -248,7 +254,14 @@ static const Path GetInitPath() { }; static_assert(std::size(TABLE) == ENVIRONMENT_COUNT); - return GetAppDataPath().RelativePath() + TABLE[VKC_ENV]; + Path path(GetAppDataPath().RelativePath() + TABLE[VKC_ENV]); + Path folder(path.AbsoluteDir()); + + if (!folder.Exists()) { + folder.Create(); + } + + return path; } static const Path GetConfigsPath() { diff --git a/vkconfig_core/path.h b/vkconfig_core/path.h index 9ddc71bc26..4babccdcf4 100644 --- a/vkconfig_core/path.h +++ b/vkconfig_core/path.h @@ -52,6 +52,8 @@ class Path { bool IsFile() const; bool IsDir() const; + bool IsBuiltIn() const; + void Clear(); bool Exists() const; bool Create(bool as_file = false) const; diff --git a/vkconfig_core/test/test_configuration_built_in.cpp b/vkconfig_core/test/test_configuration_built_in.cpp index ca3d0f7160..8185814f2a 100644 --- a/vkconfig_core/test/test_configuration_built_in.cpp +++ b/vkconfig_core/test/test_configuration_built_in.cpp @@ -60,9 +60,11 @@ static bool operator==(const Parameter& a, const Parameter& b) { static bool operator!=(const std::vector& a, const std::vector& b) { return !(a == b); } +std::map Dummy() { return std::map(); } + struct TestBuilin { - TestBuilin() : environment(), layer_manager() { - this->layer_manager.LoadLayersFromPath(":/sdk"); + TestBuilin() : environment(Environment::MODE_UNINITIALIZED), layer_manager() { + this->layer_manager.LoadLayersFromPath(":/sdk", Dummy()); EXPECT_TRUE(!this->layer_manager.selected_layers.empty()); } diff --git a/vkconfig_core/test/test_layer.cpp b/vkconfig_core/test/test_layer.cpp index cc61f0e102..23852f2fcb 100644 --- a/vkconfig_core/test/test_layer.cpp +++ b/vkconfig_core/test/test_layer.cpp @@ -36,6 +36,8 @@ inline SettingMetaString* InstantiateString(Layer& layer, const std::string& key return static_cast(layer.Instantiate(layer.settings, key, SETTING_STRING)); } +std::map Dummy() { return std::map(); } + TEST(test_layer, collect_settings) { Layer layer; @@ -58,7 +60,7 @@ TEST(test_layer, collect_settings) { TEST(test_layer, load_header_overridden) { Layer layer; - const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_00.json", LAYER_TYPE_EXPLICIT); + const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_00.json", Dummy(), LAYER_TYPE_EXPLICIT); ASSERT_TRUE(load_loaded); EXPECT_EQ(Version(1, 2, 0), layer.file_format_version); @@ -76,7 +78,7 @@ TEST(test_layer, load_header_overridden) { TEST(test_layer, load_header_default) { Layer layer; - const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_01.json", LAYER_TYPE_EXPLICIT); + const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_01.json", Dummy(), LAYER_TYPE_EXPLICIT); ASSERT_TRUE(load_loaded); EXPECT_EQ(Version(1, 2, 0), layer.file_format_version); @@ -94,7 +96,7 @@ TEST(test_layer, load_header_default) { TEST(test_layer, load_header_override) { Layer layer; - const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_02.json", LAYER_TYPE_EXPLICIT); + const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_02.json", Dummy(), LAYER_TYPE_EXPLICIT); ASSERT_TRUE(load_loaded); EXPECT_EQ(Version(1, 2, 0), layer.file_format_version); @@ -106,7 +108,7 @@ TEST(test_layer, load_header_override) { TEST(test_layer, load_setting_interit) { Layer layer; - const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_03.json", LAYER_TYPE_EXPLICIT); + const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_03.json", Dummy(), LAYER_TYPE_EXPLICIT); ASSERT_TRUE(load_loaded); EXPECT_EQ(Version(1, 2, 0), layer.file_format_version); @@ -128,7 +130,7 @@ TEST(test_layer, load_setting_interit) { TEST(test_layer, load_preset_interit) { Layer layer; - const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_04.json", LAYER_TYPE_EXPLICIT); + const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_04.json", Dummy(), LAYER_TYPE_EXPLICIT); ASSERT_TRUE(load_loaded); EXPECT_EQ(Version(1, 2, 0), layer.file_format_version); @@ -148,7 +150,7 @@ TEST(test_layer, load_preset_interit) { TEST(test_layer, load_setting_children_interit) { Layer layer; - const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_05.json", LAYER_TYPE_EXPLICIT); + const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_05.json", Dummy(), LAYER_TYPE_EXPLICIT); ASSERT_TRUE(load_loaded); EXPECT_EQ(Version(1, 2, 0), layer.file_format_version); @@ -170,7 +172,7 @@ TEST(test_layer, load_setting_children_interit) { TEST(test_layer, load_setting_enum_interit) { Layer layer; - const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_06.json", LAYER_TYPE_EXPLICIT); + const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_test_06.json", Dummy(), LAYER_TYPE_EXPLICIT); ASSERT_TRUE(load_loaded); EXPECT_EQ(Version(1, 2, 0), layer.file_format_version); @@ -212,7 +214,7 @@ TEST(test_layer, load_setting_enum_interit) { TEST(test_layer, load_1_1_0_header) { Layer layer; - const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_reference_1_1_0.json", LAYER_TYPE_EXPLICIT); + const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_reference_1_1_0.json", Dummy(), LAYER_TYPE_EXPLICIT); ASSERT_TRUE(load_loaded); EXPECT_EQ(Version(1, 1, 0), layer.file_format_version); @@ -230,7 +232,7 @@ TEST(test_layer, load_1_1_0_header) { TEST(test_layer, load_1_2_0_preset_and_setting_type) { Layer layer; - const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_reference_1_2_0.json", LAYER_TYPE_EXPLICIT); + const bool load_loaded = layer.Load(":/layers/VK_LAYER_LUNARG_reference_1_2_0.json", Dummy(), LAYER_TYPE_EXPLICIT); ASSERT_TRUE(load_loaded); // Preset Enum diff --git a/vkconfig_core/test/test_layer_manager.cpp b/vkconfig_core/test/test_layer_manager.cpp index b81e10f6c0..ce40a13157 100644 --- a/vkconfig_core/test/test_layer_manager.cpp +++ b/vkconfig_core/test/test_layer_manager.cpp @@ -19,12 +19,14 @@ */ #include "../layer_manager.h" +#include "../environment.h" #include +std::map Dummy() { return std::map(); } + TEST(test_layer_manager, clear) { LayerManager layer_manager; - layer_manager.Clear(); EXPECT_TRUE(layer_manager.Empty()); EXPECT_TRUE(layer_manager.Size() == 0); @@ -34,7 +36,10 @@ TEST(test_layer_manager, load_all) { std::vector user_defined_paths; user_defined_paths.push_back(":/layers"); + Environment environment; + LayerManager layer_manager(user_defined_paths); + layer_manager.LoadAllInstalledLayers(environment.layers_validated); EXPECT_TRUE(layer_manager.Size() >= 10); EXPECT_TRUE(!layer_manager.Empty()); @@ -45,10 +50,9 @@ TEST(test_layer_manager, load_all) { TEST(test_layer_manager, load_dir) { LayerManager layer_manager; - layer_manager.Clear(); EXPECT_TRUE(layer_manager.Empty()); - layer_manager.LoadLayersFromPath(":/layers"); + layer_manager.LoadLayersFromPath(":/layers", Dummy()); EXPECT_TRUE(!layer_manager.Empty()); EXPECT_EQ(10, layer_manager.Size()); @@ -61,10 +65,9 @@ TEST(test_layer_manager, load_dir) { TEST(test_layer_manager, load_file) { LayerManager layer_manager; - layer_manager.Clear(); EXPECT_TRUE(layer_manager.Empty()); - layer_manager.LoadLayersFromPath(":/layers/VK_LAYER_LUNARG_reference_1_1_0.json"); + layer_manager.LoadLayersFromPath(":/layers/VK_LAYER_LUNARG_reference_1_1_0.json", Dummy()); EXPECT_TRUE(!layer_manager.Empty()); EXPECT_EQ(1, layer_manager.Size()); @@ -79,7 +82,12 @@ TEST(test_layer_manager, find) { std::vector user_defined_paths; user_defined_paths.push_back(":/layers"); + Environment environment; + LayerManager layer_manager(user_defined_paths); + EXPECT_TRUE(layer_manager.Empty()); + + layer_manager.LoadAllInstalledLayers(environment.layers_validated); EXPECT_TRUE(layer_manager.Find("VK_LAYER_LUNARG_reference_1_1_0") != nullptr); EXPECT_TRUE(layer_manager.Find("VK_LAYER_LUNARG_test_03") != nullptr); @@ -87,12 +95,11 @@ TEST(test_layer_manager, find) { TEST(test_layer_manager, avoid_duplicate) { LayerManager layer_manager; - layer_manager.Clear(); EXPECT_TRUE(layer_manager.Empty()); - layer_manager.LoadLayersFromPath(":/layers"); + layer_manager.LoadLayersFromPath(":/layers", Dummy()); EXPECT_EQ(10, layer_manager.Size()); - layer_manager.LoadLayersFromPath(":/layers"); + layer_manager.LoadLayersFromPath(":/layers", Dummy()); EXPECT_EQ(10, layer_manager.Size()); }