1d588b254c71cbdd35f80230db2bb197af11b8d3
[platform/upstream/libzypp.git] / devel / devel.ma / Iorder.cc
1 #include "Tools.h"
2 #include <zypp/ResObjects.h>
3
4 #include "zypp/pool/GetResolvablesToInsDel.h"
5
6 Pathname mroot( "/tmp/Bb" );
7 TestSetup test( mroot, Arch_ppc64 );
8
9 bool checkCaps( Capabilities caps_r );
10
11 struct RunableCache
12 {
13   typedef std::tr1::unordered_map<sat::Solvable,TriBool> CacheType;
14   typedef std::vector<sat::Solvable>                     AnalyzeStack;
15
16   RunableCache()
17   : _ltag( "[0000]" )
18   {}
19
20   /**
21    * Test whether there is a runable provider for each requirement.
22    */
23   bool isRunable( const PoolItem & pi ) const
24   { return isRunable( pi.satSolvable() ); }
25
26   bool isRunable( sat::Solvable solv_r ) const
27   {
28     tribool & cent( get( solv_r ) );
29     if ( indeterminate( cent ) )
30       return (cent = analyze( solv_r ));
31     return cent;
32   }
33
34   /**
35    * Test whether there is a runable provider for each pre-requirement.
36    */
37   bool isInstallable( const PoolItem & pi ) const
38   { return isInstallable( pi.satSolvable() ); }
39
40   bool isInstallable( sat::Solvable solv_r ) const
41   {
42     tribool & cent( get( solv_r ) );
43     if ( cent )
44       return true; // if runable then also installable.
45     return checkCaps( solv_r.prerequires() );
46   }
47
48   /** Clear the cache. */
49   void clear() const
50   {
51     _cache.clear();
52     _stack.clear();
53     _ltag = "[0000]";
54   }
55
56   private:
57     /**
58      * Determine whether this solvable is runable.
59      */
60     bool analyze( sat::Solvable solv_r ) const
61     {
62       if ( ! push( solv_r ) )
63       {
64         if ( _stack.back() != solv_r )
65           SEC << _ltag << "??Already on stack: " << solv_r << " " << _stack << endl;
66         // else it's a self requirement
67         return true; // assume runnable?
68       }
69
70       INT << _ltag << "->" << solv_r << " " << _stack << endl;
71       bool ret = checkCaps( solv_r.requires() );
72       if ( ! ret )
73       {
74         ERR << " Not runable: " << solv_r << endl;
75       }
76       INT << _ltag << "<-" << solv_r << " " << _stack << endl;
77
78       if ( ! pop( solv_r ) )
79       {
80         INT << "Stack corrupted! Expect " << solv_r << " " << _stack << endl;
81       }
82       return ret;
83     }
84
85     /**
86      * For each capability find a runable provider.
87      */
88     bool checkCaps( Capabilities caps_r ) const
89     {
90       for_( it, caps_r.begin(), caps_r.end() )
91       {
92         if ( ! findRunableProvider( *it ) )
93           return false;
94       }
95       return true;
96     }
97
98     /**
99      * Find a runable provider of a capability on system.
100      *
101      * A runable package is already installed and all of
102      * its requirements are met by runable packages.
103      */
104     bool findRunableProvider( Capability cap_r ) const
105     {
106       _MIL("findRunableProvider") << _ltag << "  " << cap_r << endl;
107       sat::WhatProvides prv( cap_r );
108       for_( pit, prv.begin(), prv.end() )
109       {
110         if ( ! *pit )
111         {
112           _DBG("findRunableProvider") << _ltag << "     by system" << endl;
113           return true; // noSolvable provides: i.e. system provides
114         }
115
116         PoolItem pi( *pit );
117         if ( pi.status().onSystem() )
118         {
119           if ( isRunable( pi ) )
120           {
121             _DBG("findRunableProvider") << _ltag << "    " << pi << endl;
122             return true;
123           }
124           else
125           {
126             _WAR("findRunableProvider") << _ltag << "    " << pi << endl;
127           }
128         }
129       }
130       ERR << _ltag << "    NO on system provider for " << cap_r << endl;
131       return false;
132     }
133
134   private:
135     /** Push a new solvable to the AnalyzeStack, or return false is already on stack. */
136     bool push( sat::Solvable solv_r ) const
137     {
138       if ( find( _stack.begin(), _stack.end(), solv_r ) == _stack.end() )
139       {
140         _stack.push_back( solv_r );
141         _ltag = str::form( "[%04u]", _stack.size() );
142         return true;
143       }
144       // cycle?
145       return false;
146     }
147
148     /** Pop solvable from AnalyzeStack (expecting it to be \c solv_r). */
149     bool pop( sat::Solvable solv_r ) const
150     {
151       if ( _stack.back() == solv_r )
152       {
153         _stack.pop_back();
154         _ltag = str::form( "[%04u]", _stack.size() );
155         return true;
156       }
157       // stack corrupted?
158       return false;
159     }
160
161     /** Return cache entry, initializing new entries with \ref indeterminate.*/
162     tribool & get( sat::Solvable solv_r ) const
163     {
164       CacheType::iterator it( _cache.find( solv_r ) );
165       if ( it == _cache.end() )
166         return (_cache[solv_r] = indeterminate);
167       return _cache[solv_r];
168     }
169
170     mutable CacheType    _cache;
171     mutable AnalyzeStack _stack;
172     mutable std::string  _ltag;
173 };
174
175 RunableCache rcache;
176
177 //==================================================
178
179 bool upgrade()
180 {
181   bool rres = false;
182   {
183     zypp::base::LogControl::TmpLineWriter shutUp;
184     UpgradeStatistics u;
185     rres = getZYpp()->resolver()->doUpgrade( u );
186   }
187   if ( ! rres )
188   {
189     ERR << "upgrade " << rres << endl;
190     getZYpp()->resolver()->problems();
191     return false;
192   }
193   MIL << "upgrade " << rres << endl;
194   return true;
195 }
196
197 bool solve()
198 {
199   static unsigned run = 0;
200   USR << "Solve " << run++ << endl;
201   bool rres = false;
202   {
203     //zypp::base::LogControl::TmpLineWriter shutUp;
204     rres = getZYpp()->resolver()->resolvePool();
205   }
206   if ( ! rres )
207   {
208     ERR << "resolve " << rres << endl;
209     getZYpp()->resolver()->problems();
210     return false;
211   }
212
213   return true;
214 }
215
216 bool verify()
217 {
218   bool rres = solve();
219   ResPool pool( test.pool() );
220   for_( it, make_filter_begin<resfilter::ByTransact>(pool),
221         make_filter_end<resfilter::ByTransact>(pool) )
222   {
223     if ( it->status().transacts() &&
224          it->status().isBySolver() )
225     {
226       WAR << "MISSING " << *it << endl;
227     }
228   }
229   return rres;
230 }
231
232 inline void save()
233 {
234   test.poolProxy().saveState();
235 }
236
237 inline void restore()
238 {
239   test.poolProxy().restoreState();
240 }
241
242 /******************************************************************
243 **
244 **      FUNCTION NAME : main
245 **      FUNCTION TYPE : int
246 */
247 int main( int argc, char * argv[] )
248 {
249   INT << "===[START]==========================================" << endl;
250
251   Pathname mroot( "/tmp/Bb" );
252   TestSetup test( mroot, Arch_ppc64 );
253
254   ResPool pool( test.pool() );
255   sat::Pool satpool( test.satpool() );
256
257   {
258     zypp::base::LogControl::TmpLineWriter shutUp;
259     test.loadTarget();
260     test.loadTestcaseRepos( "/suse/ma/BUGS/439802/bug439802/YaST2/solverTestcase" );
261   }
262
263   if ( 0 )
264   {
265     PoolItem p = getPi<Package>( "bash", Edition("3.1-24.14"), Arch("ppc64") );
266     p.status().setTransact( true, ResStatus::USER );
267   }
268
269   save();
270   {
271     zypp::base::LogControl::TmpLineWriter shutUp;
272     getPi<Product>( "SUSE_SLES", Edition("11"), Arch("ppc64") ).status().setTransact( true, ResStatus::USER );
273     getPi<Package>( "sles-release", Edition("11-54.3"), Arch("ppc64") ).status().setTransact( true, ResStatus::USER );
274     upgrade();
275   }
276   vdumpPoolStats( USR << "Transacting:"<< endl,
277                   make_filter_begin<resfilter::ByTransact>(pool),
278                   make_filter_end<resfilter::ByTransact>(pool) ) << endl;
279
280   pool::GetResolvablesToInsDel collect( pool, pool::GetResolvablesToInsDel::ORDER_BY_MEDIANR );
281   restore();
282   vdumpPoolStats( USR << "Transacting:"<< endl,
283                   make_filter_begin<resfilter::ByTransact>(pool),
284                   make_filter_end<resfilter::ByTransact>(pool) ) << endl;
285
286   {
287     for_( it, collect._toDelete.begin(), collect._toDelete.end() )
288     {
289       it->status().setTransact( true, ResStatus::USER );
290       SEC << *it << endl;
291 //       vdumpPoolStats( SEC << "Transacting:"<< endl,
292 //                       make_filter_begin<resfilter::ByTransact>(pool),
293 //                       make_filter_end<resfilter::ByTransact>(pool) ) << endl;
294
295       (rcache.isInstallable( *it ) ? MIL : ERR) << *it << " deletable?" << endl;
296     }
297   }
298
299   if ( 0 ) {
300     for_( it, collect._toInstall.begin(), collect._toInstall.end() )
301     {
302       it->status().setTransact( true, ResStatus::USER );
303       SEC << *it << endl;
304 //       vdumpPoolStats( SEC << "Transacting:"<< endl,
305 //                       make_filter_begin<resfilter::ByTransact>(pool),
306 //                       make_filter_end<resfilter::ByTransact>(pool) ) << endl;
307       (rcache.isInstallable( *it ) ? MIL : ERR) << *it << " installable?" << endl;
308     }
309   }
310
311
312 #if 0
313   //getPi<>( "", "", Edition(""), Arch("") );
314   getPi<Product>( "SUSE_SLES", Edition("11"), Arch("ppc64") ).status().setTransact( true, ResStatus::USER );
315   getPi<Package>( "sles-release", Edition("11-54.3"), Arch("ppc64") ).status().setTransact( true, ResStatus::USER );
316
317   ResPool pool( test.pool() );
318   vdumpPoolStats( USR << "Transacting:"<< endl,
319                   make_filter_begin<resfilter::ByTransact>(pool),
320                   make_filter_end<resfilter::ByTransact>(pool) ) << endl;
321   upgrade();
322   vdumpPoolStats( USR << "Transacting:"<< endl,
323                   make_filter_begin<resfilter::ByTransact>(pool),
324                   make_filter_end<resfilter::ByTransact>(pool) ) << endl;
325
326   pool::GetResolvablesToInsDel collect( pool, pool::GetResolvablesToInsDel::ORDER_BY_MEDIANR );
327   MIL << "GetResolvablesToInsDel:" << endl << collect << endl;
328
329   if ( 1 )
330   {
331     // Collect until the 1st package from an unwanted media occurs.
332     // Further collection could violate install order.
333     bool hitUnwantedMedia = false;
334     typedef pool::GetResolvablesToInsDel::PoolItemList PoolItemList;
335     PoolItemList::iterator fst=collect._toInstall.end();
336     for ( PoolItemList::iterator it = collect._toInstall.begin(); it != collect._toInstall.end(); ++it)
337     {
338       ResObject::constPtr res( it->resolvable() );
339
340       if ( hitUnwantedMedia
341            || ( res->mediaNr() && res->mediaNr() != 1 ) )
342       {
343         if ( !hitUnwantedMedia )
344           fst=it;
345         hitUnwantedMedia = true;
346       }
347     }
348     dumpRange( WAR << "toInstall1: " << endl,
349                collect._toInstall.begin(), fst ) << endl;
350     dumpRange( WAR << "toInstall2: " << endl,
351                fst, collect._toInstall.end() ) << endl;
352     dumpRange( ERR << "toDelete: " << endl,
353                collect._toDelete.begin(), collect._toDelete.end() ) << endl;
354   }
355   else
356   {
357     dumpRange( WAR << "toInstall: " << endl,
358                collect._toInstall.begin(), collect._toInstall.end() ) << endl;
359     dumpRange( ERR << "toDelete: " << endl,
360                collect._toDelete.begin(), collect._toDelete.end() ) << endl;
361   }
362   INT << "===[END]============================================" << endl << endl;
363   return 0;
364 #endif
365
366
367
368
369
370   INT << "===[END]============================================" << endl << endl;
371   zypp::base::LogControl::TmpLineWriter shutUp;
372   return 0;
373 }
374