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/base/Deprecated.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 if ( status_r.isLocked() == status_r.isUserLockQueryMatch() )
66 return status_r.isLocked() ? 1 : -1;
74 inline PoolQuery makeTrivialQuery( IdString ident_r )
76 sat::Solvable::SplitIdent ident( ident_r );
79 q.addAttribute( sat::SolvAttr::name, ident.name().asString() );
80 q.addKind( ident.kind() );
82 q.setCaseSensitive(true);
86 inline bool hardLockQueriesRemove( pool::PoolTraits::HardLockQueries & activeLocks_r, IdString ident_r )
88 unsigned s( activeLocks_r.size() );
89 activeLocks_r.remove( makeTrivialQuery( ident_r ) );
90 return( activeLocks_r.size() != s );
93 inline bool hardLockQueriesAdd( pool::PoolTraits::HardLockQueries & activeLocks_r, IdString ident_r )
95 PoolQuery q( makeTrivialQuery( ident_r ) );
96 for_( it, activeLocks_r.begin(), activeLocks_r.end() )
101 activeLocks_r.push_back( q );
106 ///////////////////////////////////////////////////////////////////
108 { /////////////////////////////////////////////////////////////////
110 ///////////////////////////////////////////////////////////////////
112 // CLASS NAME : PoolImpl
117 friend std::ostream & operator<<( std::ostream & str, const PoolImpl & obj );
121 typedef PoolTraits::ItemContainerT ContainerT;
122 typedef PoolTraits::size_type size_type;
123 typedef PoolTraits::const_iterator const_iterator;
124 typedef PoolTraits::Id2ItemT Id2ItemT;
126 typedef PoolTraits::repository_iterator repository_iterator;
128 typedef sat::detail::SolvableIdType SolvableIdType;
138 const sat::Pool satpool() const
139 { return sat::Pool::instance(); }
141 /** Housekeeping data serial number. */
142 const SerialNumber & serial() const
143 { return satpool().serial(); }
145 ///////////////////////////////////////////////////////////////////
147 ///////////////////////////////////////////////////////////////////
151 { return satpool().solvablesEmpty(); }
154 size_type size() const
155 { return satpool().solvablesSize(); }
157 const_iterator begin() const
158 { return make_filter_begin( pool::ByPoolItem(), store() ); }
160 const_iterator end() const
161 { return make_filter_end( pool::ByPoolItem(), store() ); }
164 /** Return the corresponding \ref PoolItem.
165 * Pool and sat pool should be in sync. Returns an empty
166 * \ref PoolItem if there is no corresponding \ref PoolItem.
167 * \see \ref PoolItem::satSolvable.
169 PoolItem find( const sat::Solvable & slv_r ) const
171 const ContainerT & mystore( store() );
172 return( slv_r.id() < mystore.size() ? mystore[slv_r.id()] : PoolItem() );
175 ///////////////////////////////////////////////////////////////////
177 ///////////////////////////////////////////////////////////////////
179 /** \name Save and restore state. */
181 void SaveState( const ResObject::Kind & kind_r );
183 void RestoreState( const ResObject::Kind & kind_r );
186 ///////////////////////////////////////////////////////////////////
188 ///////////////////////////////////////////////////////////////////
190 ResPoolProxy proxy( ResPool self ) const
195 _poolProxy.reset( new ResPoolProxy( self, *this ) );
201 /** Forward list of Repositories that contribute ResObjects from \ref sat::Pool */
202 size_type knownRepositoriesSize() const
203 { checkSerial(); return satpool().reposSize(); }
205 repository_iterator knownRepositoriesBegin() const
206 { checkSerial(); return satpool().reposBegin(); }
208 repository_iterator knownRepositoriesEnd() const
209 { checkSerial(); return satpool().reposEnd(); }
211 Repository reposFind( const std::string & alias_r ) const
212 { checkSerial(); return satpool().reposFind( alias_r ); }
214 ///////////////////////////////////////////////////////////////////
216 ///////////////////////////////////////////////////////////////////
218 typedef PoolTraits::HardLockQueries HardLockQueries;
219 typedef PoolTraits::hardLockQueries_iterator hardLockQueries_iterator;
221 const HardLockQueries & hardLockQueries() const
222 { return _hardLockQueries; }
224 void reapplyHardLocks() const
226 // It is assumed that reapplyHardLocks is called after new
227 // items were added to the pool, but the _hardLockQueries
228 // did not change since. Action is to be performed only on
229 // those items that gained the bit in the UserLockQueryField.
230 MIL << "Re-apply " << _hardLockQueries.size() << " HardLockQueries" << endl;
231 PoolQueryResult locked;
232 for_( it, _hardLockQueries.begin(), _hardLockQueries.end() )
236 MIL << "HardLockQueries match " << locked.size() << " Solvables." << endl;
237 for_( it, begin(), end() )
239 resstatus::UserLockQueryManip::reapplyLock( it->status(), locked.contains( *it ) );
243 void setHardLockQueries( const HardLockQueries & newLocks_r )
245 MIL << "Apply " << newLocks_r.size() << " HardLockQueries" << endl;
246 _hardLockQueries = newLocks_r;
247 // now adjust the pool status
248 PoolQueryResult locked;
249 for_( it, _hardLockQueries.begin(), _hardLockQueries.end() )
253 MIL << "HardLockQueries match " << locked.size() << " Solvables." << endl;
254 for_( it, begin(), end() )
256 resstatus::UserLockQueryManip::setLock( it->status(), locked.contains( *it ) );
260 bool getHardLockQueries( HardLockQueries & activeLocks_r )
262 activeLocks_r = _hardLockQueries; // current queries
263 // Now diff to the pool collecting names only.
264 // Thus added and removed locks are not necessarily
265 // disjoint. Added locks win.
266 typedef std::tr1::unordered_set<IdString> IdentSet;
268 IdentSet removedLocks;
269 for_( it, begin(), end() )
271 switch ( resstatus::UserLockQueryManip::diffLock( it->status() ) )
276 addedLocks.insert( it->satSolvable().ident() );
279 removedLocks.insert( it->satSolvable().ident() );
283 // now the bad part - adjust the queries
284 bool setChanged = false;
285 for_( it, removedLocks.begin(), removedLocks.end() )
287 if ( addedLocks.find( *it ) != addedLocks.end() )
288 continue; // Added locks win
289 if ( hardLockQueriesRemove( activeLocks_r, *it ) && ! setChanged )
292 for_( it, addedLocks.begin(), addedLocks.end() )
294 if ( hardLockQueriesAdd( activeLocks_r, *it ) && ! setChanged )
301 typedef PoolTraits::AutoSoftLocks AutoSoftLocks;
302 typedef PoolTraits::autoSoftLocks_iterator autoSoftLocks_iterator;
304 const AutoSoftLocks & autoSoftLocks() const
305 { return _autoSoftLocks; }
307 bool autoSoftLockAppliesTo( sat::Solvable solv_r ) const
308 { return( _autoSoftLocks.find( solv_r.ident() ) != _autoSoftLocks.end() ); }
310 void setAutoSoftLocks( const AutoSoftLocks & newLocks_r )
312 MIL << "Apply " << newLocks_r.size() << " AutoSoftLocks: " << newLocks_r << endl;
313 _autoSoftLocks = newLocks_r;
314 // now adjust the pool status
315 for_( it, begin(), end() )
317 if ( ! it->status().isKept() )
320 if ( autoSoftLockAppliesTo( it->satSolvable() ) )
321 it->status().setSoftLock( ResStatus::USER );
323 it->status().resetTransact( ResStatus::USER );
327 void getActiveSoftLocks( AutoSoftLocks & activeLocks_r )
329 activeLocks_r = _autoSoftLocks; // current soft-locks
330 AutoSoftLocks todel; // + names to be deleted
331 AutoSoftLocks toins; // - names to be installed
333 for_( it, begin(), end() )
335 ResStatus & status( it->status() );
336 if ( ! status.isByUser() )
337 continue; // ignore non-uer requests
339 switch ( status.getTransactValue() )
341 case ResStatus::KEEP_STATE:
342 // Filter only items included in the last recommended set.
343 if ( status.isRecommended() )
344 activeLocks_r.insert( it->satSolvable().ident() );
346 case ResStatus::LOCKED:
349 case ResStatus::TRANSACT:
350 (status.isInstalled() ? todel : toins).insert( it->satSolvable().ident() );
354 for_( it, todel.begin(), todel.end() )
356 activeLocks_r.insert( *it );
358 for_( it, toins.begin(), toins.end() )
360 activeLocks_r.erase( *it );
365 const ContainerT & store() const
370 sat::Pool pool( satpool() );
371 bool addedItems = false;
372 std::list<PoolItem> addedProducts;
374 if ( pool.capacity() != _store.capacity() )
376 _store.resize( pool.capacity() );
379 if ( pool.capacity() )
381 for ( sat::detail::SolvableIdType i = pool.capacity()-1; i != 0; --i )
383 sat::Solvable s( i );
384 PoolItem & pi( _store[i] );
387 // the PoolItem got invalidated (e.g unloaded repo)
390 else if ( s && ! pi )
392 // new PoolItem to add
393 pi = PoolItem::makePoolItem( s ); // the only way to create a new one!
394 // remember products for buddy processing (requires clean store)
395 if ( s.isKind( ResKind::product ) )
396 addedProducts.push_back( pi );
397 // and on the fly check for weak locks...
398 if ( autoSoftLockAppliesTo( s ) )
400 pi.status().setSoftLock( ResStatus::USER );
409 // Now, as the pool is adjusted, ....
411 // .... we check for product buddies.
412 if ( ! addedProducts.empty() )
414 for_( it, addedProducts.begin(), addedProducts.end() )
416 it->setBuddy( asKind<Product>(*it)->referencePackage() );
420 // .... we must reapply those query based hard locks.
429 const Id2ItemT & id2item () const
435 _id2item = Id2ItemT( size() );
436 for_( it, begin(), end() )
438 const sat::Solvable &s = (*it)->satSolvable();
439 sat::detail::IdType id = s.ident().id();
440 if ( s.isKind( ResKind::srcpackage ) )
442 _id2item.insert( std::make_pair( id, *it ) );
444 //INT << _id2item << endl;
445 _id2itemDirty = false;
450 ///////////////////////////////////////////////////////////////////
452 ///////////////////////////////////////////////////////////////////
454 void checkSerial() const
456 if ( _watcher.remember( serial() ) )
458 satpool().prepare(); // always ajust dependencies.
461 void invalidate() const
464 _id2itemDirty = true;
470 /** Watch sat pools serial number. */
471 SerialNumberWatcher _watcher;
472 mutable ContainerT _store;
473 mutable DefaultIntegral<bool,true> _storeDirty;
474 mutable Id2ItemT _id2item;
475 mutable DefaultIntegral<bool,true> _id2itemDirty;
478 mutable shared_ptr<ResPoolProxy> _poolProxy;
481 /** Set of solvable idents that should be soft locked per default. */
482 AutoSoftLocks _autoSoftLocks;
483 /** Set of queries that define hardlocks. */
484 HardLockQueries _hardLockQueries;
486 ///////////////////////////////////////////////////////////////////
488 /////////////////////////////////////////////////////////////////
490 ///////////////////////////////////////////////////////////////////
491 /////////////////////////////////////////////////////////////////
493 ///////////////////////////////////////////////////////////////////
494 #endif // ZYPP_POOL_POOLIMPL_H