libzypp 8.13.6
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 00005 | / /__ | | | | | | | 00006 | /_____||_| |_| |_| | 00007 | | 00008 \---------------------------------------------------------------------*/ 00012 #ifndef ZYPP_POOL_POOLIMPL_H 00013 #define ZYPP_POOL_POOLIMPL_H 00014 00015 #include <iosfwd> 00016 00017 #include "zypp/base/Easy.h" 00018 #include "zypp/base/LogTools.h" 00019 #include "zypp/base/SerialNumber.h" 00020 #include "zypp/base/Deprecated.h" 00021 00022 #include "zypp/pool/PoolTraits.h" 00023 #include "zypp/ResPoolProxy.h" 00024 #include "zypp/PoolQueryResult.h" 00025 00026 #include "zypp/sat/Pool.h" 00027 #include "zypp/Product.h" 00028 00029 using std::endl; 00030 00032 namespace zypp 00033 { 00034 00035 namespace resstatus 00036 { 00042 struct UserLockQueryManip 00043 { 00045 static void setLock( ResStatus & status_r, bool yesno_r ) 00046 { 00047 status_r.setLock( yesno_r, ResStatus::USER ); 00048 status_r.setUserLockQueryMatch( yesno_r ); 00049 } 00050 00052 static void reapplyLock( ResStatus & status_r, bool yesno_r ) 00053 { 00054 if ( yesno_r && ! status_r.isUserLockQueryMatch() ) 00055 { 00056 status_r.setLock( yesno_r, ResStatus::USER ); 00057 status_r.setUserLockQueryMatch( yesno_r ); 00058 } 00059 } 00060 00062 static int diffLock( const ResStatus & status_r ) 00063 { 00064 bool userLock( status_r.isUserLocked() ); 00065 if ( userLock == status_r.isUserLockQueryMatch() ) 00066 return 0; 00067 return userLock ? 1 : -1; 00068 } 00069 00070 }; 00071 } 00072 00073 namespace 00074 { 00075 inline PoolQuery makeTrivialQuery( IdString ident_r ) 00076 { 00077 sat::Solvable::SplitIdent ident( ident_r ); 00078 00079 PoolQuery q; 00080 q.addAttribute( sat::SolvAttr::name, ident.name().asString() ); 00081 q.addKind( ident.kind() ); 00082 q.setMatchExact(); 00083 q.setCaseSensitive(true); 00084 return q; 00085 } 00086 00087 inline bool hardLockQueriesRemove( pool::PoolTraits::HardLockQueries & activeLocks_r, IdString ident_r ) 00088 { 00089 unsigned s( activeLocks_r.size() ); 00090 activeLocks_r.remove( makeTrivialQuery( ident_r ) ); 00091 return( activeLocks_r.size() != s ); 00092 } 00093 00094 inline bool hardLockQueriesAdd( pool::PoolTraits::HardLockQueries & activeLocks_r, IdString ident_r ) 00095 { 00096 PoolQuery q( makeTrivialQuery( ident_r ) ); 00097 for_( it, activeLocks_r.begin(), activeLocks_r.end() ) 00098 { 00099 if ( *it == q ) 00100 return false; 00101 } 00102 activeLocks_r.push_back( q ); 00103 return true; 00104 } 00105 } 00106 00108 namespace pool 00109 { 00110 00112 // 00113 // CLASS NAME : PoolImpl 00114 // 00116 class PoolImpl 00117 { 00118 friend std::ostream & operator<<( std::ostream & str, const PoolImpl & obj ); 00119 00120 public: 00122 typedef PoolTraits::ItemContainerT ContainerT; 00123 typedef PoolTraits::size_type size_type; 00124 typedef PoolTraits::const_iterator const_iterator; 00125 typedef PoolTraits::Id2ItemT Id2ItemT; 00126 00127 typedef PoolTraits::repository_iterator repository_iterator; 00128 00129 typedef sat::detail::SolvableIdType SolvableIdType; 00130 00131 public: 00133 PoolImpl(); 00135 ~PoolImpl(); 00136 00137 public: 00139 const sat::Pool satpool() const 00140 { return sat::Pool::instance(); } 00141 00143 const SerialNumber & serial() const 00144 { return satpool().serial(); } 00145 00147 // 00149 public: 00151 bool empty() const 00152 { return satpool().solvablesEmpty(); } 00153 00155 size_type size() const 00156 { return satpool().solvablesSize(); } 00157 00158 const_iterator begin() const 00159 { return make_filter_begin( pool::ByPoolItem(), store() ); } 00160 00161 const_iterator end() const 00162 { return make_filter_end( pool::ByPoolItem(), store() ); } 00163 00164 public: 00170 PoolItem find( const sat::Solvable & slv_r ) const 00171 { 00172 const ContainerT & mystore( store() ); 00173 return( slv_r.id() < mystore.size() ? mystore[slv_r.id()] : PoolItem() ); 00174 } 00175 00177 // 00179 public: 00182 void SaveState( const ResObject::Kind & kind_r ); 00183 00184 void RestoreState( const ResObject::Kind & kind_r ); 00186 00188 // 00190 public: 00191 ResPoolProxy proxy( ResPool self ) const 00192 { 00193 checkSerial(); 00194 if ( !_poolProxy ) 00195 { 00196 _poolProxy.reset( new ResPoolProxy( self, *this ) ); 00197 } 00198 return *_poolProxy; 00199 } 00200 00201 public: 00203 size_type knownRepositoriesSize() const 00204 { checkSerial(); return satpool().reposSize(); } 00205 00206 repository_iterator knownRepositoriesBegin() const 00207 { checkSerial(); return satpool().reposBegin(); } 00208 00209 repository_iterator knownRepositoriesEnd() const 00210 { checkSerial(); return satpool().reposEnd(); } 00211 00212 Repository reposFind( const std::string & alias_r ) const 00213 { checkSerial(); return satpool().reposFind( alias_r ); } 00214 00216 // 00218 public: 00219 typedef PoolTraits::HardLockQueries HardLockQueries; 00220 typedef PoolTraits::hardLockQueries_iterator hardLockQueries_iterator; 00221 00222 const HardLockQueries & hardLockQueries() const 00223 { return _hardLockQueries; } 00224 00225 void reapplyHardLocks() const 00226 { 00227 // It is assumed that reapplyHardLocks is called after new 00228 // items were added to the pool, but the _hardLockQueries 00229 // did not change since. Action is to be performed only on 00230 // those items that gained the bit in the UserLockQueryField. 00231 MIL << "Re-apply " << _hardLockQueries.size() << " HardLockQueries" << endl; 00232 PoolQueryResult locked; 00233 for_( it, _hardLockQueries.begin(), _hardLockQueries.end() ) 00234 { 00235 locked += *it; 00236 } 00237 MIL << "HardLockQueries match " << locked.size() << " Solvables." << endl; 00238 for_( it, begin(), end() ) 00239 { 00240 resstatus::UserLockQueryManip::reapplyLock( it->status(), locked.contains( *it ) ); 00241 } 00242 } 00243 00244 void setHardLockQueries( const HardLockQueries & newLocks_r ) 00245 { 00246 MIL << "Apply " << newLocks_r.size() << " HardLockQueries" << endl; 00247 _hardLockQueries = newLocks_r; 00248 // now adjust the pool status 00249 PoolQueryResult locked; 00250 for_( it, _hardLockQueries.begin(), _hardLockQueries.end() ) 00251 { 00252 locked += *it; 00253 } 00254 MIL << "HardLockQueries match " << locked.size() << " Solvables." << endl; 00255 for_( it, begin(), end() ) 00256 { 00257 resstatus::UserLockQueryManip::setLock( it->status(), locked.contains( *it ) ); 00258 } 00259 } 00260 00261 bool getHardLockQueries( HardLockQueries & activeLocks_r ) 00262 { 00263 activeLocks_r = _hardLockQueries; // current queries 00264 // Now diff to the pool collecting names only. 00265 // Thus added and removed locks are not necessarily 00266 // disjoint. Added locks win. 00267 typedef std::tr1::unordered_set<IdString> IdentSet; 00268 IdentSet addedLocks; 00269 IdentSet removedLocks; 00270 for_( it, begin(), end() ) 00271 { 00272 switch ( resstatus::UserLockQueryManip::diffLock( it->status() ) ) 00273 { 00274 case 0: // unchanged 00275 break; 00276 case 1: 00277 addedLocks.insert( it->satSolvable().ident() ); 00278 break; 00279 case -1: 00280 removedLocks.insert( it->satSolvable().ident() ); 00281 break; 00282 } 00283 } 00284 // now the bad part - adjust the queries 00285 bool setChanged = false; 00286 for_( it, removedLocks.begin(), removedLocks.end() ) 00287 { 00288 if ( addedLocks.find( *it ) != addedLocks.end() ) 00289 continue; // Added locks win 00290 if ( hardLockQueriesRemove( activeLocks_r, *it ) && ! setChanged ) 00291 setChanged = true; 00292 } 00293 for_( it, addedLocks.begin(), addedLocks.end() ) 00294 { 00295 if ( hardLockQueriesAdd( activeLocks_r, *it ) && ! setChanged ) 00296 setChanged = true; 00297 } 00298 return setChanged; 00299 } 00300 00301 public: 00302 typedef PoolTraits::AutoSoftLocks AutoSoftLocks; 00303 typedef PoolTraits::autoSoftLocks_iterator autoSoftLocks_iterator; 00304 00305 const AutoSoftLocks & autoSoftLocks() const 00306 { return _autoSoftLocks; } 00307 00308 bool autoSoftLockAppliesTo( sat::Solvable solv_r ) const 00309 { return( _autoSoftLocks.find( solv_r.ident() ) != _autoSoftLocks.end() ); } 00310 00311 void setAutoSoftLocks( const AutoSoftLocks & newLocks_r ) 00312 { 00313 MIL << "Apply " << newLocks_r.size() << " AutoSoftLocks: " << newLocks_r << endl; 00314 _autoSoftLocks = newLocks_r; 00315 // now adjust the pool status 00316 for_( it, begin(), end() ) 00317 { 00318 if ( ! it->status().isKept() ) 00319 continue; 00320 00321 if ( autoSoftLockAppliesTo( it->satSolvable() ) ) 00322 it->status().setSoftLock( ResStatus::USER ); 00323 else 00324 it->status().resetTransact( ResStatus::USER ); 00325 } 00326 } 00327 00328 void getActiveSoftLocks( AutoSoftLocks & activeLocks_r ) 00329 { 00330 activeLocks_r = _autoSoftLocks; // current soft-locks 00331 AutoSoftLocks todel; // + names to be deleted 00332 AutoSoftLocks toins; // - names to be installed 00333 00334 for_( it, begin(), end() ) 00335 { 00336 ResStatus & status( it->status() ); 00337 if ( ! ( status.isByUser() || status.isByApplLow() ) ) 00338 continue; // ignore non-user requests; ApplLow means selected 00339 // by solver, but on behalf of a user request. 00340 00341 switch ( status.getTransactValue() ) 00342 { 00343 case ResStatus::KEEP_STATE: 00344 // Filter only items included in the last recommended set. 00345 if ( status.isRecommended() ) 00346 activeLocks_r.insert( it->satSolvable().ident() ); 00347 break; 00348 case ResStatus::LOCKED: 00349 // NOOP 00350 break; 00351 case ResStatus::TRANSACT: 00352 (status.isInstalled() ? todel : toins).insert( it->satSolvable().ident() ); 00353 break; 00354 } 00355 } 00356 for_( it, todel.begin(), todel.end() ) 00357 { 00358 activeLocks_r.insert( *it ); 00359 } 00360 for_( it, toins.begin(), toins.end() ) 00361 { 00362 activeLocks_r.erase( *it ); 00363 } 00364 } 00365 00366 public: 00367 const ContainerT & store() const 00368 { 00369 checkSerial(); 00370 if ( _storeDirty ) 00371 { 00372 sat::Pool pool( satpool() ); 00373 bool addedItems = false; 00374 std::list<PoolItem> addedProducts; 00375 00376 if ( pool.capacity() != _store.capacity() ) 00377 { 00378 _store.resize( pool.capacity() ); 00379 } 00380 00381 if ( pool.capacity() ) 00382 { 00383 for ( sat::detail::SolvableIdType i = pool.capacity()-1; i != 0; --i ) 00384 { 00385 sat::Solvable s( i ); 00386 PoolItem & pi( _store[i] ); 00387 if ( ! s && pi ) 00388 { 00389 // the PoolItem got invalidated (e.g unloaded repo) 00390 pi = PoolItem(); 00391 } 00392 else if ( s && ! pi ) 00393 { 00394 // new PoolItem to add 00395 pi = PoolItem::makePoolItem( s ); // the only way to create a new one! 00396 // remember products for buddy processing (requires clean store) 00397 if ( s.isKind( ResKind::product ) ) 00398 addedProducts.push_back( pi ); 00399 // and on the fly check for weak locks... 00400 if ( autoSoftLockAppliesTo( s ) ) 00401 { 00402 pi.status().setSoftLock( ResStatus::USER ); 00403 } 00404 if ( !addedItems ) 00405 addedItems = true; 00406 } 00407 } 00408 } 00409 _storeDirty = false; 00410 00411 // Now, as the pool is adjusted, .... 00412 00413 // .... we check for product buddies. 00414 if ( ! addedProducts.empty() ) 00415 { 00416 for_( it, addedProducts.begin(), addedProducts.end() ) 00417 { 00418 it->setBuddy( asKind<Product>(*it)->referencePackage() ); 00419 } 00420 } 00421 00422 // .... we must reapply those query based hard locks. 00423 if ( addedItems ) 00424 { 00425 reapplyHardLocks(); 00426 } 00427 } 00428 return _store; 00429 } 00430 00431 const Id2ItemT & id2item () const 00432 { 00433 checkSerial(); 00434 if ( _id2itemDirty ) 00435 { 00436 store(); 00437 _id2item = Id2ItemT( size() ); 00438 for_( it, begin(), end() ) 00439 { 00440 const sat::Solvable &s = (*it)->satSolvable(); 00441 sat::detail::IdType id = s.ident().id(); 00442 if ( s.isKind( ResKind::srcpackage ) ) 00443 id = -id; 00444 _id2item.insert( std::make_pair( id, *it ) ); 00445 } 00446 //INT << _id2item << endl; 00447 _id2itemDirty = false; 00448 } 00449 return _id2item; 00450 } 00451 00453 // 00455 private: 00456 void checkSerial() const 00457 { 00458 if ( _watcher.remember( serial() ) ) 00459 invalidate(); 00460 satpool().prepare(); // always ajust dependencies. 00461 } 00462 00463 void invalidate() const 00464 { 00465 _storeDirty = true; 00466 _id2itemDirty = true; 00467 _id2item.clear(); 00468 _poolProxy.reset(); 00469 } 00470 00471 private: 00473 SerialNumberWatcher _watcher; 00474 mutable ContainerT _store; 00475 mutable DefaultIntegral<bool,true> _storeDirty; 00476 mutable Id2ItemT _id2item; 00477 mutable DefaultIntegral<bool,true> _id2itemDirty; 00478 00479 private: 00480 mutable shared_ptr<ResPoolProxy> _poolProxy; 00481 00482 private: 00484 AutoSoftLocks _autoSoftLocks; 00486 HardLockQueries _hardLockQueries; 00487 }; 00489 00491 } // namespace pool 00494 } // namespace zypp 00496 #endif // ZYPP_POOL_POOLIMPL_H