From e273f5767cad168941644713d39b34e81b6aaaba Mon Sep 17 00:00:00 2001 From: Marek Blaha Date: Tue, 17 Sep 2024 13:36:34 +0200 Subject: [PATCH] RepoSack: New API to reload system repo Introduce a new API to clear all solvables from the system repo and reload fresh data from the RPM database. Re-creating the Base object can be resource-intensive, and there is a use case in dnfdaemon where the current session (which wraps around the Base instance) needs to be reused even after executing an RPM transaction - whether for queries or running another transaction. --- include/libdnf5/repo/repo.hpp | 7 ++++++- include/libdnf5/repo/repo_sack.hpp | 3 +++ libdnf5/repo/repo.cpp | 22 ++++++++++++++++------ libdnf5/repo/repo_sack.cpp | 4 ++++ libdnf5/repo/solv_repo.cpp | 5 +++++ libdnf5/repo/solv_repo.hpp | 4 ++++ 6 files changed, 38 insertions(+), 7 deletions(-) diff --git a/include/libdnf5/repo/repo.hpp b/include/libdnf5/repo/repo.hpp index 425982882..433056d9c 100644 --- a/include/libdnf5/repo/repo.hpp +++ b/include/libdnf5/repo/repo.hpp @@ -319,11 +319,16 @@ class LIBDNF_API Repo { friend class PackageDownloader; friend class solv::Pool; - /// Loads the repository objects into sacks. + /// Loads the repository objects into sacks. Only the first call actually loads the repo. /// /// Also writes the libsolv's solv/solvx cache files. LIBDNF_LOCAL void load(); + /// Empties currently loaded repo and loads it again. + LIBDNF_LOCAL void reload(); + + LIBDNF_LOCAL void _load(); + /// Downloads repository metadata. // @replaces libdnf:repo/Repo.hpp:method:Repo.downloadMetadata(const std::string & destdir) LIBDNF_LOCAL void download_metadata(const std::string & destdir); diff --git a/include/libdnf5/repo/repo_sack.hpp b/include/libdnf5/repo/repo_sack.hpp index 416ed5eb4..769b5afcb 100644 --- a/include/libdnf5/repo/repo_sack.hpp +++ b/include/libdnf5/repo/repo_sack.hpp @@ -91,6 +91,9 @@ class LIBDNF_API RepoSack : public sack::Sack { /// @return The system repository. libdnf5::repo::RepoWeakPtr get_system_repo(); + /// Reloads the system repository. If the system repository has not been created yet, it will create and load it. + void reload_system_repo(); + /// Add given paths to comdline repository. /// @param paths Vector of paths to rpm files to be inserted to cmdline repo. Can contain paths to local files or URLs of remote rpm files. Specifications that are neither file paths, nor URLs are ignored. /// @param calculate_checksum Whether libsolv should calculate and store checksum of added packages. Setting to true significantly reduces performance. diff --git a/libdnf5/repo/repo.cpp b/libdnf5/repo/repo.cpp index c621eab67..c9c9822ac 100644 --- a/libdnf5/repo/repo.cpp +++ b/libdnf5/repo/repo.cpp @@ -216,12 +216,7 @@ void Repo::download_metadata(const std::string & destdir) { p_impl->downloader->download_metadata(destdir); } -void Repo::load() { - // Each repository can only be loaded once. This one has already loaded, so just return instantly - if (is_loaded()) { - return; - } - +void Repo::_load() { make_solv_repo(); if (p_impl->type == Type::AVAILABLE) { @@ -234,6 +229,21 @@ void Repo::load() { p_impl->base->get_rpm_package_sack()->p_impl->invalidate_provides(); } +void Repo::load() { + // Each repository can only be loaded once. This one has already loaded, so just return instantly + if (is_loaded()) { + return; + } + _load(); +} + +void Repo::reload() { + if (p_impl->solv_repo) { + p_impl->solv_repo->empty(); + } + _load(); +} + void Repo::add_libsolv_testcase(const std::string & path) { make_solv_repo(); diff --git a/libdnf5/repo/repo_sack.cpp b/libdnf5/repo/repo_sack.cpp index 4dd6cabc2..000c70fd5 100644 --- a/libdnf5/repo/repo_sack.cpp +++ b/libdnf5/repo/repo_sack.cpp @@ -286,6 +286,10 @@ RepoWeakPtr RepoSack::get_system_repo() { return p_impl->system_repo->get_weak_ptr(); } +void RepoSack::reload_system_repo() { + get_system_repo()->reload(); +} + /** * * @param repos Set of repositories to load diff --git a/libdnf5/repo/solv_repo.cpp b/libdnf5/repo/solv_repo.cpp index b41e37b5f..b9c67d959 100644 --- a/libdnf5/repo/solv_repo.cpp +++ b/libdnf5/repo/solv_repo.cpp @@ -792,4 +792,9 @@ void SolvRepo::create_environment_solvable( repodata_internalize(data); } +void SolvRepo::empty() { + // TODO(mblaha): is resuseid=true safe enough? + repo_empty(repo, true); +} + } // namespace libdnf5::repo diff --git a/libdnf5/repo/solv_repo.hpp b/libdnf5/repo/solv_repo.hpp index f3f9b822a..6099ae017 100644 --- a/libdnf5/repo/solv_repo.hpp +++ b/libdnf5/repo/solv_repo.hpp @@ -120,6 +120,10 @@ class SolvRepo { /// @return True if the group was successfully read. bool read_group_solvable_from_xml(const std::string & path); + /// Free all solvables in the repository. The repository will be empty + /// after this call. + void empty(); + private: // "type_name == nullptr" means load "primary" cache (.solv file) bool load_solv_cache(solv::Pool & pool, const char * type_name, int flags);