9ff20235733e2f9b69b61f1a9271325541b926d2
[platform/upstream/libsolv.git] / src / solverdebug.c
1 /*
2  * Copyright (c) 2008, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 /*
9  * solverdebug.c
10  *
11  * debug functions for the SAT solver
12  */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <string.h>
18 #include <assert.h>
19
20 #include "solver.h"
21 #include "bitmap.h"
22 #include "pool.h"
23 #include "util.h"
24 #include "evr.h"
25 #include "policy.h"
26
27
28 /*
29  * create obsoletesmap from solver decisions
30  *
31  * for solvables in installed repo:
32  *   0 - not obsoleted
33  *   p - one of the packages that obsolete us
34  * for all others:
35  *   n - number of packages this package obsoletes
36  *
37  */
38
39 Id *
40 solver_create_decisions_obsoletesmap(Solver *solv)
41 {
42   Pool *pool = solv->pool;
43   Repo *installed = solv->installed;
44   Id p, *obsoletesmap = NULL;
45   int i;
46   Solvable *s;
47
48   obsoletesmap = (Id *)sat_calloc(pool->nsolvables, sizeof(Id));
49   if (installed)
50     {
51       for (i = 0; i < solv->decisionq.count; i++)
52         {
53           Id *pp, n;
54
55           n = solv->decisionq.elements[i];
56           if (n < 0)
57             continue;
58           if (n == SYSTEMSOLVABLE)
59             continue;
60           s = pool->solvables + n;
61           if (s->repo == installed)             /* obsoletes don't count for already installed packages */
62             continue;
63           FOR_PROVIDES(p, pp, s->name)
64             if (s->name == pool->solvables[p].name)
65               {
66                 if (pool->solvables[p].repo == installed && !obsoletesmap[p])
67                   {
68                     obsoletesmap[p] = n;
69                     obsoletesmap[n]++;
70                   }
71               }
72         }
73       for (i = 0; i < solv->decisionq.count; i++)
74         {
75           Id obs, *obsp;
76           Id *pp, n;
77
78           n = solv->decisionq.elements[i];
79           if (n < 0)
80             continue;
81           if (n == SYSTEMSOLVABLE)
82             continue;
83           s = pool->solvables + n;
84           if (s->repo == installed)             /* obsoletes don't count for already installed packages */
85             continue;
86           if (!s->obsoletes)
87             continue;
88           obsp = s->repo->idarraydata + s->obsoletes;
89           while ((obs = *obsp++) != 0)
90             FOR_PROVIDES(p, pp, obs)
91               {
92                 if (pool->solvables[p].repo == installed && !obsoletesmap[p])
93                   {
94                     obsoletesmap[p] = n;
95                     obsoletesmap[n]++;
96                   }
97               }
98         }
99     }
100   return obsoletesmap;
101 }
102
103 void
104 solver_printruleelement(Solver *solv, int type, Rule *r, Id v)
105 {
106   Pool *pool = solv->pool;
107   Solvable *s;
108   if (v < 0)
109     {
110       s = pool->solvables + -v;
111       POOL_DEBUG(type, "    !%s [%d]", solvable2str(pool, s), -v);
112     }
113   else
114     {
115       s = pool->solvables + v;
116       POOL_DEBUG(type, "    %s [%d]", solvable2str(pool, s), v);
117     }
118   if (r)
119     {
120       if (r->w1 == v)
121         POOL_DEBUG(type, " (w1)");
122       if (r->w2 == v)
123         POOL_DEBUG(type, " (w2)");
124     }
125   if (solv->decisionmap[s - pool->solvables] > 0)
126     POOL_DEBUG(type, " Install.level%d", solv->decisionmap[s - pool->solvables]);
127   if (solv->decisionmap[s - pool->solvables] < 0)
128     POOL_DEBUG(type, " Conflict.level%d", -solv->decisionmap[s - pool->solvables]);
129   POOL_DEBUG(type, "\n");
130 }
131
132
133 /*
134  * print rule
135  */
136
137 void
138 solver_printrule(Solver *solv, int type, Rule *r)
139 {
140   Pool *pool = solv->pool;
141   int i;
142   Id v;
143
144   if (r >= solv->rules && r < solv->rules + solv->nrules)   /* r is a solver rule */
145     POOL_DEBUG(type, "Rule #%d:", (int)(r - solv->rules));
146   else
147     POOL_DEBUG(type, "Rule:");                 /* r is any rule */
148   if (r && r->w1 == 0)
149     POOL_DEBUG(type, " (disabled)");
150   POOL_DEBUG(type, "\n");
151   for (i = 0; ; i++)
152     {
153       if (i == 0)
154           /* print direct literal */
155         v = r->p;
156       else if (r->d == ID_NULL)
157         {
158           if (i == 2)
159             break;
160           /* binary rule --> print w2 as second literal */
161           v = r->w2;
162         }
163       else
164           /* every other which is in d */
165         v = solv->pool->whatprovidesdata[r->d + i - 1];
166       if (v == ID_NULL)
167         break;
168       solver_printruleelement(solv, type, r, v);
169     }
170   POOL_DEBUG(type, "    next rules: %d %d\n", r->n1, r->n2);
171 }
172
173 void
174 solver_printruleclass(Solver *solv, int type, Rule *r)
175 {
176   Pool *pool = solv->pool;
177   Id p = r - solv->rules;
178   assert(p >= 0);
179   if (p < solv->learntrules)
180     if (MAPTST(&solv->weakrulemap, p))
181       POOL_DEBUG(type, "WEAK ");
182   if (p >= solv->learntrules)
183     POOL_DEBUG(type, "LEARNT ");
184   else if (p >= solv->featurerules)
185     POOL_DEBUG(type, "FEATURE ");
186   else if (p >= solv->updaterules)
187     POOL_DEBUG(type, "UPDATE ");
188   else if (p >= solv->jobrules)
189     POOL_DEBUG(type, "JOB ");
190   solver_printrule(solv, type, r);
191 }
192
193 void
194 solver_printproblem(Solver *solv, Id v)
195 {
196   Pool *pool = solv->pool;
197   int i;
198   Rule *r;
199   Id *jp;
200
201   if (v > 0)
202     solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, solv->rules + v);
203   else
204     {
205       v = -(v + 1);
206       POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "JOB %d\n", v);
207       jp = solv->ruletojob.elements;
208       for (i = solv->jobrules, r = solv->rules + i; i < solv->updaterules; i++, r++, jp++)
209         if (*jp == v)
210           {
211             POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "- ");
212             solver_printrule(solv, SAT_DEBUG_SOLUTIONS, r);
213           }
214       POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "ENDJOB\n");
215     }
216 }
217
218 void
219 solver_printwatches(Solver *solv, int type)
220 {
221   Pool *pool = solv->pool;
222   int counter;
223
224   POOL_DEBUG(type, "Watches: \n");
225   for (counter = -(pool->nsolvables - 1); counter < pool->nsolvables; counter++)
226     POOL_DEBUG(type, "    solvable [%d] -- rule [%d]\n", counter, solv->watches[counter + pool->nsolvables]);
227 }
228
229 /*
230  * printdecisions
231  */
232
233 void
234 solver_printdecisions(Solver *solv)
235 {
236   Pool *pool = solv->pool;
237   Repo *installed = solv->installed;
238   Id p, *obsoletesmap = solver_create_decisions_obsoletesmap(solv);
239   int i;
240   Solvable *s;
241
242   IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
243     {
244       POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- Decisions -----\n");
245       for (i = 0; i < solv->decisionq.count; i++)
246         {
247           p = solv->decisionq.elements[i];
248           solver_printruleelement(solv, SAT_DEBUG_SCHUBI, 0, p);
249         }
250       POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- Decisions end -----\n");
251     }
252
253   /* print solvables to be erased */
254
255   if (installed)
256     {
257       FOR_REPO_SOLVABLES(installed, p, s)
258         {
259           if (solv->decisionmap[p] >= 0)
260             continue;
261           if (obsoletesmap[p])
262             continue;
263           POOL_DEBUG(SAT_DEBUG_RESULT, "erase   %s\n", solvable2str(pool, s));
264         }
265     }
266
267   /* print solvables to be installed */
268
269   for (i = 0; i < solv->decisionq.count; i++)
270     {
271       int j;
272       p = solv->decisionq.elements[i];
273       if (p < 0)
274         continue;
275       if (p == SYSTEMSOLVABLE)
276         continue;
277       s = pool->solvables + p;
278       if (installed && s->repo == installed)
279         continue;
280
281       if (!obsoletesmap[p])
282         {
283           POOL_DEBUG(SAT_DEBUG_RESULT, "install   %s", solvable2str(pool, s));
284         }
285       else
286         {
287           Id xp, *xpp;
288           FOR_PROVIDES(xp, xpp, s->name)
289             {
290               Solvable *s2 = pool->solvables + xp;
291               if (s2->name != s->name)
292                 continue;
293               if (evrcmp(pool, s->evr, s2->evr, EVRCMP_MATCH_RELEASE) < 0)
294                 break;
295             }
296           if (xp)
297             POOL_DEBUG(SAT_DEBUG_RESULT, "downgrade %s", solvable2str(pool, s));
298           else
299             POOL_DEBUG(SAT_DEBUG_RESULT, "upgrade   %s", solvable2str(pool, s));
300           POOL_DEBUG(SAT_DEBUG_RESULT, "  (obsoletes");
301           for (j = installed->start; j < installed->end; j++)
302             if (obsoletesmap[j] == p)
303               POOL_DEBUG(SAT_DEBUG_RESULT, " %s", solvable2str(pool, pool->solvables + j));
304           POOL_DEBUG(SAT_DEBUG_RESULT, ")");
305         }
306       POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
307     }
308
309   sat_free(obsoletesmap);
310
311   if (solv->recommendations.count)
312     {
313       POOL_DEBUG(SAT_DEBUG_RESULT, "\nrecommended packages:\n");
314       for (i = 0; i < solv->recommendations.count; i++)
315         {
316           s = pool->solvables + solv->recommendations.elements[i];
317           if (solv->decisionmap[solv->recommendations.elements[i]] > 0)
318             {
319               if (installed && s->repo == installed)
320                 POOL_DEBUG(SAT_DEBUG_RESULT, "- %s (installed)\n", solvable2str(pool, s));
321               else
322                 POOL_DEBUG(SAT_DEBUG_RESULT, "- %s (selected)\n", solvable2str(pool, s));
323             }
324           else
325             POOL_DEBUG(SAT_DEBUG_RESULT, "- %s\n", solvable2str(pool, s));
326         }
327     }
328
329   if (solv->suggestions.count)
330     {
331       POOL_DEBUG(SAT_DEBUG_RESULT, "\nsuggested packages:\n");
332       for (i = 0; i < solv->suggestions.count; i++)
333         {
334           s = pool->solvables + solv->suggestions.elements[i];
335           if (solv->decisionmap[solv->suggestions.elements[i]] > 0)
336             {
337               if (installed && s->repo == installed)
338                 POOL_DEBUG(SAT_DEBUG_RESULT, "- %s (installed)\n", solvable2str(pool, s));
339               else
340                 POOL_DEBUG(SAT_DEBUG_RESULT, "- %s (selected)\n", solvable2str(pool, s));
341             }
342           else
343             POOL_DEBUG(SAT_DEBUG_RESULT, "- %s\n", solvable2str(pool, s));
344         }
345     }
346 }
347
348 void
349 solver_printprobleminfo(Solver *solv, Queue *job, Id problem)
350 {
351   Pool *pool = solv->pool;
352   Id probr;
353   Id dep, source, target;
354   Solvable *s, *s2;
355
356   probr = solver_findproblemrule(solv, problem);
357   switch (solver_problemruleinfo(solv, job, probr, &dep, &source, &target))
358     {
359     case SOLVER_PROBLEM_UPDATE_RULE:
360       s = pool_id2solvable(pool, source);
361       POOL_DEBUG(SAT_DEBUG_RESULT, "problem with installed package %s\n", solvable2str(pool, s));
362       return;
363     case SOLVER_PROBLEM_JOB_RULE:
364       POOL_DEBUG(SAT_DEBUG_RESULT, "conflicting requests\n");
365       return;
366     case SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP:
367       POOL_DEBUG(SAT_DEBUG_RESULT, "nothing provides requested %s\n", dep2str(pool, dep));
368       return;
369     case SOLVER_PROBLEM_NOT_INSTALLABLE:
370       s = pool_id2solvable(pool, source);
371       POOL_DEBUG(SAT_DEBUG_RESULT, "package %s is not installable\n", solvable2str(pool, s));
372       return;
373     case SOLVER_PROBLEM_NOTHING_PROVIDES_DEP:
374       s = pool_id2solvable(pool, source);
375       POOL_DEBUG(SAT_DEBUG_RESULT, "nothing provides %s needed by %s\n", dep2str(pool, dep), solvable2str(pool, s));
376       return;
377     case SOLVER_PROBLEM_SAME_NAME:
378       s = pool_id2solvable(pool, source);
379       s2 = pool_id2solvable(pool, target);
380       POOL_DEBUG(SAT_DEBUG_RESULT, "cannot install both %s and %s\n", solvable2str(pool, s), solvable2str(pool, s2));
381       return;
382     case SOLVER_PROBLEM_PACKAGE_CONFLICT:
383       s = pool_id2solvable(pool, source);
384       s2 = pool_id2solvable(pool, target);
385       POOL_DEBUG(SAT_DEBUG_RESULT, "package %s conflicts with %s provided by %s\n", solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
386       return;
387     case SOLVER_PROBLEM_PACKAGE_OBSOLETES:
388       s = pool_id2solvable(pool, source);
389       s2 = pool_id2solvable(pool, target);
390       POOL_DEBUG(SAT_DEBUG_RESULT, "package %s obsoletes %s provided by %s\n", solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
391       return;
392     case SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE:
393       s = pool_id2solvable(pool, source);
394       POOL_DEBUG(SAT_DEBUG_RESULT, "package %s requires %s, but none of the providers can be installed\n", solvable2str(pool, s), dep2str(pool, dep));
395       return;
396     case SOLVER_PROBLEM_SELF_CONFLICT:
397       s = pool_id2solvable(pool, source);
398       POOL_DEBUG(SAT_DEBUG_RESULT, "package %s conflicts with %s provided by itself\n", solvable2str(pool, s), dep2str(pool, dep));
399       return;
400     }
401 }
402
403 void
404 solver_printsolutions(Solver *solv, Queue *job)
405 {
406   Pool *pool = solv->pool;
407   int pcnt;
408   Id p, rp, how, what;
409   Id problem, solution, element;
410   Solvable *s, *sd;
411
412   POOL_DEBUG(SAT_DEBUG_RESULT, "Encountered problems! Here are the solutions:\n\n");
413   pcnt = 1;
414   problem = 0;
415   while ((problem = solver_next_problem(solv, problem)) != 0)
416     {
417       POOL_DEBUG(SAT_DEBUG_RESULT, "Problem %d:\n", pcnt++);
418       POOL_DEBUG(SAT_DEBUG_RESULT, "====================================\n");
419       solver_printprobleminfo(solv, job, problem);
420       POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
421       solution = 0;
422       while ((solution = solver_next_solution(solv, problem, solution)) != 0)
423         {
424           element = 0;
425           while ((element = solver_next_solutionelement(solv, problem, solution, element, &p, &rp)) != 0)
426             {
427               if (p == 0)
428                 {
429                   /* job, rp is index into job queue */
430                   how = job->elements[rp - 1] & ~SOLVER_WEAK;
431                   what = job->elements[rp];
432                   switch (how)
433                     {
434                     case SOLVER_INSTALL_SOLVABLE:
435                       s = pool->solvables + what;
436                       if (solv->installed && s->repo == solv->installed)
437                         POOL_DEBUG(SAT_DEBUG_RESULT, "- do not keep %s installed\n", solvable2str(pool, s));
438                       else
439                         POOL_DEBUG(SAT_DEBUG_RESULT, "- do not install %s\n", solvable2str(pool, s));
440                       break;
441                     case SOLVER_ERASE_SOLVABLE:
442                       s = pool->solvables + what;
443                       if (solv->installed && s->repo == solv->installed)
444                         POOL_DEBUG(SAT_DEBUG_RESULT, "- do not deinstall %s\n", solvable2str(pool, s));
445                       else
446                         POOL_DEBUG(SAT_DEBUG_RESULT, "- do not forbid installation of %s\n", solvable2str(pool, s));
447                       break;
448                     case SOLVER_INSTALL_SOLVABLE_NAME:
449                       POOL_DEBUG(SAT_DEBUG_RESULT, "- do not install %s\n", dep2str(pool, what));
450                       break;
451                     case SOLVER_ERASE_SOLVABLE_NAME:
452                       POOL_DEBUG(SAT_DEBUG_RESULT, "- do not deinstall %s\n", dep2str(pool, what));
453                       break;
454                     case SOLVER_INSTALL_SOLVABLE_PROVIDES:
455                       POOL_DEBUG(SAT_DEBUG_RESULT, "- do not install a solvable providing %s\n", dep2str(pool, what));
456                       break;
457                     case SOLVER_ERASE_SOLVABLE_PROVIDES:
458                       POOL_DEBUG(SAT_DEBUG_RESULT, "- do not deinstall all solvables providing %s\n", dep2str(pool, what));
459                       break;
460                     case SOLVER_INSTALL_SOLVABLE_UPDATE:
461                       s = pool->solvables + what;
462                       POOL_DEBUG(SAT_DEBUG_RESULT, "- do not install most recent version of %s\n", solvable2str(pool, s));
463                       break;
464                     default:
465                       POOL_DEBUG(SAT_DEBUG_RESULT, "- do something different\n");
466                       break;
467                     }
468                 }
469               else
470                 {
471                   /* policy, replace p with rp */
472                   s = pool->solvables + p;
473                   sd = rp ? pool->solvables + rp : 0;
474                   if (sd)
475                     {
476                       int gotone = 0;
477                       if (!solv->allowdowngrade && evrcmp(pool, s->evr, sd->evr, EVRCMP_MATCH_RELEASE) > 0)
478                         {
479                           POOL_DEBUG(SAT_DEBUG_RESULT, "- allow downgrade of %s to %s\n", solvable2str(pool, s), solvable2str(pool, sd));
480                           gotone = 1;
481                         }
482                       if (!solv->allowarchchange && s->name == sd->name && s->arch != sd->arch && policy_illegal_archchange(solv, s, sd))
483                         {
484                           POOL_DEBUG(SAT_DEBUG_RESULT, "- allow architecture change of %s to %s\n", solvable2str(pool, s), solvable2str(pool, sd));
485                           gotone = 1;
486                         }
487                       if (!solv->allowvendorchange && s->name == sd->name && s->vendor != sd->vendor && policy_illegal_vendorchange(solv, s, sd))
488                         {
489                           if (sd->vendor)
490                             POOL_DEBUG(SAT_DEBUG_RESULT, "- allow vendor change from '%s' (%s) to '%s' (%s)\n", id2str(pool, s->vendor), solvable2str(pool, s), id2str(pool, sd->vendor), solvable2str(pool, sd));
491                           else
492                             POOL_DEBUG(SAT_DEBUG_RESULT, "- allow vendor change from '%s' (%s) to no vendor (%s)\n", id2str(pool, s->vendor), solvable2str(pool, s), solvable2str(pool, sd));
493                           gotone = 1;
494                         }
495                       if (!gotone)
496                         POOL_DEBUG(SAT_DEBUG_RESULT, "- allow replacement of %s with %s\n", solvable2str(pool, s), solvable2str(pool, sd));
497                     }
498                   else
499                     {
500                       POOL_DEBUG(SAT_DEBUG_RESULT, "- allow deinstallation of %s\n", solvable2str(pool, s));
501                     }
502
503                 }
504             }
505           POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
506         }
507     }
508 }
509