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 _store.resize( pool.capacity() );
00377
00378 if ( pool.capacity() )
00379 {
00380 for ( sat::detail::SolvableIdType i = pool.capacity()-1; i != 0; --i )
00381 {
00382 sat::Solvable s( i );
00383 PoolItem & pi( _store[i] );
00384 if ( ! s && pi )
00385 {
00386
00387 pi = PoolItem();
00388 }
00389 else if ( s && ! pi )
00390 {
00391
00392 pi = PoolItem::makePoolItem( s );
00393
00394 if ( s.isKind( ResKind::product ) )
00395 addedProducts.push_back( pi );
00396
00397 if ( autoSoftLockAppliesTo( s ) )
00398 {
00399 pi.status().setSoftLock( ResStatus::USER );
00400 }
00401 if ( !addedItems )
00402 addedItems = true;
00403 }
00404 }
00405 }
00406 _storeDirty = false;
00407
00408
00409
00410
00411 if ( ! addedProducts.empty() )
00412 {
00413 for_( it, addedProducts.begin(), addedProducts.end() )
00414 {
00415 it->setBuddy( asKind<Product>(*it)->referencePackage() );
00416 }
00417 }
00418
00419
00420 if ( addedItems )
00421 {
00422 reapplyHardLocks();
00423 }
00424 }
00425 return _store;
00426 }
00427
00428 const Id2ItemT & id2item () const
00429 {
00430 checkSerial();
00431 if ( _id2itemDirty )
00432 {
00433 store();
00434 _id2item = Id2ItemT( size() );
00435 for_( it, begin(), end() )
00436 {
00437 const sat::Solvable &s = (*it)->satSolvable();
00438 sat::detail::IdType id = s.ident().id();
00439 if ( s.isKind( ResKind::srcpackage ) )
00440 id = -id;
00441 _id2item.insert( std::make_pair( id, *it ) );
00442 }
00443
00444 _id2itemDirty = false;
00445 }
00446 return _id2item;
00447 }
00448
00450
00452 private:
00453 void checkSerial() const
00454 {
00455 if ( _watcher.remember( serial() ) )
00456 invalidate();
00457 satpool().prepare();
00458 }
00459
00460 void invalidate() const
00461 {
00462 _storeDirty = true;
00463 _id2itemDirty = true;
00464 _id2item.clear();
00465 _poolProxy.reset();
00466 }
00467
00468 private:
00470 SerialNumberWatcher _watcher;
00471 mutable ContainerT _store;
00472 mutable DefaultIntegral<bool,true> _storeDirty;
00473 mutable Id2ItemT _id2item;
00474 mutable DefaultIntegral<bool,true> _id2itemDirty;
00475
00476 private:
00477 mutable shared_ptr<ResPoolProxy> _poolProxy;
00478
00479 private:
00481 AutoSoftLocks _autoSoftLocks;
00483 HardLockQueries _hardLockQueries;
00484 };
00486
00488 }
00491 }
00493 #endif // ZYPP_POOL_POOLIMPL_H