0f9c9faf7933ed0bc0eb8dfc54c54d33d6826dd4
[platform/upstream/libzypp.git] / zypp / pool / GetResolvablesToInsDel.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/pool/GetResolvablesToInsDel.cc
10  *
11 */
12 #include <iostream>
13 #include <set>
14
15 #include "zypp/base/Logger.h"
16
17 #include "zypp/pool/GetResolvablesToInsDel.h"
18 #include "zypp/pool/PoolStats.h"
19
20 #include "zypp/solver/detail/InstallOrder.h"
21
22 using std::endl;
23 using zypp::solver::detail::InstallOrder;
24
25 #undef  ZYPP_BASE_LOGGER_LOGGROUP
26 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::GetResolvablesToInsDel"
27
28
29 ///////////////////////////////////////////////////////////////////
30 namespace zypp
31 { /////////////////////////////////////////////////////////////////
32   ///////////////////////////////////////////////////////////////////
33   namespace pool
34   { /////////////////////////////////////////////////////////////////
35
36     /******************************************************************
37      **
38      ** FUNCTION NAME : strip_obsoleted_to_delete
39      ** FUNCTION TYPE : void
40      **
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...
44     */
45
46     static void
47     strip_obsoleted_to_delete( GetResolvablesToInsDel::PoolItemList & deleteList_r,
48                                const GetResolvablesToInsDel::PoolItemList & instlist_r )
49     {
50       if ( deleteList_r.size() == 0 || instlist_r.size() == 0 )
51         return; // ---> nothing to do
52
53       // build obsoletes from instlist_r
54       CapSet obsoletes;
55       for ( GetResolvablesToInsDel::PoolItemList::const_iterator it = instlist_r.begin();
56             it != instlist_r.end(); ++it )
57         {
58           PoolItem_Ref item( *it );
59           obsoletes.insert( item->dep(Dep::OBSOLETES).begin(), item->dep(Dep::OBSOLETES).end() );
60         }
61       if ( obsoletes.size() == 0 )
62         return; // ---> nothing to do
63
64       // match them... ;(
65       GetResolvablesToInsDel::PoolItemList undelayed;
66       // forall applDelete Packages...
67       for ( GetResolvablesToInsDel::PoolItemList::iterator it = deleteList_r.begin();
68             it != deleteList_r.end(); ++it )
69         {
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 )
75             {
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 )
79                 {
80                   if ( obs->matches( *prov ) == CapMatch::yes )
81                     {
82                       // if so, delay package deletion
83                       DBG << "Ignore appl_delete (should be obsoleted): " << ipkg << endl;
84                       delayPkg = true;
85                       ipkg.status().resetTransact( ResStatus::USER );
86                       break;
87                     }
88                 }
89             }
90           if ( ! delayPkg ) {
91             DBG << "undelayed " << ipkg << endl;
92             undelayed.push_back( ipkg );
93           }
94         }
95       // Puhh...
96       deleteList_r.swap( undelayed );
97     }
98
99     ///////////////////////////////////////////////////////////////////
100     //
101     //  METHOD NAME : GetResolvablesToInsDel::GetResolvablesToInsDel
102     //  METHOD TYPE : Ctor
103     //
104     GetResolvablesToInsDel::GetResolvablesToInsDel( ResPool pool_r )
105     {
106       typedef std::set<PoolItem_Ref> PoolItemSet;
107
108       PoolItemList & dellist_r( _toDelete );
109       PoolItemList & instlist_r( _toInstall );
110       PoolItemList & srclist_r( _toSrcinstall );
111
112       for ( ResPool::const_iterator it = pool_r.begin(); it != pool_r.end(); ++it )
113         {
114           if (it->status().isToBeInstalled())
115             {
116               if ((*it)->kind() == ResTraits<SrcPackage>::kind) {
117                 srclist_r.push_back( *it );
118               }
119               else
120                 instlist_r.push_back( *it );
121             }
122           else if (it->status().isToBeUninstalled())
123             {
124               if ( it->status().isToBeUninstalledDueToObsolete() )
125                 {
126                   DBG << "Ignore auto_delete (should be obsoleted): " << *it << endl;
127                 }
128               else if ( it->status().isToBeUninstalledDueToUpgrade() )
129                 {
130                   DBG << "Ignore auto_delete (should be upgraded): " << *it << endl;
131                 }
132               else {
133                 dellist_r.push_back( *it );
134               }
135             }
136         }
137
138       MIL << "ResolvablesToInsDel: delete " << dellist_r.size()
139       << ", install " << instlist_r.size()
140       << ", srcinstall " << srclist_r.size() << endl;
141
142       ///////////////////////////////////////////////////////////////////
143       //
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...
147       //
148       ///////////////////////////////////////////////////////////////////
149       strip_obsoleted_to_delete( dellist_r, instlist_r );
150
151       if ( dellist_r.size() ) {
152         ///////////////////////////////////////////////////////////////////
153         //
154         // sort delete list...
155         //
156         ///////////////////////////////////////////////////////////////////
157         PoolItemSet delset( dellist_r.begin(), dellist_r.end() );  // for delete order
158         PoolItemSet dummy; // dummy, empty, should contain already installed
159
160         InstallOrder order( pool_r, delset, dummy ); // sort according top prereq
161         order.init();
162         const PoolItemList dsorted( order.getTopSorted() );
163
164         dellist_r.clear();
165         for ( PoolItemList::const_reverse_iterator cit = dsorted.rbegin();
166               cit != dsorted.rend(); ++cit )
167           {
168             dellist_r.push_back( *cit );
169           }
170       }
171
172       ///////////////////////////////////////////////////////////////////
173       //
174       // sort installed list...
175       //
176       ///////////////////////////////////////////////////////////////////
177       if ( instlist_r.empty() )
178         return;
179
180 #warning Source Rank Priority ?
181 #if 0
182       ///////////////////////////////////////////////////////////////////
183       // Get desired order of InstSrc'es to install from.
184       ///////////////////////////////////////////////////////////////////
185       typedef map<unsigned,unsigned> RankPriority;
186
187       RankPriority rankPriority;
188       {
189         InstSrcManager::ISrcIdList sourcerank( Y2PM::instSrcManager().instOrderSources() );
190         // map InstSrc rank to install priority
191         unsigned prio = 0;
192         for ( InstSrcManager::ISrcIdList::const_iterator it = sourcerank.begin();
193               it != sourcerank.end(); ++it, ++prio ) {
194           rankPriority[(*it)->descr()->default_rank()] = prio;
195         }
196       }
197 #endif
198
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 );
207
208       PoolItemSet insset( instbackup_r.begin(), instbackup_r.end() ); // for install order
209       PoolItemSet installed; // dummy, empty, should contain already installed
210
211       InstallOrder order( pool_r, insset, installed );
212       // start recursive depth-first-search
213       order.init();
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;
222
223       PoolItemList last_list;
224       unsigned last_prio     = 0;
225       unsigned last_medianum = 0;
226
227       PoolItemList other_list;
228
229       for ( PoolItemList items = order.computeNextSet(); ! items.empty(); items = order.computeNextSet() )
230         {
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           ///////////////////////////////////////////////////////////////////
237
238           best_list.clear();
239           last_list.clear();
240           other_list.clear();
241
242           for ( PoolItemList::iterator cit = items.begin(); cit != items.end(); ++cit )
243             {
244               ResObject::constPtr cobj( cit->resolvable() );
245               if (!cobj)
246                 continue;
247
248               if ( ! cobj->sourceMediaNr() ) {
249                 XXX << "No media access required for " << *cit << endl;
250                 order.setInstalled( *cit );
251                 other_list.push_back( *cit );
252                 continue;
253               }
254
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 );
260                 continue;
261               }
262
263               if ( last_list.empty() ) {
264                 // check for best media as long as there are no packages for current media.
265
266                 if ( ! best_list.empty() ) {
267
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
275                       continue;
276                     } else {
277                       continue; // worse
278                     }
279                   } else {
280                     continue; // worse
281                   }
282                 }
283
284                 if ( best_list.empty() )
285                   {
286                     // first package or new best
287                     best_list.push_back( *cit );
288                     best_prio     = cobj->source().numericId();
289                     best_medianum = cobj->sourceMediaNr();
290                     continue;
291                   }
292               }
293
294             } // for all objects in current set
295
296           ///////////////////////////////////////////////////////////////////
297           // remove objects picked from install order and append them to
298           // install list.
299           ///////////////////////////////////////////////////////////////////
300           PoolItemList & take_list( last_list.empty() ? best_list : last_list );
301           if ( last_list.empty() )
302             {
303               MIL << "SET NEW media " << best_medianum << endl;
304               last_prio     = best_prio;
305               last_medianum = best_medianum;
306             }
307           else
308             {
309               MIL << "SET CONTINUE" << endl;
310             }
311
312           for ( PoolItemList::iterator it = take_list.begin(); it != take_list.end(); ++it )
313             {
314               order.setInstalled( *it );
315               XXX << "SET isrc " << (*it)->source().numericId() << " -> " << (*it) << endl;
316             }
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 );
321
322         } // for all sets computed
323
324
325       if ( instbackup_r.size() != instlist_r.size() )
326         {
327           ERR << "***************** Lost packages in InstallOrder sort." << endl;
328         }
329
330     }
331
332     /******************************************************************
333      **
334      ** FUNCTION NAME : operator<<
335      ** FUNCTION TYPE : std::ostream &
336     */
337     std::ostream & operator<<( std::ostream & str, const GetResolvablesToInsDel & obj )
338     {
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;
343       return str;
344     }
345
346     /////////////////////////////////////////////////////////////////
347   } // namespace pool
348   ///////////////////////////////////////////////////////////////////
349   /////////////////////////////////////////////////////////////////
350 } // namespace zypp
351 ///////////////////////////////////////////////////////////////////
352