diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bitmap.c | 20 | ||||
-rw-r--r-- | src/bitmap.h | 8 | ||||
-rw-r--r-- | src/cleandeps.c | 13 | ||||
-rw-r--r-- | src/libsolv.ver | 4 | ||||
-rw-r--r-- | src/policy.c | 20 | ||||
-rw-r--r-- | src/pool.c | 2 | ||||
-rw-r--r-- | src/pool.h | 6 | ||||
-rw-r--r-- | src/poolarch.c | 7 | ||||
-rw-r--r-- | src/poolarch.h | 6 | ||||
-rw-r--r-- | src/poolid.c | 67 | ||||
-rw-r--r-- | src/poolid.h | 1 | ||||
-rw-r--r-- | src/problems.c | 2 | ||||
-rw-r--r-- | src/queue.c | 22 | ||||
-rw-r--r-- | src/queue.h | 4 | ||||
-rw-r--r-- | src/repo.h | 5 | ||||
-rw-r--r-- | src/repo_solv.c | 69 | ||||
-rw-r--r-- | src/repo_write.c | 154 | ||||
-rw-r--r-- | src/repodata.c | 93 | ||||
-rw-r--r-- | src/repodata.h | 3 | ||||
-rw-r--r-- | src/rules.c | 54 | ||||
-rw-r--r-- | src/selection.c | 6 | ||||
-rw-r--r-- | src/solvversion.h.in | 1 | ||||
-rw-r--r-- | src/strpool.c | 50 | ||||
-rw-r--r-- | src/strpool.h | 1 |
24 files changed, 295 insertions, 323 deletions
diff --git a/src/bitmap.c b/src/bitmap.c index e004bf2..4e8adbd 100644 --- a/src/bitmap.c +++ b/src/bitmap.c @@ -32,18 +32,18 @@ map_free(Map *m) m->size = 0; } -/* copy constructor t <- s */ +/* copy constructor target <- source */ void -map_init_clone(Map *t, Map *s) +map_init_clone(Map *target, const Map *source) { - t->size = s->size; - if (s->size) + target->size = source->size; + if (source->size) { - t->map = solv_malloc(s->size); - memcpy(t->map, s->map, s->size); + target->map = solv_malloc(source->size); + memcpy(target->map, source->map, source->size); } else - t->map = 0; + target->map = 0; } /* grow a map */ @@ -61,7 +61,7 @@ map_grow(Map *m, int n) /* bitwise-ands maps t and s, stores the result in t. */ void -map_and(Map *t, Map *s) +map_and(Map *t, const Map *s) { unsigned char *ti, *si, *end; ti = t->map; @@ -73,7 +73,7 @@ map_and(Map *t, Map *s) /* bitwise-ors maps t and s, stores the result in t. */ void -map_or(Map *t, Map *s) +map_or(Map *t, const Map *s) { unsigned char *ti, *si, *end; if (t->size < s->size) @@ -87,7 +87,7 @@ map_or(Map *t, Map *s) /* remove all set bits in s from t. */ void -map_subtract(Map *t, Map *s) +map_subtract(Map *t, const Map *s) { unsigned char *ti, *si, *end; ti = t->map; diff --git a/src/bitmap.h b/src/bitmap.h index 0050a6a..1e89590 100644 --- a/src/bitmap.h +++ b/src/bitmap.h @@ -37,12 +37,12 @@ typedef struct _Map { #define MAPCLR_AT(m, n) ((m)->map[(n) >> 3] = 0) extern void map_init(Map *m, int n); -extern void map_init_clone(Map *t, Map *s); +extern void map_init_clone(Map *target, const Map *source); extern void map_grow(Map *m, int n); extern void map_free(Map *m); -extern void map_and(Map *t, Map *s); -extern void map_or(Map *t, Map *s); -extern void map_subtract(Map *t, Map *s); +extern void map_and(Map *t, const Map *s); +extern void map_or(Map *t, const Map *s); +extern void map_subtract(Map *t, const Map *s); extern void map_invertall(Map *m); static inline void map_empty(Map *m) diff --git a/src/cleandeps.c b/src/cleandeps.c index cbe2020..1da28f6 100644 --- a/src/cleandeps.c +++ b/src/cleandeps.c @@ -1122,23 +1122,22 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded) #endif if (s->repo == installed && pool->implicitobsoleteusescolors) { - Id a, bestarch = 0; + unsigned int a, bestscore = 0; FOR_PROVIDES(p, pp, s->name) { Solvable *ps = pool->solvables + p; if (ps->name != s->name || ps->repo == installed) continue; - a = ps->arch; - a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; - if (a && a != 1 && (!bestarch || a < bestarch)) - bestarch = a; + a = pool_arch2score(pool, ps->arch); + if (a && a != 1 && (!bestscore || a < bestscore)) + bestscore = a; } - if (bestarch && (s->arch > pool->lastarch || pool->id2arch[s->arch] != bestarch)) + if (bestscore && pool_arch2score(pool, s->arch) != bestscore) { FOR_PROVIDES(p, pp, s->name) { Solvable *ps = pool->solvables + p; - if (ps->repo == installed && ps->name == s->name && ps->evr == s->evr && ps->arch != s->arch && ps->arch < pool->lastarch && pool->id2arch[ps->arch] == bestarch) + if (ps->repo == installed && ps->name == s->name && ps->evr == s->evr && ps->arch != s->arch && pool_arch2score(pool, ps->arch) == bestscore) if (!MAPTST(&im, p)) { #ifdef CLEANDEPSDEBUG diff --git a/src/libsolv.ver b/src/libsolv.ver index 9adf60d..a3fa19a 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -431,3 +431,7 @@ SOLV_1.2 { pool_set_whatprovides; selection_subtract; } SOLV_1.1; + +SOLV_1.3 { + repodata_set_kv; +} SOLV_1.2; diff --git a/src/policy.c b/src/policy.c index 6f06101..a38dea0 100644 --- a/src/policy.c +++ b/src/policy.c @@ -56,11 +56,11 @@ prune_to_best_version_sortcmp(const void *ap, const void *bp, void *dp) } if (sa->arch != sb->arch) { - int aa, ab; - aa = (sa->arch <= pool->lastarch) ? pool->id2arch[sa->arch] : 0; - ab = (sb->arch <= pool->lastarch) ? pool->id2arch[sb->arch] : 0; + unsigned int aa, ab; + aa = pool_arch2score(pool, sa->arch); + ab = pool_arch2score(pool, sb->arch); if (aa != ab && aa > 1 && ab > 1) - return aa - ab; /* lowest score first */ + return aa < ab ? -1 : 1; /* lowest score first */ } /* the same name, bring installed solvables to the front */ @@ -646,8 +646,7 @@ prune_to_best_arch(const Pool *pool, Queue *plist) for (i = 0; i < plist->count; i++) { s = pool->solvables + plist->elements[i]; - a = s->arch; - a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; + a = pool_arch2score(pool, s->arch); if (a && a != 1 && (!bestscore || a < bestscore)) bestscore = a; } @@ -656,10 +655,9 @@ prune_to_best_arch(const Pool *pool, Queue *plist) for (i = j = 0; i < plist->count; i++) { s = pool->solvables + plist->elements[i]; - a = s->arch; - if (a > pool->lastarch) + a = pool_arch2score(pool, s->arch); + if (!a) continue; - a = pool->id2arch[a]; /* a == 1 -> noarch */ if (a != 1 && ((a ^ bestscore) & 0xffff0000) != 0) continue; @@ -1383,8 +1381,8 @@ policy_illegal_archchange(Solver *solv, Solvable *s1, Solvable *s2) return 0; if (!pool->id2arch) return 0; - a1 = a1 <= pool->lastarch ? pool->id2arch[a1] : 0; - a2 = a2 <= pool->lastarch ? pool->id2arch[a2] : 0; + a1 = pool_arch2score(pool, a1); + a2 = pool_arch2score(pool, a2); if (((a1 ^ a2) & 0xffff0000) != 0) return 1; return 0; @@ -44,7 +44,7 @@ pool_create(void) pool = (Pool *)solv_calloc(1, sizeof(*pool)); - stringpool_init (&pool->ss, initpool_data); + stringpool_init(&pool->ss, initpool_data); /* alloc space for RelDep 0 */ pool->rels = solv_extend_resize(0, 1, sizeof(Reldep), REL_BLOCK); @@ -88,7 +88,7 @@ struct _Pool { Id *id2arch; /* map arch ids to scores */ unsigned char *id2color; /* map arch ids to colors */ - Id lastarch; /* last valid entry in id2arch/id2color */ + Id lastarch; /* size of the id2arch/id2color arrays */ Queue vendormap; /* map vendor to vendorclasses mask */ const char **vendorclasses; /* vendor equivalence classes */ @@ -282,6 +282,10 @@ static inline Solvable *pool_id2solvable(const Pool *pool, Id p) { return pool->solvables + p; } +static inline Id pool_solvable2id(const Pool *pool, Solvable *s) +{ + return s - pool->solvables; +} extern const char *pool_solvable2str(Pool *pool, Solvable *s); static inline const char *pool_solvid2str(Pool *pool, Id p) diff --git a/src/poolarch.c b/src/poolarch.c index 8da16c1..4a1fa50 100644 --- a/src/poolarch.c +++ b/src/poolarch.c @@ -104,6 +104,9 @@ pool_setarchpolicy(Pool *pool, const char *arch) } id = pool->noarchid; lastarch = id + 255; + /* note that we overallocate one element to be compatible with + * old versions that accessed id2arch[lastarch]. + * id2arch[lastarch] will always be zero */ id2arch = solv_calloc(lastarch + 1, sizeof(Id)); id2arch[id] = 1; /* the "noarch" class */ @@ -114,7 +117,7 @@ pool_setarchpolicy(Pool *pool, const char *arch) if (l) { id = pool_strn2id(pool, arch, l, 1); - if (id > lastarch) + if (id >= lastarch) { id2arch = solv_realloc2(id2arch, (id + 255 + 1), sizeof(Id)); memset(id2arch + lastarch + 1, 0, (id + 255 - lastarch) * sizeof(Id)); @@ -143,7 +146,7 @@ pool_arch2color_slow(Pool *pool, Id arch) const char *s; unsigned char color; - if (arch > pool->lastarch) + if ((unsigned int)arch >= (unsigned int)pool->lastarch) return ARCHCOLOR_ALL; if (!pool->id2color) pool->id2color = solv_calloc(pool->lastarch + 1, 1); diff --git a/src/poolarch.h b/src/poolarch.h index 3fe5f02..787883b 100644 --- a/src/poolarch.h +++ b/src/poolarch.h @@ -24,7 +24,7 @@ extern unsigned char pool_arch2color_slow(Pool *pool, Id arch); static inline unsigned char pool_arch2color(Pool *pool, Id arch) { - if (arch > pool->lastarch) + if ((unsigned int)arch >= (unsigned int)pool->lastarch) return ARCHCOLOR_ALL; if (pool->id2color && pool->id2color[arch]) return pool->id2color[arch]; @@ -40,6 +40,10 @@ static inline int pool_colormatch(Pool *pool, Solvable *s1, Solvable *s2) return 0; } +static inline unsigned int pool_arch2score(const Pool *pool, Id arch) { + return (unsigned int)arch < (unsigned int)pool->lastarch ? (unsigned int)pool->id2arch[arch] : 0; +} + #ifdef __cplusplus } #endif diff --git a/src/poolid.c b/src/poolid.c index bb8d4f6..3b55f76 100644 --- a/src/poolid.c +++ b/src/poolid.c @@ -51,39 +51,58 @@ pool_strn2id(Pool *pool, const char *str, unsigned int len, int create) return id; } +void +pool_resize_rels_hash(Pool *pool, int numnew) +{ + Hashval h, hh, hashmask; + Hashtable hashtbl; + int i; + Reldep *rd; + + if (numnew <= 0) + return; + hashmask = mkmask(pool->nrels + numnew); + if (hashmask <= pool->relhashmask) + return; /* same as before */ + + /* realloc hash table */ + pool->relhashmask = hashmask; + solv_free(pool->relhashtbl); + pool->relhashtbl = hashtbl = solv_calloc(hashmask + 1, sizeof(Id)); + + /* rehash all rels into new hashtable */ + for (i = 1, rd = pool->rels + i; i < pool->nrels; i++, rd++) + { + h = relhash(rd->name, rd->evr, rd->flags) & hashmask; + hh = HASHCHAIN_START; + while (hashtbl[h]) + h = HASHCHAIN_NEXT(h, hh, hashmask); + hashtbl[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 */ + hashmask = pool->relhashmask; if ((Hashval)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; - } + pool_resize_rels_hash(pool, REL_BLOCK); + hashmask = pool->relhashmask; } + hashtbl = pool->relhashtbl; /* compute hash and check for match */ h = relhash(name, evr, flags) & hashmask; hh = HASHCHAIN_START; + ran = pool->rels; while ((id = hashtbl[h]) != 0) { if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags) @@ -297,15 +316,28 @@ pool_dep2str(Pool *pool, Id id) return p; } +static void +pool_free_rels_hash(Pool *pool) +{ + pool->relhashtbl = solv_free(pool->relhashtbl); + pool->relhashmask = 0; +} + void pool_shrink_strings(Pool *pool) { + /* free excessive big hashes */ + if (pool->ss.stringhashmask && pool->ss.stringhashmask > mkmask(pool->ss.nstrings + 8192)) + stringpool_freehash(&pool->ss); stringpool_shrink(&pool->ss); } void pool_shrink_rels(Pool *pool) { + /* free excessive big hashes */ + if (pool->relhashmask && pool->relhashmask > mkmask(pool->nrels + 4096)) + pool_free_rels_hash(pool); pool->rels = solv_extend_resize(pool->rels, pool->nrels, sizeof(Reldep), REL_BLOCK); } @@ -314,8 +346,7 @@ void pool_freeidhashes(Pool *pool) { stringpool_freehash(&pool->ss); - pool->relhashtbl = solv_free(pool->relhashtbl); - pool->relhashmask = 0; + pool_free_rels_hash(pool); } /* EOF */ diff --git a/src/poolid.h b/src/poolid.h index 2363595..79a3ccd 100644 --- a/src/poolid.h +++ b/src/poolid.h @@ -41,6 +41,7 @@ extern const char *pool_dep2str(Pool *pool, Id); /* might alloc tmpspace */ extern void pool_shrink_strings(Pool *pool); extern void pool_shrink_rels(Pool *pool); extern void pool_freeidhashes(Pool *pool); +extern void pool_resize_rels_hash(Pool *pool, int numnew); #ifdef __cplusplus } diff --git a/src/problems.c b/src/problems.c index 5bd2bf5..df751c4 100644 --- a/src/problems.c +++ b/src/problems.c @@ -1281,7 +1281,7 @@ solver_problemruleinfo2str(Solver *solv, SolverRuleinfo type, Id source, Id targ if (pool_disabled_solvable(pool, ss)) return pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " is disabled"); if (ss->arch && ss->arch != ARCH_SRC && ss->arch != ARCH_NOSRC && - pool->id2arch && (ss->arch > pool->lastarch || !pool->id2arch[ss->arch])) + pool->id2arch && pool_arch2score(pool, ss->arch) == 0) return pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " does not have a compatible architecture"); return pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " is not installable"); case SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP: diff --git a/src/queue.c b/src/queue.c index ceb1062..6d5e531 100644 --- a/src/queue.c +++ b/src/queue.c @@ -36,21 +36,21 @@ queue_init(Queue *q) } void -queue_init_clone(Queue *t, Queue *s) +queue_init_clone(Queue *target, const Queue *source) { int extra_space; - if (!s->elements) + if (!source->elements) { - t->alloc = t->elements = 0; - t->count = t->left = 0; + target->alloc = target->elements = 0; + target->count = target->left = 0; return; } - extra_space = queue_extra_space(s->count); - t->alloc = t->elements = solv_malloc2(s->count + extra_space, sizeof(Id)); - if (s->count) - memcpy(t->alloc, s->elements, s->count * sizeof(Id)); - t->count = s->count; - t->left = extra_space; + extra_space = queue_extra_space(source->count); + target->alloc = target->elements = solv_malloc2(source->count + extra_space, sizeof(Id)); + if (source->count) + memcpy(target->alloc, source->elements, source->count * sizeof(Id)); + target->count = source->count; + target->left = extra_space; } void @@ -168,7 +168,7 @@ queue_delete2(Queue *q, int pos) } void -queue_insertn(Queue *q, int pos, int n, Id *elements) +queue_insertn(Queue *q, int pos, int n, const Id *elements) { if (n <= 0) return; diff --git a/src/queue.h b/src/queue.h index 4785e67..7e56035 100644 --- a/src/queue.h +++ b/src/queue.h @@ -109,12 +109,12 @@ queue_truncate(Queue *q, int n) extern void queue_init(Queue *q); extern void queue_init_buffer(Queue *q, Id *buf, int size); -extern void queue_init_clone(Queue *t, Queue *s); +extern void queue_init_clone(Queue *target, const Queue *source); extern void queue_free(Queue *q); extern void queue_insert(Queue *q, int pos, Id id); extern void queue_insert2(Queue *q, int pos, Id id1, Id id2); -extern void queue_insertn(Queue *q, int pos, int n, Id *elements); +extern void queue_insertn(Queue *q, int pos, int n, const Id *elements); extern void queue_delete(Queue *q, int pos); extern void queue_delete2(Queue *q, int pos); extern void queue_deleten(Queue *q, int pos, int n); @@ -15,6 +15,7 @@ #include "pooltypes.h" #include "pool.h" +#include "poolarch.h" #include "repodata.h" #include "dataiterator.h" #include "hash.h" @@ -102,7 +103,7 @@ static inline int pool_badarch_solvable(const Pool *pool, Solvable *s) { if (!s->arch) return 1; - if (pool->id2arch && (s->arch > pool->lastarch || !pool->id2arch[s->arch])) + if (pool->id2arch && pool_arch2score(pool, s->arch) == 0) return 1; return 0; } @@ -113,7 +114,7 @@ static inline int pool_installable(const Pool *pool, Solvable *s) return 0; if (s->repo && s->repo->disabled) return 0; - if (pool->id2arch && (s->arch > pool->lastarch || !pool->id2arch[s->arch])) + if (pool->id2arch && pool_arch2score(pool, s->arch) == 0) return 0; if (pool->considered) { diff --git a/src/repo_solv.c b/src/repo_solv.c index 2460e30..5858d4f 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -223,7 +223,7 @@ data_read_idarray(unsigned char *dp, Id **storep, Id *map, int max, Repodata *da data->error = SOLV_ERROR_ID_RANGE; break; } - *store++ = x; + *store++ = map ? map[x] : x; if ((c & 64) == 0) break; x = 0; @@ -612,7 +612,7 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) unsigned int pfsize = read_u32(&data); char *prefix = solv_malloc(pfsize); char *pp = prefix; - char *old_str = 0; + char *old_str = strsp; char *dest = strsp; int freesp = sizeid; @@ -682,35 +682,16 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) /* alloc id map for name and rel Ids. this maps ids in the solv files * to the ids in our pool */ idmap = solv_calloc(numid + numrel, sizeof(Id)); - - /* grow hash if needed, otherwise reuse */ - hashmask = mkmask(spool->nstrings + numid); + stringpool_resize_hash(spool, numid); + hashtbl = spool->stringhashtbl; + hashmask = spool->stringhashmask; #if 0 POOL_DEBUG(SOLV_DEBUG_STATS, "read %d strings\n", numid); - POOL_DEBUG(SOLV_DEBUG_STATS, "string hash buckets: %d, old %d\n", hashmask + 1, spool->stringhashmask + 1); + POOL_DEBUG(SOLV_DEBUG_STATS, "string hash buckets: %d\n", hashmask + 1); #endif - if (hashmask > spool->stringhashmask) - { - spool->stringhashtbl = solv_free(spool->stringhashtbl); - spool->stringhashmask = hashmask; - spool->stringhashtbl = hashtbl = solv_calloc(hashmask + 1, sizeof(Id)); - for (i = 1; i < spool->nstrings; i++) - { - h = strhash(spool->stringspace + spool->strings[i]) & hashmask; - hh = HASHCHAIN_START; - while (hashtbl[h]) - h = HASHCHAIN_NEXT(h, hh, hashmask); - hashtbl[h] = i; - } - } - else - { - hashtbl = spool->stringhashtbl; - hashmask = spool->stringhashmask; - } - /* * run over strings and merge with pool. + * we could use stringpool_str2id, but this is faster. * also populate id map (maps solv Id -> pool Id) */ for (i = 1; i < numid; i++) @@ -758,11 +739,6 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) idmap[i] = id; /* repo relative -> pool relative */ sp += l; /* next string */ } - if (hashmask > mkmask(spool->nstrings + 8192)) - { - spool->stringhashtbl = solv_free(spool->stringhashtbl); - spool->stringhashmask = 0; - } stringpool_shrink(spool); /* vacuum */ } @@ -780,31 +756,13 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) pool->rels = solv_realloc2(pool->rels, pool->nrels + numrel, sizeof(Reldep)); ran = pool->rels; - /* grow hash if needed, otherwise reuse */ - hashmask = mkmask(pool->nrels + numrel); + pool_resize_rels_hash(pool, numrel); + hashtbl = pool->relhashtbl; + hashmask = pool->relhashmask; #if 0 POOL_DEBUG(SOLV_DEBUG_STATS, "read %d rels\n", numrel); - POOL_DEBUG(SOLV_DEBUG_STATS, "rel hash buckets: %d, old %d\n", hashmask + 1, pool->relhashmask + 1); + POOL_DEBUG(SOLV_DEBUG_STATS, "rel hash buckets: %d\n", hashmask + 1); #endif - if (hashmask > pool->relhashmask) - { - pool->relhashtbl = solv_free(pool->relhashtbl); - pool->relhashmask = hashmask; - pool->relhashtbl = hashtbl = solv_calloc(hashmask + 1, sizeof(Id)); - 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; - } - } - else - { - hashtbl = pool->relhashtbl; - hashmask = pool->relhashmask; - } /* * read RelDeps from repo @@ -837,11 +795,6 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) } idmap[i + numid] = MAKERELDEP(id); /* fill Id map */ } - if (hashmask > mkmask(pool->nrels + 4096)) - { - pool->relhashtbl = solv_free(pool->relhashtbl); - pool->relhashmask = 0; - } pool_shrink_rels(pool); /* vacuum */ } diff --git a/src/repo_write.c b/src/repo_write.c index 396cd42..7e78af5 100644 --- a/src/repo_write.c +++ b/src/repo_write.c @@ -260,106 +260,6 @@ write_idarray(Repodata *data, Pool *pool, NeedId *needid, Id *ids) } } -static int -cmp_ids(const void *pa, const void *pb, void *dp) -{ - Id a = *(Id *)pa; - Id b = *(Id *)pb; - return a - b; -} - -#if 0 -static void -write_idarray_sort(Repodata *data, Pool *pool, NeedId *needid, Id *ids, Id marker) -{ - int len, i; - Id lids[64], *sids; - - if (!ids) - return; - if (!*ids) - { - write_u8(data, 0); - return; - } - for (len = 0; len < 64 && ids[len]; len++) - { - Id id = ids[len]; - if (needid) - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; - lids[len] = id; - } - if (ids[len]) - { - for (i = len + 1; ids[i]; i++) - ; - sids = solv_malloc2(i, sizeof(Id)); - memcpy(sids, lids, 64 * sizeof(Id)); - for (; ids[len]; len++) - { - Id id = ids[len]; - if (needid) - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; - sids[len] = id; - } - } - else - sids = lids; - - /* That bloody solvable:prereqmarker needs to stay in position :-( */ - if (needid) - marker = needid[marker].need; - for (i = 0; i < len; i++) - if (sids[i] == marker) - break; - if (i > 1) - solv_sort(sids, i, sizeof(Id), cmp_ids, 0); - if ((len - i) > 2) - solv_sort(sids + i + 1, len - i - 1, sizeof(Id), cmp_ids, 0); - - Id id, old = 0; - - /* The differencing above produces many runs of ones and twos. I tried - fairly elaborate schemes to RLE those, but they give only very mediocre - improvements in compression, as coding the escapes costs quite some - space. Even if they are coded only as bits in IDs. The best improvement - was about 2.7% for the whole .solv file. It's probably better to - invest some complexity into sharing idarrays, than RLEing. */ - for (i = 0; i < len - 1; i++) - { - id = sids[i]; - /* Ugly PREREQ handling. A "difference" of 0 is the prereq marker, - hence all real differences are offsetted by 1. Otherwise we would - have to handle negative differences, which would cost code space for - the encoding of the sign. We loose the exact mapping of prereq here, - but we know the result, so we can recover from that in the reader. */ - if (id == marker) - id = old = 0; - else - { - id = id - old + 1; - old = sids[i]; - } - /* XXX If difference is zero we have multiple equal elements, - we might want to skip writing them out. */ - if (id >= 64) - id = (id & 63) | ((id & ~63) << 1); - write_id(data, id | 64); - } - id = sids[i]; - if (id == marker) - id = 0; - else - id = id - old + 1; - if (id >= 64) - id = (id & 63) | ((id & ~63) << 1); - write_id(data, id); - if (sids != lids) - solv_free(sids); -} -#endif - - struct extdata { unsigned char *buf; int len; @@ -482,8 +382,19 @@ data_addid64(struct extdata *xd, unsigned int x, unsigned int hx) data_addid(xd, (Id)x); } +#define USE_REL_IDARRAY +#ifdef USE_REL_IDARRAY + +static int +cmp_ids(const void *pa, const void *pb, void *dp) +{ + Id a = *(Id *)pa; + Id b = *(Id *)pb; + return a - b; +} + static void -data_addidarray_sort(struct extdata *xd, Pool *pool, NeedId *needid, Id *ids, Id marker) +data_adddepids(struct extdata *xd, Pool *pool, NeedId *needid, Id *ids, Id marker) { int len, i; Id lids[64], *sids; @@ -568,6 +479,27 @@ data_addidarray_sort(struct extdata *xd, Pool *pool, NeedId *needid, Id *ids, Id solv_free(sids); } +#else + +static void +data_adddepids(struct extdata *xd, Pool *pool, NeedId *needid, Id *ids, Id marker) +{ + Id id; + if (!ids || !*ids) + { + data_addid(xd, 0); + return; + } + while ((id = *ids++) != 0) + { + if (needid) + id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; + data_addideof(xd, id, *ids ? 0 : 1); + } +} + +#endif + static inline void data_addblob(struct extdata *xd, unsigned char *blob, int len) { @@ -1169,7 +1101,11 @@ repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey * if (i < SOLVABLE_PROVIDES) keyd.type = REPOKEY_TYPE_ID; else if (i < RPM_RPMDBID) +#ifdef USE_REL_IDARRAY keyd.type = REPOKEY_TYPE_REL_IDARRAY; +#else + keyd.type = REPOKEY_TYPE_IDARRAY; +#endif else keyd.type = REPOKEY_TYPE_NUM; keyd.size = 0; @@ -1807,21 +1743,21 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); if (s->vendor && cbdata.keymap[SOLVABLE_VENDOR]) data_addid(xd, needid[s->vendor].need); if (s->provides && cbdata.keymap[SOLVABLE_PROVIDES]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->provides, SOLVABLE_FILEMARKER); + data_adddepids(xd, pool, needid, idarraydata + s->provides, SOLVABLE_FILEMARKER); if (s->obsoletes && cbdata.keymap[SOLVABLE_OBSOLETES]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->obsoletes, 0); + data_adddepids(xd, pool, needid, idarraydata + s->obsoletes, 0); if (s->conflicts && cbdata.keymap[SOLVABLE_CONFLICTS]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->conflicts, 0); + data_adddepids(xd, pool, needid, idarraydata + s->conflicts, 0); if (s->requires && cbdata.keymap[SOLVABLE_REQUIRES]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->requires, SOLVABLE_PREREQMARKER); + data_adddepids(xd, pool, needid, idarraydata + s->requires, SOLVABLE_PREREQMARKER); if (s->recommends && cbdata.keymap[SOLVABLE_RECOMMENDS]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->recommends, 0); + data_adddepids(xd, pool, needid, idarraydata + s->recommends, 0); if (s->suggests && cbdata.keymap[SOLVABLE_SUGGESTS]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->suggests, 0); + data_adddepids(xd, pool, needid, idarraydata + s->suggests, 0); if (s->supplements && cbdata.keymap[SOLVABLE_SUPPLEMENTS]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->supplements, 0); + data_adddepids(xd, pool, needid, idarraydata + s->supplements, 0); if (s->enhances && cbdata.keymap[SOLVABLE_ENHANCES]) - data_addidarray_sort(xd, pool, needid, idarraydata + s->enhances, 0); + data_adddepids(xd, pool, needid, idarraydata + s->enhances, 0); if (repo->rpmdbid && cbdata.keymap[RPM_RPMDBID]) data_addid(xd, repo->rpmdbid[i - repo->start]); if (anyrepodataused) diff --git a/src/repodata.c b/src/repodata.c index 06b2ea3..4ab5d18 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -1016,7 +1016,11 @@ repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback ddp = get_data(data, key, &dp, *keyp ? 1 : 0); if (key->type == REPOKEY_TYPE_DELETED) - continue; + { + if (onekey) + return; + continue; + } if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY) { struct subschema_data subd; @@ -2804,6 +2808,47 @@ repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle) } void +repodata_set_kv(Repodata *data, Id solvid, Id keyname, Id keytype, KeyValue *kv) +{ + switch (keytype) + { + case REPOKEY_TYPE_ID: + repodata_set_id(data, solvid, keyname, kv->id); + break; + case REPOKEY_TYPE_CONSTANTID: + repodata_set_constantid(data, solvid, keyname, kv->id); + break; + case REPOKEY_TYPE_IDARRAY: + repodata_add_idarray(data, solvid, keyname, kv->id); + break; + case REPOKEY_TYPE_STR: + repodata_set_str(data, solvid, keyname, kv->str); + break; + case REPOKEY_TYPE_VOID: + repodata_set_void(data, solvid, keyname); + break; + case REPOKEY_TYPE_NUM: + repodata_set_num(data, solvid, keyname, SOLV_KV_NUM64(kv)); + break; + case REPOKEY_TYPE_CONSTANT: + repodata_set_constant(data, solvid, keyname, kv->num); + break; + case REPOKEY_TYPE_DIRNUMNUMARRAY: + if (kv->id) + repodata_add_dirnumnum(data, solvid, keyname, kv->id, kv->num, kv->num2); + break; + case REPOKEY_TYPE_DIRSTRARRAY: + repodata_add_dirstr(data, solvid, keyname, kv->id, kv->str); + break; + case_CHKSUM_TYPES: + repodata_set_bin_checksum(data, solvid, keyname, keytype, (const unsigned char *)kv->str); + break; + default: + break; + } +} + +void repodata_unset_uninternalized(Repodata *data, Id solvid, Id keyname) { Id *pp, *ap, **app; @@ -3512,7 +3557,6 @@ entrydone: data->incoredatalen = newincore.len; data->incoredatafree = 0; - solv_free(data->vincore); data->vincore = newvincore.buf; data->vincorelen = newvincore.len; @@ -3639,44 +3683,19 @@ repodata_create_stubs(Repodata *data) xkeyname = 0; continue; } - switch (di.key->type) + repodata_set_kv(sdata, SOLVID_META, di.key->name, di.key->type, &di.kv); + if (di.key->name == REPOSITORY_KEYS && di.key->type == REPOKEY_TYPE_IDARRAY) { - case REPOKEY_TYPE_ID: - repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id); - break; - case REPOKEY_TYPE_CONSTANTID: - repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id); - break; - case REPOKEY_TYPE_STR: - repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str); - break; - case REPOKEY_TYPE_VOID: - repodata_set_void(sdata, SOLVID_META, di.key->name); - break; - case REPOKEY_TYPE_NUM: - repodata_set_num(sdata, SOLVID_META, di.key->name, SOLV_KV_NUM64(&di.kv)); - break; - case_CHKSUM_TYPES: - repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str); - break; - case REPOKEY_TYPE_IDARRAY: - repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id); - if (di.key->name == REPOSITORY_KEYS) + if (!xkeyname) { - if (!xkeyname) - { - if (!di.kv.eof) - xkeyname = di.kv.id; - } - else - { - repodata_add_stubkey(sdata, xkeyname, di.kv.id); - xkeyname = 0; - } + if (!di.kv.eof) + xkeyname = di.kv.id; + } + else + { + repodata_add_stubkey(sdata, xkeyname, di.kv.id); + xkeyname = 0; } - break; - default: - break; } } dataiterator_free(&di); diff --git a/src/repodata.h b/src/repodata.h index d72c60f..7208e95 100644 --- a/src/repodata.h +++ b/src/repodata.h @@ -258,7 +258,6 @@ void repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type, const char *str); void repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q); - /* directory (for package file list) */ void repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2); void repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str); @@ -271,6 +270,8 @@ void repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname, const cha void repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle); void repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle); +/* generic */ +void repodata_set_kv(Repodata *data, Id solvid, Id keyname, Id keytype, struct _KeyValue *kv); void repodata_unset(Repodata *data, Id solvid, Id keyname); void repodata_unset_uninternalized(Repodata *data, Id solvid, Id keyname); diff --git a/src/rules.c b/src/rules.c index cf368e4..df32341 100644 --- a/src/rules.c +++ b/src/rules.c @@ -1031,16 +1031,17 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) } } - if (m && pool->implicitobsoleteusescolors && (s->arch > pool->lastarch || pool->id2arch[s->arch] != 1)) + if (m && pool->implicitobsoleteusescolors && pool_arch2score(pool, s->arch) > 1) { - int a = pool->id2arch[s->arch]; + unsigned int pa, a = pool_arch2score(pool, s->arch); /* check lock-step candidates */ FOR_PROVIDES(p, pp, s->name) { Solvable *ps = pool->solvables + p; if (s->name != ps->name || s->evr != ps->evr || MAPTST(m, p)) continue; - if (ps->arch > pool->lastarch || pool->id2arch[ps->arch] == 1 || pool->id2arch[ps->arch] >= a) + pa = pool_arch2score(pool, ps->arch); + if (!pa || pa == 1 || pa >= a) continue; queue_push(&workq, p); } @@ -1058,7 +1059,7 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) if (pool_is_complex_dep(pool, rec)) { pool_add_pos_literals_complex_dep(pool, rec, &workq, m, 0); - continue; + continue; } #endif FOR_PROVIDES(p, pp, rec) @@ -1075,7 +1076,7 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) if (pool_is_complex_dep(pool, sug)) { pool_add_pos_literals_complex_dep(pool, sug, &workq, m, 0); - continue; + continue; } #endif FOR_PROVIDES(p, pp, sug) @@ -1531,7 +1532,8 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) Pool *pool = solv->pool; Repo *installed = pool->installed; int first, i, j; - Id p, pp, a, aa, bestarch; + Id p, pp, aa; + unsigned int a, bestscore; Solvable *s, *ps, *bests; Queue badq, allowedarchs; Queue lsq; @@ -1546,7 +1548,7 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) continue; s = pool->solvables + i; first = i; - bestarch = 0; + bestscore = 0; bests = 0; queue_empty(&allowedarchs); FOR_PROVIDES(p, pp, s->name) @@ -1558,8 +1560,7 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) first = 0; if (first) break; - a = ps->arch; - a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; + a = pool_arch2score(pool, ps->arch); if (a != 1 && installed && ps->repo == installed) { if (solv->dupinvolvedmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))) @@ -1567,9 +1568,9 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) queue_pushunique(&allowedarchs, ps->arch); /* also ok to keep this architecture */ continue; /* but ignore installed solvables when calculating the best arch */ } - if (a && a != 1 && (!bestarch || a < bestarch)) + if (a && a != 1 && (!bestscore || a < bestscore)) { - bestarch = a; + bestscore = a; bests = ps; } } @@ -1580,7 +1581,7 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) if (allowedarchs.count == 1 && bests && allowedarchs.elements[0] == bests->arch) allowedarchs.count--; /* installed arch is best */ - if (allowedarchs.count && pool->implicitobsoleteusescolors && installed && bestarch) + if (allowedarchs.count && pool->implicitobsoleteusescolors && installed && bestscore) { /* need an extra pass for lockstep checking: we only allow to keep an inferior arch * if the corresponding installed package is not lock-stepped */ @@ -1593,25 +1594,23 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) continue; if (solv->dupinvolvedmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))) continue; - a = ps->arch; - a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; + a = pool_arch2score(pool, ps->arch); if (!a) { queue_pushunique(&allowedarchs, ps->arch); /* strange arch, allow */ continue; } - if (a == 1 || ((a ^ bestarch) & 0xffff0000) == 0) + if (a == 1 || ((a ^ bestscore) & 0xffff0000) == 0) continue; /* have installed package with inferior arch, check if lock-stepped */ FOR_PROVIDES(p2, pp2, s->name) { Solvable *s2 = pool->solvables + p2; - Id a2; + unsigned int a2; if (p2 == p || s2->name != s->name || s2->evr != pool->solvables[p].evr || s2->arch == pool->solvables[p].arch) continue; - a2 = s2->arch; - a2 = (a2 <= pool->lastarch) ? pool->id2arch[a2] : 0; - if (a2 && (a2 == 1 || ((a2 ^ bestarch) & 0xffff0000) == 0)) + a2 = pool_arch2score(pool, s2->arch); + if (a2 && (a2 == 1 || ((a2 ^ bestscore) & 0xffff0000) == 0)) break; } if (!p2) @@ -1626,9 +1625,8 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) ps = pool->solvables + p; if (ps->name != s->name || !MAPTST(addedmap, p)) continue; - a = ps->arch; - a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; - if (a != 1 && bestarch && ((a ^ bestarch) & 0xffff0000) != 0) + a = pool_arch2score(pool, ps->arch); + if (a != 1 && bestscore && ((a ^ bestscore) & 0xffff0000) != 0) { if (installed && ps->repo == installed) { @@ -1638,11 +1636,12 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) } for (j = 0; j < allowedarchs.count; j++) { + unsigned int aas; aa = allowedarchs.elements[j]; if (ps->arch == aa) break; - aa = (aa <= pool->lastarch) ? pool->id2arch[aa] : 0; - if (aa && ((a ^ aa) & 0xffff0000) == 0) + aas = pool_arch2score(pool, aa); + if (aas && ((a ^ aas) & 0xffff0000) == 0) break; /* compatible */ } if (j == allowedarchs.count) @@ -1654,7 +1653,7 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) for (j = 0; j < badq.count; j++) { p = badq.elements[j]; - /* lock-step */ + /* special lock-step handling */ if (pool->implicitobsoleteusescolors) { Id p2; @@ -1665,9 +1664,8 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) Solvable *s2 = pool->solvables + p2; if (p2 == p || s2->name != s->name || s2->evr != pool->solvables[p].evr || s2->arch == pool->solvables[p].arch) continue; - a = s2->arch; - a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; - if (a && (a == 1 || ((a ^ bestarch) & 0xffff000) == 0)) + a = pool_arch2score(pool, s2->arch); + if (a && (a == 1 || ((a ^ bestscore) & 0xffff000) == 0)) { queue_push(&lsq, p2); if (installed && s2->repo == installed) diff --git a/src/selection.c b/src/selection.c index 6ca72e5..d44c482 100644 --- a/src/selection.c +++ b/src/selection.c @@ -32,7 +32,7 @@ str2archid(Pool *pool, const char *arch) id = pool_str2id(pool, arch, 0); if (!id || id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH) return id; - if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id])) + if (pool->id2arch && pool_arch2score(pool, id) == 0) return 0; return id; } @@ -1383,6 +1383,8 @@ setup_limiter(Pool *pool, int flags, struct limiter *limiter) static int matchdep_str(const char *pattern, const char *string, int flags) { + if (!pattern || !string) + return 0; if (flags & SELECTION_GLOB) { int globflags = (flags & SELECTION_NOCASE) != 0 ? FNM_CASEFOLD : 0; @@ -1444,6 +1446,8 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char return 0; if (!name && !dep) return 0; + if (name && dep) + return 0; if ((flags & SELECTION_MATCH_DEPSTR) != 0) flags &= ~SELECTION_REL; diff --git a/src/solvversion.h.in b/src/solvversion.h.in index 7d107f9..4caba47 100644 --- a/src/solvversion.h.in +++ b/src/solvversion.h.in @@ -43,6 +43,7 @@ extern int solv_version_patch; #cmakedefine LIBSOLVEXT_FEATURE_ZLIB_COMPRESSION #cmakedefine LIBSOLVEXT_FEATURE_LZMA_COMPRESSION #cmakedefine LIBSOLVEXT_FEATURE_BZIP2_COMPRESSION +#cmakedefine LIBSOLVEXT_FEATURE_ZSTD_COMPRESSION /* see tools/common_write.c for toolversion history */ #define LIBSOLV_TOOLVERSION "1.1" diff --git a/src/strpool.c b/src/strpool.c index af43e01..5e87918 100644 --- a/src/strpool.c +++ b/src/strpool.c @@ -76,11 +76,39 @@ stringpool_clone(Stringpool *ss, Stringpool *from) ss->sstrings = from->sstrings; } +void +stringpool_resize_hash(Stringpool *ss, int numnew) +{ + Hashval h, hh, hashmask; + Hashtable hashtbl; + int i; + + if (numnew <= 0) + return; + hashmask = mkmask(ss->nstrings + numnew); + if (hashmask <= ss->stringhashmask) + return; /* same as before */ + + /* realloc hash table */ + ss->stringhashmask = hashmask; + solv_free(ss->stringhashtbl); + ss->stringhashtbl = hashtbl = (Hashtable)solv_calloc(hashmask + 1, sizeof(Id)); + + /* rehash all strings into new hashtable */ + for (i = 1; i < ss->nstrings; i++) + { + h = strhash(ss->stringspace + ss->strings[i]) & hashmask; + hh = HASHCHAIN_START; + while (hashtbl[h] != 0) + h = HASHCHAIN_NEXT(h, hh, hashmask); + hashtbl[h] = i; + } +} + Id stringpool_strn2id(Stringpool *ss, const char *str, unsigned int len, int create) { Hashval h, hh, hashmask, oldhashmask; - int i; Id id; Hashtable hashtbl; @@ -90,27 +118,13 @@ stringpool_strn2id(Stringpool *ss, const char *str, unsigned int len, int create return STRID_EMPTY; hashmask = oldhashmask = ss->stringhashmask; - hashtbl = ss->stringhashtbl; - /* expand hashtable if needed */ if ((Hashval)ss->nstrings * 2 > hashmask) { - solv_free(hashtbl); - - /* realloc hash table */ - ss->stringhashmask = hashmask = mkmask(ss->nstrings + STRING_BLOCK); - ss->stringhashtbl = hashtbl = (Hashtable)solv_calloc(hashmask + 1, sizeof(Id)); - - /* rehash all strings into new hashtable */ - for (i = 1; i < ss->nstrings; i++) - { - h = strhash(ss->stringspace + ss->strings[i]) & hashmask; - hh = HASHCHAIN_START; - while (hashtbl[h] != 0) - h = HASHCHAIN_NEXT(h, hh, hashmask); - hashtbl[h] = i; - } + stringpool_resize_hash(ss, STRING_BLOCK); + hashmask = ss->stringhashmask; } + hashtbl = ss->stringhashtbl; /* compute hash and check for match */ h = strnhash(str, len) & hashmask; diff --git a/src/strpool.h b/src/strpool.h index c97b873..f96c5c1 100644 --- a/src/strpool.h +++ b/src/strpool.h @@ -33,6 +33,7 @@ void stringpool_init_empty(Stringpool *ss); void stringpool_clone(Stringpool *ss, Stringpool *from); void stringpool_free(Stringpool *ss); void stringpool_freehash(Stringpool *ss); +void stringpool_resize_hash(Stringpool *ss, int numnew); Id stringpool_str2id(Stringpool *ss, const char *str, int create); Id stringpool_strn2id(Stringpool *ss, const char *str, unsigned int len, int create); |