X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fpool.c;h=f78f71ad4892b51627deb0aac8885a1e109d8608;hb=refs%2Ftags%2Fupstream%2F0.6.11;hp=981c76770604ef333b0cc41d6242f25d5767bbef;hpb=84957715aacbe8405e3cb367fe763220d5ba6b42;p=platform%2Fupstream%2Flibsolv.git diff --git a/src/pool.c b/src/pool.c index 981c767..f78f71a 100644 --- a/src/pool.c +++ b/src/pool.c @@ -30,6 +30,7 @@ #define SOLVABLE_BLOCK 255 +#undef LIBSOLV_KNOWNID_H #define KNOWNID_INITIALIZE #include "knownid.h" #undef KNOWNID_INITIALIZE @@ -117,7 +118,7 @@ pool_free(Pool *pool) solv_free(pool->tmpspace.buf[i]); for (i = 0; i < pool->nlanguages; i++) free((char *)pool->languages[i]); - solv_free(pool->languages); + solv_free((void *)pool->languages); solv_free(pool->languagecache); solv_free(pool->errstr); solv_free(pool->rootdir); @@ -140,22 +141,33 @@ pool_freeallrepos(Pool *pool, int reuseids) pool_free_solvable_block(pool, 2, pool->nsolvables - 2, reuseids); } -#ifdef MULTI_SEMANTICS -void +int pool_setdisttype(Pool *pool, int disttype) { +#ifdef MULTI_SEMANTICS + int olddisttype = pool->disttype; + switch(disttype) + { + case DISTTYPE_RPM: + pool->noarchid = ARCH_NOARCH; + break; + case DISTTYPE_DEB: + pool->noarchid = ARCH_ALL; + break; + case DISTTYPE_ARCH: + case DISTTYPE_HAIKU: + pool->noarchid = ARCH_ANY; + break; + default: + return -1; + } pool->disttype = disttype; - if (disttype == DISTTYPE_RPM) - pool->noarchid = ARCH_NOARCH; - if (disttype == DISTTYPE_DEB) - pool->noarchid = ARCH_ALL; - if (disttype == DISTTYPE_ARCH) - pool->noarchid = ARCH_ANY; - if (disttype == DISTTYPE_HAIKU) - pool->noarchid = ARCH_ANY; pool->solvables[SYSTEMSOLVABLE].arch = pool->noarchid; -} + return olddisttype; +#else + return pool->disttype == disttype ? disttype : -1; #endif +} int pool_get_flag(Pool *pool, int flag) @@ -182,6 +194,8 @@ pool_get_flag(Pool *pool, int flag) return pool->noobsoletesmultiversion; case POOL_FLAG_ADDFILEPROVIDESFILTERED: return pool->addfileprovidesfiltered; + case POOL_FLAG_NOWHATPROVIDESAUX: + return pool->nowhatprovidesaux; default: break; } @@ -224,6 +238,9 @@ pool_set_flag(Pool *pool, int flag, int value) case POOL_FLAG_ADDFILEPROVIDESFILTERED: pool->addfileprovidesfiltered = value; break; + case POOL_FLAG_NOWHATPROVIDESAUX: + pool->nowhatprovidesaux = value; + break; default: break; } @@ -381,6 +398,34 @@ pool_shrink_whatprovides(Pool *pool) memset(pool->whatprovidesdata + o, 0, r * sizeof(Id)); } +/* this gets rid of all the zeros in the aux */ +static void +pool_shrink_whatprovidesaux(Pool *pool) +{ + int num = pool->whatprovidesauxoff; + Id id; + Offset newoff; + Id *op, *wp = pool->whatprovidesauxdata + 1; + int i; + + for (i = 0; i < num; i++) + { + Offset o = pool->whatprovidesaux[i]; + if (o < 2) + continue; + op = pool->whatprovidesauxdata + o; + pool->whatprovidesaux[i] = wp - pool->whatprovidesauxdata; + if (op < wp) + abort(); + while ((id = *op++) != 0) + *wp++ = id; + } + newoff = wp - pool->whatprovidesauxdata; + solv_realloc(pool->whatprovidesauxdata, newoff * sizeof(Id)); + POOL_DEBUG(SOLV_DEBUG_STATS, "shrunk whatprovidesauxdata from %d to %d\n", pool->whatprovidesauxdataoff, newoff); + pool->whatprovidesauxdataoff = newoff; +} + /* * pool_createwhatprovides() @@ -397,7 +442,8 @@ pool_createwhatprovides(Pool *pool) Id id; Offset *idp, n; Offset *whatprovides; - Id *whatprovidesdata, *d; + Id *whatprovidesdata, *dp, *whatprovidesauxdata; + Offset *whatprovidesaux; Repo *installed = pool->installed; unsigned int now; @@ -465,6 +511,16 @@ pool_createwhatprovides(Pool *pool) whatprovidesdata = solv_calloc(off + extra, sizeof(Id)); whatprovidesdata[2] = SYSTEMSOLVABLE; + /* alloc aux vector */ + whatprovidesauxdata = 0; + if (!pool->nowhatprovidesaux) + { + pool->whatprovidesaux = whatprovidesaux = solv_calloc(num, sizeof(Offset)); + pool->whatprovidesauxoff = num; + pool->whatprovidesauxdataoff = off; + pool->whatprovidesauxdata = whatprovidesauxdata = solv_calloc(pool->whatprovidesauxdataoff, sizeof(Id)); + } + /* now fill data for all provides */ for (i = pool->nsolvables - 1; i > 0; i--) { @@ -479,24 +535,35 @@ pool_createwhatprovides(Pool *pool) pp = s->repo->idarraydata + s->provides; while ((id = *pp++) != 0) { + Id auxid = id; while (ISRELDEP(id)) { Reldep *rd = GETRELDEP(pool, id); id = rd->name; } - d = whatprovidesdata + whatprovides[id]; /* offset into whatprovidesdata */ - if (*d != i) /* don't add same solvable twice */ + dp = whatprovidesdata + whatprovides[id]; /* offset into whatprovidesdata */ + if (*dp != i) /* don't add same solvable twice */ { - d[-1] = i; + dp[-1] = i; whatprovides[id]--; } + else + auxid = 1; + if (whatprovidesauxdata) + whatprovidesauxdata[whatprovides[id]] = auxid; } } + if (pool->whatprovidesaux) + memcpy(pool->whatprovidesaux, pool->whatprovides, num * sizeof(Id)); pool->whatprovidesdata = whatprovidesdata; pool->whatprovidesdataoff = off; pool->whatprovidesdataleft = extra; pool_shrink_whatprovides(pool); + if (pool->whatprovidesaux) + pool_shrink_whatprovidesaux(pool); POOL_DEBUG(SOLV_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))); + if (pool->whatprovidesaux) + POOL_DEBUG(SOLV_DEBUG_STATS, "whatprovidesaux memory used: %d K id array, %d K data\n", pool->whatprovidesauxoff / (int)(1024/sizeof(Id)), pool->whatprovidesauxdataoff / (int)(1024/sizeof(Id))); queue_empty(&pool->lazywhatprovidesq); if ((!pool->addedfileprovides && pool->disttype == DISTTYPE_RPM) || pool->addedfileprovides == 1) @@ -515,6 +582,8 @@ pool_createwhatprovides(Pool *pool) if (pool->whatprovides[i] > 1) queue_push2(&pool->lazywhatprovidesq, i, pool->whatprovides[i]); pool->whatprovides[i] = 0; + if (pool->whatprovidesaux) + pool->whatprovidesaux[i] = 0; /* sorry */ } POOL_DEBUG(SOLV_DEBUG_STATS, "lazywhatprovidesq size: %d entries\n", pool->lazywhatprovidesq.count / 2); } @@ -535,6 +604,10 @@ pool_freewhatprovides(Pool *pool) pool->whatprovidesdata = solv_free(pool->whatprovidesdata); pool->whatprovidesdataoff = 0; pool->whatprovidesdataleft = 0; + pool->whatprovidesaux = solv_free(pool->whatprovidesaux); + pool->whatprovidesauxdata = solv_free(pool->whatprovidesauxdata); + pool->whatprovidesauxoff = 0; + pool->whatprovidesauxdataoff = 0; } @@ -548,15 +621,15 @@ pool_freewhatprovides(Pool *pool) * returns: Offset into whatprovidesdata * */ + Id -pool_queuetowhatprovides(Pool *pool, Queue *q) +pool_ids2whatprovides(Pool *pool, Id *ids, int count) { Offset off; - int count = q->count; if (count == 0) /* queue empty -> 1 */ return 1; - if (count == 1 && q->elements[0] == SYSTEMSOLVABLE) + if (count == 1 && *ids == SYSTEMSOLVABLE) return 2; /* extend whatprovidesdata if needed, +1 for 0-termination */ @@ -569,7 +642,7 @@ pool_queuetowhatprovides(Pool *pool, Queue *q) /* copy queue to next free slot */ off = pool->whatprovidesdataoff; - memcpy(pool->whatprovidesdata + pool->whatprovidesdataoff, q->elements, count * sizeof(Id)); + memcpy(pool->whatprovidesdata + pool->whatprovidesdataoff, ids, count * sizeof(Id)); /* adapt count and 0-terminate */ pool->whatprovidesdataoff += count; @@ -579,6 +652,17 @@ pool_queuetowhatprovides(Pool *pool, Queue *q) return (Id)off; } +Id +pool_queuetowhatprovides(Pool *pool, Queue *q) +{ + int count = q->count; + if (count == 0) /* queue empty -> 1 */ + return 1; + if (count == 1 && q->elements[0] == SYSTEMSOLVABLE) + return 2; + return pool_ids2whatprovides(pool, q->elements, count); +} + /*************************************************************************/ @@ -879,6 +963,10 @@ pool_is_kind(Pool *pool, Id name, Id kind) * * add packages fulfilling the relation to whatprovides array * + * some words about REL_AND and REL_IF: we assume the best case + * here, so that you get a "potential" result if you ask for a match. + * E.g. if you ask for "whatrequires A" and package X contains + * "Requires: A & B", you'll get "X" as an answer. */ Id pool_addrelproviders(Pool *pool, Id d) @@ -908,7 +996,6 @@ pool_addrelproviders(Pool *pool, Id d) switch (flags) { - case REL_AND: case REL_WITH: wp = pool_whatprovides(pool, name); pp2 = pool_whatprovides_ptr(pool, evr); @@ -924,24 +1011,43 @@ pool_addrelproviders(Pool *pool, Id d) wp = 0; } break; + + case REL_AND: case REL_OR: wp = pool_whatprovides(pool, name); - pp = pool->whatprovidesdata + wp; - if (!*pp) + if (!pool->whatprovidesdata[wp]) wp = pool_whatprovides(pool, evr); else { - int cnt; - while ((p = *pp++) != 0) - queue_push(&plist, p); - cnt = plist.count; - pp = pool_whatprovides_ptr(pool, evr); - while ((p = *pp++) != 0) - queue_pushunique(&plist, p); - if (plist.count != cnt) + /* sorted merge */ + pp2 = pool_whatprovides_ptr(pool, evr); + pp = pool->whatprovidesdata + wp; + while (*pp && *pp2) + { + if (*pp < *pp2) + queue_push(&plist, *pp++); + else + { + if (*pp == *pp2) + pp++; + queue_push(&plist, *pp2++); + } + } + while (*pp) + queue_push(&plist, *pp++); + while (*pp2) + queue_push(&plist, *pp2++); + /* if the number of elements did not change, we can reuse wp */ + if (pp - (pool->whatprovidesdata + wp) != plist.count) wp = 0; } break; + + case REL_COND: + /* assume the condition is true */ + wp = pool_whatprovides(pool, name); + break; + case REL_NAMESPACE: if (name == NAMESPACE_OTHERPROVIDERS) { @@ -1066,11 +1172,14 @@ pool_addrelproviders(Pool *pool, Id d) } else if (flags) { + Id *ppaux = 0; /* simple version comparison relation */ #if 0 POOL_DEBUG(SOLV_DEBUG_STATS, "addrelproviders: what provides %s?\n", pool_dep2str(pool, name)); #endif pp = pool_whatprovides_ptr(pool, name); + if (!ISRELDEP(name) && name < pool->whatprovidesauxoff) + ppaux = pool->whatprovidesaux[name] ? pool->whatprovidesauxdata + pool->whatprovidesaux[name] : 0; while (ISRELDEP(name)) { rd = GETRELDEP(pool, name); @@ -1079,6 +1188,34 @@ pool_addrelproviders(Pool *pool, Id d) while ((p = *pp++) != 0) { Solvable *s = pool->solvables + p; + if (ppaux) + { + pid = *ppaux++; + if (pid && pid != 1) + { +#if 0 + POOL_DEBUG(SOLV_DEBUG_STATS, "addrelproviders: aux hit %d %s\n", p, pool_dep2str(pool, pid)); +#endif + if (!ISRELDEP(pid)) + { + if (pid != name) + continue; /* wrong provides name */ + if (pool->disttype == DISTTYPE_DEB) + continue; /* unversioned provides can never match versioned deps */ + } + else + { + prd = GETRELDEP(pool, pid); + if (prd->name != name) + continue; /* wrong provides name */ + /* right package, both deps are rels. check flags/evr */ + if (!pool_match_flags_evr(pool, prd->flags, prd->evr, flags, evr)) + continue; + } + queue_push(&plist, p); + continue; + } + } if (!s->provides) { /* no provides - check nevr */ @@ -1273,8 +1410,6 @@ void pool_setnamespacecallback(Pool *pool, Id (*cb)(struct _Pool *, void *, Id, struct searchfiles { Id *ids; - char **dirs; - char **names; int nfiles; Map seen; }; @@ -1285,7 +1420,7 @@ static void pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct searchfiles *isf) { Id dep, sid; - const char *s, *sr; + const char *s; struct searchfiles *csf; while ((dep = *ida++) != 0) @@ -1306,7 +1441,7 @@ pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct sea dep = rd->name; else if (rd->flags == REL_NAMESPACE) { - if (rd->name == NAMESPACE_INSTALLED || rd->name == NAMESPACE_SPLITPROVIDES) + if (rd->name == NAMESPACE_SPLITPROVIDES) { csf = isf; if (!csf || MAPTST(&csf->seen, sid)) @@ -1343,16 +1478,7 @@ pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct sea if (csf != isf && pool->addedfileprovides == 1 && !repodata_filelistfilter_matches(0, s)) continue; /* skip non-standard locations csf == isf: installed case */ csf->ids = solv_extend(csf->ids, csf->nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK); - csf->dirs = solv_extend(csf->dirs, csf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK); - csf->names = solv_extend(csf->names, csf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK); - csf->ids[csf->nfiles] = dep; - sr = strrchr(s, '/'); - csf->names[csf->nfiles] = solv_strdup(sr + 1); - csf->dirs[csf->nfiles] = solv_malloc(sr - s + 1); - if (sr != s) - strncpy(csf->dirs[csf->nfiles], s, sr - s); - csf->dirs[csf->nfiles][sr - s] = 0; - csf->nfiles++; + csf->ids[csf->nfiles++] = dep; } } @@ -1378,6 +1504,19 @@ addfileprovides_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyV if (!cbd->useddirs.size) { map_init(&cbd->useddirs, data->dirpool.ndirs + 1); + if (!cbd->dirs) + { + cbd->dirs = solv_malloc2(cbd->nfiles, sizeof(char *)); + cbd->names = solv_malloc2(cbd->nfiles, sizeof(char *)); + for (i = 0; i < cbd->nfiles; i++) + { + char *s = solv_strdup(pool_id2str(data->repo->pool, cbd->ids[i])); + cbd->dirs[i] = s; + s = strrchr(s, '/'); + *s = 0; + cbd->names[i] = s + 1; + } + } for (i = 0; i < cbd->nfiles; i++) { Id did; @@ -1396,15 +1535,8 @@ addfileprovides_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyV if (value->id >= data->dirpool.ndirs || !MAPTST(&cbd->useddirs, value->id)) return 0; for (i = 0; i < cbd->nfiles; i++) - { - if (cbd->dids[i] != value->id) - continue; - if (!strcmp(cbd->names[i], value->str)) - break; - } - if (i == cbd->nfiles) - return 0; - s->provides = repo_addid_dep(s->repo, s->provides, cbd->ids[i], SOLVABLE_FILEMARKER); + if (cbd->dids[i] == value->id && !strcmp(cbd->names[i], value->str)) + s->provides = repo_addid_dep(s->repo, s->provides, cbd->ids[i], SOLVABLE_FILEMARKER); return 0; } @@ -1425,8 +1557,8 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru cbd->nfiles = sf->nfiles; cbd->ids = sf->ids; - cbd->dirs = sf->dirs; - cbd->names = sf->names; + cbd->dirs = 0; + cbd->names = 0; cbd->dids = solv_realloc2(cbd->dids, sf->nfiles, sizeof(Id)); map_init(&cbd->providedids, pool->ss.nstrings); @@ -1530,6 +1662,13 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru map_free(&donemap); queue_free(&fileprovidesq); map_free(&cbd->providedids); + if (cbd->dirs) + { + for (i = 0; i < cbd->nfiles; i++) + solv_free(cbd->dirs[i]); + cbd->dirs = solv_free(cbd->dirs); + cbd->names = solv_free(cbd->names); + } } void @@ -1593,13 +1732,6 @@ pool_addfileprovides_queue(Pool *pool, Queue *idq, Queue *idqinst) for (i = 0; i < sf.nfiles; i++) queue_push(idqinst, sf.ids[i]); solv_free(sf.ids); - for (i = 0; i < sf.nfiles; i++) - { - solv_free(sf.dirs[i]); - solv_free(sf.names[i]); - } - solv_free(sf.dirs); - solv_free(sf.names); } if (isf.nfiles) { @@ -1613,13 +1745,6 @@ pool_addfileprovides_queue(Pool *pool, Queue *idq, Queue *idqinst) for (i = 0; i < isf.nfiles; i++) queue_pushunique(idqinst, isf.ids[i]); solv_free(isf.ids); - for (i = 0; i < isf.nfiles; i++) - { - solv_free(isf.dirs[i]); - solv_free(isf.names[i]); - } - solv_free(isf.dirs); - solv_free(isf.names); } solv_free(cbd.dids); pool_freewhatprovides(pool); /* as we have added provides */ @@ -1663,7 +1788,7 @@ pool_set_languages(Pool *pool, const char **languages, int nlanguages) pool->languagecacheother = 0; for (i = 0; i < pool->nlanguages; i++) free((char *)pool->languages[i]); - pool->languages = solv_free(pool->languages); + pool->languages = solv_free((void *)pool->languages); pool->nlanguages = nlanguages; if (!nlanguages) return; @@ -1911,7 +2036,7 @@ solver_fill_DU_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyVa cbd->mps[mp].kbytes += value->num; cbd->mps[mp].files += value->num2; } - else + else if (!(cbd->mps[mp].flags & DUCHANGES_ONLYADD)) { cbd->mps[mp].kbytes -= value->num; cbd->mps[mp].files -= value->num2; @@ -2019,13 +2144,17 @@ pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps) struct mptree *mptree; struct ducbdata cbd; Solvable *s; - int sp; + int i, sp; Map ignoredu; Repo *oldinstalled = pool->installed; + int haveonlyadd = 0; map_init(&ignoredu, 0); mptree = create_mptree(mps, nmps); + for (i = 0; i < nmps; i++) + if ((mps[i].flags & DUCHANGES_ONLYADD) != 0) + haveonlyadd = 1; cbd.mps = mps; cbd.dirmap = 0; cbd.nmap = 0; @@ -2043,21 +2172,55 @@ pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps) if (!cbd.hasdu && oldinstalled) { Id op, opp; + int didonlyadd = 0; /* no du data available, ignore data of all installed solvables we obsolete */ if (!ignoredu.size) map_grow(&ignoredu, oldinstalled->end - oldinstalled->start); + FOR_PROVIDES(op, opp, s->name) + { + Solvable *s2 = pool->solvables + op; + if (!pool->implicitobsoleteusesprovides && s->name != s2->name) + continue; + if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, s2)) + continue; + if (op >= oldinstalled->start && op < oldinstalled->end) + { + MAPSET(&ignoredu, op - oldinstalled->start); + if (haveonlyadd && pool->solvables[op].repo == oldinstalled && !didonlyadd) + { + repo_search(oldinstalled, op, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); + cbd.addsub = -1; + repo_search(oldinstalled, op, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); + cbd.addsub = 1; + didonlyadd = 1; + } + } + } if (s->obsoletes) { Id obs, *obsp = s->repo->idarraydata + s->obsoletes; while ((obs = *obsp++) != 0) FOR_PROVIDES(op, opp, obs) - if (op >= oldinstalled->start && op < oldinstalled->end) - MAPSET(&ignoredu, op - oldinstalled->start); + { + Solvable *s2 = pool->solvables + op; + if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, s2, obs)) + continue; + if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) + continue; + if (op >= oldinstalled->start && op < oldinstalled->end) + { + MAPSET(&ignoredu, op - oldinstalled->start); + if (haveonlyadd && pool->solvables[op].repo == oldinstalled && !didonlyadd) + { + repo_search(oldinstalled, op, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); + cbd.addsub = -1; + repo_search(oldinstalled, op, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); + cbd.addsub = 1; + didonlyadd = 1; + } + } + } } - FOR_PROVIDES(op, opp, s->name) - if (pool->solvables[op].name == s->name) - if (op >= oldinstalled->start && op < oldinstalled->end) - MAPSET(&ignoredu, op - oldinstalled->start); } } cbd.addsub = -1; @@ -2439,6 +2602,8 @@ add_new_provider(Pool *pool, Id id, Id p) if (p) queue_push(&q, p); pool->whatprovides[id] = pool_queuetowhatprovides(pool, &q); + if (id < pool->whatprovidesauxoff) + pool->whatprovidesaux[id] = 0; /* sorry */ queue_free(&q); }