static Hashtable joinhash_init(Repo *repo, Hashval *hmp) { Hashval hm = mkmask(repo->nsolvables); Hashtable ht = solv_calloc(hm + 1, sizeof(*ht)); Hashval h, hh; Solvable *s; int i; FOR_REPO_SOLVABLES(repo, i, s) { hh = HASHCHAIN_START; h = s->name & hm; while (ht[h]) h = HASHCHAIN_NEXT(h, hh, hm); ht[h] = i; }
Id pool_rel2id(Pool *pool, Id name, Id evr, int flags, int create) { Hashval h, hh, hashmask; int i; Id id; Hashtable hashtbl; Reldep *ran; hashmask = pool->relhashmask; hashtbl = pool->relhashtbl; ran = pool->rels; /* extend hashtable if needed */ if (pool->nrels * 2 > hashmask) { solv_free(pool->relhashtbl); pool->relhashmask = hashmask = mkmask(pool->nrels + REL_BLOCK); pool->relhashtbl = hashtbl = solv_calloc(hashmask + 1, sizeof(Id)); /* rehash all rels into new hashtable */ for (i = 1; i < pool->nrels; i++) { h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask; hh = HASHCHAIN_START; while (hashtbl[h]) h = HASHCHAIN_NEXT(h, hh, hashmask); hashtbl[h] = i; } } /* compute hash and check for match */ h = relhash(name, evr, flags) & hashmask; hh = HASHCHAIN_START; while ((id = hashtbl[h]) != 0) { if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags) break; h = HASHCHAIN_NEXT(h, hh, hashmask); } if (id) return MAKERELDEP(id); if (!create) return ID_NULL; id = pool->nrels++; /* extend rel space if needed */ pool->rels = solv_extend(pool->rels, id, 1, sizeof(Reldep), REL_BLOCK); hashtbl[h] = id; ran = pool->rels + id; ran->name = name; ran->evr = evr; ran->flags = flags; /* extend whatprovides_rel if needed */ if (pool->whatprovides_rel && (id & WHATPROVIDES_BLOCK) == 0) { pool->whatprovides_rel = solv_realloc2(pool->whatprovides_rel, id + (WHATPROVIDES_BLOCK + 1), sizeof(Offset)); memset(pool->whatprovides_rel + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset)); } return MAKERELDEP(id); }
/* * Optimization for packages with an excessive amount of provides/requires: * if the number of deps exceed a threshold, we build a hash of the already * seen ids. */ static Offset repo_addid_dep_hash(Repo *repo, Offset olddeps, Id id, Id marker, int size) { Id oid, *oidp; int before; Hashval h, hh; Id hid; before = 0; if (marker) { if (marker < 0) { marker = -marker; before = 1; } if (marker == id) marker = 0; } /* maintain hash and lastmarkerpos */ if (repo->lastidhash_idarraysize != repo->idarraysize || size * 2 > repo->lastidhash_mask || repo->lastmarker != marker) { repo->lastmarkerpos = 0; if (size * 2 > repo->lastidhash_mask) { repo->lastidhash_mask = mkmask(size < REPO_ADDID_DEP_HASHMIN ? REPO_ADDID_DEP_HASHMIN : size); repo->lastidhash = solv_realloc2(repo->lastidhash, repo->lastidhash_mask + 1, sizeof(Id)); } memset(repo->lastidhash, 0, (repo->lastidhash_mask + 1) * sizeof(Id)); for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != 0; oidp++) { h = oid & repo->lastidhash_mask; hh = HASHCHAIN_START; while (repo->lastidhash[h] != 0) h = HASHCHAIN_NEXT(h, hh, repo->lastidhash_mask); repo->lastidhash[h] = oid; if (marker && oid == marker) repo->lastmarkerpos = oidp - repo->idarraydata; } repo->lastmarker = marker; repo->lastidhash_idarraysize = repo->idarraysize; } /* check the hash! */ h = id & repo->lastidhash_mask; hh = HASHCHAIN_START; while ((hid = repo->lastidhash[h]) != 0 && hid != id) h = HASHCHAIN_NEXT(h, hh, repo->lastidhash_mask); /* put new element in hash */ if (!hid) repo->lastidhash[h] = id; else if (marker == SOLVABLE_FILEMARKER && (!before || !repo->lastmarkerpos)) return olddeps; if (marker && !before && !repo->lastmarkerpos) { /* we have to add the marker first */ repo->lastmarkerpos = repo->idarraysize - 1; olddeps = repo_addid(repo, olddeps, marker); /* now put marker in hash */ h = marker & repo->lastidhash_mask; hh = HASHCHAIN_START; while (repo->lastidhash[h] != 0) h = HASHCHAIN_NEXT(h, hh, repo->lastidhash_mask); repo->lastidhash[h] = marker; repo->lastidhash_idarraysize = repo->idarraysize; } if (!hid) { /* new entry, insert in correct position */ if (marker && before && repo->lastmarkerpos) { /* need to add it before the marker */ olddeps = repo_addid(repo, olddeps, id); /* dummy to make room */ memmove(repo->idarraydata + repo->lastmarkerpos + 1, repo->idarraydata + repo->lastmarkerpos, (repo->idarraysize - repo->lastmarkerpos - 2) * sizeof(Id)); repo->idarraydata[repo->lastmarkerpos++] = id; } else { /* just append it to the end */ olddeps = repo_addid(repo, olddeps, id); } repo->lastidhash_idarraysize = repo->idarraysize; return olddeps; } /* we already have it in the hash */ if (!marker) return olddeps; if (marker == SOLVABLE_FILEMARKER) { /* check if it is in the wrong half */ /* (we already made sure that "before" and "lastmarkerpos" are set, see above) */ for (oidp = repo->idarraydata + repo->lastmarkerpos + 1; (oid = *oidp) != 0; oidp++) if (oid == id) break; if (!oid) return olddeps; /* yes, wrong half. copy it over */ memmove(repo->idarraydata + repo->lastmarkerpos + 1, repo->idarraydata + repo->lastmarkerpos, (oidp - (repo->idarraydata + repo->lastmarkerpos)) * sizeof(Id)); repo->idarraydata[repo->lastmarkerpos++] = id; return olddeps; } if (before) return olddeps; /* check if it is in the correct half */ for (oidp = repo->idarraydata + repo->lastmarkerpos + 1; (oid = *oidp) != 0; oidp++) if (oid == id) return olddeps; /* nope, copy it over */ for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != 0; oidp++) if (oid == id) break; if (!oid) return olddeps; /* should not happen */ memmove(oidp, oidp + 1, (repo->idarraydata + repo->idarraysize - oidp - 2) * sizeof(Id)); repo->idarraydata[repo->idarraysize - 2] = id; repo->lastmarkerpos--; /* marker has been moved */ return olddeps; }