00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include <unistd.h>
00016 #include <string.h>
00017 #include <assert.h>
00018
00019 #include "solver.h"
00020 #include "bitmap.h"
00021 #include "pool.h"
00022 #include "util.h"
00023 #include "evr.h"
00024 #include "solverdebug.h"
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 void
00035 solver_disableproblem(Solver *solv, Id v)
00036 {
00037 Rule *r;
00038 int i;
00039 Id *jp;
00040
00041 if (v > 0)
00042 {
00043 if (v >= solv->infarchrules && v < solv->infarchrules_end)
00044 {
00045 Pool *pool = solv->pool;
00046 Id name = pool->solvables[-solv->rules[v].p].name;
00047 while (v > solv->infarchrules && pool->solvables[-solv->rules[v - 1].p].name == name)
00048 v--;
00049 for (; v < solv->infarchrules_end && pool->solvables[-solv->rules[v].p].name == name; v++)
00050 solver_disablerule(solv, solv->rules + v);
00051 return;
00052 }
00053 if (v >= solv->duprules && v < solv->duprules_end)
00054 {
00055 Pool *pool = solv->pool;
00056 Id name = pool->solvables[-solv->rules[v].p].name;
00057 while (v > solv->duprules && pool->solvables[-solv->rules[v - 1].p].name == name)
00058 v--;
00059 for (; v < solv->duprules_end && pool->solvables[-solv->rules[v].p].name == name; v++)
00060 solver_disablerule(solv, solv->rules + v);
00061 return;
00062 }
00063 solver_disablerule(solv, solv->rules + v);
00064 #if 0
00065
00066 if (v >= solv->updaterules && v < solv->updaterules_end)
00067 {
00068
00069 r = solv->rules + (v - solv->updaterules + solv->featurerules);
00070 if (r->p)
00071 solver_enablerule(solv, r);
00072 }
00073 #endif
00074 return;
00075 }
00076 v = -(v + 1);
00077 jp = solv->ruletojob.elements;
00078 for (i = solv->jobrules, r = solv->rules + i; i < solv->jobrules_end; i++, r++, jp++)
00079 if (*jp == v)
00080 solver_disablerule(solv, r);
00081 }
00082
00083
00084
00085
00086
00087 void
00088 solver_enableproblem(Solver *solv, Id v)
00089 {
00090 Rule *r;
00091 int i;
00092 Id *jp;
00093
00094 if (v > 0)
00095 {
00096 if (v >= solv->infarchrules && v < solv->infarchrules_end)
00097 {
00098 Pool *pool = solv->pool;
00099 Id name = pool->solvables[-solv->rules[v].p].name;
00100 while (v > solv->infarchrules && pool->solvables[-solv->rules[v - 1].p].name == name)
00101 v--;
00102 for (; v < solv->infarchrules_end && pool->solvables[-solv->rules[v].p].name == name; v++)
00103 solver_enablerule(solv, solv->rules + v);
00104 return;
00105 }
00106 if (v >= solv->duprules && v < solv->duprules_end)
00107 {
00108 Pool *pool = solv->pool;
00109 Id name = pool->solvables[-solv->rules[v].p].name;
00110 while (v > solv->duprules && pool->solvables[-solv->rules[v - 1].p].name == name)
00111 v--;
00112 for (; v < solv->duprules_end && pool->solvables[-solv->rules[v].p].name == name; v++)
00113 solver_enablerule(solv, solv->rules + v);
00114 return;
00115 }
00116 if (v >= solv->featurerules && v < solv->featurerules_end)
00117 {
00118
00119 r = solv->rules + (v - solv->featurerules + solv->updaterules);
00120 if (r->d >= 0)
00121 return;
00122 }
00123 solver_enablerule(solv, solv->rules + v);
00124 if (v >= solv->updaterules && v < solv->updaterules_end)
00125 {
00126
00127 r = solv->rules + (v - solv->updaterules + solv->featurerules);
00128 if (r->p)
00129 solver_disablerule(solv, r);
00130 }
00131 return;
00132 }
00133 v = -(v + 1);
00134 jp = solv->ruletojob.elements;
00135 for (i = solv->jobrules, r = solv->rules + i; i < solv->jobrules_end; i++, r++, jp++)
00136 if (*jp == v)
00137 solver_enablerule(solv, r);
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 static void
00149 enableweakrules(Solver *solv)
00150 {
00151 int i;
00152 Rule *r;
00153
00154 for (i = 1, r = solv->rules + i; i < solv->learntrules; i++, r++)
00155 {
00156 if (r->d >= 0)
00157 continue;
00158 if (!MAPTST(&solv->weakrulemap, i))
00159 continue;
00160 solver_enablerule(solv, r);
00161 }
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 static void
00177 refine_suggestion(Solver *solv, Id *problem, Id sug, Queue *refined, int essentialok)
00178 {
00179 Pool *pool = solv->pool;
00180 int i, j;
00181 Id v;
00182 Queue disabled;
00183 int disabledcnt;
00184
00185 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
00186 {
00187 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "refine_suggestion start\n");
00188 for (i = 0; problem[i]; i++)
00189 {
00190 if (problem[i] == sug)
00191 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "=> ");
00192 solver_printproblem(solv, problem[i]);
00193 }
00194 }
00195 queue_empty(refined);
00196 if (!essentialok && sug < 0 && (solv->job.elements[-sug - 1] & SOLVER_ESSENTIAL) != 0)
00197 return;
00198 queue_init(&disabled);
00199 queue_push(refined, sug);
00200
00201
00202 solver_reset(solv);
00203
00204 for (i = 0; problem[i]; i++)
00205 if (problem[i] != sug)
00206 solver_enableproblem(solv, problem[i]);
00207
00208 if (sug < 0)
00209 solver_reenablepolicyrules(solv, -(sug + 1));
00210 else if (sug >= solv->updaterules && sug < solv->updaterules_end)
00211 {
00212
00213 Rule *r = solv->rules + solv->featurerules + (sug - solv->updaterules);
00214 if (r->p)
00215 solver_enablerule(solv, r);
00216 }
00217
00218 enableweakrules(solv);
00219
00220 for (;;)
00221 {
00222 int njob, nfeature, nupdate;
00223 queue_empty(&solv->problems);
00224 solver_reset(solv);
00225
00226 if (!solv->problems.count)
00227 solver_run_sat(solv, 0, 0);
00228
00229 if (!solv->problems.count)
00230 {
00231 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "no more problems!\n");
00232 IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
00233 solver_printdecisions(solv);
00234 break;
00235 }
00236 disabledcnt = disabled.count;
00237
00238 njob = nfeature = nupdate = 0;
00239 for (i = 1; i < solv->problems.count - 1; i++)
00240 {
00241
00242 v = solv->problems.elements[i];
00243 if (v == 0)
00244 break;
00245 for (j = 0; problem[j]; j++)
00246 if (problem[j] != sug && problem[j] == v)
00247 break;
00248 if (problem[j])
00249 continue;
00250 if (v >= solv->featurerules && v < solv->featurerules_end)
00251 nfeature++;
00252 else if (v > 0)
00253 nupdate++;
00254 else
00255 {
00256 if (!essentialok && (solv->job.elements[-v -1] & SOLVER_ESSENTIAL) != 0)
00257 continue;
00258 njob++;
00259 }
00260 queue_push(&disabled, v);
00261 }
00262 if (disabled.count == disabledcnt)
00263 {
00264
00265 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "no solution found!\n");
00266 refined->count = 0;
00267 break;
00268 }
00269 if (!njob && nupdate && nfeature)
00270 {
00271
00272 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "throwing away feature rules\n");
00273 for (i = j = disabledcnt; i < disabled.count; i++)
00274 {
00275 v = disabled.elements[i];
00276 if (v < solv->featurerules || v >= solv->featurerules_end)
00277 disabled.elements[j++] = v;
00278 }
00279 disabled.count = j;
00280 nfeature = 0;
00281 }
00282 if (disabled.count == disabledcnt + 1)
00283 {
00284
00285 v = disabled.elements[disabledcnt];
00286 if (!nfeature)
00287 queue_push(refined, v);
00288 solver_disableproblem(solv, v);
00289 if (v >= solv->updaterules && v < solv->updaterules_end)
00290 {
00291 Rule *r = solv->rules + (v - solv->updaterules + solv->featurerules);
00292 if (r->p)
00293 solver_enablerule(solv, r);
00294 }
00295 if (v < 0)
00296 solver_reenablepolicyrules(solv, -(v + 1));
00297 }
00298 else
00299 {
00300
00301
00302
00303
00304 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
00305 {
00306 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "more than one solution found:\n");
00307 for (i = disabledcnt; i < disabled.count; i++)
00308 solver_printproblem(solv, disabled.elements[i]);
00309 }
00310 for (i = disabledcnt; i < disabled.count; i++)
00311 {
00312 v = disabled.elements[i];
00313 solver_disableproblem(solv, v);
00314 if (v >= solv->updaterules && v < solv->updaterules_end)
00315 {
00316 Rule *r = solv->rules + (v - solv->updaterules + solv->featurerules);
00317 if (r->p)
00318 solver_enablerule(solv, r);
00319 }
00320 }
00321 }
00322 }
00323
00324
00325 for (i = 0; i < disabled.count; i++)
00326 solver_enableproblem(solv, disabled.elements[i]);
00327 queue_free(&disabled);
00328
00329 for (i = 0; problem[i]; i++)
00330 solver_enableproblem(solv, problem[i]);
00331 solver_disablepolicyrules(solv);
00332
00333 for (i = 0; problem[i]; i++)
00334 solver_disableproblem(solv, problem[i]);
00335 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "refine_suggestion end\n");
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 static int
00347 problems_sortcmp(const void *ap, const void *bp, void *dp)
00348 {
00349 Queue *job = dp;
00350 Id a = *(Id *)ap, b = *(Id *)bp;
00351 if (a < 0 && b > 0)
00352 return 1;
00353 if (a > 0 && b < 0)
00354 return -1;
00355 if (a < 0 && b < 0)
00356 {
00357 int af = job->elements[-a - 1] & SOLVER_ESSENTIAL;
00358 int bf = job->elements[-b - 1] & SOLVER_ESSENTIAL;
00359 int x = af - bf;
00360 if (x)
00361 return x;
00362 }
00363 return a - b;
00364 }
00365
00366
00367
00368
00369 static void
00370 convertsolution(Solver *solv, Id why, Queue *solutionq)
00371 {
00372 Pool *pool = solv->pool;
00373 if (why < 0)
00374 {
00375 queue_push(solutionq, 0);
00376 queue_push(solutionq, -why);
00377 return;
00378 }
00379 if (why >= solv->infarchrules && why < solv->infarchrules_end)
00380 {
00381 Id p, name;
00382
00383 assert(solv->rules[why].p < 0);
00384 name = pool->solvables[-solv->rules[why].p].name;
00385 while (why > solv->infarchrules && pool->solvables[-solv->rules[why - 1].p].name == name)
00386 why--;
00387 p = 0;
00388 for (; why < solv->infarchrules_end && pool->solvables[-solv->rules[why].p].name == name; why++)
00389 if (solv->decisionmap[-solv->rules[why].p] > 0)
00390 {
00391 p = -solv->rules[why].p;
00392 break;
00393 }
00394 if (!p)
00395 return;
00396 queue_push(solutionq, SOLVER_SOLUTION_INFARCH);
00397 queue_push(solutionq, p);
00398 return;
00399 }
00400 if (why >= solv->duprules && why < solv->duprules_end)
00401 {
00402 Id p, name;
00403
00404 assert(solv->rules[why].p < 0);
00405 name = pool->solvables[-solv->rules[why].p].name;
00406 while (why > solv->duprules && pool->solvables[-solv->rules[why - 1].p].name == name)
00407 why--;
00408 p = 0;
00409 for (; why < solv->duprules_end && pool->solvables[-solv->rules[why].p].name == name; why++)
00410 if (solv->decisionmap[-solv->rules[why].p] > 0)
00411 {
00412 p = -solv->rules[why].p;
00413 break;
00414 }
00415 if (!p)
00416 return;
00417 queue_push(solutionq, SOLVER_SOLUTION_DISTUPGRADE);
00418 queue_push(solutionq, p);
00419 return;
00420 }
00421 if (why >= solv->updaterules && why < solv->updaterules_end)
00422 {
00423
00424 Id p, *dp, rp = 0;
00425 Rule *rr;
00426
00427 assert(why >= solv->updaterules && why < solv->updaterules_end);
00428
00429 rr = solv->rules + why;
00430 FOR_RULELITERALS(p, dp, rr)
00431 if (p > 0 && solv->decisionmap[p] > 0)
00432 break;
00433 if (p)
00434 return;
00435
00436 p = solv->installed->start + (why - solv->updaterules);
00437 rr = solv->rules + solv->featurerules + (why - solv->updaterules);
00438 if (!rr->p)
00439 rr = solv->rules + why;
00440 if (solv->distupgrade && solv->rules[why].p != p && solv->decisionmap[p] > 0)
00441 {
00442
00443 queue_push(solutionq, SOLVER_SOLUTION_DISTUPGRADE);
00444 queue_push(solutionq, p);
00445 return;
00446 }
00447 if (solv->decisionmap[p] > 0)
00448 return;
00449 if (rr->w2)
00450 {
00451 int mvrp = 0;
00452 FOR_RULELITERALS(rp, dp, rr)
00453 {
00454 if (rp > 0 && solv->decisionmap[rp] > 0 && pool->solvables[rp].repo != solv->installed)
00455 {
00456 mvrp = rp;
00457 if (!(solv->noobsoletes.size && MAPTST(&solv->noobsoletes, rp)))
00458 break;
00459 }
00460 }
00461 if (!rp && mvrp)
00462 {
00463
00464
00465 queue_push(solutionq, p);
00466 queue_push(solutionq, mvrp);
00467 }
00468 }
00469 queue_push(solutionq, p);
00470 queue_push(solutionq, rp);
00471 return;
00472 }
00473 }
00474
00475
00476
00477
00478
00479 int
00480 solver_prepare_solutions(Solver *solv)
00481 {
00482 int i, j = 1, idx = 1;
00483
00484 if (!solv->problems.count)
00485 return 0;
00486 queue_push(&solv->solutions, 0);
00487 queue_push(&solv->solutions, -1);
00488 for (i = 1; i < solv->problems.count; i++)
00489 {
00490 Id p = solv->problems.elements[i];
00491 queue_push(&solv->solutions, p);
00492 if (p)
00493 continue;
00494 solv->problems.elements[j++] = idx;
00495 if (i + 1 >= solv->problems.count)
00496 break;
00497 solv->problems.elements[j++] = solv->problems.elements[++i];
00498 idx = solv->solutions.count;
00499 queue_push(&solv->solutions, -1);
00500 }
00501 solv->problems.count = j;
00502 return j / 2;
00503 }
00504
00505
00506
00507
00508
00509 static void
00510 create_solutions(Solver *solv, int probnr, int solidx)
00511 {
00512 Pool *pool = solv->pool;
00513 Queue redoq;
00514 Queue problem, solution, problems_save;
00515 int i, j, nsol;
00516 int essentialok;
00517 int recocount;
00518 unsigned int now;
00519
00520 now = sat_timems(0);
00521 recocount = solv->recommendations.count;
00522 solv->recommendations.count = 0;
00523 queue_init(&redoq);
00524
00525 for (i = 0; i < solv->decisionq.count; i++)
00526 {
00527 Id p = solv->decisionq.elements[i];
00528 queue_push(&redoq, p);
00529 queue_push(&redoq, solv->decisionq_why.elements[i]);
00530 queue_push(&redoq, solv->decisionmap[p > 0 ? p : -p]);
00531 }
00532
00533 problems_save = solv->problems;
00534 memset(&solv->problems, 0, sizeof(solv->problems));
00535
00536
00537 queue_init(&problem);
00538 for (i = solidx + 1; i < solv->solutions.count; i++)
00539 {
00540 Id v = solv->solutions.elements[i];
00541 if (!v)
00542 break;
00543 queue_push(&problem, v);
00544 }
00545 if (problem.count > 1)
00546 sat_sort(problem.elements, problem.count, sizeof(Id), problems_sortcmp, &solv->job);
00547 queue_push(&problem, 0);
00548 problem.count--;
00549 #if 0
00550 for (i = 0; i < problem.count; i++)
00551 printf("PP %d %d\n", i, problem.elements[i]);
00552 #endif
00553
00554
00555 nsol = 0;
00556 essentialok = 0;
00557 queue_init(&solution);
00558 for (i = 0; i < problem.count; i++)
00559 {
00560 int solstart = solv->solutions.count;
00561 refine_suggestion(solv, problem.elements, problem.elements[i], &solution, essentialok);
00562 queue_push(&solv->solutions, 0);
00563 for (j = 0; j < solution.count; j++)
00564 convertsolution(solv, solution.elements[j], &solv->solutions);
00565 if (solv->solutions.count == solstart + 1)
00566 {
00567 solv->solutions.count--;
00568 if (!essentialok && i + 1 == problem.count && !nsol)
00569 {
00570
00571 essentialok = 1;
00572 i = -1;
00573 }
00574 continue;
00575 }
00576
00577 solv->solutions.elements[solstart] = (solv->solutions.count - (solstart + 1)) / 2;
00578 queue_push(&solv->solutions, 0);
00579 queue_push(&solv->solutions, 0);
00580 solv->solutions.elements[solidx + 1 + nsol++] = solstart;
00581 }
00582 solv->solutions.elements[solidx + 1 + nsol] = 0;
00583 solv->solutions.elements[solidx] = nsol;
00584 queue_free(&problem);
00585 queue_free(&solution);
00586
00587
00588 memset(solv->decisionmap, 0, pool->nsolvables * sizeof(Id));
00589 queue_empty(&solv->decisionq);
00590 queue_empty(&solv->decisionq_why);
00591 for (i = 0; i < redoq.count; i += 3)
00592 {
00593 Id p = redoq.elements[i];
00594 queue_push(&solv->decisionq, p);
00595 queue_push(&solv->decisionq_why, redoq.elements[i + 1]);
00596 solv->decisionmap[p > 0 ? p : -p] = redoq.elements[i + 2];
00597 }
00598 solv->recommendations.count = recocount;
00599 queue_free(&redoq);
00600
00601 queue_free(&solv->problems);
00602 solv->problems = problems_save;
00603 POOL_DEBUG(SAT_DEBUG_STATS, "create_solutions for problem #%d took %d ms\n", probnr, sat_timems(now));
00604 }
00605
00606
00607
00608
00609 unsigned int
00610 solver_problem_count(Solver *solv)
00611 {
00612 return solv->problems.count / 2;
00613 }
00614
00615 Id
00616 solver_next_problem(Solver *solv, Id problem)
00617 {
00618 if (!problem)
00619 return solv->problems.count ? 1 : 0;
00620 return (problem + 1) * 2 - 1 < solv->problems.count ? problem + 1 : 0;
00621 }
00622
00623 unsigned int
00624 solver_solution_count(Solver *solv, Id problem)
00625 {
00626 Id solidx = solv->problems.elements[problem * 2 - 1];
00627 if (solv->solutions.elements[solidx] < 0)
00628 create_solutions(solv, problem, solidx);
00629 return solv->solutions.elements[solidx];
00630 }
00631
00632 Id
00633 solver_next_solution(Solver *solv, Id problem, Id solution)
00634 {
00635 Id solidx = solv->problems.elements[problem * 2 - 1];
00636 if (solv->solutions.elements[solidx] < 0)
00637 create_solutions(solv, problem, solidx);
00638 return solv->solutions.elements[solidx + solution + 1] ? solution + 1 : 0;
00639 }
00640
00641 unsigned int
00642 solver_solutionelement_count(Solver *solv, Id problem, Id solution)
00643 {
00644 Id solidx = solv->problems.elements[problem * 2 - 1];
00645 solidx = solv->solutions.elements[solidx + solution];
00646 return solv->solutions.elements[solidx];
00647 }
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 Id
00675 solver_next_solutionelement(Solver *solv, Id problem, Id solution, Id element, Id *p, Id *rp)
00676 {
00677 Id solidx = solv->problems.elements[problem * 2 - 1];
00678 solidx = solv->solutions.elements[solidx + solution];
00679 if (!solidx)
00680 return 0;
00681 solidx += 1 + element * 2;
00682 if (!solv->solutions.elements[solidx] && !solv->solutions.elements[solidx + 1])
00683 return 0;
00684 *p = solv->solutions.elements[solidx];
00685 *rp = solv->solutions.elements[solidx + 1];
00686 return element + 1;
00687 }
00688
00689 void
00690 solver_take_solutionelement(Solver *solv, Id p, Id rp, Queue *job)
00691 {
00692 int i;
00693
00694 if (p == SOLVER_SOLUTION_JOB)
00695 {
00696 job->elements[rp - 1] = SOLVER_NOOP;
00697 job->elements[rp] = 0;
00698 return;
00699 }
00700 if (rp <= 0 && p <= 0)
00701 return;
00702 if (rp > 0)
00703 p = SOLVER_INSTALL|SOLVER_SOLVABLE;
00704 else
00705 {
00706 rp = p;
00707 p = SOLVER_ERASE|SOLVER_SOLVABLE;
00708 }
00709 for (i = 0; i < job->count; i += 2)
00710 if (job->elements[i] == p && job->elements[i + 1] == rp)
00711 return;
00712 queue_push2(job, p, rp);
00713 }
00714
00715 void
00716 solver_take_solution(Solver *solv, Id problem, Id solution, Queue *job)
00717 {
00718 Id p, rp, element = 0;
00719 while ((element = solver_next_solutionelement(solv, problem, solution, element, &p, &rp)) != 0)
00720 solver_take_solutionelement(solv, p, rp, job);
00721 }
00722
00723
00724
00725
00726
00727
00728
00729 static void
00730 findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp, Id *jobrp)
00731 {
00732 Id rid, d;
00733 Id lreqr, lconr, lsysr, ljobr;
00734 Rule *r;
00735 Id jobassert = 0;
00736 int i, reqset = 0;
00737
00738
00739 for (i = idx; (rid = solv->learnt_pool.elements[i]) != 0; i++)
00740 {
00741 if (rid < solv->jobrules || rid >= solv->jobrules_end)
00742 continue;
00743 r = solv->rules + rid;
00744 d = r->d < 0 ? -r->d - 1 : r->d;
00745 if (!d && r->w2 == 0 && r->p > 0)
00746 {
00747 jobassert = r->p;
00748 break;
00749 }
00750 }
00751
00752
00753
00754 lreqr = lconr = lsysr = ljobr = 0;
00755 while ((rid = solv->learnt_pool.elements[idx++]) != 0)
00756 {
00757 assert(rid > 0);
00758 if (rid >= solv->learntrules)
00759 findproblemrule_internal(solv, solv->learnt_why.elements[rid - solv->learntrules], &lreqr, &lconr, &lsysr, &ljobr);
00760 else if ((rid >= solv->jobrules && rid < solv->jobrules_end) || (rid >= solv->infarchrules && rid < solv->infarchrules_end) || (rid >= solv->duprules && rid < solv->duprules_end))
00761 {
00762 if (!*jobrp)
00763 *jobrp = rid;
00764 }
00765 else if (rid >= solv->updaterules && rid < solv->updaterules_end)
00766 {
00767 if (!*sysrp)
00768 *sysrp = rid;
00769 }
00770 else
00771 {
00772 assert(rid < solv->rpmrules_end);
00773 r = solv->rules + rid;
00774 d = r->d < 0 ? -r->d - 1 : r->d;
00775 if (!d && r->w2 < 0)
00776 {
00777 if (!*conrp)
00778 *conrp = rid;
00779 }
00780 else
00781 {
00782 if (!d && r->w2 == 0 && reqset < 3)
00783 {
00784 if (*reqrp > 0 && r->p < -1)
00785 {
00786 Id op = -solv->rules[*reqrp].p;
00787 if (op > 1 && solv->pool->solvables[op].arch != solv->pool->solvables[-r->p].arch)
00788 continue;
00789 }
00790
00791 *reqrp = rid;
00792 reqset = 3;
00793 }
00794 else if (jobassert && r->p == -jobassert)
00795 {
00796
00797 *reqrp = rid;
00798 reqset = 2;
00799 }
00800 else if (solv->installed && r->p < 0 && solv->pool->solvables[-r->p].repo == solv->installed && reqset <= 1)
00801 {
00802
00803 *reqrp = rid;
00804 reqset = 1;
00805 }
00806 else if (!*reqrp)
00807 *reqrp = rid;
00808 }
00809 }
00810 }
00811 if (!*reqrp && lreqr)
00812 *reqrp = lreqr;
00813 if (!*conrp && lconr)
00814 *conrp = lconr;
00815 if (!*jobrp && ljobr)
00816 *jobrp = ljobr;
00817 if (!*sysrp && lsysr)
00818 *sysrp = lsysr;
00819 }
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830 Id
00831 solver_findproblemrule(Solver *solv, Id problem)
00832 {
00833 Id reqr, conr, sysr, jobr;
00834 Id idx = solv->problems.elements[2 * problem - 2];
00835 reqr = conr = sysr = jobr = 0;
00836 findproblemrule_internal(solv, idx, &reqr, &conr, &sysr, &jobr);
00837 if (reqr)
00838 return reqr;
00839 if (conr)
00840 return conr;
00841 if (sysr)
00842 return sysr;
00843 if (jobr)
00844 return jobr;
00845 assert(0);
00846 }
00847
00848
00849
00850 static void
00851 findallproblemrules_internal(Solver *solv, Id idx, Queue *rules)
00852 {
00853 Id rid;
00854 while ((rid = solv->learnt_pool.elements[idx++]) != 0)
00855 {
00856 if (rid >= solv->learntrules)
00857 {
00858 findallproblemrules_internal(solv, solv->learnt_why.elements[rid - solv->learntrules], rules);
00859 continue;
00860 }
00861 queue_pushunique(rules, rid);
00862 }
00863 }
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 void
00874 solver_findallproblemrules(Solver *solv, Id problem, Queue *rules)
00875 {
00876 queue_empty(rules);
00877 findallproblemrules_internal(solv, solv->problems.elements[2 * problem - 2], rules);
00878 }
00879
00880
00881 SolverRuleinfo
00882 solver_problemruleinfo(Solver *solv, Queue *job, Id rid, Id *depp, Id *sourcep, Id *targetp)
00883 {
00884 return solver_ruleinfo(solv, rid, sourcep, targetp, depp);
00885 }
00886
00887