1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/pool/GetResolvablesToInsDel.cc
15 #include "zypp/base/Logger.h"
17 #include "zypp/pool/GetResolvablesToInsDel.h"
18 #include "zypp/pool/PoolStats.h"
20 #include "zypp/solver/detail/InstallOrder.h"
23 using zypp::solver::detail::InstallOrder;
25 #undef ZYPP_BASE_LOGGER_LOGGROUP
26 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::GetResolvablesToInsDel"
29 ///////////////////////////////////////////////////////////////////
31 { /////////////////////////////////////////////////////////////////
32 ///////////////////////////////////////////////////////////////////
34 { /////////////////////////////////////////////////////////////////
36 /******************************************************************
38 ** FUNCTION NAME : strip_obsoleted_to_delete
39 ** FUNCTION TYPE : void
41 ** strip packages to_delete which get obsoleted by
42 ** to_install (i.e. delay deletion in case the
43 ** obsoleting package likes to save whatever...
47 strip_obsoleted_to_delete( GetResolvablesToInsDel::PoolItemList & deleteList_r,
48 const GetResolvablesToInsDel::PoolItemList & instlist_r )
50 if ( deleteList_r.size() == 0 || instlist_r.size() == 0 )
51 return; // ---> nothing to do
53 // build obsoletes from instlist_r
55 for ( GetResolvablesToInsDel::PoolItemList::const_iterator it = instlist_r.begin();
56 it != instlist_r.end(); ++it )
58 PoolItem_Ref item( *it );
59 obsoletes.insert( item->dep(Dep::OBSOLETES).begin(), item->dep(Dep::OBSOLETES).end() );
61 if ( obsoletes.size() == 0 )
62 return; // ---> nothing to do
65 GetResolvablesToInsDel::PoolItemList undelayed;
66 // forall applDelete Packages...
67 for ( GetResolvablesToInsDel::PoolItemList::iterator it = deleteList_r.begin();
68 it != deleteList_r.end(); ++it )
70 PoolItem_Ref ipkg( *it );
71 bool delayPkg = false;
72 // ...check whether an obsoletes....
73 for ( CapSet::iterator obs = obsoletes.begin();
74 ! delayPkg && obs != obsoletes.end(); ++obs )
76 // ...matches anything provided by the package?
77 for ( CapSet::const_iterator prov = ipkg->dep(Dep::PROVIDES).begin();
78 prov != ipkg->dep(Dep::PROVIDES).end(); ++prov )
80 if ( obs->matches( *prov ) == CapMatch::yes )
82 // if so, delay package deletion
83 DBG << "Ignore appl_delete (should be obsoleted): " << ipkg << endl;
85 ipkg.status().resetTransact( ResStatus::USER );
91 DBG << "undelayed " << ipkg << endl;
92 undelayed.push_back( ipkg );
96 deleteList_r.swap( undelayed );
99 ///////////////////////////////////////////////////////////////////
101 // METHOD NAME : GetResolvablesToInsDel::GetResolvablesToInsDel
102 // METHOD TYPE : Ctor
104 GetResolvablesToInsDel::GetResolvablesToInsDel( ResPool pool_r )
106 typedef std::set<PoolItem_Ref> PoolItemSet;
108 PoolItemList & dellist_r( _toDelete );
109 PoolItemList & instlist_r( _toInstall );
110 PoolItemList & srclist_r( _toSrcinstall );
112 for ( ResPool::const_iterator it = pool_r.begin(); it != pool_r.end(); ++it )
114 if (it->status().isToBeInstalled())
116 if ((*it)->kind() == ResTraits<SrcPackage>::kind) {
117 srclist_r.push_back( *it );
120 instlist_r.push_back( *it );
122 else if (it->status().isToBeUninstalled())
124 if ( it->status().isToBeUninstalledDueToObsolete() )
126 DBG << "Ignore auto_delete (should be obsoleted): " << *it << endl;
128 else if ( it->status().isToBeUninstalledDueToUpgrade() )
130 DBG << "Ignore auto_delete (should be upgraded): " << *it << endl;
133 dellist_r.push_back( *it );
138 MIL << "ResolvablesToInsDel: delete " << dellist_r.size()
139 << ", install " << instlist_r.size()
140 << ", srcinstall " << srclist_r.size() << endl;
142 ///////////////////////////////////////////////////////////////////
144 // strip packages to_delete which get obsoleted by
145 // to_install (i.e. delay deletion in case the
146 // obsoleting package likes to save whatever...
148 ///////////////////////////////////////////////////////////////////
149 strip_obsoleted_to_delete( dellist_r, instlist_r );
151 if ( dellist_r.size() ) {
152 ///////////////////////////////////////////////////////////////////
154 // sort delete list...
156 ///////////////////////////////////////////////////////////////////
157 PoolItemSet delset( dellist_r.begin(), dellist_r.end() ); // for delete order
158 PoolItemSet dummy; // dummy, empty, should contain already installed
160 InstallOrder order( pool_r, delset, dummy ); // sort according top prereq
162 const PoolItemList dsorted( order.getTopSorted() );
165 for ( PoolItemList::const_reverse_iterator cit = dsorted.rbegin();
166 cit != dsorted.rend(); ++cit )
168 dellist_r.push_back( *cit );
172 ///////////////////////////////////////////////////////////////////
174 // sort installed list...
176 ///////////////////////////////////////////////////////////////////
177 if ( instlist_r.empty() )
180 #warning Source Rank Priority ?
182 ///////////////////////////////////////////////////////////////////
183 // Get desired order of InstSrc'es to install from.
184 ///////////////////////////////////////////////////////////////////
185 typedef map<unsigned,unsigned> RankPriority;
187 RankPriority rankPriority;
189 InstSrcManager::ISrcIdList sourcerank( Y2PM::instSrcManager().instOrderSources() );
190 // map InstSrc rank to install priority
192 for ( InstSrcManager::ISrcIdList::const_iterator it = sourcerank.begin();
193 it != sourcerank.end(); ++it, ++prio ) {
194 rankPriority[(*it)->descr()->default_rank()] = prio;
199 ///////////////////////////////////////////////////////////////////
200 // Compute install order according to packages prereq.
201 // Try to group packages with respect to the desired install order
202 ///////////////////////////////////////////////////////////////////
203 // backup list for debug purpose.
204 // You can as well build the set, clear the list and rebuild it in install order.
205 PoolItemList instbackup_r;
206 instbackup_r.swap( instlist_r );
208 PoolItemSet insset( instbackup_r.begin(), instbackup_r.end() ); // for install order
209 PoolItemSet installed; // dummy, empty, should contain already installed
211 InstallOrder order( pool_r, insset, installed );
212 // start recursive depth-first-search
214 MIL << "order.init() done" << endl;
215 order.printAdj( XXX, false );
216 ///////////////////////////////////////////////////////////////////
217 // build install list in install order
218 ///////////////////////////////////////////////////////////////////
219 PoolItemList best_list;
220 unsigned best_prio = 0;
221 unsigned best_medianum = 0;
223 PoolItemList last_list;
224 unsigned last_prio = 0;
225 unsigned last_medianum = 0;
227 PoolItemList other_list;
229 for ( PoolItemList items = order.computeNextSet(); ! items.empty(); items = order.computeNextSet() )
231 MIL << "order.computeNextSet: " << items.size() << " resolvables" << endl;
232 ///////////////////////////////////////////////////////////////////
233 // items contains all objects we could install now. Pick all objects
234 // from current media, or best media if none for current. Alwayys pick
235 // objects that do not require media access.
236 ///////////////////////////////////////////////////////////////////
242 for ( PoolItemList::iterator cit = items.begin(); cit != items.end(); ++cit )
244 ResObject::constPtr cobj( cit->resolvable() );
248 if ( ! cobj->sourceMediaNr() ) {
249 XXX << "No media access required for " << *cit << endl;
250 order.setInstalled( *cit );
251 other_list.push_back( *cit );
255 XXX << "Package " << *cobj << ", media " << cobj->sourceMediaNr() << " last_medianum " << last_medianum << " best_medianum " << best_medianum << endl;
256 if ( cobj->source().numericId() == last_prio &&
257 cobj->sourceMediaNr() == last_medianum ) {
258 // prefer packages on current media.
259 last_list.push_back( *cit );
263 if ( last_list.empty() ) {
264 // check for best media as long as there are no packages for current media.
266 if ( ! best_list.empty() ) {
268 if ( cobj->source().numericId() < best_prio ) {
269 best_list.clear(); // new best
270 } else if ( cobj->source().numericId() == best_prio ) {
271 if ( cobj->sourceMediaNr() < best_medianum ) {
272 best_list.clear(); // new best
273 } else if ( cobj->sourceMediaNr() == best_medianum ) {
274 best_list.push_back( *cit ); // same as best -> add
284 if ( best_list.empty() )
286 // first package or new best
287 best_list.push_back( *cit );
288 best_prio = cobj->source().numericId();
289 best_medianum = cobj->sourceMediaNr();
294 } // for all objects in current set
296 ///////////////////////////////////////////////////////////////////
297 // remove objects picked from install order and append them to
299 ///////////////////////////////////////////////////////////////////
300 PoolItemList & take_list( last_list.empty() ? best_list : last_list );
301 if ( last_list.empty() )
303 MIL << "SET NEW media " << best_medianum << endl;
304 last_prio = best_prio;
305 last_medianum = best_medianum;
309 MIL << "SET CONTINUE" << endl;
312 for ( PoolItemList::iterator it = take_list.begin(); it != take_list.end(); ++it )
314 order.setInstalled( *it );
315 XXX << "SET isrc " << (*it)->source().numericId() << " -> " << (*it) << endl;
317 // move everthing from take_list to the end of instlist_r, clean take_list
318 instlist_r.splice( instlist_r.end(), take_list );
319 // same for other_list
320 instlist_r.splice( instlist_r.end(), other_list );
322 } // for all sets computed
325 if ( instbackup_r.size() != instlist_r.size() )
327 ERR << "***************** Lost packages in InstallOrder sort." << endl;
332 /******************************************************************
334 ** FUNCTION NAME : operator<<
335 ** FUNCTION TYPE : std::ostream &
337 std::ostream & operator<<( std::ostream & str, const GetResolvablesToInsDel & obj )
339 dumpPoolStats( str << "toInstall: " << endl,
340 obj._toInstall.begin(), obj._toInstall.end() ) << endl;
341 dumpPoolStats( str << "toDelete: " << endl,
342 obj._toDelete.begin(), obj._toDelete.end() ) << endl;
346 /////////////////////////////////////////////////////////////////
348 ///////////////////////////////////////////////////////////////////
349 /////////////////////////////////////////////////////////////////
351 ///////////////////////////////////////////////////////////////////