00001
00002
00003
00004
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
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
00228
00229
00230
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
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;
00264
00265
00266
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:
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
00285 bool setChanged = false;
00286 for_( it, removedLocks.begin(), removedLocks.end() )
00287 {
00288 if ( addedLocks.find( *it ) != addedLocks.end() )
00289 continue;
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
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;
00331 AutoSoftLocks todel;
00332 AutoSoftLocks toins;
00333
00334 for_( it, begin(), end() )
00335 {
00336 ResStatus & status( it->status() );
00337 if ( ! ( status.isByUser() || status.isByApplLow() ) )
00338 continue;
00339
00340
00341 switch ( status.getTransactValue() )
00342 {
00343 case ResStatus::KEEP_STATE:
00344
00345 if ( status.isRecommended() )
00346 activeLocks_r.insert( it->satSolvable().ident() );
00347 break;
00348 case ResStatus::LOCKED:
00349
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
00390 pi = PoolItem();
00391 }
00392 else if ( s && ! pi )
00393 {
00394
00395 pi = PoolItem::makePoolItem( s );
00396
00397 if ( s.isKind( ResKind::product ) )
00398 addedProducts.push_back( pi );
00399
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
00412
00413
00414 if ( ! addedProducts.empty() )
00415 {
00416 for_( it, addedProducts.begin(), addedProducts.end() )
00417 {
00418 it->setBuddy( asKind<Product>(*it)->referencePackage() );
00419 }
00420 }
00421
00422
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
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();
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 }
00494 }
00496 #endif // ZYPP_POOL_POOLIMPL_H