libzypp  10.5.0
GetResolvablesToInsDel.cc
Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include <set>
00014 
00015 #include "zypp/base/LogTools.h"
00016 #include "zypp/base/LogControl.h"
00017 #include "zypp/sat/Solvable.h"
00018 #include "zypp/sat/WhatObsoletes.h"
00019 #include "zypp/pool/GetResolvablesToInsDel.h"
00020 #include "zypp/pool/PoolStats.h"
00021 #include "zypp/solver/detail/InstallOrder.h"
00022 
00023 #include "zypp/Resolver.h"
00024 #include "zypp/sat/Transaction.h"
00025 
00026 using std::endl;
00027 using zypp::solver::detail::InstallOrder;
00028 
00029 #undef  ZYPP_BASE_LOGGER_LOGGROUP
00030 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::GetResolvablesToInsDel"
00031 
00033 namespace zypp
00034 { 
00035 
00036   namespace pool
00037   { 
00038 
00039     /******************************************************************
00040      **
00041      ** FUNCTION NAME : strip_obsoleted_to_delete
00042      ** FUNCTION TYPE : void
00043      **
00044      ** strip packages to_delete which get obsoleted by
00045      ** to_install (i.e. delay deletion in case the
00046      ** obsoleting package likes to save whatever...
00047     */
00048 
00049     static void
00050     strip_obsoleted_to_delete( GetResolvablesToInsDel::PoolItemList & deleteList_r,
00051                                const GetResolvablesToInsDel::PoolItemList & instlist_r )
00052     {
00053       if ( deleteList_r.size() == 0 || instlist_r.size() == 0 )
00054         return; // ---> nothing to do
00055 
00056       // These are all installed packages obsoleted by any package to be installed.
00057       // Actually we expect all of them to appear in the deleteList_r, and we want
00058       // to kick them out. Rpm will delete them when the obsoleter gets installed.
00059       sat::WhatObsoletes obsoleted( instlist_r.begin(), instlist_r.end() );
00060       for_( it, obsoleted.poolItemBegin(), obsoleted.poolItemEnd() )
00061       {
00062         DBG << "Ignore appl_delete (should be obsoleted): " << *it << endl;
00063         deleteList_r.remove( *it );
00064       }
00065 
00066       MIL << "Undelayed deletes: " << deleteList_r << endl;
00067     }
00068 
00070     //
00071     //  METHOD NAME : GetResolvablesToInsDel::GetResolvablesToInsDel
00072     //  METHOD TYPE : Ctor
00073     //
00074     GetResolvablesToInsDel::GetResolvablesToInsDel( ResPool pool_r, Order order_r )
00075     {
00076       zypp::base::LogControl::TmpLineWriter shutUp;
00077       typedef std::set<PoolItem> PoolItemSet;
00078 
00079       PoolItemList & dellist_r( _toDelete );
00080       PoolItemList & instlist_r( _toInstall );
00081       PoolItemList & srclist_r( _toSrcinstall );
00082 
00083       for ( ResPool::const_iterator it = pool_r.begin(); it != pool_r.end(); ++it )
00084         {
00085           if (it->status().isToBeInstalled())
00086             {
00087               if ((*it)->kind() == ResKind::srcpackage) {
00088                 srclist_r.push_back( *it );
00089               }
00090               else
00091                 instlist_r.push_back( *it );
00092             }
00093           else if (it->status().isToBeUninstalled())
00094             {
00095               if ( it->status().isToBeUninstalledDueToObsolete() )
00096                 {
00097                   DBG << "Ignore auto_delete (should be obsoleted): " << *it << endl;
00098                 }
00099               else if ( it->status().isToBeUninstalledDueToUpgrade() )
00100                 {
00101                   DBG << "Ignore auto_delete (should be upgraded): " << *it << endl;
00102                 }
00103               else {
00104                 dellist_r.push_back( *it );
00105               }
00106             }
00107         }
00108 
00109       MIL << "ResolvablesToInsDel: delete " << dellist_r.size()
00110       << ", install " << instlist_r.size()
00111       << ", srcinstall " << srclist_r.size() << endl;
00112 
00114       //
00115       // strip packages to_delete which get obsoleted by
00116       // to_install (i.e. delay deletion in case the
00117       // obsoleting package likes to save whatever...
00118       //
00120       strip_obsoleted_to_delete( dellist_r, instlist_r );
00121 
00122       if ( dellist_r.size() ) {
00124         //
00125         // sort delete list...
00126         //
00128         PoolItemSet delset( dellist_r.begin(), dellist_r.end() );  // for delete order
00129         PoolItemSet dummy; // dummy, empty, should contain already installed
00130 
00131         InstallOrder order( pool_r, delset, dummy ); // sort according top prereq
00132         order.init();
00133         const PoolItemList dsorted( order.getTopSorted() );
00134 
00135         dellist_r.clear();
00136         for ( PoolItemList::const_reverse_iterator cit = dsorted.rbegin();
00137               cit != dsorted.rend(); ++cit )
00138           {
00139             dellist_r.push_back( *cit );
00140           }
00141       }
00142 
00144       //
00145       // sort installed list...
00146       //
00148       if ( instlist_r.empty() )
00149         return;
00150 
00152       // Compute install order according to packages prereq.
00153       // Try to group packages with respect to the desired install order
00155       // backup list for debug purpose.
00156       // You can as well build the set, clear the list and rebuild it in install order.
00157       PoolItemList instbackup_r;
00158       instbackup_r.swap( instlist_r );
00159 
00160       PoolItemSet insset( instbackup_r.begin(), instbackup_r.end() ); // for install order
00161       PoolItemSet installed; // dummy, empty, should contain already installed
00162 
00163       InstallOrder order( pool_r, insset, installed );
00164       // start recursive depth-first-search
00165       order.init();
00166       MIL << "order.init() done" << endl;
00167       order.printAdj( XXX, false );
00169       // build install list in install order
00171       PoolItemList best_list;
00172       sat::detail::RepoIdType best_prio     = 0;
00173       unsigned best_medianum = 0;
00174 
00175       PoolItemList last_list;
00176       sat::detail::RepoIdType last_prio     = 0;
00177       unsigned last_medianum = 0;
00178 
00179       PoolItemList other_list;
00180 
00181       for ( PoolItemList items = order.computeNextSet(); ! items.empty(); items = order.computeNextSet() )
00182         {
00183           XXX << "order.computeNextSet: " << items.size() << " resolvables" << endl;
00185           // items contains all objects we could install now. Pick all objects
00186           // from current media, or best media if none for current. Alwayys pick
00187           // objects that do not require media access.
00189 
00190           best_list.clear();
00191           last_list.clear();
00192           other_list.clear();
00193 
00194           for ( PoolItemList::iterator cit = items.begin(); cit != items.end(); ++cit )
00195             {
00196               ResObject::constPtr cobj( cit->resolvable() );
00197               if (!cobj)
00198                 continue;
00199 
00200               if ( ! cobj->mediaNr() ) {
00201                 XXX << "No media access required for " << *cit << endl;
00202                 order.setInstalled( *cit );
00203                 other_list.push_back( *cit );
00204                 continue;
00205               }
00206 
00207               if ( cobj->satSolvable().repository().id() == last_prio &&
00208                    cobj->mediaNr() == last_medianum ) {
00209                 // prefer packages on current media.
00210                 XXX << "Stay with current media " << *cit << endl;
00211                 last_list.push_back( *cit );
00212                 continue;
00213               }
00214 
00215               if ( last_list.empty() ) {
00216                 // check for best media as long as there are no packages for current media.
00217 
00218                 if ( ! best_list.empty() ) {
00219 
00220                   if ( order_r == ORDER_BY_MEDIANR )
00221                     {
00222                       if ( cobj->mediaNr() < best_medianum ) {
00223                         best_list.clear(); // new best
00224                       } else if ( cobj->mediaNr() == best_medianum ) {
00225                         if ( cobj->satSolvable().repository().id() < best_prio ) {
00226                           best_list.clear(); // new best
00227                         } else if ( cobj->satSolvable().repository().id() == best_prio ) {
00228                           XXX << "Add to best list " << *cit << endl;
00229                           best_list.push_back( *cit ); // same as best -> add
00230                           continue;
00231                         } else {
00232                           continue; // worse
00233                         }
00234                       } else {
00235                         continue; // worse
00236                       }
00237                     }
00238                   else // default: ORDER_BY_SOURCE
00239                     {
00240                       if ( cobj->satSolvable().repository().id() < best_prio ) {
00241                         best_list.clear(); // new best
00242                       } else if ( cobj->satSolvable().repository().id() == best_prio ) {
00243                         if ( cobj->mediaNr() < best_medianum ) {
00244                           best_list.clear(); // new best
00245                         } else if ( cobj->mediaNr() == best_medianum ) {
00246                           XXX << "Add to best list " << *cit << endl;
00247                           best_list.push_back( *cit ); // same as best -> add
00248                           continue;
00249                         } else {
00250                           continue; // worse
00251                         }
00252                       } else {
00253                         continue; // worse
00254                       }
00255                     }
00256                 }
00257 
00258                 if ( best_list.empty() )
00259                   {
00260                     XXX << "NEW BEST LIST [S" << cobj->satSolvable().repository().id() << ":" << cobj->mediaNr()
00261                         << "] (last [S" << best_prio << ":" << best_medianum << "])" << endl;
00262                     best_prio     = cobj->satSolvable().repository().id();
00263                     best_medianum = cobj->mediaNr();
00264                     // first package or new best
00265                     XXX << "Add to best list " << *cit << endl;
00266                     best_list.push_back( *cit );
00267                     continue;
00268                   }
00269               }
00270 
00271             } // for all objects in current set
00272 
00274           // remove objects picked from install order and append them to
00275           // install list.
00277           PoolItemList & take_list( last_list.empty() ? best_list : last_list );
00278           if ( last_list.empty() )
00279             {
00280               MIL << "SET NEW media [S" << best_prio << ":" << best_medianum << "]" << endl;
00281               last_prio     = best_prio;
00282               last_medianum = best_medianum;
00283             }
00284           else
00285             {
00286               XXX << "SET CONTINUE [S" << best_prio << ":" << best_medianum << "]" << endl;
00287             }
00288 
00289           for ( PoolItemList::iterator it = take_list.begin(); it != take_list.end(); ++it )
00290             {
00291               order.setInstalled( *it );
00292               XXX << "SET collect " << (*it) << endl;
00293             }
00294           // move everthing from take_list to the end of instlist_r, clean take_list
00295           instlist_r.splice( instlist_r.end(), take_list );
00296           // same for other_list
00297           instlist_r.splice( instlist_r.end(), other_list );
00298 
00299         } // for all sets computed
00300 
00301 
00302       MIL << "order done" << endl;
00303       if ( instbackup_r.size() != instlist_r.size() )
00304         {
00305           ERR << "***************** Lost packages in InstallOrder sort." << endl;
00306         }
00307 
00308     }
00309 
00310     void GetResolvablesToInsDel::debugDiffTransaction() const
00311     {
00312       SEC << "START debugDiffTransaction" << endl;
00313       sat::Transaction trans( ResPool::instance().resolver().getTransaction() );
00314 
00315       {
00316         const PoolItemList & clist( _toDelete );
00317         for_( it, clist.begin(), clist.end() )
00318         {
00319           sat::Transaction::const_iterator ci( trans.find( *it ) );
00320           if ( ci == trans.end() )
00321             ERR << "Missing to del in NEW trans: " << *it << endl;
00322         }
00323       }
00324       {
00325         const PoolItemList & clist( _toInstall );
00326         for_( it, clist.begin(), clist.end() )
00327         {
00328           sat::Transaction::const_iterator ci( trans.find( *it ) );
00329           if ( ci == trans.end() )
00330             ERR << "Missing to ins in NEW trans: " << *it << endl;
00331         }
00332       }
00333       {
00334         const PoolItemList & clist( _toSrcinstall );
00335         for_( it, clist.begin(), clist.end() )
00336         {
00337           sat::Transaction::const_iterator ci( trans.find( *it ) );
00338           if ( ci == trans.end() )
00339             ERR << "Missing srcins in NEW trans: " << *it << endl;
00340         }
00341       }
00342 
00343       SEC << "END debugDiffTransaction" << endl;
00344     }
00345 
00346     /******************************************************************
00347      **
00348      ** FUNCTION NAME : operator<<
00349      ** FUNCTION TYPE : std::ostream &
00350     */
00351     std::ostream & operator<<( std::ostream & str, const GetResolvablesToInsDel & obj )
00352     {
00353       dumpPoolStats( str << "toInstall: " << endl,
00354                      obj._toInstall.begin(), obj._toInstall.end() ) << endl;
00355       dumpPoolStats( str << "toDelete: " << endl,
00356                      obj._toDelete.begin(), obj._toDelete.end() ) << endl;
00357       return str;
00358     }
00359 
00361   } // namespace pool
00364 } // namespace zypp
00366