1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/pool/PoolImpl.h
12 #ifndef ZYPP_POOL_POOLIMPL_H
13 #define ZYPP_POOL_POOLIMPL_H
17 #include "zypp/base/Easy.h"
18 #include "zypp/base/LogTools.h"
19 #include "zypp/base/SerialNumber.h"
20 #include "zypp/APIConfig.h"
22 #include "zypp/pool/PoolTraits.h"
23 #include "zypp/ResPoolProxy.h"
24 #include "zypp/PoolQueryResult.h"
26 #include "zypp/sat/Pool.h"
27 #include "zypp/Product.h"
31 ///////////////////////////////////////////////////////////////////
33 { /////////////////////////////////////////////////////////////////
37 /** Manipulator for \ref ResStatus::UserLockQueryField.
38 * Field is not public available. It is intended to remember the
39 * initial lock status usually derived from /etc/zypp/locks. So
40 * we are able to detect changes we have to write back on commit.
42 struct UserLockQueryManip
44 /** Set lock and UserLockQuery bit according to \c yesno_r. */
45 static void setLock( ResStatus & status_r, bool yesno_r )
47 status_r.setLock( yesno_r, ResStatus::USER );
48 status_r.setUserLockQueryMatch( yesno_r );
51 /** Update lock and UserLockQuery bit IFF the item gained the bit. */
52 static void reapplyLock( ResStatus & status_r, bool yesno_r )
54 if ( yesno_r && ! status_r.isUserLockQueryMatch() )
56 status_r.setLock( yesno_r, ResStatus::USER );
57 status_r.setUserLockQueryMatch( yesno_r );
61 /** Test whether the lock status differs from the remembered UserLockQuery bit. */
62 static int diffLock( const ResStatus & status_r )
64 bool userLock( status_r.isUserLocked() );
65 if ( userLock == status_r.isUserLockQueryMatch() )
67 return userLock ? 1 : -1;
75 inline PoolQuery makeTrivialQuery( IdString ident_r )
77 sat::Solvable::SplitIdent ident( ident_r );
80 q.addAttribute( sat::SolvAttr::name, ident.name().asString() );
81 q.addKind( ident.kind() );
83 q.setCaseSensitive(true);
87 inline bool hardLockQueriesRemove( pool::PoolTraits::HardLockQueries & activeLocks_r, IdString ident_r )
89 unsigned s( activeLocks_r.size() );
90 activeLocks_r.remove( makeTrivialQuery( ident_r ) );
91 return( activeLocks_r.size() != s );
94 inline bool hardLockQueriesAdd( pool::PoolTraits::HardLockQueries & activeLocks_r, IdString ident_r )
96 PoolQuery q( makeTrivialQuery( ident_r ) );
97 for_( it, activeLocks_r.begin(), activeLocks_r.end() )
102 activeLocks_r.push_back( q );
107 ///////////////////////////////////////////////////////////////////
110 void establish( sat::Queue & pseudoItems_r, sat::Queue & pseudoFlags_r ); // in solver/detail/SATResolver.cc
113 ///////////////////////////////////////////////////////////////////
114 /// Store initial establish status of pseudo installed items.
116 class ResPool::EstablishedStates::Impl
120 { solver::detail::establish( _pseudoItems, _pseudoFlags ); }
122 /** Return all pseudo installed items whose current state differs from their initial one. */
123 ResPool::EstablishedStates::ChangedPseudoInstalled changedPseudoInstalled() const
125 ChangedPseudoInstalled ret;
127 if ( ! _pseudoItems.empty() )
129 for ( sat::Queue::size_type i = 0; i < _pseudoItems.size(); ++i )
131 PoolItem pi { sat::Solvable(_pseudoItems[i]) };
132 ResStatus::ValidateValue vorig { validateValue( i ) };
133 if ( pi.status().validate() != vorig )
141 ResStatus::ValidateValue validateValue( sat::Queue::size_type i ) const
143 ResStatus::ValidateValue ret { ResStatus::UNDETERMINED };
144 switch ( _pseudoFlags[i] )
146 case 0: ret = ResStatus::BROKEN /*2*/; break;
147 case 1: ret = ResStatus::SATISFIED /*4*/; break;
148 case -1: ret = ResStatus::NONRELEVANT /*6*/; break;
154 sat::Queue _pseudoItems;
155 sat::Queue _pseudoFlags;
158 ///////////////////////////////////////////////////////////////////
160 { /////////////////////////////////////////////////////////////////
162 ///////////////////////////////////////////////////////////////////
164 // CLASS NAME : PoolImpl
169 friend std::ostream & operator<<( std::ostream & str, const PoolImpl & obj );
173 typedef PoolTraits::ItemContainerT ContainerT;
174 typedef PoolTraits::size_type size_type;
175 typedef PoolTraits::const_iterator const_iterator;
176 typedef PoolTraits::Id2ItemT Id2ItemT;
178 typedef PoolTraits::repository_iterator repository_iterator;
180 typedef sat::detail::SolvableIdType SolvableIdType;
182 typedef ResPool::EstablishedStates::Impl EstablishedStatesImpl;
192 const sat::Pool satpool() const
193 { return sat::Pool::instance(); }
195 /** Housekeeping data serial number. */
196 const SerialNumber & serial() const
197 { return satpool().serial(); }
199 ///////////////////////////////////////////////////////////////////
201 ///////////////////////////////////////////////////////////////////
205 { return satpool().solvablesEmpty(); }
208 size_type size() const
209 { return satpool().solvablesSize(); }
211 const_iterator begin() const
212 { return make_filter_begin( pool::ByPoolItem(), store() ); }
214 const_iterator end() const
215 { return make_filter_end( pool::ByPoolItem(), store() ); }
218 /** Return the corresponding \ref PoolItem.
219 * Pool and sat pool should be in sync. Returns an empty
220 * \ref PoolItem if there is no corresponding \ref PoolItem.
221 * \see \ref PoolItem::satSolvable.
223 PoolItem find( const sat::Solvable & slv_r ) const
225 const ContainerT & mystore( store() );
226 return( slv_r.id() < mystore.size() ? mystore[slv_r.id()] : PoolItem() );
229 ///////////////////////////////////////////////////////////////////
231 ///////////////////////////////////////////////////////////////////
233 /** \name Save and restore state. */
235 void SaveState( const ResKind & kind_r );
237 void RestoreState( const ResKind & kind_r );
240 ///////////////////////////////////////////////////////////////////
242 ///////////////////////////////////////////////////////////////////
244 ResPoolProxy proxy( ResPool self ) const
249 _poolProxy.reset( new ResPoolProxy( self, *this ) );
254 /** True factory for \ref ResPool::EstablishedStates.
255 * Internally we maintain the ResPool::EstablishedStates::Impl
256 * reference shared_ptr. Updated whenever the pool content changes.
257 * On demand hand it out as ResPool::EstablishedStates Impl.
259 ResPool::EstablishedStates establishedStates() const
260 { store(); return ResPool::EstablishedStates( _establishedStates ); }
263 /** Forward list of Repositories that contribute ResObjects from \ref sat::Pool */
264 size_type knownRepositoriesSize() const
265 { checkSerial(); return satpool().reposSize(); }
267 repository_iterator knownRepositoriesBegin() const
268 { checkSerial(); return satpool().reposBegin(); }
270 repository_iterator knownRepositoriesEnd() const
271 { checkSerial(); return satpool().reposEnd(); }
273 Repository reposFind( const std::string & alias_r ) const
274 { checkSerial(); return satpool().reposFind( alias_r ); }
276 ///////////////////////////////////////////////////////////////////
278 ///////////////////////////////////////////////////////////////////
280 typedef PoolTraits::HardLockQueries HardLockQueries;
281 typedef PoolTraits::hardLockQueries_iterator hardLockQueries_iterator;
283 const HardLockQueries & hardLockQueries() const
284 { return _hardLockQueries; }
286 void reapplyHardLocks() const
288 // It is assumed that reapplyHardLocks is called after new
289 // items were added to the pool, but the _hardLockQueries
290 // did not change since. Action is to be performed only on
291 // those items that gained the bit in the UserLockQueryField.
292 MIL << "Re-apply " << _hardLockQueries.size() << " HardLockQueries" << endl;
293 PoolQueryResult locked;
294 for_( it, _hardLockQueries.begin(), _hardLockQueries.end() )
298 MIL << "HardLockQueries match " << locked.size() << " Solvables." << endl;
299 for_( it, begin(), end() )
301 resstatus::UserLockQueryManip::reapplyLock( it->status(), locked.contains( *it ) );
305 void setHardLockQueries( const HardLockQueries & newLocks_r )
307 MIL << "Apply " << newLocks_r.size() << " HardLockQueries" << endl;
308 _hardLockQueries = newLocks_r;
309 // now adjust the pool status
310 PoolQueryResult locked;
311 for_( it, _hardLockQueries.begin(), _hardLockQueries.end() )
315 MIL << "HardLockQueries match " << locked.size() << " Solvables." << endl;
316 for_( it, begin(), end() )
318 resstatus::UserLockQueryManip::setLock( it->status(), locked.contains( *it ) );
322 bool getHardLockQueries( HardLockQueries & activeLocks_r )
324 activeLocks_r = _hardLockQueries; // current queries
325 // Now diff to the pool collecting names only.
326 // Thus added and removed locks are not necessarily
327 // disjoint. Added locks win.
328 typedef std::unordered_set<IdString> IdentSet;
330 IdentSet removedLocks;
331 for_( it, begin(), end() )
333 switch ( resstatus::UserLockQueryManip::diffLock( it->status() ) )
338 addedLocks.insert( it->satSolvable().ident() );
341 removedLocks.insert( it->satSolvable().ident() );
345 // now the bad part - adjust the queries
346 bool setChanged = false;
347 for_( it, removedLocks.begin(), removedLocks.end() )
349 if ( addedLocks.find( *it ) != addedLocks.end() )
350 continue; // Added locks win
351 if ( hardLockQueriesRemove( activeLocks_r, *it ) && ! setChanged )
354 for_( it, addedLocks.begin(), addedLocks.end() )
356 if ( hardLockQueriesAdd( activeLocks_r, *it ) && ! setChanged )
363 const ContainerT & store() const
368 sat::Pool pool( satpool() );
369 bool addedItems = false;
370 bool reusedIDs = _watcherIDs.remember( pool.serialIDs() );
371 std::list<PoolItem> addedProducts;
373 _store.resize( pool.capacity() );
375 if ( pool.capacity() )
377 for ( sat::detail::SolvableIdType i = pool.capacity()-1; i != 0; --i )
379 sat::Solvable s( i );
380 PoolItem & pi( _store[i] );
383 // the PoolItem got invalidated (e.g unloaded repo)
386 else if ( reusedIDs || (s && ! pi) )
388 // new PoolItem to add
389 pi = PoolItem::makePoolItem( s ); // the only way to create a new one!
390 // remember products for buddy processing (requires clean store)
391 if ( s.isKind( ResKind::product ) )
392 addedProducts.push_back( pi );
400 // Now, as the pool is adjusted, ....
402 // .... we check for product buddies.
403 if ( ! addedProducts.empty() )
405 for_( it, addedProducts.begin(), addedProducts.end() )
407 it->setBuddy( asKind<Product>(*it)->referencePackage() );
411 // .... we must reapply those query based hard locks.
417 // Compute the initial status of Patches etc.
418 if ( !_establishedStates )
419 _establishedStates.reset( new EstablishedStatesImpl );
424 const Id2ItemT & id2item () const
430 _id2item = Id2ItemT( size() );
431 for_( it, begin(), end() )
433 const sat::Solvable &s = (*it)->satSolvable();
434 sat::detail::IdType id = s.ident().id();
435 if ( s.isKind( ResKind::srcpackage ) )
437 _id2item.insert( std::make_pair( id, *it ) );
439 //INT << _id2item << endl;
440 _id2itemDirty = false;
445 ///////////////////////////////////////////////////////////////////
447 ///////////////////////////////////////////////////////////////////
449 void checkSerial() const
451 if ( _watcher.remember( serial() ) )
453 satpool().prepare(); // always ajust dependencies.
456 void invalidate() const
459 _id2itemDirty = true;
462 _establishedStates.reset();
466 /** Watch sat pools serial number. */
467 SerialNumberWatcher _watcher;
468 /** Watch sat pools Serial number of IDs - changes whenever resusePoolIDs==true - ResPool must also invalidate it's PoolItems! */
469 SerialNumberWatcher _watcherIDs;
470 mutable ContainerT _store;
471 mutable DefaultIntegral<bool,true> _storeDirty;
472 mutable Id2ItemT _id2item;
473 mutable DefaultIntegral<bool,true> _id2itemDirty;
476 mutable shared_ptr<ResPoolProxy> _poolProxy;
477 mutable shared_ptr<EstablishedStatesImpl> _establishedStates;
480 /** Set of queries that define hardlocks. */
481 HardLockQueries _hardLockQueries;
483 ///////////////////////////////////////////////////////////////////
485 /////////////////////////////////////////////////////////////////
487 ///////////////////////////////////////////////////////////////////
488 /////////////////////////////////////////////////////////////////
490 ///////////////////////////////////////////////////////////////////
491 #endif // ZYPP_POOL_POOLIMPL_H