00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <stdarg.h>
00018 #include <unistd.h>
00019 #include <string.h>
00020
00021 #include "pool.h"
00022 #include "repo.h"
00023 #include "poolid.h"
00024 #include "poolid_private.h"
00025 #include "poolarch.h"
00026 #include "util.h"
00027 #include "bitmap.h"
00028 #include "evr.h"
00029
00030 #define SOLVABLE_BLOCK 255
00031
00032 #define KNOWNID_INITIALIZE
00033 #include "knownid.h"
00034 #undef KNOWNID_INITIALIZE
00035
00036
00037 Pool *
00038 pool_create(void)
00039 {
00040 Pool *pool;
00041 Solvable *s;
00042
00043 pool = (Pool *)sat_calloc(1, sizeof(*pool));
00044
00045 stringpool_init (&pool->ss, initpool_data);
00046
00047
00048 pool->rels = sat_extend_resize(0, 1, sizeof(Reldep), REL_BLOCK);
00049 pool->nrels = 1;
00050 memset(pool->rels, 0, sizeof(Reldep));
00051
00052
00053 pool->solvables = sat_extend_resize(0, 2, sizeof(Solvable), SOLVABLE_BLOCK);
00054 pool->nsolvables = 2;
00055 memset(pool->solvables, 0, 2 * sizeof(Solvable));
00056 s = pool->solvables + SYSTEMSOLVABLE;
00057 s->name = SYSTEM_SYSTEM;
00058 s->arch = ARCH_NOARCH;
00059 s->evr = ID_EMPTY;
00060
00061 queue_init(&pool->vendormap);
00062
00063 pool->debugmask = SAT_DEBUG_RESULT;
00064 return pool;
00065 }
00066
00067
00068
00069 void
00070 pool_free(Pool *pool)
00071 {
00072 int i;
00073
00074 pool_freewhatprovides(pool);
00075 pool_freeidhashes(pool);
00076 repo_freeallrepos(pool, 1);
00077 sat_free(pool->id2arch);
00078 sat_free(pool->solvables);
00079 stringpool_free(&pool->ss);
00080 sat_free(pool->rels);
00081 queue_free(&pool->vendormap);
00082 for (i = 0; i < POOL_TMPSPACEBUF; i++)
00083 sat_free(pool->tmpspacebuf[i]);
00084 for (i = 0; i < pool->nlanguages; i++)
00085 free((char *)pool->languages[i]);
00086 sat_free(pool->languages);
00087 sat_free(pool->languagecache);
00088 sat_free(pool);
00089 }
00090
00091 #ifdef MULTI_SEMANTICS
00092 void
00093 pool_setdisttype(Pool *pool, int disttype)
00094 {
00095 pool->disttype = disttype;
00096 }
00097 #endif
00098
00099 Id
00100 pool_add_solvable(Pool *pool)
00101 {
00102 pool->solvables = sat_extend(pool->solvables, pool->nsolvables, 1, sizeof(Solvable), SOLVABLE_BLOCK);
00103 memset(pool->solvables + pool->nsolvables, 0, sizeof(Solvable));
00104 return pool->nsolvables++;
00105 }
00106
00107 Id
00108 pool_add_solvable_block(Pool *pool, int count)
00109 {
00110 Id nsolvables = pool->nsolvables;
00111 if (!count)
00112 return nsolvables;
00113 pool->solvables = sat_extend(pool->solvables, pool->nsolvables, count, sizeof(Solvable), SOLVABLE_BLOCK);
00114 memset(pool->solvables + nsolvables, 0, sizeof(Solvable) * count);
00115 pool->nsolvables += count;
00116 return nsolvables;
00117 }
00118
00119 void
00120 pool_free_solvable_block(Pool *pool, Id start, int count, int reuseids)
00121 {
00122 if (!count)
00123 return;
00124 if (reuseids && start + count == pool->nsolvables)
00125 {
00126
00127 pool->nsolvables = start;
00128 return;
00129 }
00130 memset(pool->solvables + start, 0, sizeof(Solvable) * count);
00131 }
00132
00133
00134 void
00135 pool_set_installed(Pool *pool, Repo *installed)
00136 {
00137 if (pool->installed == installed)
00138 return;
00139 pool->installed = installed;
00140 pool_freewhatprovides(pool);
00141 }
00142
00143 static int
00144 pool_shrink_whatprovides_sortcmp(const void *ap, const void *bp, void *dp)
00145 {
00146 int r;
00147 Pool *pool = dp;
00148 Id oa, ob, *da, *db;
00149 oa = pool->whatprovides[*(Id *)ap];
00150 ob = pool->whatprovides[*(Id *)bp];
00151 if (oa == ob)
00152 return *(Id *)ap - *(Id *)bp;
00153 if (!oa)
00154 return -1;
00155 if (!ob)
00156 return 1;
00157 da = pool->whatprovidesdata + oa;
00158 db = pool->whatprovidesdata + ob;
00159 while (*db)
00160 if ((r = (*da++ - *db++)) != 0)
00161 return r;
00162 if (*da)
00163 return *da;
00164 return *(Id *)ap - *(Id *)bp;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173 static void
00174 pool_shrink_whatprovides(Pool *pool)
00175 {
00176 Id i, id;
00177 Id *sorted;
00178 Id lastid, *last, *dp, *lp;
00179 Offset o;
00180 int r;
00181
00182 if (pool->ss.nstrings < 3)
00183 return;
00184 sorted = sat_malloc2(pool->ss.nstrings, sizeof(Id));
00185 for (id = 0; id < pool->ss.nstrings; id++)
00186 sorted[id] = id;
00187 sat_sort(sorted + 1, pool->ss.nstrings - 1, sizeof(Id), pool_shrink_whatprovides_sortcmp, pool);
00188 last = 0;
00189 lastid = 0;
00190 for (i = 1; i < pool->ss.nstrings; i++)
00191 {
00192 id = sorted[i];
00193 o = pool->whatprovides[id];
00194 if (o == 0 || o == 1)
00195 continue;
00196 dp = pool->whatprovidesdata + o;
00197 if (last)
00198 {
00199 lp = last;
00200 while (*dp)
00201 if (*dp++ != *lp++)
00202 {
00203 last = 0;
00204 break;
00205 }
00206 if (last && *lp)
00207 last = 0;
00208 if (last)
00209 {
00210 pool->whatprovides[id] = -lastid;
00211 continue;
00212 }
00213 }
00214 last = pool->whatprovidesdata + o;
00215 lastid = id;
00216 }
00217 sat_free(sorted);
00218 dp = pool->whatprovidesdata + 2;
00219 for (id = 1; id < pool->ss.nstrings; id++)
00220 {
00221 o = pool->whatprovides[id];
00222 if (o == 0 || o == 1)
00223 continue;
00224 if ((Id)o < 0)
00225 {
00226 i = -(Id)o;
00227 if (i >= id)
00228 abort();
00229 pool->whatprovides[id] = pool->whatprovides[i];
00230 continue;
00231 }
00232 lp = pool->whatprovidesdata + o;
00233 if (lp < dp)
00234 abort();
00235 pool->whatprovides[id] = dp - pool->whatprovidesdata;
00236 while ((*dp++ = *lp++) != 0)
00237 ;
00238 }
00239 o = dp - pool->whatprovidesdata;
00240 POOL_DEBUG(SAT_DEBUG_STATS, "shrunk whatprovidesdata from %d to %d\n", pool->whatprovidesdataoff, o);
00241 if (pool->whatprovidesdataoff == o)
00242 return;
00243 r = pool->whatprovidesdataoff - o;
00244 pool->whatprovidesdataoff = o;
00245 pool->whatprovidesdata = sat_realloc(pool->whatprovidesdata, (o + pool->whatprovidesdataleft) * sizeof(Id));
00246 if (r > pool->whatprovidesdataleft)
00247 r = pool->whatprovidesdataleft;
00248 memset(pool->whatprovidesdata + o, 0, r * sizeof(Id));
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 void
00259 pool_createwhatprovides(Pool *pool)
00260 {
00261 int i, num, np, extra;
00262 Offset off;
00263 Solvable *s;
00264 Id id;
00265 Offset *idp, n;
00266 Offset *whatprovides;
00267 Id *whatprovidesdata, *d;
00268 Repo *installed = pool->installed;
00269 unsigned int now;
00270
00271 now = sat_timems(0);
00272 POOL_DEBUG(SAT_DEBUG_STATS, "number of solvables: %d\n", pool->nsolvables);
00273 POOL_DEBUG(SAT_DEBUG_STATS, "number of ids: %d + %d\n", pool->ss.nstrings, pool->nrels);
00274
00275 pool_freeidhashes(pool);
00276 pool_freewhatprovides(pool);
00277 num = pool->ss.nstrings;
00278 pool->whatprovides = whatprovides = sat_calloc_block(num, sizeof(Offset), WHATPROVIDES_BLOCK);
00279 pool->whatprovides_rel = sat_calloc_block(pool->nrels, sizeof(Offset), WHATPROVIDES_BLOCK);
00280
00281
00282 for (i = pool->nsolvables - 1; i > 0; i--)
00283 {
00284 Id *pp;
00285 s = pool->solvables + i;
00286 if (!s->provides || !s->repo || s->repo->disabled)
00287 continue;
00288
00289
00290 if (s->repo != installed && !pool_installable(pool, s))
00291 continue;
00292 pp = s->repo->idarraydata + s->provides;
00293 while ((id = *pp++) != 0)
00294 {
00295 while (ISRELDEP(id))
00296 {
00297 Reldep *rd = GETRELDEP(pool, id);
00298 id = rd->name;
00299 }
00300 whatprovides[id]++;
00301 }
00302 }
00303
00304 off = 2;
00305 np = 0;
00306 for (i = 0, idp = whatprovides; i < num; i++, idp++)
00307 {
00308 n = *idp;
00309 if (!n)
00310 continue;
00311 off += n;
00312 *idp = off++;
00313 np++;
00314 }
00315
00316 POOL_DEBUG(SAT_DEBUG_STATS, "provide ids: %d\n", np);
00317
00318
00319 extra = 2 * pool->nrels;
00320 if (extra < 256)
00321 extra = 256;
00322
00323 POOL_DEBUG(SAT_DEBUG_STATS, "provide space needed: %d + %d\n", off, extra);
00324
00325
00326 whatprovidesdata = sat_calloc(off + extra, sizeof(Id));
00327
00328
00329 for (i = pool->nsolvables - 1; i > 0; i--)
00330 {
00331 Id *pp;
00332 s = pool->solvables + i;
00333 if (!s->provides || !s->repo || s->repo->disabled)
00334 continue;
00335 if (s->repo != installed && !pool_installable(pool, s))
00336 continue;
00337
00338
00339 pp = s->repo->idarraydata + s->provides;
00340 while ((id = *pp++) != 0)
00341 {
00342 while (ISRELDEP(id))
00343 {
00344 Reldep *rd = GETRELDEP(pool, id);
00345 id = rd->name;
00346 }
00347 d = whatprovidesdata + whatprovides[id];
00348 if (*d != i)
00349 {
00350 d[-1] = i;
00351 whatprovides[id]--;
00352 }
00353 }
00354 }
00355 pool->whatprovidesdata = whatprovidesdata;
00356 pool->whatprovidesdataoff = off;
00357 pool->whatprovidesdataleft = extra;
00358 pool_shrink_whatprovides(pool);
00359 POOL_DEBUG(SAT_DEBUG_STATS, "whatprovides memory used: %d K id array, %d K data\n", (pool->ss.nstrings + pool->nrels + WHATPROVIDES_BLOCK) / (int)(1024/sizeof(Id)), (pool->whatprovidesdataoff + pool->whatprovidesdataleft) / (int)(1024/sizeof(Id)));
00360 POOL_DEBUG(SAT_DEBUG_STATS, "createwhatprovides took %d ms\n", sat_timems(now));
00361 }
00362
00363
00364
00365
00366
00367
00368 void
00369 pool_freewhatprovides(Pool *pool)
00370 {
00371 pool->whatprovides = sat_free(pool->whatprovides);
00372 pool->whatprovides_rel = sat_free(pool->whatprovides_rel);
00373 pool->whatprovidesdata = sat_free(pool->whatprovidesdata);
00374 pool->whatprovidesdataoff = 0;
00375 pool->whatprovidesdataleft = 0;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 Id
00391 pool_queuetowhatprovides(Pool *pool, Queue *q)
00392 {
00393 Offset off;
00394 int count = q->count;
00395
00396 if (count == 0)
00397 return 1;
00398
00399
00400 if (pool->whatprovidesdataleft < count + 1)
00401 {
00402 POOL_DEBUG(SAT_DEBUG_STATS, "growing provides hash data...\n");
00403 pool->whatprovidesdata = sat_realloc(pool->whatprovidesdata, (pool->whatprovidesdataoff + count + 4096) * sizeof(Id));
00404 pool->whatprovidesdataleft = count + 4096;
00405 }
00406
00407
00408 off = pool->whatprovidesdataoff;
00409 memcpy(pool->whatprovidesdata + pool->whatprovidesdataoff, q->elements, count * sizeof(Id));
00410
00411
00412 pool->whatprovidesdataoff += count;
00413 pool->whatprovidesdata[pool->whatprovidesdataoff++] = ID_NULL;
00414 pool->whatprovidesdataleft -= count + 1;
00415
00416 return (Id)off;
00417 }
00418
00419
00420
00421
00422 #if defined(MULTI_SEMANTICS)
00423 # define EVRCMP_DEPCMP (pool->disttype == DISTTYPE_DEB ? EVRCMP_COMPARE : EVRCMP_MATCH_RELEASE)
00424 #elif defined(DEBIAN_SEMANTICS)
00425 # define EVRCMP_DEPCMP EVRCMP_COMPARE
00426 #else
00427 # define EVRCMP_DEPCMP EVRCMP_MATCH_RELEASE
00428 #endif
00429
00430
00431
00432 int
00433 pool_match_nevr_rel(Pool *pool, Solvable *s, Id d)
00434 {
00435 Reldep *rd = GETRELDEP(pool, d);
00436 Id name = rd->name;
00437 Id evr = rd->evr;
00438 int flags = rd->flags;
00439
00440 if (flags > 7)
00441 {
00442 switch (flags)
00443 {
00444 case REL_ARCH:
00445 if (s->arch != evr)
00446 return 0;
00447 return pool_match_nevr(pool, s, name);
00448 case REL_OR:
00449 if (pool_match_nevr(pool, s, name))
00450 return 1;
00451 return pool_match_nevr(pool, s, evr);
00452 case REL_AND:
00453 case REL_WITH:
00454 if (!pool_match_nevr(pool, s, name))
00455 return 0;
00456 return pool_match_nevr(pool, s, evr);
00457 default:
00458 return 0;
00459 }
00460 }
00461 if (!pool_match_nevr(pool, s, name))
00462 return 0;
00463 if (evr == s->evr)
00464 return flags & 2 ? 1 : 0;
00465 if (!flags)
00466 return 0;
00467 if (flags == 7)
00468 return 1;
00469 if (flags != 2 && flags != 5)
00470 flags ^= 5;
00471 if ((flags & (1 << (1 + evrcmp(pool, s->evr, evr, EVRCMP_DEPCMP)))) != 0)
00472 return 1;
00473 return 0;
00474 }
00475
00476
00477
00478 int
00479 pool_match_dep(Pool *pool, Id d1, Id d2)
00480 {
00481 Reldep *rd1, *rd2;
00482 int pflags, flags;
00483
00484 if (d1 == d2)
00485 return 1;
00486 if (!ISRELDEP(d1))
00487 {
00488 if (!ISRELDEP(d2))
00489 return 0;
00490 rd2 = GETRELDEP(pool, d2);
00491 return pool_match_dep(pool, d1, rd2->name);
00492 }
00493 rd1 = GETRELDEP(pool, d1);
00494 if (!ISRELDEP(d2))
00495 {
00496 return pool_match_dep(pool, rd1->name, d2);
00497 }
00498 rd2 = GETRELDEP(pool, d2);
00499 if (!pool_match_dep(pool, rd1->name, rd2->name))
00500 return 0;
00501 pflags = rd1->flags;
00502 flags = rd2->flags;
00503 if (!pflags || !flags || pflags >= 8 || flags >= 8)
00504 return 0;
00505 if (flags == 7 || pflags == 7)
00506 return 1;
00507 if ((pflags & flags & 5) != 0)
00508 return 1;
00509 if (rd1->evr == rd2->evr)
00510 {
00511 if ((pflags & flags & 2) != 0)
00512 return 1;
00513 }
00514 else
00515 {
00516 int f = flags == 5 ? 5 : flags == 2 ? pflags : (flags ^ 5) & (pflags | 5);
00517 if ((f & (1 << (1 + evrcmp(pool, rd1->evr, rd2->evr, EVRCMP_DEPCMP)))) != 0)
00518 return 1;
00519 }
00520 return 0;
00521 }
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 Id
00532 pool_addrelproviders(Pool *pool, Id d)
00533 {
00534 Reldep *rd = GETRELDEP(pool, d);
00535 Reldep *prd;
00536 Queue plist;
00537 Id buf[16];
00538 Id name = rd->name;
00539 Id evr = rd->evr;
00540 int flags = rd->flags;
00541 Id pid, *pidp;
00542 Id p, wp, *pp, *pp2, *pp3;
00543
00544 d = GETRELID(d);
00545 queue_init_buffer(&plist, buf, sizeof(buf)/sizeof(*buf));
00546 switch (flags)
00547 {
00548 case REL_AND:
00549 case REL_WITH:
00550 pp = pool_whatprovides_ptr(pool, name);
00551 pp2 = pool_whatprovides_ptr(pool, evr);
00552 while ((p = *pp++) != 0)
00553 {
00554 for (pp3 = pp2; *pp3;)
00555 if (*pp3++ == p)
00556 {
00557 queue_push(&plist, p);
00558 break;
00559 }
00560 }
00561 break;
00562 case REL_OR:
00563 pp = pool_whatprovides_ptr(pool, name);
00564 while ((p = *pp++) != 0)
00565 queue_push(&plist, p);
00566 pp = pool_whatprovides_ptr(pool, evr);
00567 while ((p = *pp++) != 0)
00568 queue_pushunique(&plist, p);
00569 break;
00570 case REL_NAMESPACE:
00571 if (name == NAMESPACE_OTHERPROVIDERS)
00572 {
00573 wp = pool_whatprovides(pool, evr);
00574 pool->whatprovides_rel[d] = wp;
00575 return wp;
00576 }
00577 if (pool->nscallback)
00578 {
00579
00580
00581
00582
00583
00584 p = pool->nscallback(pool, pool->nscallbackdata, name, evr);
00585 if (p > 1)
00586 {
00587 queue_free(&plist);
00588 pool->whatprovides_rel[d] = p;
00589 return p;
00590 }
00591 if (p == 1)
00592 queue_push(&plist, SYSTEMSOLVABLE);
00593 }
00594 break;
00595 case REL_ARCH:
00596
00597
00598
00599
00600 if (evr == ARCH_SRC)
00601 {
00602 Solvable *s;
00603 for (p = 1, s = pool->solvables + p; p < pool->nsolvables; p++, s++)
00604 {
00605 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
00606 continue;
00607 if (pool_match_nevr(pool, s, name))
00608 queue_push(&plist, p);
00609 }
00610 break;
00611 }
00612 wp = pool_whatprovides(pool, name);
00613 pp = pool->whatprovidesdata + wp;
00614 while ((p = *pp++) != 0)
00615 {
00616 Solvable *s = pool->solvables + p;
00617 if (s->arch == evr)
00618 queue_push(&plist, p);
00619 else
00620 wp = 0;
00621 }
00622 if (wp)
00623 {
00624
00625 pool->whatprovides_rel[d] = wp;
00626 return wp;
00627 }
00628 break;
00629 case REL_FILECONFLICT:
00630 pp = pool_whatprovides_ptr(pool, name);
00631 while ((p = *pp++) != 0)
00632 {
00633 Id origd = MAKERELDEP(d);
00634 Solvable *s = pool->solvables + p;
00635 if (!s->provides)
00636 continue;
00637 pidp = s->repo->idarraydata + s->provides;
00638 while ((pid = *pidp++) != 0)
00639 if (pid == origd)
00640 break;
00641 if (pid)
00642 queue_push(&plist, p);
00643 }
00644 break;
00645 default:
00646 break;
00647 }
00648
00649
00650 #if 0
00651 POOL_DEBUG(SAT_DEBUG_STATS, "addrelproviders: what provides %s?\n", dep2str(pool, name));
00652 #endif
00653 if (flags && flags < 8)
00654 {
00655 pp = pool_whatprovides_ptr(pool, name);
00656 while (ISRELDEP(name))
00657 {
00658 rd = GETRELDEP(pool, name);
00659 name = rd->name;
00660 }
00661 while ((p = *pp++) != 0)
00662 {
00663 Solvable *s = pool->solvables + p;
00664 #if 0
00665 POOL_DEBUG(DEBUG_1, "addrelproviders: checking package %s\n", id2str(pool, s->name));
00666 #endif
00667 if (!s->provides)
00668 {
00669
00670 if (pool_match_nevr_rel(pool, s, MAKERELDEP(d)))
00671 queue_push(&plist, p);
00672 continue;
00673 }
00674
00675 pidp = s->repo->idarraydata + s->provides;
00676 while ((pid = *pidp++) != 0)
00677 {
00678 int pflags;
00679 Id pevr;
00680
00681 if (pid == name)
00682 {
00683 #if defined(MULTI_SEMANTICS)
00684 if (pool->disttype == DISTTYPE_DEB)
00685 continue;
00686 else
00687 break;
00688 #elif defined(DEBIAN_SEMANTICS)
00689 continue;
00690
00691 #else
00692 break;
00693 #endif
00694 }
00695 if (!ISRELDEP(pid))
00696 continue;
00697 prd = GETRELDEP(pool, pid);
00698 if (prd->name != name)
00699 continue;
00700
00701 pflags = prd->flags;
00702 if (!pflags)
00703 continue;
00704 if (flags == 7 || pflags == 7)
00705 break;
00706 if ((pflags & flags & 5) != 0)
00707 break;
00708 pevr = prd->evr;
00709 if (pevr == evr)
00710 {
00711 if ((pflags & flags & 2) != 0)
00712 break;
00713 }
00714 else
00715 {
00716 int f = flags == 5 ? 5 : flags == 2 ? pflags : (flags ^ 5) & (pflags | 5);
00717 if ((f & (1 << (1 + evrcmp(pool, pevr, evr, EVRCMP_DEPCMP)))) != 0)
00718 break;
00719 }
00720 }
00721 if (!pid)
00722 continue;
00723 queue_push(&plist, p);
00724 }
00725
00726 if (plist.count == 0 && !strncmp(id2str(pool, name), "rpmlib(", 7))
00727 queue_push(&plist, SYSTEMSOLVABLE);
00728 }
00729
00730 #if 0
00731 POOL_DEBUG(SAT_DEBUG_STATS, "addrelproviders: adding %d packages to %d\n", plist.count, d);
00732 #endif
00733 pool->whatprovides_rel[d] = pool_queuetowhatprovides(pool, &plist);
00734 queue_free(&plist);
00735
00736 return pool->whatprovides_rel[d];
00737 }
00738
00739
00740
00741 void
00742 pool_debug(Pool *pool, int type, const char *format, ...)
00743 {
00744 va_list args;
00745 char buf[1024];
00746
00747 if ((type & (SAT_FATAL|SAT_ERROR)) == 0)
00748 {
00749 if ((pool->debugmask & type) == 0)
00750 return;
00751 }
00752 va_start(args, format);
00753 if (!pool->debugcallback)
00754 {
00755 if ((type & (SAT_FATAL|SAT_ERROR)) == 0 && !(pool->debugmask & SAT_DEBUG_TO_STDERR))
00756 vprintf(format, args);
00757 else
00758 vfprintf(stderr, format, args);
00759 return;
00760 }
00761 vsnprintf(buf, sizeof(buf), format, args);
00762 pool->debugcallback(pool, pool->debugcallbackdata, type, buf);
00763 }
00764
00765 void
00766 pool_setdebuglevel(Pool *pool, int level)
00767 {
00768 int mask = SAT_DEBUG_RESULT;
00769 if (level > 0)
00770 mask |= SAT_DEBUG_STATS|SAT_DEBUG_ANALYZE|SAT_DEBUG_UNSOLVABLE|SAT_DEBUG_SOLVER|SAT_DEBUG_TRANSACTION;
00771 if (level > 1)
00772 mask |= SAT_DEBUG_JOB|SAT_DEBUG_SOLUTIONS|SAT_DEBUG_POLICY;
00773 if (level > 2)
00774 mask |= SAT_DEBUG_PROPAGATE;
00775 if (level > 3)
00776 mask |= SAT_DEBUG_RULE_CREATION;
00777 if (level > 4)
00778 mask |= SAT_DEBUG_SCHUBI;
00779 mask |= pool->debugmask & SAT_DEBUG_TO_STDERR;
00780 pool->debugmask = mask;
00781 }
00782
00783
00784
00785 struct searchfiles {
00786 Id *ids;
00787 char **dirs;
00788 char **names;
00789 int nfiles;
00790 Map seen;
00791 };
00792
00793 #define SEARCHFILES_BLOCK 127
00794
00795 static void
00796 pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct searchfiles *isf)
00797 {
00798 Id dep, sid;
00799 const char *s, *sr;
00800 struct searchfiles *csf;
00801
00802 while ((dep = *ida++) != 0)
00803 {
00804 csf = sf;
00805 while (ISRELDEP(dep))
00806 {
00807 Reldep *rd;
00808 sid = pool->ss.nstrings + GETRELID(dep);
00809 if (MAPTST(&csf->seen, sid))
00810 {
00811 dep = 0;
00812 break;
00813 }
00814 MAPSET(&csf->seen, sid);
00815 rd = GETRELDEP(pool, dep);
00816 if (rd->flags < 8)
00817 dep = rd->name;
00818 else if (rd->flags == REL_NAMESPACE)
00819 {
00820 if (rd->name == NAMESPACE_INSTALLED || rd->name == NAMESPACE_SPLITPROVIDES)
00821 {
00822 csf = isf;
00823 if (!csf || MAPTST(&csf->seen, sid))
00824 {
00825 dep = 0;
00826 break;
00827 }
00828 MAPSET(&csf->seen, sid);
00829 }
00830 dep = rd->evr;
00831 }
00832 else if (rd->flags == REL_FILECONFLICT)
00833 {
00834 dep = 0;
00835 break;
00836 }
00837 else
00838 {
00839 Id ids[2];
00840 ids[0] = rd->name;
00841 ids[1] = 0;
00842 pool_addfileprovides_dep(pool, ids, csf, isf);
00843 dep = rd->evr;
00844 }
00845 }
00846 if (!dep)
00847 continue;
00848 if (MAPTST(&csf->seen, dep))
00849 continue;
00850 MAPSET(&csf->seen, dep);
00851 s = id2str(pool, dep);
00852 if (*s != '/')
00853 continue;
00854 csf->ids = sat_extend(csf->ids, csf->nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK);
00855 csf->dirs = sat_extend(csf->dirs, csf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK);
00856 csf->names = sat_extend(csf->names, csf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK);
00857 csf->ids[csf->nfiles] = dep;
00858 sr = strrchr(s, '/');
00859 csf->names[csf->nfiles] = strdup(sr + 1);
00860 csf->dirs[csf->nfiles] = sat_malloc(sr - s + 1);
00861 if (sr != s)
00862 strncpy(csf->dirs[csf->nfiles], s, sr - s);
00863 csf->dirs[csf->nfiles][sr - s] = 0;
00864 csf->nfiles++;
00865 }
00866 }
00867
00868 struct addfileprovides_cbdata {
00869 int nfiles;
00870 Id *ids;
00871 char **dirs;
00872 char **names;
00873
00874 Id *dids;
00875
00876 Map providedids;
00877
00878 Map useddirs;
00879 };
00880
00881 static int
00882 addfileprovides_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value)
00883 {
00884 struct addfileprovides_cbdata *cbd = cbdata;
00885 int i;
00886
00887 if (!cbd->useddirs.size)
00888 {
00889 map_init(&cbd->useddirs, data->dirpool.ndirs + 1);
00890 for (i = 0; i < cbd->nfiles; i++)
00891 {
00892 Id did;
00893 if (MAPTST(&cbd->providedids, cbd->ids[i]))
00894 {
00895 cbd->dids[i] = 0;
00896 continue;
00897 }
00898 did = repodata_str2dir(data, cbd->dirs[i], 0);
00899 cbd->dids[i] = did;
00900 if (did)
00901 MAPSET(&cbd->useddirs, did);
00902 }
00903 }
00904 if (value->id >= data->dirpool.ndirs || !MAPTST(&cbd->useddirs, value->id))
00905 return 0;
00906 for (i = 0; i < cbd->nfiles; i++)
00907 {
00908 if (cbd->dids[i] != value->id)
00909 continue;
00910 if (!strcmp(cbd->names[i], value->str))
00911 break;
00912 }
00913 if (i == cbd->nfiles)
00914 return 0;
00915 s->provides = repo_addid_dep(s->repo, s->provides, cbd->ids[i], SOLVABLE_FILEMARKER);
00916 return 0;
00917 }
00918
00919 static void
00920 pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, struct searchfiles *sf, Repo *repoonly)
00921 {
00922 Id p;
00923 Repodata *data;
00924 Repo *repo;
00925 Queue fileprovidesq;
00926 int i, j, repoid, repodataid;
00927 int provstart, provend;
00928 Map donemap;
00929 int ndone, incomplete;
00930
00931 if (!pool->nrepos)
00932 return;
00933
00934 cbd->nfiles = sf->nfiles;
00935 cbd->ids = sf->ids;
00936 cbd->dirs = sf->dirs;
00937 cbd->names = sf->names;
00938 cbd->dids = sat_realloc2(cbd->dids, sf->nfiles, sizeof(Id));
00939 map_init(&cbd->providedids, pool->ss.nstrings);
00940
00941 repoid = 0;
00942 repo = repoonly ? repoonly : pool->repos[0];
00943 map_init(&donemap, pool->nsolvables);
00944 queue_init(&fileprovidesq);
00945 provstart = provend = 0;
00946 for (;;)
00947 {
00948 if (repo->disabled)
00949 {
00950 if (repoonly || ++repoid == pool->nrepos)
00951 break;
00952 repo = pool->repos[repoid];
00953 continue;
00954 }
00955 ndone = 0;
00956 for (data = repo->repodata, repodataid = 0; repodataid < repo->nrepodata; repodataid++, data++)
00957 {
00958 if (ndone >= repo->nsolvables)
00959 break;
00960
00961 if (repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &fileprovidesq))
00962 {
00963 map_empty(&cbd->providedids);
00964 for (i = 0; i < fileprovidesq.count; i++)
00965 MAPSET(&cbd->providedids, fileprovidesq.elements[i]);
00966 provstart = data->start;
00967 provend = data->end;
00968 for (i = 0; i < cbd->nfiles; i++)
00969 if (!MAPTST(&cbd->providedids, cbd->ids[i]))
00970 break;
00971 if (i == cbd->nfiles)
00972 {
00973
00974 for (p = data->start; p < data->end; p++)
00975 if (pool->solvables[p].repo == repo)
00976 {
00977 if (MAPTST(&donemap, p))
00978 continue;
00979 MAPSET(&donemap, p);
00980 ndone++;
00981 }
00982 continue;
00983 }
00984 }
00985
00986 if (!repodata_has_keyname(data, SOLVABLE_FILELIST))
00987 continue;
00988
00989 if (data->start < provstart || data->end > provend)
00990 {
00991 map_empty(&cbd->providedids);
00992 provstart = provend = 0;
00993 }
00994
00995
00996 incomplete = 0;
00997 if (data->state == REPODATA_AVAILABLE)
00998 {
00999 for (j = 1; j < data->nkeys; j++)
01000 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
01001 break;
01002 if (j < data->nkeys)
01003 {
01004 #if 0
01005 for (i = 0; i < cbd->nfiles; i++)
01006 if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, id2str(pool, cbd->ids[i])))
01007 printf("need complete filelist because of %s\n", id2str(pool, cbd->ids[i]));
01008 #endif
01009 for (i = 0; i < cbd->nfiles; i++)
01010 if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, id2str(pool, cbd->ids[i])))
01011 break;
01012 if (i < cbd->nfiles)
01013 incomplete = 1;
01014 }
01015 }
01016
01017
01018 map_init(&cbd->useddirs, 0);
01019 for (p = data->start; p < data->end; p++)
01020 if (pool->solvables[p].repo == repo)
01021 {
01022 if (MAPTST(&donemap, p))
01023 continue;
01024 repodata_search(data, p, SOLVABLE_FILELIST, 0, addfileprovides_cb, cbd);
01025 if (!incomplete)
01026 {
01027 MAPSET(&donemap, p);
01028 ndone++;
01029 }
01030 }
01031 map_free(&cbd->useddirs);
01032 }
01033
01034 if (repoonly || ++repoid == pool->nrepos)
01035 break;
01036 repo = pool->repos[repoid];
01037 }
01038 map_free(&donemap);
01039 queue_free(&fileprovidesq);
01040 map_free(&cbd->providedids);
01041 }
01042
01043 void
01044 pool_addfileprovides_ids(Pool *pool, Repo *installed, Id **idp)
01045 {
01046 Solvable *s;
01047 Repo *repo;
01048 struct searchfiles sf, isf, *isfp;
01049 struct addfileprovides_cbdata cbd;
01050 int i;
01051 unsigned int now;
01052
01053 now = sat_timems(0);
01054 memset(&sf, 0, sizeof(sf));
01055 map_init(&sf.seen, pool->ss.nstrings + pool->nrels);
01056 memset(&isf, 0, sizeof(isf));
01057 map_init(&isf.seen, pool->ss.nstrings + pool->nrels);
01058
01059 isfp = installed ? &isf : 0;
01060 for (i = 1, s = pool->solvables + i; i < pool->nsolvables; i++, s++)
01061 {
01062 repo = s->repo;
01063 if (!repo)
01064 continue;
01065 if (s->obsoletes)
01066 pool_addfileprovides_dep(pool, repo->idarraydata + s->obsoletes, &sf, isfp);
01067 if (s->conflicts)
01068 pool_addfileprovides_dep(pool, repo->idarraydata + s->conflicts, &sf, isfp);
01069 if (s->requires)
01070 pool_addfileprovides_dep(pool, repo->idarraydata + s->requires, &sf, isfp);
01071 if (s->recommends)
01072 pool_addfileprovides_dep(pool, repo->idarraydata + s->recommends, &sf, isfp);
01073 if (s->suggests)
01074 pool_addfileprovides_dep(pool, repo->idarraydata + s->suggests, &sf, isfp);
01075 if (s->supplements)
01076 pool_addfileprovides_dep(pool, repo->idarraydata + s->supplements, &sf, isfp);
01077 if (s->enhances)
01078 pool_addfileprovides_dep(pool, repo->idarraydata + s->enhances, &sf, isfp);
01079 }
01080 map_free(&sf.seen);
01081 map_free(&isf.seen);
01082 POOL_DEBUG(SAT_DEBUG_STATS, "found %d file dependencies, %d installed file dependencies\n", sf.nfiles, isf.nfiles);
01083 cbd.dids = 0;
01084 if (idp)
01085 *idp = 0;
01086 if (sf.nfiles)
01087 {
01088 #if 0
01089 for (i = 0; i < sf.nfiles; i++)
01090 POOL_DEBUG(SAT_DEBUG_STATS, "looking up %s in filelist\n", id2str(pool, sf.ids[i]));
01091 #endif
01092 pool_addfileprovides_search(pool, &cbd, &sf, 0);
01093 if (idp)
01094 {
01095 sf.ids = sat_extend(sf.ids, sf.nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK);
01096 sf.ids[sf.nfiles] = 0;
01097 *idp = sf.ids;
01098 sf.ids = 0;
01099 }
01100 sat_free(sf.ids);
01101 for (i = 0; i < sf.nfiles; i++)
01102 {
01103 sat_free(sf.dirs[i]);
01104 sat_free(sf.names[i]);
01105 }
01106 sat_free(sf.dirs);
01107 sat_free(sf.names);
01108 }
01109 if (isf.nfiles)
01110 {
01111 #if 0
01112 for (i = 0; i < isf.nfiles; i++)
01113 POOL_DEBUG(SAT_DEBUG_STATS, "looking up %s in installed filelist\n", id2str(pool, isf.ids[i]));
01114 #endif
01115 if (installed)
01116 pool_addfileprovides_search(pool, &cbd, &isf, installed);
01117 sat_free(isf.ids);
01118 for (i = 0; i < isf.nfiles; i++)
01119 {
01120 sat_free(isf.dirs[i]);
01121 sat_free(isf.names[i]);
01122 }
01123 sat_free(isf.dirs);
01124 sat_free(isf.names);
01125 }
01126 sat_free(cbd.dids);
01127 pool_freewhatprovides(pool);
01128 POOL_DEBUG(SAT_DEBUG_STATS, "addfileprovides took %d ms\n", sat_timems(now));
01129 }
01130
01131 void
01132 pool_addfileprovides(Pool *pool)
01133 {
01134 pool_addfileprovides_ids(pool, pool->installed, 0);
01135 }
01136
01137 void
01138 pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, struct _Repodata *data, struct _Repokey *key, struct _KeyValue *kv), void *cbdata)
01139 {
01140 if (p)
01141 {
01142 if (pool->solvables[p].repo)
01143 repo_search(pool->solvables[p].repo, p, key, match, flags, callback, cbdata);
01144 return;
01145 }
01146
01147 for (p = 1; p < pool->nsolvables; p++)
01148 if (pool->solvables[p].repo)
01149 repo_search(pool->solvables[p].repo, p, key, match, flags, callback, cbdata);
01150 }
01151
01152 void
01153 pool_clear_pos(Pool *pool)
01154 {
01155 memset(&pool->pos, 0, sizeof(pool->pos));
01156 }
01157
01158
01159 void
01160 pool_set_languages(Pool *pool, const char **languages, int nlanguages)
01161 {
01162 int i;
01163
01164 pool->languagecache = sat_free(pool->languagecache);
01165 pool->languagecacheother = 0;
01166 if (pool->nlanguages)
01167 {
01168 for (i = 0; i < pool->nlanguages; i++)
01169 free((char *)pool->languages[i]);
01170 free(pool->languages);
01171 }
01172 pool->nlanguages = nlanguages;
01173 if (!nlanguages)
01174 return;
01175 pool->languages = sat_calloc(nlanguages, sizeof(const char **));
01176 for (i = 0; i < pool->nlanguages; i++)
01177 pool->languages[i] = strdup(languages[i]);
01178 }
01179
01180 Id
01181 pool_id2langid(Pool *pool, Id id, const char *lang, int create)
01182 {
01183 const char *n;
01184 char buf[256], *p;
01185 int l;
01186
01187 if (!lang)
01188 return id;
01189 n = id2str(pool, id);
01190 l = strlen(n) + strlen(lang) + 2;
01191 if (l > sizeof(buf))
01192 p = sat_malloc(strlen(n) + strlen(lang) + 2);
01193 else
01194 p = buf;
01195 sprintf(p, "%s:%s", n, lang);
01196 id = str2id(pool, p, create);
01197 if (p != buf)
01198 free(p);
01199 return id;
01200 }
01201
01202 char *
01203 pool_alloctmpspace(Pool *pool, int len)
01204 {
01205 int n = pool->tmpspacen;
01206 if (!len)
01207 return 0;
01208 if (len > pool->tmpspacelen[n])
01209 {
01210 pool->tmpspacebuf[n] = sat_realloc(pool->tmpspacebuf[n], len + 32);
01211 pool->tmpspacelen[n] = len + 32;
01212 }
01213 pool->tmpspacen = (n + 1) % POOL_TMPSPACEBUF;
01214 return pool->tmpspacebuf[n];
01215 }
01216
01217 char *
01218 pool_tmpjoin(Pool *pool, const char *str1, const char *str2, const char *str3)
01219 {
01220 int l1, l2, l3;
01221 char *s, *str;
01222 l1 = str1 ? strlen(str1) : 0;
01223 l2 = str2 ? strlen(str2) : 0;
01224 l3 = str3 ? strlen(str3) : 0;
01225 s = str = pool_alloctmpspace(pool, l1 + l2 + l3 + 1);
01226 if (l1)
01227 {
01228 strcpy(s, str1);
01229 s += l1;
01230 }
01231 if (l2)
01232 {
01233 strcpy(s, str2);
01234 s += l2;
01235 }
01236 if (l3)
01237 {
01238 strcpy(s, str3);
01239 s += l3;
01240 }
01241 *s = 0;
01242 return str;
01243 }
01244
01245
01246
01247
01248 struct mptree {
01249 Id sibling;
01250 Id child;
01251 const char *comp;
01252 int compl;
01253 Id mountpoint;
01254 };
01255
01256 struct ducbdata {
01257 DUChanges *mps;
01258 struct mptree *mptree;
01259 int addsub;
01260 int hasdu;
01261
01262 Id *dirmap;
01263 int nmap;
01264 Repodata *olddata;
01265 };
01266
01267
01268 static int
01269 solver_fill_DU_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value)
01270 {
01271 struct ducbdata *cbd = cbdata;
01272 Id mp;
01273
01274 if (data != cbd->olddata)
01275 {
01276 Id dn, mp, comp, *dirmap, *dirs;
01277 int i, compl;
01278 const char *compstr;
01279 struct mptree *mptree;
01280
01281
01282 cbd->dirmap = sat_free(cbd->dirmap);
01283 cbd->nmap = 0;
01284 dirmap = sat_calloc(data->dirpool.ndirs, sizeof(Id));
01285 mptree = cbd->mptree;
01286 mp = 0;
01287 for (dn = 2, dirs = data->dirpool.dirs + dn; dn < data->dirpool.ndirs; dn++)
01288 {
01289 comp = *dirs++;
01290 if (comp <= 0)
01291 {
01292 mp = dirmap[-comp];
01293 continue;
01294 }
01295 if (mp < 0)
01296 {
01297
01298 dirmap[dn] = mp;
01299 continue;
01300 }
01301 if (!mptree[mp].child)
01302 {
01303 dirmap[dn] = -mp;
01304 continue;
01305 }
01306 if (data->localpool)
01307 compstr = stringpool_id2str(&data->spool, comp);
01308 else
01309 compstr = id2str(data->repo->pool, comp);
01310 compl = strlen(compstr);
01311 for (i = mptree[mp].child; i; i = mptree[i].sibling)
01312 if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl))
01313 break;
01314 dirmap[dn] = i ? i : -mp;
01315 }
01316
01317 for (dn = 0; dn < data->dirpool.ndirs; dn++)
01318 {
01319 mp = dirmap[dn];
01320 dirmap[dn] = mptree[mp > 0 ? mp : -mp].mountpoint;
01321 }
01322 cbd->dirmap = dirmap;
01323 cbd->nmap = data->dirpool.ndirs;
01324 cbd->olddata = data;
01325 }
01326 cbd->hasdu = 1;
01327 if (value->id < 0 || value->id >= cbd->nmap)
01328 return 0;
01329 mp = cbd->dirmap[value->id];
01330 if (mp < 0)
01331 return 0;
01332 if (cbd->addsub > 0)
01333 {
01334 cbd->mps[mp].kbytes += value->num;
01335 cbd->mps[mp].files += value->num2;
01336 }
01337 else
01338 {
01339 cbd->mps[mp].kbytes -= value->num;
01340 cbd->mps[mp].files -= value->num2;
01341 }
01342 return 0;
01343 }
01344
01345 static void
01346 propagate_mountpoints(struct mptree *mptree, int pos, Id mountpoint)
01347 {
01348 int i;
01349 if (mptree[pos].mountpoint == -1)
01350 mptree[pos].mountpoint = mountpoint;
01351 else
01352 mountpoint = mptree[pos].mountpoint;
01353 for (i = mptree[pos].child; i; i = mptree[i].sibling)
01354 propagate_mountpoints(mptree, i, mountpoint);
01355 }
01356
01357 #define MPTREE_BLOCK 15
01358
01359 void
01360 pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps)
01361 {
01362 char *p;
01363 const char *path, *compstr;
01364 struct mptree *mptree;
01365 int i, nmptree;
01366 int pos, compl;
01367 int mp;
01368 struct ducbdata cbd;
01369 Solvable *s;
01370 Id sp;
01371 Map ignoredu;
01372 Repo *oldinstalled = pool->installed;
01373
01374 memset(&ignoredu, 0, sizeof(ignoredu));
01375 cbd.mps = mps;
01376 cbd.addsub = 0;
01377 cbd.dirmap = 0;
01378 cbd.nmap = 0;
01379 cbd.olddata = 0;
01380
01381 mptree = sat_extend_resize(0, 1, sizeof(struct mptree), MPTREE_BLOCK);
01382
01383
01384 mptree[0].sibling = 0;
01385 mptree[0].child = 0;
01386 mptree[0].comp = 0;
01387 mptree[0].compl = 0;
01388 mptree[0].mountpoint = -1;
01389 nmptree = 1;
01390
01391
01392 for (mp = 0; mp < nmps; mp++)
01393 {
01394 mps[mp].kbytes = 0;
01395 mps[mp].files = 0;
01396 pos = 0;
01397 path = mps[mp].path;
01398 while(*path == '/')
01399 path++;
01400 while (*path)
01401 {
01402 if ((p = strchr(path, '/')) == 0)
01403 {
01404 compstr = path;
01405 compl = strlen(compstr);
01406 path += compl;
01407 }
01408 else
01409 {
01410 compstr = path;
01411 compl = p - path;
01412 path = p + 1;
01413 while(*path == '/')
01414 path++;
01415 }
01416 for (i = mptree[pos].child; i; i = mptree[i].sibling)
01417 if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl))
01418 break;
01419 if (!i)
01420 {
01421
01422 mptree = sat_extend(mptree, nmptree, 1, sizeof(struct mptree), MPTREE_BLOCK);
01423 i = nmptree++;
01424 mptree[i].sibling = mptree[pos].child;
01425 mptree[i].child = 0;
01426 mptree[i].comp = compstr;
01427 mptree[i].compl = compl;
01428 mptree[i].mountpoint = -1;
01429 mptree[pos].child = i;
01430 }
01431 pos = i;
01432 }
01433 mptree[pos].mountpoint = mp;
01434 }
01435
01436 propagate_mountpoints(mptree, 0, mptree[0].mountpoint);
01437
01438 #if 0
01439 for (i = 0; i < nmptree; i++)
01440 {
01441 printf("#%d sibling: %d\n", i, mptree[i].sibling);
01442 printf("#%d child: %d\n", i, mptree[i].child);
01443 printf("#%d comp: %s\n", i, mptree[i].comp);
01444 printf("#%d compl: %d\n", i, mptree[i].compl);
01445 printf("#%d mountpont: %d\n", i, mptree[i].mountpoint);
01446 }
01447 #endif
01448
01449 cbd.mptree = mptree;
01450 cbd.addsub = 1;
01451 for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++)
01452 {
01453 if (!s->repo || (oldinstalled && s->repo == oldinstalled))
01454 continue;
01455 if (!MAPTST(installedmap, sp))
01456 continue;
01457 cbd.hasdu = 0;
01458 repo_search(s->repo, sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
01459 if (!cbd.hasdu && oldinstalled)
01460 {
01461 Id op, opp;
01462
01463 if (!ignoredu.map)
01464 map_init(&ignoredu, oldinstalled->end - oldinstalled->start);
01465 if (s->obsoletes)
01466 {
01467 Id obs, *obsp = s->repo->idarraydata + s->obsoletes;
01468 while ((obs = *obsp++) != 0)
01469 FOR_PROVIDES(op, opp, obs)
01470 if (op >= oldinstalled->start && op < oldinstalled->end)
01471 MAPSET(&ignoredu, op - oldinstalled->start);
01472 }
01473 FOR_PROVIDES(op, opp, s->name)
01474 if (pool->solvables[op].name == s->name)
01475 if (op >= oldinstalled->start && op < oldinstalled->end)
01476 MAPSET(&ignoredu, op - oldinstalled->start);
01477 }
01478 }
01479 cbd.addsub = -1;
01480 if (oldinstalled)
01481 {
01482
01483 FOR_REPO_SOLVABLES(oldinstalled, sp, s)
01484 {
01485 if (MAPTST(installedmap, sp))
01486 continue;
01487 if (ignoredu.map && MAPTST(&ignoredu, sp - oldinstalled->start))
01488 continue;
01489 repo_search(oldinstalled, sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
01490 }
01491 }
01492 if (ignoredu.map)
01493 map_free(&ignoredu);
01494 sat_free(cbd.dirmap);
01495 sat_free(mptree);
01496 }
01497
01498 int
01499 pool_calc_installsizechange(Pool *pool, Map *installedmap)
01500 {
01501 Id sp;
01502 Solvable *s;
01503 int change = 0;
01504 Repo *oldinstalled = pool->installed;
01505
01506 for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++)
01507 {
01508 if (!s->repo || (oldinstalled && s->repo == oldinstalled))
01509 continue;
01510 if (!MAPTST(installedmap, sp))
01511 continue;
01512 change += solvable_lookup_num(s, SOLVABLE_INSTALLSIZE, 0);
01513 }
01514 if (oldinstalled)
01515 {
01516 FOR_REPO_SOLVABLES(oldinstalled, sp, s)
01517 {
01518 if (MAPTST(installedmap, sp))
01519 continue;
01520 change -= solvable_lookup_num(s, SOLVABLE_INSTALLSIZE, 0);
01521 }
01522 }
01523 return change;
01524 }
01525
01526
01527
01528
01529
01530
01531
01532
01533 static inline Id dep2name(Pool *pool, Id dep)
01534 {
01535 while (ISRELDEP(dep))
01536 {
01537 Reldep *rd = rd = GETRELDEP(pool, dep);
01538 dep = rd->name;
01539 }
01540 return dep;
01541 }
01542
01543 static int providedbyinstalled_multiversion(Pool *pool, unsigned char *map, Id n, Id con)
01544 {
01545 Id p, pp;
01546 Solvable *sn = pool->solvables + n;
01547
01548 FOR_PROVIDES(p, pp, sn->name)
01549 {
01550 Solvable *s = pool->solvables + p;
01551 if (s->name != sn->name || s->arch != sn->arch)
01552 continue;
01553 if ((map[p] & 9) != 9)
01554 continue;
01555 if (pool_match_nevr(pool, pool->solvables + p, con))
01556 continue;
01557 return 1;
01558 }
01559 return 0;
01560 }
01561
01562 static inline int providedbyinstalled(Pool *pool, unsigned char *map, Id dep, int ispatch, Map *noobsoletesmap)
01563 {
01564 Id p, pp;
01565 int r = 0;
01566 FOR_PROVIDES(p, pp, dep)
01567 {
01568 if (p == SYSTEMSOLVABLE)
01569 return 1;
01570 if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep))
01571 continue;
01572 if (ispatch && noobsoletesmap && noobsoletesmap->size && MAPTST(noobsoletesmap, p) && ISRELDEP(dep))
01573 if (providedbyinstalled_multiversion(pool, map, p, dep))
01574 continue;
01575 if ((map[p] & 9) == 9)
01576 return 9;
01577 r |= map[p] & 17;
01578 }
01579 return r;
01580 }
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593 void
01594 pool_trivial_installable_noobsoletesmap(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res, Map *noobsoletesmap)
01595 {
01596 int i, r, m, did;
01597 Id p, *dp, con, *conp, req, *reqp;
01598 unsigned char *map;
01599 Solvable *s;
01600
01601 map = sat_calloc(pool->nsolvables, 1);
01602 for (p = 1; p < pool->nsolvables; p++)
01603 {
01604 if (!MAPTST(installedmap, p))
01605 continue;
01606 map[p] |= 9;
01607 s = pool->solvables + p;
01608 if (!s->conflicts)
01609 continue;
01610 conp = s->repo->idarraydata + s->conflicts;
01611 while ((con = *conp++) != 0)
01612 {
01613 dp = pool_whatprovides_ptr(pool, con);
01614 for (; *dp; dp++)
01615 map[p] |= 2;
01616 }
01617 }
01618 for (i = 0; i < pkgs->count; i++)
01619 map[pkgs->elements[i]] = 16;
01620
01621 for (i = 0, did = 0; did < pkgs->count; i++, did++)
01622 {
01623 if (i == pkgs->count)
01624 i = 0;
01625 p = pkgs->elements[i];
01626 if ((map[p] & 16) == 0)
01627 continue;
01628 if ((map[p] & 2) != 0)
01629 {
01630 map[p] = 2;
01631 continue;
01632 }
01633 s = pool->solvables + p;
01634 m = 1;
01635 if (s->requires)
01636 {
01637 reqp = s->repo->idarraydata + s->requires;
01638 while ((req = *reqp++) != 0)
01639 {
01640 if (req == SOLVABLE_PREREQMARKER)
01641 continue;
01642 r = providedbyinstalled(pool, map, req, 0, 0);
01643 if (!r)
01644 {
01645
01646 map[p] = 2;
01647 break;
01648 }
01649 m |= r;
01650 }
01651 if (req)
01652 continue;
01653 if ((m & 9) == 9)
01654 m = 9;
01655 }
01656 if (s->conflicts)
01657 {
01658 int ispatch = 0;
01659
01660 if (!strncmp("patch:", id2str(pool, s->name), 6))
01661 ispatch = 1;
01662 conp = s->repo->idarraydata + s->conflicts;
01663 while ((con = *conp++) != 0)
01664 {
01665 if ((providedbyinstalled(pool, map, con, ispatch, noobsoletesmap) & 1) != 0)
01666 {
01667 map[p] = 2;
01668 break;
01669 }
01670 if ((m == 1 || m == 17) && ISRELDEP(con))
01671 {
01672 con = dep2name(pool, con);
01673 if ((providedbyinstalled(pool, map, con, ispatch, noobsoletesmap) & 1) != 0)
01674 m = 9;
01675 }
01676 }
01677 if (con)
01678 continue;
01679 }
01680 #if 0
01681 if (s->repo && s->repo != oldinstalled)
01682 {
01683 Id p2, obs, *obsp, *pp;
01684 Solvable *s2;
01685 if (s->obsoletes)
01686 {
01687 obsp = s->repo->idarraydata + s->obsoletes;
01688 while ((obs = *obsp++) != 0)
01689 {
01690 if ((providedbyinstalled(pool, map, obs, 0, 0) & 1) != 0)
01691 {
01692 map[p] = 2;
01693 break;
01694 }
01695 }
01696 if (obs)
01697 continue;
01698 }
01699 FOR_PROVIDES(p2, pp, s->name)
01700 {
01701 s2 = pool->solvables + p2;
01702 if (s2->name == s->name && (map[p2] & 1) != 0)
01703 {
01704 map[p] = 2;
01705 break;
01706 }
01707 }
01708 if (p2)
01709 continue;
01710 }
01711 #endif
01712 if (m != map[p])
01713 {
01714 map[p] = m;
01715 did = 0;
01716 }
01717 }
01718 queue_free(res);
01719 queue_init_clone(res, pkgs);
01720 for (i = 0; i < pkgs->count; i++)
01721 {
01722 m = map[pkgs->elements[i]];
01723 if ((m & 9) == 9)
01724 r = 1;
01725 else if (m & 1)
01726 r = -1;
01727 else
01728 r = 0;
01729 res->elements[i] = r;
01730 }
01731 free(map);
01732 }
01733
01734 void
01735 pool_trivial_installable(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res)
01736 {
01737 pool_trivial_installable_noobsoletesmap(pool, installedmap, pkgs, res, 0);
01738 }
01739
01740 const char *
01741 pool_lookup_str(Pool *pool, Id entry, Id keyname)
01742 {
01743 if (entry == SOLVID_POS && pool->pos.repo)
01744 return repodata_lookup_str(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname);
01745 if (entry <= 0)
01746 return 0;
01747 return solvable_lookup_str(pool->solvables + entry, keyname);
01748 }
01749
01750 Id
01751 pool_lookup_id(Pool *pool, Id entry, Id keyname)
01752 {
01753 if (entry == SOLVID_POS && pool->pos.repo)
01754 {
01755 Repodata *data = pool->pos.repo->repodata + pool->pos.repodataid;
01756 Id id = repodata_lookup_id(data, SOLVID_POS, keyname);
01757 return data->localpool ? repodata_globalize_id(data, id, 1) : id;
01758 }
01759 if (entry <= 0)
01760 return 0;
01761 return solvable_lookup_id(pool->solvables + entry, keyname);
01762 }
01763
01764 unsigned int
01765 pool_lookup_num(Pool *pool, Id entry, Id keyname, unsigned int notfound)
01766 {
01767 if (entry == SOLVID_POS && pool->pos.repo)
01768 {
01769 unsigned int value;
01770 if (repodata_lookup_num(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, &value))
01771 return value;
01772 return notfound;
01773 }
01774 if (entry <= 0)
01775 return notfound;
01776 return solvable_lookup_num(pool->solvables + entry, keyname, notfound);
01777 }
01778
01779 int
01780 pool_lookup_void(Pool *pool, Id entry, Id keyname)
01781 {
01782 if (entry == SOLVID_POS && pool->pos.repo)
01783 return repodata_lookup_void(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname);
01784 if (entry <= 0)
01785 return 0;
01786 return solvable_lookup_void(pool->solvables + entry, keyname);
01787 }
01788
01789 const unsigned char *
01790 pool_lookup_bin_checksum(Pool *pool, Id entry, Id keyname, Id *typep)
01791 {
01792 if (entry == SOLVID_POS && pool->pos.repo)
01793 return repodata_lookup_bin_checksum(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, typep);
01794 if (entry <= 0)
01795 return 0;
01796 return solvable_lookup_bin_checksum(pool->solvables + entry, keyname, typep);
01797 }
01798
01799 const char *
01800 pool_lookup_checksum(Pool *pool, Id entry, Id keyname, Id *typep)
01801 {
01802 if (entry == SOLVID_POS && pool->pos.repo)
01803 {
01804 const unsigned char *chk = repodata_lookup_bin_checksum(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, typep);
01805 return chk ? repodata_chk2str(pool->pos.repo->repodata + pool->pos.repodataid, *typep, chk) : 0;
01806 }
01807 if (entry <= 0)
01808 return 0;
01809 return solvable_lookup_checksum(pool->solvables + entry, keyname, typep);
01810 }
01811
01812 void
01813 pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts)
01814 {
01815 int hadhashes = pool->relhashtbl ? 1 : 0;
01816 Solvable *s;
01817 Id fn, p, q, md5;
01818 Id id;
01819 int i;
01820
01821 if (!conflicts->count)
01822 return;
01823 pool_freewhatprovides(pool);
01824 for (i = 0; i < conflicts->count; i += 5)
01825 {
01826 fn = conflicts->elements[i];
01827 p = conflicts->elements[i + 1];
01828 md5 = conflicts->elements[i + 2];
01829 q = conflicts->elements[i + 3];
01830 id = rel2id(pool, fn, md5, REL_FILECONFLICT, 1);
01831 s = pool->solvables + p;
01832 if (!s->repo)
01833 continue;
01834 s->provides = repo_addid_dep(s->repo, s->provides, id, SOLVABLE_FILEMARKER);
01835 s = pool->solvables + q;
01836 if (!s->repo)
01837 continue;
01838 s->conflicts = repo_addid_dep(s->repo, s->conflicts, id, 0);
01839 }
01840 if (!hadhashes)
01841 pool_freeidhashes(pool);
01842 }
01843
01844