static void finddirs_cb(void *cbdatav, const char *fn, struct filelistinfo *info) { struct cbdata *cbdata = cbdatav; Hashval h, hh; Id hx, qx; Id oidx, idx = cbdata->idx; hx = strhash(fn); if (!hx) hx = strlen(fn) + 1; h = hx & cbdata->dirmapn; hh = HASHCHAIN_START; for (;;) { qx = cbdata->dirmap[2 * h]; if (!qx) break; if (qx == hx) break; h = HASHCHAIN_NEXT(h, hh, cbdata->dirmapn); } if (!qx) { /* a miss */ if (!cbdata->create) return; cbdata->dirmap[2 * h] = hx; cbdata->dirmap[2 * h + 1] = idx; if (++cbdata->dirmapused * 2 > cbdata->dirmapn) cbdata->dirmap = growhash(cbdata->dirmap, &cbdata->dirmapn); return; } oidx = cbdata->dirmap[2 * h + 1]; if (oidx == idx) return; /* found a conflict, this dir may be used in multiple packages */ if (oidx != -1) { MAPSET(&cbdata->idxmap, oidx); cbdata->dirmap[2 * h + 1] = -1; cbdata->dirconflicts++; } MAPSET(&cbdata->idxmap, idx); }
void PackageSet::set(Id id) { MAPSET(&pImpl->map, id); }
void PackageSet::set(DnfPackage *pkg) { MAPSET(&pImpl->map, dnf_package_get_id(pkg)); }
static void repo_addfileprovides_search(Repo *repo, struct addfileprovides_cbdata *cbd, struct searchfiles *sf) { Repodata *data; int rdid, p, i; int provstart, provend; Map todo; Map providedids; if (repo->end <= repo->start || !repo->nsolvables || !sf->nfiles) return; /* update search data if changed */ if (cbd->nfiles != sf->nfiles || cbd->ids != sf->ids) { free_dirs_names_array(cbd); cbd->nfiles = sf->nfiles; cbd->ids = sf->ids; cbd->dids = solv_realloc2(cbd->dids, sf->nfiles, sizeof(Id)); } /* create todo map and range */ map_init(&todo, repo->end - repo->start); for (p = repo->start; p < repo->end; p++) if (repo->pool->solvables[p].repo == repo) MAPSET(&todo, p - repo->start); cbd->todo = &todo; cbd->todo_start = repo->start; cbd->todo_end = repo->end; prune_todo_range(repo, cbd); provstart = provend = 0; map_init(&providedids, 0); data = repo_lookup_repodata(repo, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES); if (data) { Queue fileprovidesq; queue_init(&fileprovidesq); if (repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &fileprovidesq)) { map_grow(&providedids, repo->pool->ss.nstrings); cbd->providedids = &providedids; provstart = data->start; provend = data->end; for (i = 0; i < fileprovidesq.count; i++) MAPSET(&providedids, fileprovidesq.elements[i]); for (i = 0; i < cbd->nfiles; i++) if (!MAPTST(&providedids, cbd->ids[i])) break; if (i == cbd->nfiles) { /* all included, clear entries from todo list */ if (provstart <= cbd->todo_start && provend >= cbd->todo_end) cbd->todo_end = cbd->todo_start; /* clear complete range */ else { for (p = provstart; p < provend; p++) MAPCLR(&todo, p - repo->start); prune_todo_range(repo, cbd); } } } queue_free(&fileprovidesq); } if (cbd->todo_start >= cbd->todo_end) { map_free(&todo); cbd->todo = 0; map_free(&providedids); cbd->providedids = 0; return; } /* this is similar to repo_lookup_filelist_repodata in repo.c */ for (rdid = 1, data = repo->repodata + rdid; rdid < repo->nrepodata; rdid++, data++) if (data->filelisttype == REPODATA_FILELIST_FILTERED) break; for (; rdid < repo->nrepodata; rdid++, data++) if (data->filelisttype == REPODATA_FILELIST_EXTENSION) break; if (rdid < repo->nrepodata) { /* have at least one repodata with REPODATA_FILELIST_FILTERED followed by REPODATA_FILELIST_EXTENSION */ Map postpone; map_init(&postpone, 0); for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > 0; rdid--, data--) { if (data->filelisttype != REPODATA_FILELIST_FILTERED) continue; if (!repodata_intersects_todo(data, cbd)) continue; if (data->state != REPODATA_AVAILABLE) { if (data->state != REPODATA_STUB) continue; repodata_load(data); if (data->state != REPODATA_AVAILABLE || data->filelisttype != REPODATA_FILELIST_FILTERED) continue; } repo_addfileprovides_search_filtered(repo, cbd, rdid, &postpone); } if (postpone.size) { /* add postponed entries back to todo */ map_or(&todo, &postpone); cbd->todo_start = repo->start; cbd->todo_end = repo->end; prune_todo_range(repo, cbd); } map_free(&postpone); } /* search remaining entries in the standard way */ if (cbd->todo_start < cbd->todo_end) { for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > 0; rdid--, data--) { if (data->start >= cbd->todo_end || data->end <= cbd->todo_start) continue; if (!repodata_has_keyname(data, SOLVABLE_FILELIST)) continue; if (!repodata_intersects_todo(data, cbd)) continue; repodata_addfileprovides_search(data, cbd); if (cbd->todo_start >= cbd->todo_end) break; } } map_free(&todo); cbd->todo = 0; map_free(&providedids); cbd->providedids = 0; }
static void pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct searchfiles *isf) { Id dep, sid; const char *s; struct searchfiles *csf; while ((dep = *ida++) != 0) { csf = sf; while (ISRELDEP(dep)) { Reldep *rd; sid = pool->ss.nstrings + GETRELID(dep); if (MAPTST(&csf->seen, sid)) { dep = 0; break; } MAPSET(&csf->seen, sid); rd = GETRELDEP(pool, dep); if (rd->flags < 8) dep = rd->name; else if (rd->flags == REL_NAMESPACE) { if (rd->name == NAMESPACE_SPLITPROVIDES) { csf = isf; if (!csf || MAPTST(&csf->seen, sid)) { dep = 0; break; } MAPSET(&csf->seen, sid); } dep = rd->evr; } else if (rd->flags == REL_FILECONFLICT) { dep = 0; break; } else { Id ids[2]; ids[0] = rd->name; ids[1] = 0; pool_addfileprovides_dep(pool, ids, csf, isf); dep = rd->evr; } } if (!dep) continue; if (MAPTST(&csf->seen, dep)) continue; MAPSET(&csf->seen, dep); s = pool_id2str(pool, dep); if (*s != '/') continue; 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->ids[csf->nfiles++] = dep; } }
static void repo_addfileprovides_search_filtered(Repo *repo, struct addfileprovides_cbdata *cbd, int filteredid, Map *postpone) { Repodata *data = repo->repodata + filteredid; Map *providedids = cbd->providedids; int rdid; int start, end, p, i; Map old_todo; int old_todo_start, old_todo_end; start = cbd->todo_start > data->start ? cbd->todo_start : data->start; end = cbd->todo_end > data->end ? data->end : cbd->todo_end; if (providedids) { /* check if all solvables are in the provide range */ if (start < cbd->provstart || end > cbd->provend) { /* unclear, check each solvable */ for (p = start; p < end; p++) { if (p >= cbd->provstart && p < cbd->provend) continue; if (data->incoreoffset[p - data->start] && MAPTST(cbd->todo, p - repo->start)) { providedids = 0; /* nope, cannot prune with providedids */ break; } } } } /* check if the filtered files are enough */ for (i = 0; i < cbd->nfiles; i++) { if (providedids && MAPTST(providedids, cbd->ids[i])) /* this one is already provided */ continue; if (!repodata_filelistfilter_matches(data, pool_id2str(repo->pool, cbd->ids[i]))) break; } if (i < cbd->nfiles) { /* nope, need to search the extensions as well. postpone. */ for (p = start; p < end; p++) { if (data->incoreoffset[p - data->start] && MAPTST(cbd->todo, p - repo->start)) { if (!postpone->size) map_grow(postpone, repo->nsolvables); MAPSET(postpone, p - repo->start); MAPCLR(cbd->todo, p - repo->start); } } prune_todo_range(repo, cbd); return; } /* now check if there is no data marked withour EXTENSION */ /* limit todo to the solvables in this repodata */ old_todo_start = cbd->todo_start; old_todo_end = cbd->todo_end; old_todo = *cbd->todo; map_init(cbd->todo, repo->nsolvables); for (p = start; p < end; p++) if (data->incoreoffset[p - data->start] && MAPTST(&old_todo, p - repo->start)) { MAPCLR(&old_todo, p - repo->start); MAPSET(cbd->todo, p - repo->start); } prune_todo_range(repo, cbd); /* do the check */ for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > filteredid ; rdid--, data--) { if (data->filelisttype == REPODATA_FILELIST_EXTENSION) continue; if (data->start >= cbd->todo_end || data->end <= cbd->todo_start) continue; if (!repodata_has_keyname(data, SOLVABLE_FILELIST)) continue; if (!repodata_intersects_todo(data, cbd)) continue; /* oh no, this filelist data is not tagged with REPODATA_FILELIST_EXTENSION! */ /* postpone entries that have filelist data */ start = cbd->todo_start > data->start ? cbd->todo_start : data->start; end = cbd->todo_end > data->end ? data->end : cbd->todo_end; for (p = start; p < end; p++) if (MAPTST(cbd->todo, p - repo->start)) if (repodata_lookup_type(data, p, SOLVABLE_FILELIST)) { if (!postpone->size) map_grow(postpone, repo->nsolvables); MAPSET(postpone, p - repo->start); MAPCLR(cbd->todo, p - repo->start); } prune_todo_range(repo, cbd); if (cbd->todo_start >= cbd->todo_end) break; } /* do the search over the filtered file list with the remaining entries*/ if (cbd->todo_start < cbd->todo_end) repodata_addfileprovides_search(repo->repodata + filteredid, cbd); /* restore todo map */ map_free(cbd->todo); *cbd->todo = old_todo; cbd->todo_start = old_todo_start; cbd->todo_end = old_todo_end; prune_todo_range(repo, cbd); }
static void repodata_addfileprovides_search(Repodata *data, struct addfileprovides_cbdata *cbd) { Repo *repo = data->repo; int i, p, start, end; Map useddirs; Map *providedids = 0; /* make it available */ if (data->state == REPODATA_STUB) repodata_load(data); if (data->state != REPODATA_AVAILABLE) return; if (!data->incoredata || !data->dirpool.ndirs) return; start = cbd->todo_start > data->start ? cbd->todo_start : data->start; end = cbd->todo_end > data->end ? data->end : cbd->todo_end; if (start >= end) return; /* deal with provideids overlap */ if (cbd->providedids) { if (start >= cbd->provstart && end <= cbd->provend) providedids = cbd->providedids; /* complete overlap */ else if (start < cbd->provend && end > cbd->provstart) { /* partial overlap, need to split search */ if (start < cbd->provstart) { repodata_addfileprovides_search_limited(data, cbd, start, cbd->provstart); start = cbd->provstart; } if (end > cbd->provend) { repodata_addfileprovides_search_limited(data, cbd, cbd->provend, end); end = cbd->provend; } if (start < end) repodata_addfileprovides_search_limited(data, cbd, start, end); return; } } /* set up dirs and names array if not already done */ if (!cbd->dirs) create_dirs_names_array(cbd, repo->pool); /* set up useddirs map and the cbd->dids array */ map_init(&useddirs, data->dirpool.ndirs); for (i = 0; i < cbd->nfiles; i++) { Id did; if (providedids && MAPTST(providedids, cbd->ids[i])) { cbd->dids[i] = 0; /* already included, do not add again */ continue; } cbd->dids[i] = did = repodata_str2dir(data, cbd->dirs[i], 0); if (did) MAPSET(&useddirs, did); } repodata_free_dircache(data); /* repodata_str2dir created it */ for (p = start; p < end; p++) { const unsigned char *dp; Solvable *s; if (!MAPTST(cbd->todo, p - repo->start)) continue; dp = repodata_lookup_packed_dirstrarray(data, p, SOLVABLE_FILELIST); if (!dp) continue; /* now iterate through the packed array */ s = repo->pool->solvables + p; MAPCLR(cbd->todo, p - repo->start); /* this entry is done */ for (;;) { Id did = 0; int c; while ((c = *dp++) & 0x80) did = (did << 7) ^ c ^ 0x80; did = (did << 6) | (c & 0x3f); if ((unsigned int)did < (unsigned int)data->dirpool.ndirs && MAPTST(&useddirs, did)) { /* there is at least one entry with that did */ for (i = 0; i < cbd->nfiles; i++) if (cbd->dids[i] == did && !strcmp(cbd->names[i], (const char *)dp)) s->provides = repo_addid_dep(s->repo, s->provides, cbd->ids[i], SOLVABLE_FILEMARKER); } if (!(c & 0x40)) break; dp += strlen((const char *)dp) + 1; } } map_free(&useddirs); prune_todo_range(repo, cbd); }
static void prune_to_recommended(Solver *solv, Queue *plist) { Pool *pool = solv->pool; int i, j, k, ninst; Solvable *s; Id p, pp, rec, *recp, sug, *sugp; ninst = 0; if (pool->installed) { for (i = 0; i < plist->count; i++) { p = plist->elements[i]; s = pool->solvables + p; if (pool->installed && s->repo == pool->installed) ninst++; } } if (plist->count - ninst < 2) return; /* update our recommendsmap/suggestsmap */ if (solv->recommends_index < 0) { MAPZERO(&solv->recommendsmap); MAPZERO(&solv->suggestsmap); solv->recommends_index = 0; } while (solv->recommends_index < solv->decisionq.count) { p = solv->decisionq.elements[solv->recommends_index++]; if (p < 0) continue; s = pool->solvables + p; if (s->recommends) { recp = s->repo->idarraydata + s->recommends; while ((rec = *recp++) != 0) FOR_PROVIDES(p, pp, rec) MAPSET(&solv->recommendsmap, p); } if (s->suggests) { sugp = s->repo->idarraydata + s->suggests; while ((sug = *sugp++) != 0) FOR_PROVIDES(p, pp, sug) MAPSET(&solv->suggestsmap, p); } } /* prune to recommended/supplemented */ ninst = 0; for (i = j = 0; i < plist->count; i++) { p = plist->elements[i]; s = pool->solvables + p; if (pool->installed && s->repo == pool->installed) { ninst++; if (j) plist->elements[j++] = p; continue; } if (!MAPTST(&solv->recommendsmap, p)) if (!solver_is_supplementing(solv, s)) continue; if (!j && ninst) { for (k = 0; j < ninst; k++) { s = pool->solvables + plist->elements[k]; if (pool->installed && s->repo == pool->installed) plist->elements[j++] = plist->elements[k]; } } plist->elements[j++] = p; } if (j) plist->count = j; /* anything left to prune? */ if (plist->count - ninst < 2) return; /* prune to suggested/enhanced */ ninst = 0; for (i = j = 0; i < plist->count; i++) { p = plist->elements[i]; s = pool->solvables + p; if (pool->installed && s->repo == pool->installed) { ninst++; if (j) plist->elements[j++] = p; continue; } if (!MAPTST(&solv->suggestsmap, p)) if (!solver_is_enhancing(solv, s)) continue; if (!j && ninst) { for (k = 0; j < ninst; k++) { s = pool->solvables + plist->elements[k]; if (pool->installed && s->repo == pool->installed) plist->elements[j++] = plist->elements[k]; } } plist->elements[j++] = p; } if (j) plist->count = j; }
/* same as findfileconflicts_cb, but * - hashes with just the basename * - sets idx in a map instead of pushing to lookat * - sets the hash element to -1 if there may be a conflict */ static void findfileconflicts_basename_cb(void *cbdatav, const char *fn, struct filelistinfo *info) { struct cbdata *cbdata = cbdatav; int isdir = S_ISDIR(info->mode); const char *dp; Id idx, oidx; Id hx, qx; Hashval h, hh; idx = cbdata->idx; if (!info->dirlen) return; dp = fn + info->dirlen; hx = strhash(dp); if (!hx) hx = strlen(fn) + 1; h = hx & cbdata->cflmapn; hh = HASHCHAIN_START; for (;;) { qx = cbdata->cflmap[2 * h]; if (!qx) break; if (qx == hx) break; h = HASHCHAIN_NEXT(h, hh, cbdata->cflmapn); } if (!qx) { /* a miss */ if (!cbdata->create) return; cbdata->cflmap[2 * h] = hx; cbdata->cflmap[2 * h + 1] = (isdir ? -idx - 2 : idx); if (++cbdata->cflmapused * 2 > cbdata->cflmapn) cbdata->cflmap = growhash(cbdata->cflmap, &cbdata->cflmapn); return; } oidx = cbdata->cflmap[2 * h + 1]; if (oidx < -1) { int i; if (isdir) { /* both are directories. delay the conflict, keep oidx in slot */ queue_push2(&cbdata->lookat_dir, hx, idx); return; } oidx = -idx - 2; /* now have file, had directories before. */ cbdata->cflmap[2 * h + 1] = oidx; /* make it a file */ /* dump all delayed directory hits for hx */ for (i = 0; i < cbdata->lookat_dir.count; i += 2) if (cbdata->lookat_dir.elements[i] == hx) MAPSET(&cbdata->idxmap, cbdata->lookat_dir.elements[i + 1]); } else if (oidx == idx) return; /* no conflicts with ourself, please */ if (oidx >= 0) MAPSET(&cbdata->idxmap, oidx); MAPSET(&cbdata->idxmap, idx); if (oidx != -1) cbdata->cflmap[2 * h + 1] = -1; }