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/Logger.h"
00016 
00017 #include "zypp/pool/GetResolvablesToInsDel.h"
00018 #include "zypp/pool/PoolStats.h"
00019 
00020 #include "zypp/solver/detail/InstallOrder.h"
00021 
00022 using std::endl;
00023 using zypp::solver::detail::InstallOrder;
00024 
00025 #undef  ZYPP_BASE_LOGGER_LOGGROUP
00026 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::GetResolvablesToInsDel"
00027 
00029 namespace zypp
00030 { 
00031 
00032   namespace pool
00033   { 
00034 
00035     /******************************************************************
00036      **
00037      ** FUNCTION NAME : strip_obsoleted_to_delete
00038      ** FUNCTION TYPE : void
00039      **
00040      ** strip packages to_delete which get obsoleted by
00041      ** to_install (i.e. delay deletion in case the
00042      ** obsoleting package likes to save whatever...
00043     */
00044 
00045     static void
00046     strip_obsoleted_to_delete( GetResolvablesToInsDel::PoolItemList & deleteList_r,
00047                                const GetResolvablesToInsDel::PoolItemList & instlist_r )
00048     {
00049       if ( deleteList_r.size() == 0 || instlist_r.size() == 0 )
00050         return; // ---> nothing to do
00051 
00052       // build obsoletes from instlist_r
00053       CapSet obsoletes;
00054       for ( GetResolvablesToInsDel::PoolItemList::const_iterator it = instlist_r.begin();
00055             it != instlist_r.end(); ++it )
00056         {
00057           PoolItem_Ref item( *it );
00058           obsoletes.insert( item->dep(Dep::OBSOLETES).begin(), item->dep(Dep::OBSOLETES).end() );
00059         }
00060       if ( obsoletes.size() == 0 )
00061         return; // ---> nothing to do
00062 
00063       // match them... ;(
00064       GetResolvablesToInsDel::PoolItemList undelayed;
00065       // forall applDelete Packages...
00066       for ( GetResolvablesToInsDel::PoolItemList::iterator it = deleteList_r.begin();
00067             it != deleteList_r.end(); ++it )
00068         {
00069           PoolItem_Ref ipkg( *it );
00070           bool delayPkg = false;
00071           // ...check whether an obsoletes....
00072           for ( CapSet::iterator obs = obsoletes.begin();
00073                 ! delayPkg && obs != obsoletes.end(); ++obs )
00074             {
00075               // ...matches anything provided by the package?
00076               for ( CapSet::const_iterator prov = ipkg->dep(Dep::PROVIDES).begin();
00077                     prov != ipkg->dep(Dep::PROVIDES).end(); ++prov )
00078                 {
00079                   if ( obs->matches( *prov ) == CapMatch::yes )
00080                     {
00081                       // if so, delay package deletion
00082                       DBG << "Ignore appl_delete (should be obsoleted): " << ipkg << endl;
00083                       delayPkg = true;
00084                       ipkg.status().resetTransact( ResStatus::USER );
00085                       break;
00086                     }
00087                 }
00088             }
00089           if ( ! delayPkg ) {
00090             DBG << "undelayed " << ipkg << endl;
00091             undelayed.push_back( ipkg );
00092           }
00093         }
00094       // Puhh...
00095       deleteList_r.swap( undelayed );
00096     }
00097 
00099     //
00100     //  METHOD NAME : GetResolvablesToInsDel::GetResolvablesToInsDel
00101     //  METHOD TYPE : Ctor
00102     //
00103     GetResolvablesToInsDel::GetResolvablesToInsDel( ResPool pool_r, Order order_r )
00104     {
00105       typedef std::set<PoolItem_Ref> PoolItemSet;
00106 
00107       PoolItemList & dellist_r( _toDelete );
00108       PoolItemList & instlist_r( _toInstall );
00109       PoolItemList & srclist_r( _toSrcinstall );
00110 
00111       for ( ResPool::const_iterator it = pool_r.begin(); it != pool_r.end(); ++it )
00112         {
00113           if (it->status().isToBeInstalled())
00114             {
00115               if ((*it)->kind() == ResTraits<SrcPackage>::kind) {
00116                 srclist_r.push_back( *it );
00117               }
00118               else
00119                 instlist_r.push_back( *it );
00120             }
00121           else if (it->status().isToBeUninstalled())
00122             {
00123               if ( it->status().isToBeUninstalledDueToObsolete() )
00124                 {
00125                   DBG << "Ignore auto_delete (should be obsoleted): " << *it << endl;
00126                 }
00127               else if ( it->status().isToBeUninstalledDueToUpgrade() )
00128                 {
00129                   DBG << "Ignore auto_delete (should be upgraded): " << *it << endl;
00130                 }
00131               else {
00132                 dellist_r.push_back( *it );
00133               }
00134             }
00135         }
00136 
00137       MIL << "ResolvablesToInsDel: delete " << dellist_r.size()
00138       << ", install " << instlist_r.size()
00139       << ", srcinstall " << srclist_r.size() << endl;
00140 
00142       //
00143       // strip packages to_delete which get obsoleted by
00144       // to_install (i.e. delay deletion in case the
00145       // obsoleting package likes to save whatever...
00146       //
00148       strip_obsoleted_to_delete( dellist_r, instlist_r );
00149 
00150       if ( dellist_r.size() ) {
00152         //
00153         // sort delete list...
00154         //
00156         PoolItemSet delset( dellist_r.begin(), dellist_r.end() );  // for delete order
00157         PoolItemSet dummy; // dummy, empty, should contain already installed
00158 
00159         InstallOrder order( pool_r, delset, dummy ); // sort according top prereq
00160         order.init();
00161         const PoolItemList dsorted( order.getTopSorted() );
00162 
00163         dellist_r.clear();
00164         for ( PoolItemList::const_reverse_iterator cit = dsorted.rbegin();
00165               cit != dsorted.rend(); ++cit )
00166           {
00167             dellist_r.push_back( *cit );
00168           }
00169       }
00170 
00172       //
00173       // sort installed list...
00174       //
00176       if ( instlist_r.empty() )
00177         return;
00178 
00180       // Compute install order according to packages prereq.
00181       // Try to group packages with respect to the desired install order
00183       // backup list for debug purpose.
00184       // You can as well build the set, clear the list and rebuild it in install order.
00185       PoolItemList instbackup_r;
00186       instbackup_r.swap( instlist_r );
00187 
00188       PoolItemSet insset( instbackup_r.begin(), instbackup_r.end() ); // for install order
00189       PoolItemSet installed; // dummy, empty, should contain already installed
00190 
00191       InstallOrder order( pool_r, insset, installed );
00192       // start recursive depth-first-search
00193       order.init();
00194       MIL << "order.init() done" << endl;
00195       order.printAdj( XXX, false );
00197       // build install list in install order
00199       PoolItemList best_list;
00200       unsigned best_prio     = 0;
00201       unsigned best_medianum = 0;
00202 
00203       PoolItemList last_list;
00204       unsigned last_prio     = 0;
00205       unsigned last_medianum = 0;
00206 
00207       PoolItemList other_list;
00208 
00209       for ( PoolItemList items = order.computeNextSet(); ! items.empty(); items = order.computeNextSet() )
00210         {
00211           MIL << "order.computeNextSet: " << items.size() << " resolvables" << endl;
00213           // items contains all objects we could install now. Pick all objects
00214           // from current media, or best media if none for current. Alwayys pick
00215           // objects that do not require media access.
00217 
00218           best_list.clear();
00219           last_list.clear();
00220           other_list.clear();
00221 
00222           for ( PoolItemList::iterator cit = items.begin(); cit != items.end(); ++cit )
00223             {
00224               ResObject::constPtr cobj( cit->resolvable() );
00225               if (!cobj)
00226                 continue;
00227 
00228               if ( ! cobj->sourceMediaNr() ) {
00229                 XXX << "No media access required for " << *cit << endl;
00230                 order.setInstalled( *cit );
00231                 other_list.push_back( *cit );
00232                 continue;
00233               }
00234 
00235               if ( cobj->source().numericId() == last_prio &&
00236                    cobj->sourceMediaNr() == last_medianum ) {
00237                 // prefer packages on current media.
00238                 XXX << "Stay with current media " << *cit << endl;
00239                 last_list.push_back( *cit );
00240                 continue;
00241               }
00242 
00243               if ( last_list.empty() ) {
00244                 // check for best media as long as there are no packages for current media.
00245 
00246                 if ( ! best_list.empty() ) {
00247 
00248                   if ( order_r == ORDER_BY_MEDIANR )
00249                     {
00250                       if ( cobj->sourceMediaNr() < best_medianum ) {
00251                         best_list.clear(); // new best
00252                       } else if ( cobj->sourceMediaNr() == best_medianum ) {
00253                         if ( cobj->source().numericId() < best_prio ) {
00254                           best_list.clear(); // new best
00255                         } else if ( cobj->source().numericId() == best_prio ) {
00256                           XXX << "Add to best list " << *cit << endl;
00257                           best_list.push_back( *cit ); // same as best -> add
00258                           continue;
00259                         } else {
00260                           continue; // worse
00261                         }
00262                       } else {
00263                         continue; // worse
00264                       }
00265                     }
00266                   else // default: ORDER_BY_SOURCE
00267                     {
00268                       if ( cobj->source().numericId() < best_prio ) {
00269                         best_list.clear(); // new best
00270                       } else if ( cobj->source().numericId() == best_prio ) {
00271                         if ( cobj->sourceMediaNr() < best_medianum ) {
00272                           best_list.clear(); // new best
00273                         } else if ( cobj->sourceMediaNr() == best_medianum ) {
00274                           XXX << "Add to best list " << *cit << endl;
00275                           best_list.push_back( *cit ); // same as best -> add
00276                           continue;
00277                         } else {
00278                           continue; // worse
00279                         }
00280                       } else {
00281                         continue; // worse
00282                       }
00283                     }
00284                 }
00285 
00286                 if ( best_list.empty() )
00287                   {
00288                     XXX << "NEW BEST LIST [S" << cobj->source().numericId() << ":" << cobj->sourceMediaNr()
00289                         << "] (last [S" << best_prio << ":" << best_medianum << "])" << endl;
00290                     best_prio     = cobj->source().numericId();
00291                     best_medianum = cobj->sourceMediaNr();
00292                     // first package or new best
00293                     XXX << "Add to best list " << *cit << endl;
00294                     best_list.push_back( *cit );
00295                     continue;
00296                   }
00297               }
00298 
00299             } // for all objects in current set
00300 
00302           // remove objects picked from install order and append them to
00303           // install list.
00305           PoolItemList & take_list( last_list.empty() ? best_list : last_list );
00306           if ( last_list.empty() )
00307             {
00308               MIL << "SET NEW media [S" << best_prio << ":" << best_medianum << "]" << endl;
00309               last_prio     = best_prio;
00310               last_medianum = best_medianum;
00311             }
00312           else
00313             {
00314               MIL << "SET CONTINUE [S" << best_prio << ":" << best_medianum << "]" << endl;
00315             }
00316 
00317           for ( PoolItemList::iterator it = take_list.begin(); it != take_list.end(); ++it )
00318             {
00319               order.setInstalled( *it );
00320               XXX << "SET collect " << (*it) << endl;
00321             }
00322           // move everthing from take_list to the end of instlist_r, clean take_list
00323           instlist_r.splice( instlist_r.end(), take_list );
00324           // same for other_list
00325           instlist_r.splice( instlist_r.end(), other_list );
00326 
00327         } // for all sets computed
00328 
00329 
00330       if ( instbackup_r.size() != instlist_r.size() )
00331         {
00332           ERR << "***************** Lost packages in InstallOrder sort." << endl;
00333         }
00334 
00335     }
00336 
00337     /******************************************************************
00338      **
00339      ** FUNCTION NAME : operator<<
00340      ** FUNCTION TYPE : std::ostream &
00341     */
00342     std::ostream & operator<<( std::ostream & str, const GetResolvablesToInsDel & obj )
00343     {
00344       dumpPoolStats( str << "toInstall: " << endl,
00345                      obj._toInstall.begin(), obj._toInstall.end() ) << endl;
00346       dumpPoolStats( str << "toDelete: " << endl,
00347                      obj._toDelete.begin(), obj._toDelete.end() ) << endl;
00348       return str;
00349     }
00350 
00352   } // namespace pool
00355 } // namespace zypp
00357 

Generated on Thu Jul 6 00:07:22 2006 for zypp by  doxygen 1.4.6