TargetImpl.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <sys/types.h>
00013 #include <sys/stat.h>
00014 
00015 #include <iostream>
00016 #include <string>
00017 #include <list>
00018 #include <set>
00019 
00020 #include "zypp/base/Logger.h"
00021 #include "zypp/base/Exception.h"
00022 #include "zypp/base/Gettext.h"
00023 #include "zypp/PoolItem.h"
00024 #include "zypp/Resolvable.h"
00025 #include "zypp/ResObject.h"
00026 #include "zypp/Package.h"
00027 #include "zypp/Script.h"
00028 #include "zypp/Message.h"
00029 #include "zypp/Source.h"
00030 #include "zypp/Url.h"
00031 
00032 #include "zypp/target/TargetImpl.h"
00033 #include "zypp/target/TargetCallbackReceiver.h"
00034 
00035 #include "zypp/solver/detail/Helper.h"
00036 #include "zypp/solver/detail/InstallOrder.h"
00037 
00038 using namespace std;
00039 using zypp::solver::detail::Helper;
00040 using zypp::solver::detail::InstallOrder;
00041 
00043 namespace zypp
00044 { 
00045 
00046   namespace target
00047   { 
00048 
00050     namespace
00051     { 
00052 
00053       struct PubKeyHelper
00054       {
00055       };
00056 
00058     } // namespace
00060 
00061     IMPL_PTR_TYPE(TargetImpl);
00062 
00063     TargetImpl_Ptr TargetImpl::_nullimpl;
00064 
00066     TargetImpl_Ptr TargetImpl::nullimpl()
00067     {
00068       if (_nullimpl == 0)
00069         _nullimpl = new TargetImpl;
00070       return _nullimpl;
00071     }
00072 
00073 
00075     //
00076     //  METHOD NAME : TargetImpl::TargetImpl
00077     //  METHOD TYPE : Ctor
00078     //
00079     TargetImpl::TargetImpl(const Pathname & root_r)
00080     : _root(root_r)
00081     {
00082       _rpm.initDatabase(_root);
00083       _storage_enabled = false;
00084       MIL << "Initialized target on " << _root << endl;
00085     }
00086 
00088     //
00089     //  METHOD NAME : TargetImpl::~TargetImpl
00090     //  METHOD TYPE : Dtor
00091     //
00092     TargetImpl::~TargetImpl()
00093     {
00094       _rpm.closeDatabase();
00095       MIL << "Targets closed" << endl;
00096     }
00097 
00098     bool TargetImpl::isStorageEnabled() const
00099     {
00100       return _storage_enabled;
00101     }
00102 
00103 
00104     void TargetImpl::enableStorage(const Pathname &root_r)
00105     {
00106       _storage.init(root_r);
00107       _storage_enabled = true;
00108     }
00109 
00110     Pathname TargetImpl::root() const
00111     {
00112       return _root;
00113     }
00114 
00115     const ResStore & TargetImpl::resolvables()
00116     {
00117       _store.clear();
00118       // RPM objects
00119       std::list<Package::Ptr> packages = _rpm.getPackages();
00120       for (std::list<Package::Ptr>::const_iterator it = packages.begin();
00121            it != packages.end();
00122            it++)
00123       {
00124         _store.insert(*it);
00125       }
00126 
00127       if ( isStorageEnabled() )
00128       {
00129         // resolvables stored in the zypp storage database
00130         std::list<ResObject::Ptr> resolvables = _storage.storedObjects();
00131         for (std::list<ResObject::Ptr>::iterator it = resolvables.begin();
00132             it != resolvables.end();
00133             it++)
00134         {
00135           _store.insert(*it);
00136         }
00137       }
00138       else
00139       {
00140         WAR << "storage target not enabled" << std::endl;
00141       }
00142 
00143       return _store;
00144     }
00145 
00146 
00147 
00148     ZYppCommitResult TargetImpl::commit( ResPool pool_r, const ZYppCommitPolicy & policy_r )
00149     {
00150       MIL << "TargetImpl::commit(<pool>, " << policy_r << ")" << endl;
00151       ZYppCommitResult result;
00152 #warning Commit does not provide ZYppCommitResult::_errors
00153 
00154       TargetImpl::PoolItemList to_uninstall;
00155       TargetImpl::PoolItemList to_install;
00156       TargetImpl::PoolItemList to_srcinstall;
00157       getResolvablesToInsDel( pool_r, to_uninstall, to_install, to_srcinstall );
00158 
00159       if ( policy_r.restrictToMedia() ) {
00160         MIL << "Restrict to media number " << policy_r.restrictToMedia() << endl;
00161       }
00162 
00163       commit (to_uninstall, policy_r, pool_r );
00164 
00165       if (policy_r.restrictToMedia() == 0) {                    // commit all
00166         result._remaining = commit( to_install, policy_r, pool_r );
00167         result._srcremaining = commit( to_srcinstall, policy_r, pool_r );
00168       }
00169       else
00170       {
00171         TargetImpl::PoolItemList current_install;
00172         TargetImpl::PoolItemList current_srcinstall;
00173 
00174         for (TargetImpl::PoolItemList::iterator it = to_install.begin(); it != to_install.end(); ++it)
00175         {
00176           Resolvable::constPtr res( it->resolvable() );
00177           Package::constPtr pkg( asKind<Package>(res) );
00178           if (pkg && policy_r.restrictToMedia() != pkg->mediaId())                                                              // check medianr for packages only
00179           {
00180             XXX << "Package " << *pkg << ", wrong media " << pkg->mediaId() << endl;
00181             result._remaining.push_back( *it );
00182           }
00183           else
00184           {
00185             current_install.push_back( *it );
00186           }
00187         }
00188         TargetImpl::PoolItemList bad = commit( current_install, policy_r, pool_r );
00189         result._remaining.insert(result._remaining.end(), bad.begin(), bad.end());
00190 
00191         for (TargetImpl::PoolItemList::iterator it = to_srcinstall.begin(); it != to_srcinstall.end(); ++it)
00192         {
00193           Resolvable::constPtr res( it->resolvable() );
00194           Package::constPtr pkg( asKind<Package>(res) );
00195           if (pkg && policy_r.restrictToMedia() != pkg->mediaId()) // check medianr for packages only
00196           {
00197             XXX << "Package " << *pkg << ", wrong media " << pkg->mediaId() << endl;
00198             result._srcremaining.push_back( *it );
00199           }
00200           else {
00201             current_srcinstall.push_back( *it );
00202           }
00203         }
00204         bad = commit( current_srcinstall, policy_r, pool_r );
00205         result._srcremaining.insert(result._srcremaining.end(), bad.begin(), bad.end());
00206       }
00207 
00208 
00209       result._result = (to_install.size() - result._remaining.size());
00210       return result;
00211     }
00212 
00213 
00214     TargetImpl::PoolItemList
00215     TargetImpl::commit( const TargetImpl::PoolItemList & items_r,
00216                         const ZYppCommitPolicy & policy_r,
00217                         const ResPool & pool_r )
00218     {
00219       TargetImpl::PoolItemList remaining;
00220 
00221       MIL << "TargetImpl::commit(<list>" << policy_r << ")" << endl;
00222 
00223       bool abort = false;
00224 
00225       // remember the last used source (if any)
00226       Source_Ref lastUsedSource;
00227 
00228       for (TargetImpl::PoolItemList::const_iterator it = items_r.begin(); it != items_r.end(); it++)
00229       {
00230         if (isKind<Package>(it->resolvable()))
00231         {
00232           Package::constPtr p = dynamic_pointer_cast<const Package>(it->resolvable());
00233           if (it->status().isToBeInstalled())
00234           {
00235             Pathname localfile;
00236             try {
00237                 localfile = p->source().providePackage(p);
00238             }
00239             catch( const source::SkipRequestedException & e )
00240             {
00241                 ZYPP_CAUGHT( e );
00242                 WAR << "Skipping package " << p << " in commit" << endl;
00243                 continue;
00244             }
00245 
00246             lastUsedSource = p->source();                       // remember the package source
00247 
00248 #warning Exception handling
00249             // create a installation progress report proxy
00250             RpmInstallPackageReceiver progress( it->resolvable() );
00251             progress.connect();
00252             bool success = true;
00253             unsigned flags = 0;
00254             if (p->installOnly()) flags |= rpm::RpmDb::RPMINST_NOUPGRADE;
00255             if (policy_r.dryRun()) flags |= rpm::RpmDb::RPMINST_TEST;
00256             if (policy_r.rpmNoSignature()) flags |= rpm::RpmDb::RPMINST_NOSIGNATURE;
00257 
00258             try {
00259               progress.tryLevel( target::rpm::InstallResolvableReport::RPM );
00260               rpm().installPackage( localfile, flags );
00261 
00262               if( progress.aborted() )
00263               {
00264                 WAR << "commit aborted by the user" << endl;
00265                 progress.disconnect();
00266                 abort = true;
00267                 break;
00268               }
00269 
00270             }
00271             catch (Exception & excpt_r) {
00272               ZYPP_CAUGHT(excpt_r);
00273               WAR << "Install failed, retrying with --nodeps" << endl;
00274               if (policy_r.dryRun()) {
00275                   WAR << "dry run failed" << endl;
00276                   progress.disconnect();
00277                   break;
00278               }
00279 
00280               try {
00281                 progress.tryLevel( target::rpm::InstallResolvableReport::RPM_NODEPS );
00282                 flags |= rpm::RpmDb::RPMINST_NODEPS;
00283                 rpm().installPackage( localfile, flags );
00284 
00285                 if( progress.aborted() )
00286                 {
00287                   WAR << "commit aborted by the user" << endl;
00288                   abort = true;
00289                   progress.disconnect();
00290                   break;
00291                 }
00292               }
00293               catch (Exception & excpt_r)
00294               {
00295                 ZYPP_CAUGHT(excpt_r);
00296                 WAR << "Install failed again, retrying with --force --nodeps" << endl;
00297 
00298                 try {
00299                   progress.tryLevel( target::rpm::InstallResolvableReport::RPM_NODEPS_FORCE );
00300                   flags |= rpm::RpmDb::RPMINST_FORCE;
00301                   rpm().installPackage( localfile, flags );
00302                 }
00303                 catch (Exception & excpt_r) {
00304                   remaining.push_back( *it );
00305                   success = false;
00306                   ZYPP_CAUGHT(excpt_r);
00307                 }
00308 
00309                 if( progress.aborted() )
00310                 {
00311                     WAR << "commit aborted by the user" << endl;
00312                     abort = true;
00313                     progress.disconnect();
00314                     break;
00315                 }
00316               }
00317             }
00318             if (success
00319                 && !policy_r.dryRun())
00320             {
00321               it->status().resetTransact( ResStatus::USER );
00322             }
00323             progress.disconnect();
00324             p->source().releaseFile( p->location(), p->mediaId() );
00325           }
00326           else
00327           {
00328             bool success = true;
00329 
00330             RpmRemovePackageReceiver progress( it->resolvable() );
00331             progress.connect();
00332             unsigned flags = rpm::RpmDb::RPMINST_NODEPS;
00333             if (policy_r.dryRun()) flags |= rpm::RpmDb::RPMINST_TEST;
00334             try {
00335               rpm().removePackage( p, flags );
00336             }
00337             catch (Exception & excpt_r) {
00338               WAR << "removal of " << p << " failed";
00339               success = false;
00340               ZYPP_CAUGHT( excpt_r );
00341             }
00342             if (success
00343                 && !policy_r.dryRun())
00344             {
00345               it->status().resetTransact( ResStatus::USER );
00346             }
00347             progress.disconnect();
00348           }
00349         }
00350         else if (!policy_r.dryRun()) // other resolvables (non-Package)
00351         {
00352           if ( isStorageEnabled() )
00353           {
00354             if (it->status().isToBeInstalled())
00355             {
00356               bool success = false;
00357               try
00358               {
00359                 if (isKind<Message>(it->resolvable()))
00360                 {
00361                   Message::constPtr m = dynamic_pointer_cast<const Message>(it->resolvable());
00362                   std::string text = m->text().asString();
00363 
00364                   callback::SendReport<target::MessageResolvableReport> report;
00365 
00366                   report->show( m );
00367 
00368                   MIL << "Displaying the text '" << text << "'" << endl;
00369                 }
00370                 else if (isKind<Script>(it->resolvable()))
00371                 {
00372                   Script::constPtr s = dynamic_pointer_cast<const Script>(it->resolvable());
00373                   Pathname p = s->do_script();
00374                   if (p != "" && p != "/")
00375                   {
00376                     chmod( p.asString().c_str(), S_IRUSR|S_IXUSR );     // "r-x------"
00377                     ExternalProgram* prog = new ExternalProgram(p.asString(), ExternalProgram::Discard_Stderr, false, -1, true);
00378                     if (! prog)
00379                       ZYPP_THROW(Exception("Cannot run the script"));
00380                     int retval = prog->close();
00381                     delete prog;
00382                     if (retval != 0)
00383                       ZYPP_THROW(Exception("Exit code of script is non-zero"));
00384                   }
00385                   else
00386                   {
00387                     ERR << "Do script not defined" << endl;
00388                   }
00389                 }
00390                 else if (!isKind<Atom>(it->resolvable()))       // atoms are re-created from the patch data, no need to save them
00391                 {
00392                   // #160792 do not just add, also remove older versions
00393                   if (true) // !installOnly - only on Package?!
00394                   {
00395                     // this would delete the same item over and over
00396                     //for (PoolItem_Ref old = Helper::findInstalledItem (pool_r, *it); old; )
00397                     PoolItem_Ref old = Helper::findInstalledItem (pool_r, *it);
00398                     if (old)
00399                     {
00400                       _storage.deleteObject(old.resolvable());
00401                     }
00402                   }
00403                   _storage.storeObject(it->resolvable());
00404                 }
00405                 success = true;
00406               }
00407               catch (Exception & excpt_r)
00408               {
00409                 ZYPP_CAUGHT(excpt_r);
00410                 WAR << "Install of Resolvable from storage failed" << endl;
00411               }
00412               if (success)
00413                 it->status().resetTransact( ResStatus::USER );
00414             }
00415             else
00416             {                                   // isToBeUninstalled
00417               bool success = false;
00418               try
00419               {
00420                 if (isKind<Message>(it->resolvable()))
00421                 {
00422                   DBG << "Uninstalling message - no-op" << endl;
00423                 }
00424                 else if (isKind<Script>(it->resolvable()))
00425                 {
00426                   Script::constPtr s = dynamic_pointer_cast<const Script>(it->resolvable());
00427                   Pathname p = s->undo_script();
00428                   if (! s->undo_available())
00429                   {
00430                     DBG << "Undo script not available" << endl;
00431                   }
00432                   if (p != "" && p != "/")
00433                   {
00434                     ExternalProgram* prog = new ExternalProgram(p.asString(), ExternalProgram::Discard_Stderr, false, -1, true);
00435                     if (! prog)
00436                       ZYPP_THROW(Exception("Cannot run the script"));
00437                     int retval = prog->close();
00438                     delete prog;
00439                     if (retval != 0)
00440                       ZYPP_THROW(Exception("Exit code of script is non-zero"));
00441                   }
00442                   else
00443                   {
00444                     ERR << "Undo script not defined" << endl;
00445                   }
00446                 }
00447                 else
00448                 {
00449                   _storage.deleteObject(it->resolvable());
00450                 }
00451                 success = true;
00452               }
00453               catch (Exception & excpt_r)
00454               {
00455                 ZYPP_CAUGHT(excpt_r);
00456                 WAR << "Uninstall of Resolvable from storage failed" << endl;
00457               }
00458               if (success)
00459                 it->status().resetTransact( ResStatus::USER );
00460             }
00461           }
00462           else
00463           {
00464             WAR << "storage target disabled" << std::endl;
00465           }
00466 
00467         }  // other resolvables
00468 
00469       } // for
00470 
00471       // we're done with the commit, release the source media
00472       //   In the case of a single media, end of commit means we don't need _this_
00473       //   media any more.
00474       //   In the case of 'commit any media', end of commit means we're completely
00475       //   done and don't need the source's media anyways.
00476 
00477       if (lastUsedSource) {             // if a source was used
00478         lastUsedSource.release();       //  release their medias
00479       }
00480 
00481       if( abort )
00482         ZYPP_THROW( TargetAbortedException( N_("Target commit aborted by user.") ) );
00483 
00484       return remaining;
00485     }
00486 
00487     rpm::RpmDb & TargetImpl::rpm()
00488     { return _rpm; }
00489 
00490     bool TargetImpl::providesFile (const std::string & path_str, const std::string & name_str) const
00491     { return _rpm.hasFile(path_str, name_str); }
00492 
00495     ResObject::constPtr TargetImpl::whoOwnsFile (const std::string & path_str) const
00496     {
00497         string name = _rpm.whoOwnsFile (path_str);
00498         if (name.empty())
00499             return NULL;
00500 
00501         for (ResStore::const_iterator it = _store.begin(); it != _store.end(); ++it) {
00502             if ((*it)->name() == name) {
00503                 return *it;
00504             }
00505         }
00506         return NULL;
00507     }
00508 
00510     bool TargetImpl::setInstallationLogfile(const Pathname & path_r)
00511     {
00512       return rpm::RpmDb::setInstallationLogfile(path_r);
00513     }
00514 
00515 //-----------------------------------------------------------------------------
00516 /******************************************************************
00517 **
00518 **
00519 **      FUNCTION NAME : strip_obsoleted_to_delete
00520 **      FUNCTION TYPE : void
00521 **
00522 ** strip packages to_delete which get obsoleted by
00523 ** to_install (i.e. delay deletion in case the
00524 ** obsoleting package likes to save whatever...
00525 */
00526 
00527 static void
00528 strip_obsoleted_to_delete( TargetImpl::PoolItemList & deleteList_r,
00529                                 const TargetImpl::PoolItemList & instlist_r )
00530 {
00531   if ( deleteList_r.size() == 0 || instlist_r.size() == 0 )
00532     return; // ---> nothing to do
00533 
00534   // build obsoletes from instlist_r
00535   CapSet obsoletes;
00536   for ( TargetImpl::PoolItemList::const_iterator it = instlist_r.begin();
00537         it != instlist_r.end(); ++it )
00538   {
00539     PoolItem_Ref item( *it );
00540     obsoletes.insert( item->dep(Dep::OBSOLETES).begin(), item->dep(Dep::OBSOLETES).end() );
00541   }
00542   if ( obsoletes.size() == 0 )
00543     return; // ---> nothing to do
00544 
00545   // match them... ;(
00546   TargetImpl::PoolItemList undelayed;
00547   // forall applDelete Packages...
00548   for ( TargetImpl::PoolItemList::iterator it = deleteList_r.begin();
00549         it != deleteList_r.end(); ++it )
00550   {
00551     PoolItem_Ref ipkg( *it );
00552     bool delayPkg = false;
00553     // ...check whether an obsoletes....
00554     for ( CapSet::iterator obs = obsoletes.begin();
00555           ! delayPkg && obs != obsoletes.end(); ++obs )
00556     {
00557       // ...matches anything provided by the package?
00558       for ( CapSet::const_iterator prov = ipkg->dep(Dep::PROVIDES).begin();
00559             prov != ipkg->dep(Dep::PROVIDES).end(); ++prov )
00560       {
00561         if ( obs->matches( *prov ) == CapMatch::yes )
00562         {
00563           // if so, delay package deletion
00564           DBG << "Ignore appl_delete (should be obsoleted): " << ipkg << endl;
00565           delayPkg = true;
00566           ipkg.status().resetTransact( ResStatus::USER );
00567           break;
00568         }
00569       }
00570     }
00571     if ( ! delayPkg ) {
00572       DBG << "undelayed " << ipkg << endl;
00573       undelayed.push_back( ipkg );
00574     }
00575   }
00576   // Puhh...
00577   deleteList_r.swap( undelayed );
00578 }
00579 
00580 
00581 
00582 
00583 void
00584 TargetImpl::getResolvablesToInsDel ( const ResPool pool_r,
00585                                     TargetImpl::PoolItemList & dellist_r,
00586                                     TargetImpl::PoolItemList & instlist_r,
00587                                     TargetImpl::PoolItemList & srclist_r ) const
00588 {
00589     dellist_r.clear();
00590     instlist_r.clear();
00591     srclist_r.clear();
00592     TargetImpl::PoolItemList nonpkglist;
00593 
00594     for ( ResPool::const_iterator it = pool_r.begin(); it != pool_r.end(); ++it )
00595     {
00596         if (it->status().isToBeInstalled())
00597         {
00598             if ((*it)->kind() == ResTraits<SrcPackage>::kind) {
00599                 srclist_r.push_back( *it );
00600             }
00601             else if ((*it)->kind() != ResTraits<Package>::kind) {
00602                 nonpkglist.push_back( *it );
00603             }
00604             else
00605                 instlist_r.push_back( *it );
00606         }
00607         else if (it->status().isToBeUninstalled())
00608         {
00609             if ( it->status().isToBeUninstalledDueToObsolete() )
00610             {
00611                 DBG << "Ignore auto_delete (should be obsoleted): " << *it << endl;
00612             }
00613             else if ( it->status().isToBeUninstalledDueToUpgrade() )
00614             {
00615                 DBG << "Ignore auto_delete (should be upgraded): " << *it << endl;
00616             }
00617             else {
00618                 dellist_r.push_back( *it );
00619             }
00620         }
00621     }
00622 
00623     MIL << "ResolvablesToInsDel: delete " << dellist_r.size()
00624       << ", install " << instlist_r.size()
00625         << ", srcinstall " << srclist_r.size()
00626           << ", nonpkg " << nonpkglist.size() << endl;
00627 
00629     //
00630     // strip packages to_delete which get obsoleted by
00631     // to_install (i.e. delay deletion in case the
00632     // obsoleting package likes to save whatever...
00633     //
00635     strip_obsoleted_to_delete( dellist_r, instlist_r );
00636 
00637     if ( dellist_r.size() ) {
00639       //
00640       // sort delete list...
00641       //
00643       TargetImpl::PoolItemSet delset( dellist_r.begin(), dellist_r.end() );  // for delete order
00644       TargetImpl::PoolItemSet dummy; // dummy, empty, should contain already installed
00645 
00646       InstallOrder order( pool_r, delset, dummy ); // sort according top prereq
00647       order.init();
00648       const TargetImpl::PoolItemList dsorted( order.getTopSorted() );
00649 
00650       dellist_r.clear();
00651       for ( TargetImpl::PoolItemList::const_reverse_iterator cit = dsorted.rbegin();
00652             cit != dsorted.rend(); ++cit )
00653       {
00654         dellist_r.push_back( *cit );
00655       }
00656     }
00657 
00659     //
00660     // sort installed list...
00661     //
00663     if ( instlist_r.empty() ) {
00664       instlist_r.splice( instlist_r.end(), nonpkglist );
00665 
00666       return;
00667     }
00668 #warning Source Rank Priority ?
00669 #if 0
00670 
00671     // Get desired order of InstSrc'es to install from.
00673     typedef map<unsigned,unsigned> RankPriority;
00674 
00675     RankPriority rankPriority;
00676     {
00677       InstSrcManager::ISrcIdList sourcerank( Y2PM::instSrcManager().instOrderSources() );
00678       // map InstSrc rank to install priority
00679       unsigned prio = 0;
00680       for ( InstSrcManager::ISrcIdList::const_iterator it = sourcerank.begin();
00681             it != sourcerank.end(); ++it, ++prio ) {
00682         rankPriority[(*it)->descr()->default_rank()] = prio;
00683       }
00684     }
00685 #endif
00686 
00688     // Compute install order according to packages prereq.
00689     // Try to group packages with respect to the desired install order
00691     // backup list for debug purpose.
00692     // You can as well build the set, clear the list and rebuild it in install order.
00693     TargetImpl::PoolItemList instbackup_r;
00694     instbackup_r.swap( instlist_r );
00695 
00696     TargetImpl::PoolItemSet insset( instbackup_r.begin(), instbackup_r.end() ); // for install order
00697     TargetImpl::PoolItemSet installed; // dummy, empty, should contain already installed
00698 
00699     InstallOrder order( pool_r, insset, installed );
00700     // start recursive depth-first-search
00701     order.init();
00702     MIL << "order.init() done" << endl;
00703     order.printAdj( XXX, false );
00705     // build install list in install order
00707     TargetImpl::PoolItemList best_list;
00708     unsigned best_prio     = 0;
00709     unsigned best_medianum = 0;
00710 
00711     TargetImpl::PoolItemList last_list;
00712     unsigned last_prio     = 0;
00713     unsigned last_medianum = 0;
00714 
00715     TargetImpl::PoolItemList other_list;
00716 
00717     for ( TargetImpl::PoolItemList items = order.computeNextSet(); ! items.empty(); items = order.computeNextSet() )
00718     {
00719 MIL << "order.computeNextSet: " << items.size() << " resolvables" << endl;
00721       // items contains all packages we could install now. Pick all packages
00722       // from current media, or best media if none for current.
00724 
00725       best_list.clear();
00726       last_list.clear();
00727       other_list.clear();
00728 
00729       for ( TargetImpl::PoolItemList::iterator cit = items.begin(); cit != items.end(); ++cit )
00730       {
00731         Resolvable::constPtr res( cit->resolvable() );
00732         if (!res) continue;
00733         Package::constPtr cpkg( asKind<Package>(res) );
00734         if (!cpkg) {
00735             XXX << "Not a package " << *cit << endl;
00736             order.setInstalled( *cit );
00737             other_list.push_back( *cit );
00738             continue;
00739         }
00740         XXX << "Package " << *cpkg << ", media " << cpkg->mediaId() << " last_medianum " << last_medianum << " best_medianum " << best_medianum << endl;
00741         if ( cpkg->source().numericId() == last_prio &&
00742              cpkg->mediaId() == last_medianum ) {
00743           // prefer packages on current media.
00744           last_list.push_back( *cit );
00745           continue;
00746         }
00747 
00748         if ( last_list.empty() ) {
00749           // check for best media as long as there are no packages for current media.
00750 
00751           if ( ! best_list.empty() ) {
00752 
00753             if ( cpkg->source().numericId() < best_prio ) {
00754               best_list.clear(); // new best
00755             } else if ( cpkg->source().numericId() == best_prio ) {
00756               if ( cpkg->mediaId() < best_medianum ) {
00757                 best_list.clear(); // new best
00758               } else if ( cpkg->mediaId() == best_medianum ) {
00759                 best_list.push_back( *cit ); // same as best -> add
00760                 continue;
00761               } else {
00762                 continue; // worse
00763               }
00764             } else {
00765               continue; // worse
00766             }
00767           }
00768 
00769           if ( best_list.empty() )
00770           {
00771             // first package or new best
00772             best_list.push_back( *cit );
00773             best_prio     = cpkg->source().numericId();
00774             best_medianum = cpkg->mediaId();
00775             continue;
00776           }
00777         }
00778 
00779       } // for all packages in current set
00780 
00782       // remove packages picked from install order and append them to
00783       // install list.
00785       TargetImpl::PoolItemList & take_list( last_list.empty() ? best_list : last_list );
00786       if ( last_list.empty() )
00787       {
00788         MIL << "SET NEW media " << best_medianum << endl;
00789         last_prio     = best_prio;
00790         last_medianum = best_medianum;
00791       }
00792       else
00793       {
00794         MIL << "SET CONTINUE" << endl;
00795       }
00796 
00797       for ( TargetImpl::PoolItemList::iterator it = take_list.begin(); it != take_list.end(); ++it )
00798       {
00799         order.setInstalled( *it );
00800         XXX << "SET isrc " << (*it)->source().numericId() << " -> " << (*it) << endl;
00801       }
00802       // move everthing from take_list to the end of instlist_r, clean take_list
00803       instlist_r.splice( instlist_r.end(), take_list );
00804       // same for other_list
00805       instlist_r.splice( instlist_r.end(), other_list );
00806 
00807     } // for all sets computed
00808 
00809 
00810     if ( instbackup_r.size() != instlist_r.size() )
00811     {
00812         ERR << "***************** Lost packages in InstallOrder sort." << endl;
00813     }
00814     instlist_r.splice( instlist_r.end(), nonpkglist );
00815 }
00816 
00817 
00819   } // namespace target
00822 } // namespace zypp

Generated on Thu May 4 16:03:32 2006 for zypp by  doxygen 1.4.6