/*
- * Copyright (c) 2007, Novell Inc.
+ * Copyright (c) 2007-2009, Novell Inc.
*
* This program is licensed under the BSD license, read LICENSE.BSD
* for further information
}
-static Pool *pool_shrink_whatprovides_sortcmp_data;
+void
+pool_set_installed(Pool *pool, Repo *installed)
+{
+ if (pool->installed == installed)
+ return;
+ pool->installed = installed;
+ pool_freewhatprovides(pool);
+}
static int
-pool_shrink_whatprovides_sortcmp(const void *ap, const void *bp)
+pool_shrink_whatprovides_sortcmp(const void *ap, const void *bp, void *dp)
{
int r;
- Pool *pool = pool_shrink_whatprovides_sortcmp_data;
+ Pool *pool = dp;
Id oa, ob, *da, *db;
oa = pool->whatprovides[*(Id *)ap];
ob = pool->whatprovides[*(Id *)bp];
sorted = sat_malloc2(pool->ss.nstrings, sizeof(Id));
for (id = 0; id < pool->ss.nstrings; id++)
sorted[id] = id;
- pool_shrink_whatprovides_sortcmp_data = pool;
- qsort(sorted + 1, pool->ss.nstrings - 1, sizeof(Id), pool_shrink_whatprovides_sortcmp);
+ sat_sort(sorted + 1, pool->ss.nstrings - 1, sizeof(Id), pool_shrink_whatprovides_sortcmp, pool);
last = 0;
lastid = 0;
for (i = 1; i < pool->ss.nstrings; i++)
Offset *idp, n;
Offset *whatprovides;
Id *whatprovidesdata, *d;
+ Repo *installed = pool->installed;
+ unsigned int now;
+ now = sat_timems(0);
POOL_DEBUG(SAT_DEBUG_STATS, "number of solvables: %d\n", pool->nsolvables);
POOL_DEBUG(SAT_DEBUG_STATS, "number of ids: %d + %d\n", pool->ss.nstrings, pool->nrels);
s = pool->solvables + i;
if (!s->provides)
continue;
- if (!pool_installable(pool, s))
+ /* we always need the installed solvable in the whatprovides data,
+ otherwise obsoletes/conflicts on them won't work */
+ if (s->repo != installed && !pool_installable(pool, s))
continue;
pp = s->repo->idarraydata + s->provides;
while ((id = *pp++) != ID_NULL)
s = pool->solvables + i;
if (!s->provides)
continue;
- if (!pool_installable(pool, s))
+ if (s->repo != installed && !pool_installable(pool, s))
continue;
/* for all provides of this solvable */
pool->whatprovidesdataoff = off;
pool->whatprovidesdataleft = extra;
pool_shrink_whatprovides(pool);
+ 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)));
+ POOL_DEBUG(SAT_DEBUG_STATS, "createwhatprovides took %d ms\n", sat_timems(now));
}
/*
* free all of our whatprovides data
- * be careful, everything internalized with pool_queuetowhatprovides is gone, too
+ * be careful, everything internalized with pool_queuetowhatprovides is
+ * gone, too
*/
void
pool_freewhatprovides(Pool *pool)
return 1;
if (flags != 2 && flags != 5)
flags ^= 5;
+#ifdef DEBIAN_SEMANTICS
+ if ((flags & (1 << (1 + evrcmp(pool, s->evr, evr, EVRCMP_COMPARE)))) != 0)
+ return 1;
+#else
if ((flags & (1 << (1 + evrcmp(pool, s->evr, evr, EVRCMP_MATCH_RELEASE)))) != 0)
return 1;
+#endif
+ return 0;
+}
+
+/* match two dependencies */
+
+int
+pool_match_dep(Pool *pool, Id d1, Id d2)
+{
+ Reldep *rd1, *rd2;
+ int pflags, flags;
+
+ if (d1 == d2)
+ return 1;
+ if (!ISRELDEP(d1))
+ {
+ if (!ISRELDEP(d2))
+ return 0;
+ rd2 = GETRELDEP(pool, d2);
+ return pool_match_dep(pool, d1, rd2->name);
+ }
+ rd1 = GETRELDEP(pool, d1);
+ if (!ISRELDEP(d2))
+ {
+ return pool_match_dep(pool, rd1->name, d2);
+ }
+ rd2 = GETRELDEP(pool, d2);
+ if (!pool_match_dep(pool, rd1->name, rd2->name))
+ return 0;
+ pflags = rd1->flags;
+ flags = rd2->flags;
+ if (!pflags || !flags || pflags >= 8 || flags >= 8)
+ return 0;
+ if (flags == 7 || pflags == 7)
+ return 1;
+ if ((pflags & flags & 5) != 0)
+ return 1;
+ if (rd1->evr == rd2->evr)
+ {
+ if ((pflags & flags & 2) != 0)
+ return 1;
+ }
+ else
+ {
+ int f = flags == 5 ? 5 : flags == 2 ? pflags : (flags ^ 5) & (pflags | 5);
+#ifdef DEBIAN_SEMANTICS
+ if ((f & (1 << (1 + evrcmp(pool, rd1->evr, rd2->evr, EVRCMP_COMPARE)))) != 0)
+ return 1;
+#else
+ if ((f & (1 << (1 + evrcmp(pool, rd1->evr, rd2->evr, EVRCMP_MATCH_RELEASE)))) != 0)
+ return 1;
+#endif
+ }
return 0;
}
*
*/
-Id *
+Id
pool_addrelproviders(Pool *pool, Id d)
{
Reldep *rd = GETRELDEP(pool, d);
Id evr = rd->evr;
int flags = rd->flags;
Id pid, *pidp;
- Id p, *pp, *pp2, *pp3;
+ Id p, wp, *pp, *pp2, *pp3;
d = GETRELID(d);
queue_init_buffer(&plist, buf, sizeof(buf)/sizeof(*buf));
{
case REL_AND:
case REL_WITH:
- pp = pool_whatprovides(pool, name);
- pp2 = pool_whatprovides(pool, evr);
+ pp = pool_whatprovides_ptr(pool, name);
+ pp2 = pool_whatprovides_ptr(pool, evr);
while ((p = *pp++) != 0)
{
for (pp3 = pp2; *pp3;)
}
break;
case REL_OR:
- pp = pool_whatprovides(pool, name);
+ pp = pool_whatprovides_ptr(pool, name);
while ((p = *pp++) != 0)
queue_push(&plist, p);
- pp = pool_whatprovides(pool, evr);
+ pp = pool_whatprovides_ptr(pool, evr);
while ((p = *pp++) != 0)
queue_pushunique(&plist, p);
break;
case REL_NAMESPACE:
+ if (name == NAMESPACE_OTHERPROVIDERS)
+ {
+ wp = pool_whatprovides(pool, evr);
+ pool->whatprovides_rel[d] = wp;
+ return wp;
+ }
if (pool->nscallback)
{
/* ask callback which packages provide the dependency
{
queue_free(&plist);
pool->whatprovides_rel[d] = p;
- return pool->whatprovidesdata + p;
+ return p;
}
if (p == 1)
queue_push(&plist, SYSTEMSOLVABLE);
}
break;
}
- pp = pp2 = pool_whatprovides(pool, name);
+ wp = pool_whatprovides(pool, name);
+ pp = pool->whatprovidesdata + wp;
while ((p = *pp++) != 0)
{
Solvable *s = pool->solvables + p;
if (s->arch == evr)
queue_push(&plist, p);
else
- pp2 = 0;
+ wp = 0;
+ }
+ if (wp)
+ {
+ pool->whatprovides_rel[d] = wp;
+ return wp;
}
- if (pp2)
- return pp2;
break;
default:
break;
#endif
if (flags && flags < 8)
{
- pp = pool_whatprovides(pool, name);
+ pp = pool_whatprovides_ptr(pool, name);
while (ISRELDEP(name))
{
rd = GETRELDEP(pool, name);
else
{
int f = flags == 5 ? 5 : flags == 2 ? pflags : (flags ^ 5) & (pflags | 5);
+#ifdef DEBIAN_SEMANTICS
+ if ((f & (1 << (1 + evrcmp(pool, pevr, evr, EVRCMP_COMPARE)))) != 0)
+ break;
+#else
if ((f & (1 << (1 + evrcmp(pool, pevr, evr, EVRCMP_MATCH_RELEASE)))) != 0)
break;
+#endif
}
}
if (!pid)
pool->whatprovides_rel[d] = pool_queuetowhatprovides(pool, &plist);
queue_free(&plist);
- return pool->whatprovidesdata + pool->whatprovides_rel[d];
+ return pool->whatprovides_rel[d];
}
/*************************************************************************/
return 0;
}
+static int
+addfileprovides_setid_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv)
+{
+ Map *provideids = cbdata;
+ if (key->type != REPOKEY_TYPE_IDARRAY)
+ return 0;
+ MAPSET(provideids, kv->id);
+ return kv->eof ? SEARCH_NEXT_SOLVABLE : 0;
+}
+
static void
pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, struct searchfiles *sf, Repo *repoonly)
{
- Id p, start, end, *idp;
+ Id p, start, end;
Solvable *s;
Repodata *data = 0, *nextdata;
Repo *oldrepo = 0;
int dataincludes = 0;
- int i;
+ int i, j;
Map providedids;
cbd->nfiles = sf->nfiles;
{
if (!s->repo || (repoonly && s->repo != repoonly))
continue;
+ /* check if p is in (oldrepo,data) */
if (s->repo != oldrepo || (data && p >= data->end))
{
data = 0;
}
if (oldrepo == 0)
{
+ /* nope, find new repo/repodata */
+ /* if we don't find a match, set data to the next repodata */
nextdata = 0;
for (i = 0, data = s->repo->repodata; i < s->repo->nrepodata; i++, data++)
{
- if (!data->addedfileprovides || p >= data->end)
+ if (p >= data->end)
continue;
+ if (data->state != REPODATA_AVAILABLE)
+ continue;
+ for (j = 1; j < data->nkeys; j++)
+ if (data->keys[j].name == REPOSITORY_ADDEDFILEPROVIDES && data->keys[j].type == REPOKEY_TYPE_IDARRAY)
+ break;
+ if (j == data->nkeys)
+ continue;
+ /* great, this repodata contains addedfileprovides */
if (!nextdata || nextdata->start > data->start)
nextdata = data;
if (p >= data->start)
break;
}
if (i == s->repo->nrepodata)
- data = nextdata;
+ data = nextdata; /* no direct hit, use next repodata */
if (data)
{
map_init(&providedids, pool->ss.nstrings);
- for (idp = data->addedfileprovides; *idp; idp++)
- MAPSET(&providedids, *idp);
+ repodata_search(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, 0, addfileprovides_setid_cb, &providedids);
for (i = 0; i < cbd->nfiles; i++)
if (!MAPTST(&providedids, cbd->ids[i]))
- {
- break;
- }
+ break;
map_free(&providedids);
dataincludes = i == cbd->nfiles;
}
}
void
-pool_addfileprovides(Pool *pool, Repo *installed)
+pool_addfileprovides(Pool *pool)
{
- pool_addfileprovides_ids(pool, installed, 0);
+ pool_addfileprovides_ids(pool, pool->installed, 0);
}
void
repo_search(pool->solvables[p].repo, p, key, match, flags, callback, cbdata);
}
+void
+pool_clear_pos(Pool *pool)
+{
+ memset(&pool->pos, 0, sizeof(pool->pos));
+}
+
void
pool_set_languages(Pool *pool, const char **languages, int nlanguages)
#define MPTREE_BLOCK 15
void
-pool_calc_duchanges(Pool *pool, Repo *oldinstalled, Map *installedmap, DUChanges *mps, int nmps)
+pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps)
{
char *p;
const char *path, *compstr;
Solvable *s;
Id sp;
Map ignoredu;
+ Repo *oldinstalled = pool->installed;
memset(&ignoredu, 0, sizeof(ignoredu));
cbd.mps = mps;
repo_search(s->repo, sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
if (!cbd.hasdu && oldinstalled)
{
- Id op, *opp;
+ Id op, opp;
/* no du data available, ignore data of all installed solvables we obsolete */
if (!ignoredu.map)
map_init(&ignoredu, oldinstalled->end - oldinstalled->start);
}
int
-pool_calc_installsizechange(Pool *pool, Repo *oldinstalled, Map *installedmap)
+pool_calc_installsizechange(Pool *pool, Map *installedmap)
{
Id sp;
Solvable *s;
int change = 0;
+ Repo *oldinstalled = pool->installed;
for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++)
{
continue;
if (!MAPTST(installedmap, sp))
continue;
- change += repo_lookup_num(s, SOLVABLE_INSTALLSIZE);
+ change += solvable_lookup_num(s, SOLVABLE_INSTALLSIZE, 0);
}
if (oldinstalled)
{
{
if (MAPTST(installedmap, sp))
continue;
- change -= repo_lookup_num(s, SOLVABLE_INSTALLSIZE);
+ change -= solvable_lookup_num(s, SOLVABLE_INSTALLSIZE, 0);
}
}
return change;
return dep;
}
-static inline int providedbyinstalled(Pool *pool, unsigned char *map, Id dep)
+static int providedbyinstalled_multiversion(Pool *pool, unsigned char *map, Id n, Id dep)
{
- Id p, *pp;
+ Id p, pp;
+ Solvable *sn = pool->solvables + n;
+
+ FOR_PROVIDES(p, pp, sn->name)
+ {
+ Solvable *s = pool->solvables + p;
+ if (s->name != sn->name || s->arch != sn->arch)
+ continue;
+ if ((map[p] & 9) == 9)
+ return 1;
+ }
+ return 0;
+}
+
+static inline int providedbyinstalled(Pool *pool, unsigned char *map, Id dep, int ispatch, Map *noobsoletesmap)
+{
+ Id p, pp;
int r = 0;
FOR_PROVIDES(p, pp, dep)
{
if (p == SYSTEMSOLVABLE)
return 1; /* always boring, as never constraining */
+ if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep))
+ continue;
+ if (ispatch && noobsoletesmap && noobsoletesmap->size && MAPTST(noobsoletesmap, p) && ISRELDEP(dep))
+ if (providedbyinstalled_multiversion(pool, map, p, dep))
+ continue;
if ((map[p] & 9) == 9)
return 9;
r |= map[p] & 17;
*/
void
-pool_trivial_installable(Pool *pool, Repo *oldinstalled, Map *installedmap, Queue *pkgs, Queue *res)
+pool_trivial_installable_noobsoletesmap(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res, Map *noobsoletesmap)
{
int i, r, m, did;
Id p, *dp, con, *conp, req, *reqp;
conp = s->repo->idarraydata + s->conflicts;
while ((con = *conp++) != 0)
{
- dp = pool_whatprovides(pool, con);
+ dp = pool_whatprovides_ptr(pool, con);
for (; *dp; dp++)
map[p] |= 2; /* XXX: self conflict ? */
}
{
if (req == SOLVABLE_PREREQMARKER)
continue;
- r = providedbyinstalled(pool, map, req);
+ r = providedbyinstalled(pool, map, req, 0, 0);
if (!r)
{
/* decided and miss */
}
if (s->conflicts)
{
+ int ispatch = 0; /* see solver.c patch handling */
+
+ if (!strncmp("patch:", id2str(pool, s->name), 6))
+ ispatch = 1;
conp = s->repo->idarraydata + s->conflicts;
while ((con = *conp++) != 0)
{
- if ((providedbyinstalled(pool, map, con) & 1) != 0)
+ if ((providedbyinstalled(pool, map, con, ispatch, noobsoletesmap) & 1) != 0)
{
map[p] = 2;
break;
if ((m == 1 || m == 17) && ISRELDEP(con))
{
con = dep2name(pool, con);
- if ((providedbyinstalled(pool, map, con) & 1) != 0)
+ if ((providedbyinstalled(pool, map, con, ispatch, noobsoletesmap) & 1) != 0)
m = 9;
}
}
obsp = s->repo->idarraydata + s->obsoletes;
while ((obs = *obsp++) != 0)
{
- if ((providedbyinstalled(pool, map, obs) & 1) != 0)
+ if ((providedbyinstalled(pool, map, obs, 0, 0) & 1) != 0)
{
map[p] = 2;
break;
#endif
if (m != map[p])
{
- map[p] = m;
+ map[p] = m;
did = 0;
}
}
free(map);
}
+void
+pool_trivial_installable(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res)
+{
+ pool_trivial_installable_noobsoletesmap(pool, installedmap, pkgs, res, 0);
+}
+
// EOF