X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fpoolid.c;h=52d98c38fa4ac3535f8047a3f4973be100ccacc8;hb=9c08bb3b899936e1eb9b6ab9d0cef17501ad6bab;hp=a598514390b124a2ebf5ce187ba80c2720f83391;hpb=8f8a9ed5192a6737d63364029cb05d91f1d0e399;p=platform%2Fupstream%2Flibsolv.git diff --git a/src/poolid.c b/src/poolid.c index a598514..52d98c3 100644 --- a/src/poolid.c +++ b/src/poolid.c @@ -1,4 +1,11 @@ /* + * Copyright (c) 2007, Novell Inc. + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +/* * poolid.c * * Id management @@ -14,126 +21,88 @@ #include "util.h" -// intern string into pool -// return Id +/* intern string into pool, return id */ Id -str2id(Pool *pool, const char *str, int create) +pool_str2id(Pool *pool, const char *str, int create) { - Hashval h; - unsigned int hh; - Hashmask hashmask; - int i, space_needed; - Id id; - Hashtable hashtbl; - - // check string - if (!str) - return ID_NULL; - if (!*str) - return ID_EMPTY; - - hashmask = pool->stringhashmask; - hashtbl = pool->stringhashtbl; - - // expand hashtable if needed - // - // - if (pool->nstrings * 2 > hashmask) + int oldnstrings = pool->ss.nstrings; + Id id = stringpool_str2id(&pool->ss, str, create); + if (create && pool->whatprovides && oldnstrings != pool->ss.nstrings && (id & WHATPROVIDES_BLOCK) == 0) { - xfree(hashtbl); - - // realloc hash table - pool->stringhashmask = hashmask = mkmask(pool->nstrings + STRING_BLOCK); - pool->stringhashtbl = hashtbl = (Hashtable)xcalloc(hashmask + 1, sizeof(Id)); - - // rehash all strings into new hashtable - for (i = 1; i < pool->nstrings; i++) - { - h = strhash(pool->stringspace + pool->strings[i]) & hashmask; - hh = HASHCHAIN_START; - while (hashtbl[h] != ID_NULL) // follow overflow chain - h = HASHCHAIN_NEXT(h, hh, hashmask); - hashtbl[h] = i; - } + /* grow whatprovides array */ + pool->whatprovides = solv_realloc(pool->whatprovides, (id + (WHATPROVIDES_BLOCK + 1)) * sizeof(Offset)); + memset(pool->whatprovides + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset)); } + return id; +} - // compute hash and check for match - - h = strhash(str) & hashmask; - hh = HASHCHAIN_START; - while ((id = hashtbl[h]) != ID_NULL) // follow hash overflow chain +Id +pool_strn2id(Pool *pool, const char *str, unsigned int len, int create) +{ + int oldnstrings = pool->ss.nstrings; + Id id = stringpool_strn2id(&pool->ss, str, len, create); + if (create && pool->whatprovides && oldnstrings != pool->ss.nstrings && (id & WHATPROVIDES_BLOCK) == 0) { - // break if string already hashed - if(!strcmp(pool->stringspace + pool->strings[id], str)) - break; - h = HASHCHAIN_NEXT(h, hh, hashmask); + /* grow whatprovides array */ + pool->whatprovides = solv_realloc(pool->whatprovides, (id + (WHATPROVIDES_BLOCK + 1)) * sizeof(Offset)); + memset(pool->whatprovides + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset)); } - if (id || !create) // exit here if string found - return id; - - pool_freewhatprovides(pool); - - // generate next id and save in table - id = pool->nstrings++; - hashtbl[h] = id; + return id; +} - // - if ((id & STRING_BLOCK) == 0) - pool->strings = xrealloc(pool->strings, ((pool->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Hashval)); - // 'pointer' into stringspace is Offset of next free pos: sstrings - pool->strings[id] = pool->sstrings; +void +pool_resize_rels_hash(Pool *pool, int numnew) +{ + Hashval h, hh, hashmask; + Hashtable hashtbl; + int i; + Reldep *rd; - space_needed = strlen(str) + 1; + if (numnew <= 0) + return; + hashmask = mkmask(pool->nrels + numnew); + if (hashmask <= pool->relhashmask) + return; /* same as before */ - // resize string buffer if needed - if (((pool->sstrings + space_needed - 1) | STRINGSPACE_BLOCK) != ((pool->sstrings - 1) | STRINGSPACE_BLOCK)) - pool->stringspace = xrealloc(pool->stringspace, (pool->sstrings + space_needed + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK); - // copy new string into buffer - memcpy(pool->stringspace + pool->sstrings, str, space_needed); - // next free pos is behind new string - pool->sstrings += space_needed; + /* realloc hash table */ + pool->relhashmask = hashmask; + solv_free(pool->relhashtbl); + pool->relhashtbl = hashtbl = solv_calloc(hashmask + 1, sizeof(Id)); - return 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 -rel2id(Pool *pool, Id name, Id evr, int flags, int create) +pool_rel2id(Pool *pool, Id name, Id evr, int flags, int create) { - Hashval h; - unsigned int hh; - Hashmask hashmask; - int i; + Hashval h, hh, hashmask; Id id; Hashtable hashtbl; Reldep *ran; + + /* extend hashtable if needed */ hashmask = pool->relhashmask; - hashtbl = pool->relhashtbl; - ran = pool->rels; - - // extend hashtable if needed - if (pool->nrels * 2 > hashmask) + if ((Hashval)pool->nrels * 2 > hashmask) { - xfree(pool->relhashtbl); - pool->relhashmask = hashmask = mkmask(pool->nstrings + REL_BLOCK); - pool->relhashtbl = hashtbl = xcalloc(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; } - - // compute hash and check for match + 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) @@ -146,33 +115,37 @@ rel2id(Pool *pool, Id name, Id evr, int flags, int create) if (!create) return ID_NULL; - pool_freewhatprovides(pool); - id = pool->nrels++; - // extend rel space if needed - if ((id & REL_BLOCK) == 0) - pool->rels = xrealloc(pool->rels, ((pool->nrels + REL_BLOCK) & ~REL_BLOCK) * sizeof(Reldep)); + /* 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); } -// Id -> String -// for rels (returns name only) and strings -// +/* Id -> String + * for rels (returns name only) and strings + */ const char * -id2str(Pool *pool, Id id) +pool_id2str(const Pool *pool, Id id) { - if (ISRELDEP(id)) + while (ISRELDEP(id)) { Reldep *rd = GETRELDEP(pool, id); - return pool->stringspace + pool->strings[rd->name]; + id = rd->name; } - return pool->stringspace + pool->strings[id]; + return pool->ss.stringspace + pool->ss.strings[id]; } static const char *rels[] = { @@ -187,52 +160,196 @@ static const char *rels[] = { }; -// get operator for RelId +/* get operator for RelId */ const char * -id2rel(Pool *pool, Id id) +pool_id2rel(const Pool *pool, Id id) { Reldep *rd; if (!ISRELDEP(id)) return ""; rd = GETRELDEP(pool, id); - return rels[rd->flags & 7]; + + switch (rd->flags) + { + /* debian special cases < and > */ + /* haiku special cases <> (maybe we should use != for the others as well */ + case 0: case REL_EQ: case REL_GT | REL_EQ: + case REL_LT | REL_EQ: case REL_LT | REL_EQ | REL_GT: +#if !defined(DEBIAN) && !defined(MULTI_SEMANTICS) + case REL_LT: case REL_GT: +#endif +#if !defined(HAIKU) && !defined(MULTI_SEMANTICS) + case REL_LT | REL_GT: +#endif + return rels[rd->flags]; +#if defined(DEBIAN) || defined(MULTI_SEMANTICS) + case REL_GT: + return pool->disttype == DISTTYPE_DEB ? " >> " : rels[rd->flags]; + case REL_LT: + return pool->disttype == DISTTYPE_DEB ? " << " : rels[rd->flags]; +#endif +#if defined(HAIKU) || defined(MULTI_SEMANTICS) + case REL_LT | REL_GT: + return pool->disttype == DISTTYPE_HAIKU ? " != " : rels[rd->flags]; +#endif + case REL_AND: + return pool->disttype == DISTTYPE_RPM ? " and " : " & "; + case REL_OR: + return pool->disttype == DISTTYPE_RPM ? " or " : " | "; + case REL_WITH: + return pool->disttype == DISTTYPE_RPM ? " with " : " + "; + case REL_WITHOUT: + return pool->disttype == DISTTYPE_RPM ? " without " : " - "; + case REL_NAMESPACE: + return " NAMESPACE "; /* actually not used in dep2str */ + case REL_ARCH: + return "."; + case REL_MULTIARCH: + return ":"; + case REL_FILECONFLICT: + return " FILECONFLICT "; + case REL_COND: + return pool->disttype == DISTTYPE_RPM ? " if " : " IF "; + case REL_UNLESS: + return pool->disttype == DISTTYPE_RPM ? " unless " : " UNLESS "; + case REL_COMPAT: + return " compat >= "; + case REL_KIND: + return " KIND "; + case REL_ELSE: + return pool->disttype == DISTTYPE_RPM ? " else " : " ELSE "; + case REL_CONDA: + return " "; + case REL_ERROR: + return " ERROR "; + default: + break; + } + return " ??? "; } -// get e:v.r for Id -// +/* get e:v.r for Id */ const char * -id2evr(Pool *pool, Id id) +pool_id2evr(const Pool *pool, Id id) { Reldep *rd; if (!ISRELDEP(id)) return ""; rd = GETRELDEP(pool, id); - return pool->stringspace + pool->strings[rd->evr]; + if (ISRELDEP(rd->evr)) + return "(REL)"; + return pool->ss.stringspace + pool->ss.strings[rd->evr]; +} + +static int +dep2strlen(const Pool *pool, Id id) +{ + int l = 0; + + while (ISRELDEP(id)) + { + Reldep *rd = GETRELDEP(pool, id); + /* add 2 for parens */ + l += 2 + dep2strlen(pool, rd->name) + strlen(pool_id2rel(pool, id)); + id = rd->evr; + } + return l + strlen(pool->ss.stringspace + pool->ss.strings[id]); +} + +static void +dep2strcpy(const Pool *pool, char *p, Id id, int oldrel) +{ + while (ISRELDEP(id)) + { + Reldep *rd = GETRELDEP(pool, id); + int rel = rd->flags; + if (oldrel == REL_AND || oldrel == REL_OR || oldrel == REL_WITH || oldrel == REL_WITHOUT || oldrel == REL_COND || oldrel == REL_UNLESS || oldrel == REL_ELSE || oldrel == -1) + if (rel == REL_AND || rel == REL_OR || rel == REL_WITH || rel == REL_WITHOUT || rel == REL_COND || rel == REL_UNLESS || rel == REL_ELSE) + if ((oldrel != rel || rel == REL_COND || rel == REL_UNLESS || rel == REL_ELSE) && !((oldrel == REL_COND || oldrel == REL_UNLESS) && rel == REL_ELSE)) + { + *p++ = '('; + dep2strcpy(pool, p, rd->name, rd->flags); + p += strlen(p); + strcpy(p, pool_id2rel(pool, id)); + p += strlen(p); + dep2strcpy(pool, p, rd->evr, rd->flags); + strcat(p, ")"); + return; + } + if (rd->flags == REL_KIND) + { + dep2strcpy(pool, p, rd->evr, rd->flags); + p += strlen(p); + *p++ = ':'; + id = rd->name; + oldrel = rd->flags; + continue; + } + dep2strcpy(pool, p, rd->name, rd->flags); + p += strlen(p); + if (rd->flags == REL_NAMESPACE) + { + *p++ = '('; + dep2strcpy(pool, p, rd->evr, rd->flags); + strcat(p, ")"); + return; + } + if (rd->flags == REL_FILECONFLICT) + { + *p = 0; + return; + } + strcpy(p, pool_id2rel(pool, id)); + p += strlen(p); + id = rd->evr; + oldrel = rd->flags; + } + strcpy(p, pool->ss.stringspace + pool->ss.strings[id]); +} + +const char * +pool_dep2str(Pool *pool, Id id) +{ + char *p; + if (!ISRELDEP(id)) + return pool->ss.stringspace + pool->ss.strings[id]; + p = pool_alloctmpspace(pool, dep2strlen(pool, id) + 1); + dep2strcpy(pool, p, id, pool->disttype == DISTTYPE_RPM ? -1 : 0); + 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) { - pool->stringspace = (char *)xrealloc(pool->stringspace, (pool->sstrings + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK); - pool->strings = (Offset *)xrealloc(pool->strings, ((pool->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset)); + /* 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) { - pool->rels = (Reldep *)xrealloc(pool->rels, ((pool->nrels + REL_BLOCK) & ~REL_BLOCK) * sizeof(Reldep)); + /* 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); } -// reset all hash tables -// +/* free all hash tables */ void pool_freeidhashes(Pool *pool) { - pool->stringhashtbl = xfree(pool->stringhashtbl); - pool->relhashtbl = xfree(pool->relhashtbl); - pool->stringhashmask = 0; - pool->relhashmask = 0; + stringpool_freehash(&pool->ss); + pool_free_rels_hash(pool); } -// EOF +/* EOF */