libzypp 17.38.6
pool.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9#include "pool.h"
10#include "stringpool.h"
11#include "preparedpool.h"
12
17
18extern "C"
19{
20#include <solv/repo_helix.h>
21#include <solv/testcase.h>
22}
23
24
25#undef ZYPP_BASE_LOGGER_LOGGROUP
26#define ZYPP_BASE_LOGGER_LOGGROUP "zyppng::satpool"
27
28
29namespace zyppng::sat {
30
31 namespace env {
32 inline int LIBSOLV_DEBUGMASK() {
33 const char * envp = getenv("LIBSOLV_DEBUGMASK");
34 return envp ? zypp::str::strtonum<int>( envp ) : 0;
35 }
36 } // namespace env
37
38
39 namespace detail {
40 // Compile-time checks for satlib constants we redefine to avoid
41 // includes and defines.
42 static_assert( noId == STRID_NULL );
43 static_assert( emptyId == STRID_EMPTY );
44
45 static_assert( noSolvableId == ID_NULL );
46 static_assert( systemSolvableId == SYSTEMSOLVABLE );
47
48 static_assert( solvablePrereqMarker == SOLVABLE_PREREQMARKER );
49 static_assert( solvableFileMarker == SOLVABLE_FILEMARKER );
50
51 static_assert( Capability::CAP_AND == REL_AND );
52 static_assert( Capability::CAP_OR == REL_OR );
53 static_assert( Capability::CAP_COND == REL_COND );
54 static_assert( Capability::CAP_UNLESS == REL_UNLESS );
55 static_assert( Capability::CAP_ELSE == REL_ELSE );
56 static_assert( Capability::CAP_WITH == REL_WITH );
57 static_assert( Capability::CAP_WITHOUT == REL_WITHOUT );
58 static_assert( Capability::CAP_NAMESPACE == REL_NAMESPACE );
59 static_assert( Capability::CAP_ARCH == REL_ARCH );
60
61 static_assert( namespaceModalias == NAMESPACE_MODALIAS );
62 static_assert( namespaceLanguage == NAMESPACE_LANGUAGE );
63 static_assert( namespaceFilesystem == NAMESPACE_FILESYSTEM );
64
65
66 static void logSat( CPool *, void *data, int type, const char *logString )
67 {
68 if ( 0 == strncmp( logString, "job: drop orphaned", 18 ) )
69 return;
70 if ( 0 == strncmp( logString, "job: user installed", 19 ) )
71 return;
72 if ( 0 == strncmp( logString, "job: multiversion", 17 ) )
73 return;
74 if ( 0 == strncmp( logString, " - no rule created", 19 ) )
75 return;
76 if ( 0 == strncmp( logString, " next rules: 0 0", 19 ) )
77 return;
78
79 if ( type & (SOLV_FATAL|SOLV_ERROR) ) {
80 L_ERR("libsolv") << logString;
81 } else if ( type & SOLV_DEBUG_STATS ) {
82 L_DBG("libsolv") << logString;
83 } else {
84 L_MIL("libsolv") << logString;
85 }
86 }
87 }
88
90 : _pool( StringPool::instance().getPool() )
91 {
92 ZYPP_PRECONDITION( _pool->appdata == nullptr, "Only one zyppng::sat::Pool instance per CPool is permitted" );
93 _pool->appdata = this;
94 // TODO add logging functions
95 }
96
98 {
99 clear();
100 _pool->appdata = nullptr;
101 }
102
104 { return _pool->nsolvables; }
105
107 {
108 // Pass 1: let components probe external state.
109 // setDirty() is legal here — onInvalidate() fires synchronously,
110 // so all components see a consistent state before prepare starts.
111 _componentsSet.notifyCheckDirty( *this );
112
113#ifndef NDEBUG
114 zypp::DtorReset preparingReset( _preparing, false );
115 _preparing = true;
116#endif
117
118 // Pass 2: pre-index component work — only if data changed.
119 const bool serialDirty = _watcher.remember( _serial );
120 if ( serialDirty )
121 _componentsSet.notifyPrepare( *this );
122
123 // Pass 3: rebuild index if cleared (independent of serial — can be
124 // invalidated by onInvalidate(Dependency) without a data change).
125 const bool indexRebuilt = ( _pool->whatprovides == nullptr );
126 if ( indexRebuilt ) {
127 MIL << "pool_createwhatprovides..." << std::endl;
128 ::pool_addfileprovides( _pool );
129 ::pool_createwhatprovides( _pool );
130 }
131
132 // Early exit — nothing changed and index is valid.
133 if ( !serialDirty && !indexRebuilt )
134 return PreparedPool( *this );
135
136 // Pass 4: post-index component work — serial changed or index was rebuilt.
137 PreparedPool pp( *this );
138 _componentsSet.notifyPrepareWithIndex( pp );
139
140 return pp;
141 }
142
144 {
145 _componentsSet.notifyReset( *this );
146 ::pool_freewhatprovides( _pool );
147 ::pool_freeallrepos( _pool, /*resusePoolIDs*/true );
148 _serialIDs.setDirty();
149 _serial.setDirty();
150 }
151
152 void Pool::setDirty( PoolInvalidation invalidation, std::initializer_list<std::string_view> reasons )
153 {
154#ifndef NDEBUG
155 ZYPP_PRECONDITION( !_preparing, "setDirty() called during prepare() — only legal in checkDirty()" );
156#endif
157 if ( reasons.size() ) {
158 bool first = true;
159 for ( std::string_view r : reasons ) {
160 if ( first )
161 MIL << r;
162 else
163 MIL << " " << r;
164 first = false;
165 }
166 MIL << std::endl;
167 }
168
169 // Notify components so they can clear their caches
170 _componentsSet.notifyInvalidate( *this, invalidation );
171
172 if ( invalidation == PoolInvalidation::Data )
173 _serial.setDirty ();
174
175 ::pool_freewhatprovides( _pool );
176 }
177
178 const std::string &Pool::systemRepoAlias()
179 {
180 static const std::string _val( "@System" );
181 return _val;
182 }
183
184 Repository Pool::reposFind( const std::string & alias_r ) const
185 {
186 for( const auto &repo : repos() )
187 {
188 if ( alias_r == repo.alias() )
189 return repo;
190 }
191 return Repository();
192 }
193
194 Repository Pool::reposInsert( const std::string & alias_r )
195 {
196 Repository res( reposFind( alias_r ) );
197 if ( ! res )
198 res = Repository( _createRepo( alias_r ) );
199 return res;
200 }
201
202 bool Pool::reposEmpty() const
203 { return _pool->urepos == 0; }
204
206 { return _pool->urepos; }
207
209 {
210 detail::RepositoryIterator start, end = detail::RepositoryIterator( _pool->repos + _pool->nrepos );
211 if ( _pool->urepos )
212 { // repos[0] == NULL
213 for( auto it = _pool->repos+1; it != _pool->repos+_pool->nrepos; it++ )
214 if ( *it ) {
215 start = detail::RepositoryIterator( it );
216 break;
217 }
218 }
219 return RepositoryIterable( start, end );
220 }
221
223 { return Repository( _pool->installed ); }
224
226 {
227 if ( ! _pool->installed )
229 return Repository( _pool->installed );
230 }
231
233 {
234 // Do not return get()->nsolvables;
235 // nsolvables is the array size including
236 // invalid Solvables.
237 for( const auto &repo : repos() )
238 {
239 if ( ! repo.solvablesEmpty() )
240 return false;
241 }
242 return true;
243 }
244
246 {
247 // Do not return get()->nsolvables;
248 // nsolvables is the array size including
249 // invalid Solvables.
250 detail::size_type ret = 0;
251 for( const auto &repo : repos() )
252 {
253 ret += repo.solvablesSize();
254 }
255 return ret;
256 }
257
265
266 detail::CRepo *Pool::_createRepo(const std::string &name_r)
267 {
268 setDirty( PoolInvalidation::Data, { __FUNCTION__, name_r } );
269 detail::CRepo * ret = ::repo_create( _pool, name_r.c_str() );
270 if ( ret && name_r == systemRepoAlias() )
271 ::pool_set_installed( _pool, ret );
272 if ( ret )
273 _postRepoAdd( ret );
274 return ret;
275 }
276
278 {
279 setDirty( PoolInvalidation::Data, { __FUNCTION__, repo_r->name } );
280
281 _componentsSet.notifyRepoRemoved( *this, repo_r );
282
283 ::repo_free( repo_r, /*resusePoolIDs*/false );
284 if ( !_pool->urepos )
285 {
286 _serialIDs.setDirty();
287 ::pool_freeallrepos( _pool, /*resusePoolIDs*/true );
288 }
289 }
290
291 int Pool::_addSolv(detail::CRepo *repo_r, FILE *file_r)
292 {
293 setDirty( PoolInvalidation::Data, { __FUNCTION__, repo_r->name } );
294 int ret = ::repo_add_solv( repo_r, file_r, 0 );
295 if ( ret == 0 )
296 _postRepoAdd( repo_r );
297 return ret;
298 }
299
300 int Pool::_addHelix(detail::CRepo *repo_r, FILE *file_r)
301 {
302 setDirty( PoolInvalidation::Data, { __FUNCTION__, repo_r->name } );
303 int ret = ::repo_add_helix( repo_r, file_r, 0 );
304 if ( ret == 0 )
305 _postRepoAdd( repo_r );
306 return ret;
307 }
308
309 int Pool::_addTesttags(detail::CRepo *repo_r, FILE *file_r)
310 {
311 setDirty( PoolInvalidation::Data, { __FUNCTION__, repo_r->name } );
312 int ret = ::testcase_add_testtags( repo_r, file_r, 0 );
313 if ( ret == 0 )
314 _postRepoAdd( repo_r );
315 return ret;
316 }
317
319 {
320 setDirty( PoolInvalidation::Data, { __FUNCTION__, repo_r->name } );
321 return ::repo_add_solvable_block( repo_r, count_r );
322 }
323
325 {
326 _componentsSet.notifyRepoAdded( *this, repo_r );
327 }
328
329} // namespace zyppng::sat
#define L_ERR(GROUP)
Definition Logger.h:114
#define MIL
Definition Logger.h:103
#define L_MIL(GROUP)
Definition Logger.h:112
#define L_DBG(GROUP)
Definition Logger.h:111
@ CAP_WITHOUT
without
Definition Capability.h:161
@ CAP_ARCH
Used internally.
Definition Capability.h:164
Assign a vaiable a certain value when going out of scope.
Definition dtorreset.h:50
size_type reposSize() const
Number of repos in Pool.
Definition Pool.cc:73
Iterable< RepositoryIterator > repos() const
Iterate the repositories.
Definition Pool.h:95
Pool()
Default ctor.
Definition Pool.h:286
bool solvablesEmpty() const
Whether Pool contains solvables.
Definition Pool.cc:90
Repository findSystemRepo() const
Return the system repository if it is on the pool.
Definition Pool.cc:173
size_type capacity() const
Internal array size for stats only.
Definition Pool.cc:52
Iterable< SolvableIterator > solvables() const
Iterate the solvables.
Definition Pool.h:175
Repository reposFind(const std::string &alias_r) const
Find a Repository named alias_r.
Definition Pool.cc:163
size_type solvablesSize() const
Number of solvables in Pool.
Definition Pool.cc:103
static const std::string & systemRepoAlias()
Reserved system repository alias @System .
Definition Pool.cc:46
Repository reposInsert(const std::string &alias_r)
Return a Repository named alias_r.
Definition Pool.cc:143
void prepare() const
Update housekeeping data if necessary (e.g.
Definition Pool.cc:61
Repository systemRepo()
Return the system repository, create it if missing.
Definition Pool.cc:178
bool reposEmpty() const
Whether Pool contains repos.
Definition Pool.cc:70
~Pool()
Dtor.
Definition pool.cc:97
void _postRepoAdd(detail::CRepo *repo_r)
Helper postprocessing the repo after adding solv or helix files.
Definition pool.cc:324
bool _preparing
True while prepare() is running — setDirty() is illegal in this window.
Definition pool.h:285
detail::CRepo * _createRepo(const std::string &name_r)
Creating a new repo named name_r.
Definition pool.cc:266
void _deleteRepo(detail::CRepo *repo_r)
Delete repo repo_r from pool.
Definition pool.cc:277
SerialNumber _serialIDs
Serial number of IDs - changes whenever resusePoolIDs==true - ResPool must also invalidate its PoolIt...
Definition pool.h:278
zypp::Iterable< detail::RepositoryIterator > RepositoryIterable
Definition pool.h:42
int _addTesttags(detail::CRepo *repo_r, FILE *file_r)
Adding testtags file to a repo.
Definition pool.cc:309
zypp::Iterable< detail::SolvableIterator > SolvableIterable
Definition pool.h:43
SerialNumberWatcher _watcher
Watch serial number.
Definition pool.h:280
void clear()
Reset the pool by removing all repositories and solvables.
Definition pool.cc:143
int _addHelix(detail::CRepo *repo_r, FILE *file_r)
Adding helix file to a repo.
Definition pool.cc:300
PoolComponentSet _componentsSet
Component set managing modular pool logic.
Definition pool.h:282
detail::SolvableIdType getFirstId() const
Get id of the first valid Solvable.
Definition pool.h:242
Repository reposFind(const std::string &alias_r) const
Find a Repository named alias_r.
Definition pool.cc:184
int _addSolv(detail::CRepo *repo_r, FILE *file_r)
Adding solv file to a repo.
Definition pool.cc:291
void setDirty(PoolInvalidation invalidation, std::initializer_list< std::string_view > reasons)
Invalidate everything.
Definition pool.cc:152
detail::CPool * getPool() const
Definition pool.h:217
detail::CPool * _pool
sat-pool.
Definition pool.h:274
friend class Repository
Definition pool.h:38
SerialNumber _serial
Serial number - changes with each Pool content change.
Definition pool.h:276
RepositoryIterable repos() const
Iteratable to the repositories.
Definition pool.cc:208
static const std::string & systemRepoAlias()
Reserved system repository alias @System .
Definition pool.cc:178
detail::SolvableIdType _addSolvables(detail::CRepo *repo_r, unsigned count_r)
Adding Solvables to a repo.
Definition pool.cc:318
A move-only, non-owning view of a Pool that guarantees the whatprovides index is valid.
Singleton manager for the underlying libsolv string pool.
Definition stringpool.h:35
Iterate over valid Solvables in the pool.
Definition solvable.h:417
TInt strtonum(const C_Str &str)
Parsing numbers from string.
static const IdType namespaceLanguage(20)
static const IdType solvablePrereqMarker(15)
Internal ids satlib includes in dependencies.
static void logSat(CPool *, void *data, int type, const char *logString)
Definition pool.cc:66
static const IdType solvableFileMarker(16)
zypp::sat::detail::CPool CPool
static const IdType emptyId(1)
zypp::sat::detail::SolvableIdType SolvableIdType
static const IdType namespaceModalias(18)
static const IdType namespaceFilesystem(21)
static const IdType noId(0)
static const SolvableIdType noSolvableId(0)
Id to denote Solvable::noSolvable.
static const SolvableIdType systemSolvableId(1)
Id to denote the usually hidden Solvable::systemSolvable.
zypp::sat::detail::CRepo CRepo
SolvableIdType size_type
int LIBSOLV_DEBUGMASK()
Definition pool.cc:32
This file contains private API, this might break at any time between releases.
PoolInvalidation
Defines the scope of an invalidation request for the Pool.
@ Data
Structural or data change (e.g., Rootfs, Arch, or Repo content).
Always-on precondition checking for NG code.
#define ZYPP_PRECONDITION(EXPR,...)
Always-on precondition check — fires in debug AND release builds.
int repo_add_helix(::Repo *repo, FILE *fp, int flags)
int testcase_add_testtags(Repo *repo, FILE *fp, int flags)