PoolImpl.h

Go to the documentation of this file.
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
Generated on Fri Mar 2 09:45:52 2012 for libzypp by  doxygen 1.6.3