From 71d3d399d7de75a96b2911677b74ce8b59579ee9 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 4 Feb 2025 18:22:35 +0100 Subject: Introduce pkgDepCache::Transaction for transactional depcache updates --- apt-pkg/depcache.cc | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++ apt-pkg/depcache.h | 38 ++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 970b4c01d..ec34d010b 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -2650,3 +2650,74 @@ unsigned long long pkgDepCache::BootSize(bool initrdOnly) return std::accumulate(sizes, sizes + MAX_ARTEFACT, off_t{0}) * BootCount * 110 / 100; } /*}}}*/ +// pkgDepCache::Transaction /*{{{*/ +struct pkgDepCache::Transaction::Private +{ + template + static T *copyArray(T *array, size_t count) + { + auto out = new T[count]; + memcpy(&out[0], &array[0], sizeof(T) * count); + return out; + } + // State information + pkgDepCache &cache; + Behavior behavior; + std::unique_ptr PkgState{copyArray(cache.PkgState, cache.GetCache().Head().PackageCount)}; + std::unique_ptr DepState{copyArray(cache.DepState, cache.GetCache().Head().DependsCount)}; + signed long long iUsrSize{cache.iUsrSize}; + unsigned long long iDownloadSize{cache.iDownloadSize}; + unsigned long iInstCount{cache.iInstCount}; + unsigned long iDelCount{cache.iDelCount}; + unsigned long iKeepCount{cache.iKeepCount}; + unsigned long iBrokenCount{cache.iBrokenCount}; + unsigned long iPolicyBrokenCount{cache.iPolicyBrokenCount}; + unsigned long iBadCount{cache.iBadCount}; + + void rollback() + { + memcpy(&cache.PkgState[0], &PkgState[0], sizeof(PkgState[0]) * cache.GetCache().Head().PackageCount); + memcpy(&cache.DepState[0], &DepState[0], sizeof(DepState[0]) * cache.GetCache().Head().DependsCount); + + cache.iUsrSize = iUsrSize; + cache.iDownloadSize = iDownloadSize; + cache.iInstCount = iInstCount; + cache.iDelCount = iDelCount; + cache.iKeepCount = iKeepCount; + cache.iBrokenCount = iBrokenCount; + cache.iPolicyBrokenCount = iPolicyBrokenCount; + cache.iBadCount = iBadCount; + } +}; + +pkgDepCache::Transaction::Transaction(pkgDepCache &cache, Behavior behavior) : d(new Private{cache, behavior}) {} + +void pkgDepCache::Transaction::temporaryRollback() +{ + d->rollback(); +} + +void pkgDepCache::Transaction::commit() +{ + d.reset(); +} + +void pkgDepCache::Transaction::rollback() +{ + if (d == nullptr) + return; + + temporaryRollback(); + d.reset(); +} + +pkgDepCache::Transaction::~Transaction() +{ + if (not d) + return; + if (d->behavior == Behavior::ROLLBACK || (d->behavior == Behavior::AUTO && d->cache.iBrokenCount > d->iBrokenCount)) + rollback(); + else + commit(); +} + /*}}}*/ diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 39d34d3e4..d2a883180 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -267,6 +267,42 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace bool InstallSuggests; }; + /** + * \brief Perform changes to the depcache atomically. + * + * The default policy for a transaction is to rollback if the number of broken packages + * increased, otherwise to commit. Call commit() or rollback() to override the default + * policy. + */ + class APT_PUBLIC Transaction final + { + struct Private; + std::unique_ptr d; + + public: + enum class Behavior + { + COMMIT, + ROLLBACK, + AUTO, + }; + + explicit Transaction(pkgDepCache &cache, Behavior behavior); + /** \brief Commit the transaction immediately */ + void commit(); + /** \brief Rollback the transaction immediately */ + void rollback(); + /** \brief Like rollback, but can be called multiple times. + * + * You can for example create a new transaction, then temporarily + * rollback to the state before the previous transaction in that + * transaction. + */ + void temporaryRollback(); + /** \brief Commit or rollback the transaction based on default policy */ + ~Transaction(); + }; + private: /** The number of open "action groups"; certain post-action * operations are suppressed if this number is > 0. @@ -274,6 +310,8 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace int group_level; friend class ActionGroup; + friend class Transaction; + public: int IncreaseActionGroupLevel(); int DecreaseActionGroupLevel(); -- cgit v1.2.3-70-g09d2 From 1ab3740704f8cf478d01ef95f4ef8152b79d7b87 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 18 Feb 2025 13:37:38 +0100 Subject: depcache: Add a new UpgradeCount() member --- apt-pkg/depcache.cc | 16 ++++++++++++++++ apt-pkg/depcache.h | 1 + 2 files changed, 17 insertions(+) (limited to 'apt-pkg') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index ec34d010b..f7f508f85 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -110,6 +110,7 @@ struct pkgDepCache::Private std::unique_ptr inRootSetFunc; std::unique_ptr IsAVersionedKernelPackage, IsProtectedKernelPackage; std::string machineID; + unsigned long iUpgradeCount{0}; }; pkgDepCache::pkgDepCache(pkgCache *const pCache, Policy *const Plcy) : group_level(0), Cache(pCache), PkgState(0), DepState(0), iUsrSize(0), iDownloadSize(0), iInstCount(0), iDelCount(0), iKeepCount(0), @@ -148,6 +149,7 @@ bool pkgDepCache::CheckConsistency(char const *const msgtag) /*{{{*/ auto const origUsrSize = iUsrSize; auto const origDownloadSize = iDownloadSize; auto const origInstCount = iInstCount; + auto const origUpgradeCount = d->iUpgradeCount; auto const origDelCount = iDelCount; auto const origKeepCount = iKeepCount; auto const origBrokenCount = iBrokenCount; @@ -208,6 +210,7 @@ bool pkgDepCache::CheckConsistency(char const *const msgtag) /*{{{*/ iUsrSize = origUsrSize; iDownloadSize = origDownloadSize; iInstCount = origInstCount; + d->iUpgradeCount = origUpgradeCount; iDelCount = origDelCount; iKeepCount = origKeepCount; iBrokenCount = origBrokenCount; @@ -632,7 +635,11 @@ void pkgDepCache::AddStates(const PkgIterator &Pkg, bool const Invert) else if (State.Mode == ModeKeep) iKeepCount += Add; else if (State.Mode == ModeInstall) + { iInstCount += Add; + if (Pkg->CurrentVer != 0 && State.Status > 0) + d->iUpgradeCount += Add; + } } /*}}}*/ // DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/ @@ -762,6 +769,7 @@ void pkgDepCache::PerformDependencyPass(OpProgress * const Prog) iUsrSize = 0; iDownloadSize = 0; iInstCount = 0; + d->iUpgradeCount = 0; iDelCount = 0; iKeepCount = 0; iBrokenCount = 0; @@ -2650,6 +2658,12 @@ unsigned long long pkgDepCache::BootSize(bool initrdOnly) return std::accumulate(sizes, sizes + MAX_ARTEFACT, off_t{0}) * BootCount * 110 / 100; } /*}}}*/ +// pkgDepCache::UpgradeCount /*{{{*/ +unsigned long pkgDepCache::UpgradeCount() +{ + return d->iUpgradeCount; +} + /*}}}*/ // pkgDepCache::Transaction /*{{{*/ struct pkgDepCache::Transaction::Private { @@ -2668,6 +2682,7 @@ struct pkgDepCache::Transaction::Private signed long long iUsrSize{cache.iUsrSize}; unsigned long long iDownloadSize{cache.iDownloadSize}; unsigned long iInstCount{cache.iInstCount}; + unsigned long iUpgradeCount{cache.d->iUpgradeCount}; unsigned long iDelCount{cache.iDelCount}; unsigned long iKeepCount{cache.iKeepCount}; unsigned long iBrokenCount{cache.iBrokenCount}; @@ -2682,6 +2697,7 @@ struct pkgDepCache::Transaction::Private cache.iUsrSize = iUsrSize; cache.iDownloadSize = iDownloadSize; cache.iInstCount = iInstCount; + cache.d->iUpgradeCount = iUpgradeCount; cache.iDelCount = iDelCount; cache.iKeepCount = iKeepCount; cache.iBrokenCount = iBrokenCount; diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index d2a883180..bab524853 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -517,6 +517,7 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace inline unsigned long DelCount() {return iDelCount;}; inline unsigned long KeepCount() {return iKeepCount;}; inline unsigned long InstCount() {return iInstCount;}; + unsigned long UpgradeCount(); inline unsigned long BrokenCount() {return iBrokenCount;}; inline unsigned long PolicyBrokenCount() {return iPolicyBrokenCount;}; inline unsigned long BadCount() {return iBadCount;}; -- cgit v1.2.3-70-g09d2