void map_insert(Map* map, char key, void* value) { int start = hash(key) % map->length; int end = start ? start : map->length; int i; for (i = start; i != end - 1; i = (i + 1) % map->length) { if (key == map->items[i].key || !map->items[i].value) { map->items[i].key = key; map->items[i].value = value; return; } } map_grow(map); map_insert(map, key, value); }
void sack_recompute_considered(HySack sack) { Pool *pool = sack_pool(sack); if (sack->considered_uptodate) return; if (!pool->considered) { if (!sack->repo_excludes && !sack->pkg_excludes) return; pool->considered = solv_calloc(1, sizeof(Map)); map_init(pool->considered, pool->nsolvables); } else map_grow(pool->considered, pool->nsolvables); // considered = (all - repo_excludes - pkg_excludes) and pkg_includes map_setall(pool->considered); if (sack->repo_excludes) map_subtract(pool->considered, sack->repo_excludes); if (sack->pkg_excludes) map_subtract(pool->considered, sack->pkg_excludes); if (sack->pkg_includes) map_and(pool->considered, sack->pkg_includes); sack->considered_uptodate = 1; }
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 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); }