libzypp  17.38.7
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 
16 #include <zypp/ng/sat/capability.h>
17 
18 extern "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 
29 namespace 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.
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 );
139 
140  return pp;
141  }
142 
143  void Pool::clear()
144  {
145  _componentsSet.notifyReset( *this );
146  ::pool_freewhatprovides( _pool );
147  ::pool_freeallrepos( _pool, /*resusePoolIDs*/true );
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 
232  bool Pool::solvablesEmpty() const
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 
259  {
260  return Pool::SolvableIterable(
263  );
264  }
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  {
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
static const SolvableIdType noSolvableId(0)
Id to denote Solvable::noSolvable.
static const IdType namespaceModalias(18)
int testcase_add_testtags(Repo *repo, FILE *fp, int flags)
SerialNumberWatcher _watcher
Watch serial number.
Definition: pool.h:280
RepositoryIterable repos() const
Iteratable to the repositories.
Definition: pool.cc:208
detail::size_type solvablesSize() const
Number of solvables in Pool.
Definition: pool.cc:245
#define MIL
Definition: Logger.h:103
detail::size_type reposSize() const
Number of repos in Pool.
Definition: pool.cc:205
int _addTesttags(detail::CRepo *repo_r, FILE *file_r)
Adding testtags file to a repo.
Definition: pool.cc:309
bool _preparing
True while prepare() is running — setDirty() is illegal in this window.
Definition: pool.h:285
Namespace intended to collect all environment variables we use.
void notifyCheckDirty(Pool &pool)
Pass 1 of prepare(): probe external state.
bool remember(unsigned serial_r) const
Return isDirty, storing serial_r as new value.
Definition: SerialNumber.h:160
friend class Repository
Definition: pool.h:38
#define L_MIL(GROUP)
Definition: Logger.h:112
#define L_ERR(GROUP)
Definition: Logger.h:114
zypp::Iterable< detail::SolvableIterator > SolvableIterable
Definition: pool.h:43
static void logSat(CPool *, void *data, int type, const char *logString)
Definition: pool.cc:66
Repository findSystemRepo() const
Return the system repository if it is on the pool.
Definition: pool.cc:222
int LIBSOLV_DEBUGMASK()
Definition: pool.cc:32
void _postRepoAdd(detail::CRepo *repo_r)
Helper postprocessing the repo after adding solv or helix files.
Definition: pool.cc:324
static const IdType solvableFileMarker(16)
PreparedPool prepare()
Update housekeeping data (e.g.
Definition: pool.cc:106
zypp::sat::detail::CPool CPool
Definition: poolconstants.h:36
zypp::sat::detail::SolvableIdType SolvableIdType
Definition: poolconstants.h:44
detail::SolvableIdType _addSolvables(detail::CRepo *repo_r, unsigned count_r)
Adding Solvables to a repo.
Definition: pool.cc:318
PoolComponentSet _componentsSet
Component set managing modular pool logic.
Definition: pool.h:282
void notifyRepoAdded(Pool &pool, detail::RepoIdType id)
Structural or data change (e.g., Rootfs, Arch, or Repo content).
A move-only, non-owning view of a Pool that guarantees the whatprovides index is valid.
Definition: preparedpool.h:50
bool solvablesEmpty() const
Whether Pool contains solvables.
Definition: pool.cc:232
SerialNumber _serialIDs
Serial number of IDs - changes whenever resusePoolIDs==true - ResPool must also invalidate its PoolIt...
Definition: pool.h:278
Assign a vaiable a certain value when going out of scope.
Definition: dtorreset.h:49
int repo_add_helix(::Repo *repo, FILE *fp, int flags)
Repository systemRepo()
Return the system repository, create it if missing.
Definition: pool.cc:225
Singleton manager for the underlying libsolv string pool.
Definition: stringpool.h:35
static const IdType emptyId(1)
Iterate over valid Solvables in the pool.
Definition: solvable.h:410
static const SolvableIdType systemSolvableId(1)
Id to denote the usually hidden Solvable::systemSolvable.
This file contains private API, this might break at any time between releases.
Definition: capabilities.h:22
detail::CPool * _pool
sat-pool.
Definition: pool.h:274
void notifyRepoRemoved(Pool &pool, detail::RepoIdType id)
void setDirty(PoolInvalidation invalidation, std::initializer_list< std::string_view > reasons)
Invalidate everything.
Definition: pool.cc:152
zypp::Iterable< detail::RepositoryIterator > RepositoryIterable
Definition: pool.h:42
static const IdType namespaceFilesystem(21)
SolvableIdType size_type
Definition: poolconstants.h:59
zypp::sat::detail::CRepo CRepo
Definition: poolconstants.h:38
#define L_DBG(GROUP)
Definition: Logger.h:111
constexpr std::string_view FILE("file")
static const IdType namespaceLanguage(20)
detail::CRepo * _createRepo(const std::string &name_r)
Creating a new repo named name_r.
Definition: pool.cc:266
bool reposEmpty() const
Whether Pool contains repos.
Definition: pool.cc:202
PoolInvalidation
Defines the scope of an invalidation request for the Pool.
Definition: poolconstants.h:66
static const IdType noId(0)
#define ZYPP_PRECONDITION(EXPR,...)
Always-on precondition check — fires in debug AND release builds.
Definition: precondition.h:42
static const IdType solvablePrereqMarker(15)
Internal ids satlib includes in dependencies.
~Pool()
Dtor.
Definition: pool.cc:97
SerialNumber _serial
Serial number - changes with each Pool content change.
Definition: pool.h:276
void notifyInvalidate(Pool &pool, PoolInvalidation invalidation)
int _addHelix(detail::CRepo *repo_r, FILE *file_r)
Adding helix file to a repo.
Definition: pool.cc:300
Repository reposFind(const std::string &alias_r) const
Find a Repository named alias_r.
Definition: pool.cc:184
SolvableIterable solvables() const
Iterator to the first Solvable.
Definition: pool.cc:258
detail::size_type capacity() const
Definition: pool.cc:103
void notifyPrepare(Pool &pool)
Pass 2 of prepare(): pre-index component work (stage/priority order).
void _deleteRepo(detail::CRepo *repo_r)
Delete repo repo_r from pool.
Definition: pool.cc:277
detail::SolvableIdType getFirstId() const
Get id of the first valid Solvable.
Definition: pool.h:242
Repository reposInsert(const std::string &alias_r)
Return a Repository named alias_r.
Definition: pool.cc:194
void notifyPrepareWithIndex(PreparedPool &pp)
Pass 3 of prepare(): post-index component work (stage/priority order).
int _addSolv(detail::CRepo *repo_r, FILE *file_r)
Adding solv file to a repo.
Definition: pool.cc:291
void clear()
Reset the pool by removing all repositories and solvables.
Definition: pool.cc:143
Pool()
Default ctor.
Definition: pool.cc:89
static const std::string & systemRepoAlias()
Reserved system repository alias .
Definition: pool.cc:178
Always-on precondition checking for NG code.