extend commit()
authorKlaus Kaempf <kkaempf@suse.de>
Wed, 8 Feb 2006 12:47:44 +0000 (12:47 +0000)
committerKlaus Kaempf <kkaempf@suse.de>
Wed, 8 Feb 2006 12:47:44 +0000 (12:47 +0000)
zypp/target/TargetImpl.cc
zypp/target/TargetImpl.h

index 58dc7ac..33143cb 100644 (file)
 */
 #include <iostream>
 #include <string>
+#include <list>
+#include <set>
+
 #include "zypp/base/Logger.h"
 #include "zypp/base/Exception.h"
+#include "zypp/PoolItem.h"
+#include "zypp/Resolvable.h"
+#include "zypp/ResObject.h"
+#include "zypp/Package.h"
 
 #include "zypp/target/TargetImpl.h"
 #include "zypp/target/TargetCallbackReceiver.h"
@@ -80,6 +87,7 @@ namespace zypp
       // TODO objects from the XML store
       return _store;
     }
+
     
     Pathname TargetImpl::getRpmFile(Package::constPtr package)
     {
@@ -96,9 +104,10 @@ namespace zypp
        return file;
     }
 
-    void TargetImpl::commit(ResPool pool_r)
+
+    void TargetImpl::commit(ResPool pool_r, int medianr, PoolItemList & errors_r, PoolItemList & remaining_r, PoolItemList & srcremaining_r)
     {
-      MIL << "TargetImpl::commit(<pool>)" << endl;
+      MIL << "TargetImpl::commit(<pool>, " << medianr << ")" << endl;
 
       PoolItemList to_uninstall;
       PoolItemList to_install;
@@ -145,6 +154,7 @@ namespace zypp
       commit(installorder);
     }
 
+
     void TargetImpl::commit(const PoolItemList & items_r)
     {
       MIL << "TargetImpl::commit(<list>)" << endl;
@@ -245,14 +255,290 @@ namespace zypp
        return NULL;
     }
 
+//-----------------------------------------------------------------------------
+/******************************************************************
+**
+**
+**     FUNCTION NAME : strip_obsoleted_to_delete
+**     FUNCTION TYPE : void
+**
+** strip packages to_delete which get obsoleted by
+** to_install (i.e. delay deletion in case the
+** obsoleting package likes to save whatever...
+*/
+static void
+strip_obsoleted_to_delete( PoolItemList & deleteList_r,
+                               const PoolItemList & instlist_r )
+{
+  if ( deleteList_r.size() == 0 || instlist_r.size() == 0 )
+    return; // ---> nothing to do
+
+  // build obsoletes from instlist_r
+  CapSet obsoletes;
+  for ( PoolItemList::const_iterator it = instlist_r.begin();
+       it != instlist_r.end(); ++it )
+  {
+    PoolItem_Ref item( *it );
+    obsoletes.insert( item->dep(Dep::OBSOLETES).begin(), item->dep(Dep::OBSOLETES).end() );
+  }
+  if ( obsoletes.size() == 0 )
+    return; // ---> nothing to do
+
+  // match them... ;(
+  PoolItemList undelayed;
+  // forall applDelete Packages...
+  for ( PoolItemList::iterator it = deleteList_r.begin();
+       it != deleteList_r.end(); ++it )
+  {
+    PoolItem_Ref ipkg( *it );
+    bool delayPkg = false;
+    // ...check whether an obsolets....
+    for ( CapSet::iterator obs = obsoletes.begin();
+         ! delayPkg && obs != obsoletes.end(); ++obs )
+    {
+      // ...matches anything provided by the package?
+      for ( CapSet::const_iterator prov = ipkg->dep(Dep::PROVIDES).begin();
+           prov != ipkg->dep(Dep::PROVIDES).end(); ++prov )
+      {
+       if ( obs->matches( *prov ) == CapMatch::yes )
+       {
+         // if so, delay package deletion
+         DBG << "Ignore appl_delete (should be obsoleted): " << ipkg << endl;
+         delayPkg = true;
+         break;
+       }
+      }
+    }
+    if ( ! delayPkg ) {
+MIL << "undelayed " << ipkg << endl;
+      undelayed.push_back( ipkg );
+    }
+  }
+  // Puhh...
+  deleteList_r.swap( undelayed );
+}
+
+
 
 
 void
-TargetImpl::getResolvablesToInsDel ( ResPool pool_r,
+TargetImpl::getResolvablesToInsDel ( const ResPool pool_r,
                                    PoolItemList & dellist_r,
                                    PoolItemList & instlist_r,
                                    PoolItemList & srclist_r )
 {
+    dellist_r.clear();
+    instlist_r.clear();
+    srclist_r.clear();
+
+    for ( ResPool::const_iterator it = pool_r.begin(); it != pool_r.end(); ++it )
+    {
+       if (it->status().isToBeInstalled())
+       {
+           if (it->resolvable()->arch() == Arch_src)
+               srclist_r.push_back( *it );
+           else
+               instlist_r.push_back( *it );
+       }
+       else if (it->status().isToBeUninstalled())
+       {
+           if ( it->status().isToBeUninstalledDueToObsolete() )
+           {
+               DBG << "Ignore auto_delete (should be obsoleted): " << *it << endl;
+           } else {
+               dellist_r.push_back( *it );
+           }
+       }
+    }
+
+    MIL << "PackagesToInsDel: delete " << dellist_r.size()
+      << ", install " << instlist_r.size()
+       << ", srcinstall " << srclist_r.size() << endl;
+
+    ///////////////////////////////////////////////////////////////////
+    //
+    // strip packages to_delete which get obsoleted by
+    // to_install (i.e. delay deletion in case the
+    // obsoleting package likes to save whatever...
+    //
+    ///////////////////////////////////////////////////////////////////
+    strip_obsoleted_to_delete( dellist_r, instlist_r );
+
+    if ( dellist_r.size() ) {
+      ///////////////////////////////////////////////////////////////////
+      //
+      // sort delete list...
+      //
+      ///////////////////////////////////////////////////////////////////
+      PoolItemList dlist;  // for delete order
+      PoolItemList dummy; // dummy, empty, should contain already installed
+      for ( PoolItemList::iterator pkgIt = dellist_r.begin();
+           pkgIt != dellist_r.end(); ++pkgIt )
+      {
+       dlist.push_back( *pkgIt );
+      }
+
+      InstallOrder order( pool_r, dlist, dummy ); // sort according top prereq
+      order.init();
+      const PoolItemList dsorted( order.getTopSorted() );
+
+      dellist_r.clear();
+      for ( PoolItemList::const_reverse_iterator cit = dsorted.rbegin();
+           cit != dsorted.rend(); ++cit )
+      {
+       dellist_r.push_back( *cit );
+      }
+    }
+
+    ///////////////////////////////////////////////////////////////////
+    //
+    // sort installed list...
+    //
+    ///////////////////////////////////////////////////////////////////
+    if ( instlist_r.empty() ) {
+      return;
+    }
+#warning Source Rank Priority ?
+#if 0
+    ///////////////////////////////////////////////////////////////////
+    // Get desired order of InstSrc'es to install from.
+    ///////////////////////////////////////////////////////////////////
+    typedef map<unsigned,unsigned> RankPriority;
+
+    RankPriority rankPriority;
+    {
+      InstSrcManager::ISrcIdList sourcerank( Y2PM::instSrcManager().instOrderSources() );
+      // map InstSrc rank to install priority
+      unsigned prio = 0;
+      for ( InstSrcManager::ISrcIdList::const_iterator it = sourcerank.begin();
+           it != sourcerank.end(); ++it, ++prio ) {
+       rankPriority[(*it)->descr()->default_rank()] = prio;
+      }
+    }
+#endif
+
+    ///////////////////////////////////////////////////////////////////
+    // Compute install order according to packages prereq.
+    // Try to group packages with respect to the desired install order
+    ///////////////////////////////////////////////////////////////////
+    // backup list for debug purpose.
+    // You can as well build the set, clear the list and rebuild it in install order.
+    PoolItemList instbackup_r;
+    instbackup_r.swap( instlist_r );
+
+    PoolItemList ilist; // for install order
+    PoolItemList installed; // dummy, empty, should contain already installed
+    for ( PoolItemList::iterator pkgIt = instbackup_r.begin(); pkgIt != instbackup_r.end(); ++pkgIt ) {
+      ilist.push_back( *pkgIt );
+    }
+    InstallOrder order( pool_r, ilist, installed );
+    // start recursive depth-first-search
+    order.startrdfs();
+
+    ///////////////////////////////////////////////////////////////////
+    // build install list in install order
+    ///////////////////////////////////////////////////////////////////
+    PoolItemList best_list;
+//    unsigned best_prio     = 0;
+    unsigned best_medianum = 0;
+
+    PoolItemList last_list;
+//    unsigned last_prio     = 0;
+    unsigned last_medianum = 0;
+
+    for ( PoolItemList pkgs = order.computeNextSet(); ! pkgs.empty(); pkgs = order.computeNextSet() )
+    {
+MIL << "order.computeNextSet: " << pkgs.size() << " packages" << endl;
+      ///////////////////////////////////////////////////////////////////
+      // pkgs contains all packages we could install now. Pick all packages
+      // from current media, or best media if none for current.
+      ///////////////////////////////////////////////////////////////////
+
+      best_list.clear();
+      last_list.clear();
+
+      for ( PoolItemList::iterator cit = pkgs.begin(); cit != pkgs.end(); ++cit )
+      {
+       Resolvable::constPtr res( cit->resolvable() );
+       Package::constPtr cpkg( asKind<Package>(res) );
+
+MIL << "Packge " << cpkg << ", media " << cpkg->mediaId() << endl;
+       if (                                                                    //  rankPriority[cpkg->instSrcRank()] == last_prio &&
+            cpkg->mediaId() == last_medianum ) {
+         // prefer packages on current media.
+         last_list.push_back( *cit );
+         continue;
+       }
+
+       if ( last_list.empty() ) {
+         // check for best media as long as there are no packages for current media.
+
+         if ( ! best_list.empty() ) {
+
+#if 0
+           if ( rankPriority[cpkg->instSrcRank()] < best_prio ) {
+             best_list.clear(); // new best
+           } else if ( rankPriority[cpkg->instSrcRank()] == best_prio ) {
+#endif
+
+             if ( cpkg->mediaId() < best_medianum ) {
+               best_list.clear(); // new best
+             } else if ( cpkg->mediaId() == best_medianum ) {
+               best_list.push_back( *cit ); // same as best -> add
+               continue;
+             } else {
+               continue; // worse
+             }
+#if 0
+           } else {
+             continue; // worse
+           }
+#endif
+         }
+
+         if ( best_list.empty() )
+         {
+           // first package or new best
+           best_list.push_back( *cit );
+//         best_prio     = rankPriority[cpkg->instSrcRank()];
+           best_medianum = cpkg->mediaId();
+           continue;
+         }
+       }
+
+      } // for all packages in current set
+
+      ///////////////////////////////////////////////////////////////////
+      // remove packages picked from install order and append them to
+      // install list.
+      ///////////////////////////////////////////////////////////////////
+      PoolItemList & take_list( last_list.empty() ? best_list : last_list );
+      if ( last_list.empty() )
+      {
+       MIL << "SET NEW media " << best_medianum << endl;
+//     last_prio     = best_prio;
+       last_medianum = best_medianum;
+      }
+      else
+      {
+       MIL << "SET CONTINUE" << endl;
+      }
+
+      for ( PoolItemList::iterator it = take_list.begin(); it != take_list.end(); ++it )
+      {
+       order.setInstalled( *it );
+       MIL << "SET isrc " << (*it) << endl;
+      }
+      instlist_r.splice( instlist_r.end(), take_list );
+
+    } // for all sets computed
+
+
+    if ( instbackup_r.size() != instlist_r.size() )
+    {
+       INT << "Lost packages in InstallOrder sort." << endl;
+    }
+
 }
 
 
index f9e620c..d5d5fe6 100644 (file)
@@ -47,6 +47,14 @@ namespace zypp
     {
       friend std::ostream & operator<<( std::ostream & str, const TargetImpl & obj );
 
+    private:
+      /** Sort according to prereqs and media numbers */
+      void getResolvablesToInsDel ( const ResPool pool_r,
+                                   PoolItemList & dellist_r,
+                                   PoolItemList & instlist_r,
+                                   PoolItemList & srclist_r );
+
+
     public:
       /** Ctor. */
       TargetImpl(const Pathname & root_r = "/");
@@ -61,18 +69,13 @@ namespace zypp
       /** All resolvables in the target. */
       const ResStore & resolvables();
 
-      /** Sort according to prereqs and media numbers */
-      void getResolvablesToInsDel ( ResPool pool_r,
-                                   PoolItemList & dellist_r,
-                                   PoolItemList & instlist_r,
-                                   PoolItemList & srclist_r );
-
-      /** Commit changes in the pool */
-#warning Add support for multiple medias - eg. limit only to CD1
-      void commit(ResPool pool_r);
+      /** Commit changes in the pool
+         media = 0 means any/all medias
+         media > 0 means limit commits to this media */
+      void commit( ResPool pool_r, int medianr, PoolItemList & errors_r, PoolItemList & remaining_r, PoolItemList & srcremaining_r );
 
       /** Commit ordered changes */
-      void commit(const PoolItemList & items_r);
+      void commit( const PoolItemList & items_r );
 
       /** Overload to realize stream output. */
       virtual std::ostream & dumpOn( std::ostream & str ) const