diff options
author | Michael Matz <matz@suse.de> | 2007-11-16 13:48:23 +0000 |
---|---|---|
committer | Michael Matz <matz@suse.de> | 2007-11-16 13:48:23 +0000 |
commit | 9e09e79d5ea318d3e4ec8f9dc7b2d53c9c2a07c6 (patch) | |
tree | 096d85b660e63cc5c670a353add5b41c98536f80 /src | |
parent | 06ad039561bc89fb3937a0503870333d32ee087e (diff) | |
download | libsolv-9e09e79d5ea318d3e4ec8f9dc7b2d53c9c2a07c6.tar.gz libsolv-9e09e79d5ea318d3e4ec8f9dc7b2d53c9c2a07c6.tar.bz2 libsolv-9e09e79d5ea318d3e4ec8f9dc7b2d53c9c2a07c6.zip |
Reduce C&P code by factoring out the uniquifying string pool.
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/pool.c | 44 | ||||
-rw-r--r-- | src/pool.h | 16 | ||||
-rw-r--r-- | src/poolid.c | 98 | ||||
-rw-r--r-- | src/poolid_private.h | 4 | ||||
-rw-r--r-- | src/pooltypes.h | 3 | ||||
-rw-r--r-- | src/repo_solv.c | 28 | ||||
-rw-r--r-- | src/strpool.c | 122 | ||||
-rw-r--r-- | src/strpool.h | 31 |
9 files changed, 206 insertions, 144 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6d8aec1..be1ec6a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,10 +1,10 @@ -SET(libsatsolver_SRCS bitmap.c poolarch.c poolvendor.c poolid.c +SET(libsatsolver_SRCS bitmap.c poolarch.c poolvendor.c poolid.c strpool.c solver.c repo_solv.c evr.c pool.c queue.c repo.c util.c policy.c ) ADD_LIBRARY(satsolver STATIC ${libsatsolver_SRCS}) -SET(libsatsolver_HEADERS bitmap.h evr.h hash.h policy.h poolarch.h poolvendor.h pool.h poolid.h pooltypes.h queue.h solvable.h solver.h repo.h repo_solv.h util.h ) +SET(libsatsolver_HEADERS bitmap.h evr.h hash.h policy.h poolarch.h poolvendor.h pool.h poolid.h pooltypes.h queue.h solvable.h solver.h repo.h repo_solv.h util.h strpool.h ) SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O3 -Wall -fPIC" ) @@ -40,7 +40,7 @@ pool_freewhatprovides(Pool *pool) // list of string constants, so we can do pointer/Id instead of string comparison // index into array matches ID_xxx constants in pool.h -static char *initpool_data[] = { +static const char *initpool_data[] = { "<NULL>", // ID_NULL "", // ID_EMPTY "solvable:name", @@ -64,7 +64,8 @@ static char *initpool_data[] = { "system:system", "src", "nosrc", - "noarch" + "noarch", + 0 }; // create pool @@ -72,29 +73,12 @@ static char *initpool_data[] = { Pool * pool_create(void) { - int count, totalsize = 0; Pool *pool; Solvable *s; pool = (Pool *)xcalloc(1, sizeof(*pool)); - // count number and total size of predefined strings - for (count = 0; count < sizeof(initpool_data)/sizeof(*initpool_data); count++) - totalsize += strlen(initpool_data[count]) + 1; - - // alloc appropriate space - pool->stringspace = (char *)xmalloc((totalsize + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK); - pool->strings = (Offset *)xmalloc(((count + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset)); - - // now copy predefined strings into allocated space - pool->sstrings = 0; - for (count = 0; count < sizeof(initpool_data)/sizeof(*initpool_data); count++) - { - strcpy(pool->stringspace + pool->sstrings, initpool_data[count]); - pool->strings[count] = pool->sstrings; - pool->sstrings += strlen(initpool_data[count]) + 1; - } - pool->nstrings = count; + stringpool_init (&pool->ss, initpool_data); // pre-alloc space for a RelDep pool->rels = (Reldep *)xcalloc(1 + REL_BLOCK, sizeof(Reldep)); @@ -124,8 +108,8 @@ pool_free(Pool *pool) pool_freeallrepos(pool, 1); xfree(pool->id2arch); xfree(pool->solvables); - xfree(pool->stringspace); - xfree(pool->strings); + xfree(pool->ss.stringspace); + xfree(pool->ss.strings); xfree(pool->rels); queue_free(&pool->vendormap); for (i = 0; i < DEP2STRBUF; i++) @@ -169,16 +153,16 @@ pool_shrink_whatprovides(Pool *pool) Offset o; int r; - if (pool->nstrings < 3) + if (pool->ss.nstrings < 3) return; - sorted = xmalloc2(pool->nstrings, sizeof(Id)); - for (id = 0; id < pool->nstrings; id++) + sorted = xmalloc2(pool->ss.nstrings, sizeof(Id)); + for (id = 0; id < pool->ss.nstrings; id++) sorted[id] = id; pool_shrink_whatprovides_sortcmp_data = pool; - qsort(sorted + 1, pool->nstrings - 1, sizeof(Id), pool_shrink_whatprovides_sortcmp); + qsort(sorted + 1, pool->ss.nstrings - 1, sizeof(Id), pool_shrink_whatprovides_sortcmp); last = 0; lastid = 0; - for (i = 1; i < pool->nstrings; i++) + for (i = 1; i < pool->ss.nstrings; i++) { id = sorted[i]; o = pool->whatprovides[id]; @@ -207,7 +191,7 @@ pool_shrink_whatprovides(Pool *pool) } xfree(sorted); dp = pool->whatprovidesdata + 2; - for (id = 1; id < pool->nstrings; id++) + for (id = 1; id < pool->ss.nstrings; id++) { o = pool->whatprovides[id]; if (o == 0 || o == 1) @@ -262,11 +246,11 @@ pool_prepare(Pool *pool) if (pool->verbose) printf("number of solvables: %d\n", pool->nsolvables); if (pool->verbose) - printf("number of ids: %d + %d\n", pool->nstrings, pool->nrels); + printf("number of ids: %d + %d\n", pool->ss.nstrings, pool->nrels); pool_freeidhashes(pool); pool_freewhatprovides(pool); - num = pool->nstrings + pool->nrels; + num = pool->ss.nstrings + pool->nrels; whatprovides = (Offset *)xcalloc(num, sizeof(Offset)); /* count providers for each name */ @@ -22,12 +22,13 @@ extern "C" { #include "repo.h" #include "solvable.h" #include "queue.h" +#include "strpool.h" // see initpool_data[] in pool.c /* well known ids */ -#define ID_NULL 0 -#define ID_EMPTY 1 +#define ID_NULL STRID_NULL +#define ID_EMPTY STRID_EMPTY #define SOLVABLE_NAME 2 #define SOLVABLE_ARCH 3 #define SOLVABLE_EVR 4 @@ -58,19 +59,12 @@ extern "C" { /* how many strings to maintain (round robin) */ #define DEP2STRBUF 16 - //----------------------------------------------- struct _Pool { int verbose; // pool is used everywhere, so put the verbose flag here - Offset *strings; // table of offsets into stringspace, indexed by Id: Id -> Offset - int nstrings; // number of unique strings in stringspace - char *stringspace; // space for all unique strings: stringspace + Offset = string - Offset sstrings; // next free pos in stringspace - - Hashtable stringhashtbl; // hash table: (string ->) Hash -> Id - Hashmask stringhashmask; // modulo value for hash table (size of table - 1) + struct _Stringpool ss; Reldep *rels; // table of rels: Id -> Reldep int nrels; // number of unique rels @@ -135,7 +129,7 @@ struct _Pool { #define MAKERELDEP(id) ((id) | 0x80000000) #define ISRELDEP(id) (((id) & 0x80000000) != 0) -#define GETRELID(pool, id) ((pool)->nstrings + ((id) ^ 0x80000000)) /* returns Id */ +#define GETRELID(pool, id) ((pool)->ss.nstrings + ((id) ^ 0x80000000)) /* returns Id */ #define GETRELDEP(pool, id) ((pool)->rels + ((id) ^ 0x80000000)) /* returns Reldep* */ #define REL_GT 1 diff --git a/src/poolid.c b/src/poolid.c index bc49bba..ef76a4a 100644 --- a/src/poolid.c +++ b/src/poolid.c @@ -27,84 +27,15 @@ Id 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) - { - 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; - } - } - - // compute hash and check for match - - h = strhash(str) & hashmask; - hh = HASHCHAIN_START; - while ((id = hashtbl[h]) != ID_NULL) // follow hash overflow chain - { - // break if string already hashed - if(!strcmp(pool->stringspace + pool->strings[id], str)) - break; - h = HASHCHAIN_NEXT(h, hh, hashmask); - } - 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; - - // - 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; - - space_needed = strlen(str) + 1; - - // 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; - + int old_nstrings = pool->ss.nstrings; + Id id = stringpool_str2id (&pool->ss, str, create); + /* If we changed the ID->string relations we need to get rid of an + eventually existing provides lookup cache. */ + if (old_nstrings != pool->ss.nstrings) + pool_freewhatprovides(pool); return id; } - Id rel2id(Pool *pool, Id name, Id evr, int flags, int create) { @@ -124,7 +55,7 @@ rel2id(Pool *pool, Id name, Id evr, int flags, int create) if (pool->nrels * 2 > hashmask) { xfree(pool->relhashtbl); - pool->relhashmask = hashmask = mkmask(pool->nstrings + REL_BLOCK); + pool->relhashmask = hashmask = mkmask(pool->ss.nstrings + REL_BLOCK); pool->relhashtbl = hashtbl = xcalloc(hashmask + 1, sizeof(Id)); // rehash all rels into new hashtable for (i = 1; i < pool->nrels; i++) @@ -179,9 +110,9 @@ id2str(Pool *pool, Id id) Reldep *rd = GETRELDEP(pool, id); if (ISRELDEP(rd->name)) return "REL"; - return pool->stringspace + pool->strings[rd->name]; + return pool->ss.stringspace + pool->ss.strings[rd->name]; } - return pool->stringspace + pool->strings[id]; + return pool->ss.stringspace + pool->ss.strings[id]; } static const char *rels[] = { @@ -235,7 +166,7 @@ id2evr(Pool *pool, Id id) rd = GETRELDEP(pool, id); if (ISRELDEP(rd->evr)) return "REL"; - return pool->stringspace + pool->strings[rd->evr]; + return pool->ss.stringspace + pool->ss.strings[rd->evr]; } const char * @@ -247,7 +178,7 @@ dep2str(Pool *pool, Id id) int n, l, ls1, ls2, lsr; if (!ISRELDEP(id)) - return pool->stringspace + pool->strings[id]; + return pool->ss.stringspace + pool->ss.strings[id]; rd = GETRELDEP(pool, id); n = pool->dep2strn; @@ -305,8 +236,7 @@ dep2str(Pool *pool, Id id) 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)); + stringpool_shrink (&pool->ss); } void @@ -320,9 +250,9 @@ pool_shrink_rels(Pool *pool) void pool_freeidhashes(Pool *pool) { - pool->stringhashtbl = xfree(pool->stringhashtbl); + pool->ss.stringhashtbl = xfree(pool->ss.stringhashtbl); + pool->ss.stringhashmask = 0; pool->relhashtbl = xfree(pool->relhashtbl); - pool->stringhashmask = 0; pool->relhashmask = 0; } diff --git a/src/poolid_private.h b/src/poolid_private.h index e293dbb..374b991 100644 --- a/src/poolid_private.h +++ b/src/poolid_private.h @@ -15,10 +15,8 @@ // the size of all buffers is incremented in blocks // these are the block values (increment values) for the -// string hashtable, rel hashtable, stringspace buffer and idarray +// rel hashtable // -#define STRING_BLOCK 2047 // hashtable for strings #define REL_BLOCK 1023 // hashtable for relations -#define STRINGSPACE_BLOCK 65535 // string buffer #endif /* POOLID_PRIVATE_H */ diff --git a/src/pooltypes.h b/src/pooltypes.h index 6117c29..f3bc194 100644 --- a/src/pooltypes.h +++ b/src/pooltypes.h @@ -16,6 +16,9 @@ /* version number for .solv files */ #define SOLV_VERSION 0 +struct _Stringpool; +typedef struct _Stringpool Stringpool; + struct _Pool; typedef struct _Pool Pool; diff --git a/src/repo_solv.c b/src/repo_solv.c index 1b0b595..6c512e8 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -230,15 +230,15 @@ repo_add_solv(Repo *repo, FILE *fp) */ /* alloc string buffer */ - strsp = (char *)xrealloc(pool->stringspace, pool->sstrings + sizeid + 1); + strsp = (char *)xrealloc(pool->ss.stringspace, pool->ss.sstrings + sizeid + 1); /* alloc string offsets (Id -> Offset into string space) */ - str = (Offset *)xrealloc(pool->strings, (pool->nstrings + numid) * sizeof(Offset)); + str = (Offset *)xrealloc(pool->ss.strings, (pool->ss.nstrings + numid) * sizeof(Offset)); - pool->stringspace = strsp; - pool->strings = str; /* array of offsets into strsp, indexed by Id */ + pool->ss.stringspace = strsp; + pool->ss.strings = str; /* array of offsets into strsp, indexed by Id */ /* point to _BEHIND_ already allocated string/Id space */ - strsp += pool->sstrings; + strsp += pool->ss.sstrings; /* alloc id map for name and rel Ids. this maps ids in the solv files * to the ids in our pool */ @@ -261,7 +261,7 @@ repo_add_solv(Repo *repo, FILE *fp) * */ - hashmask = mkmask(pool->nstrings + numid); + hashmask = mkmask(pool->ss.nstrings + numid); #if 0 printf("read %d strings\n", numid); @@ -278,9 +278,9 @@ repo_add_solv(Repo *repo, FILE *fp) * fill hashtable with strings already in pool */ - for (i = 1; i < pool->nstrings; i++) /* leave out our dummy zero id */ + for (i = 1; i < pool->ss.nstrings; i++) /* leave out our dummy zero id */ { - h = strhash(pool->stringspace + pool->strings[i]) & hashmask; + h = strhash(pool->ss.stringspace + pool->ss.strings[i]) & hashmask; hh = HASHCHAIN_START; while (hashtbl[h]) h = HASHCHAIN_NEXT(h, hh, hashmask); @@ -315,7 +315,7 @@ repo_add_solv(Repo *repo, FILE *fp) id = hashtbl[h]; if (id == 0) break; - if (!strcmp(pool->stringspace + pool->strings[id], sp)) + if (!strcmp(pool->ss.stringspace + pool->ss.strings[id], sp)) break; /* existing string */ h = HASHCHAIN_NEXT(h, hh, hashmask); } @@ -324,12 +324,12 @@ repo_add_solv(Repo *repo, FILE *fp) l = strlen(sp) + 1; if (id == ID_NULL) /* end of hash chain -> new string */ { - id = pool->nstrings++; + id = pool->ss.nstrings++; hashtbl[h] = id; - str[id] = pool->sstrings; /* save Offset */ - if (sp != pool->stringspace + pool->sstrings) /* not at end-of-buffer */ - memmove(pool->stringspace + pool->sstrings, sp, l); /* append to pool buffer */ - pool->sstrings += l; + str[id] = pool->ss.sstrings; /* save Offset */ + if (sp != pool->ss.stringspace + pool->ss.sstrings) /* not at end-of-buffer */ + memmove(pool->ss.stringspace + pool->ss.sstrings, sp, l); /* append to pool buffer */ + pool->ss.sstrings += l; } idmap[i] = id; /* repo relative -> pool relative */ sp += l; /* next string */ diff --git a/src/strpool.c b/src/strpool.c new file mode 100644 index 0000000..622664f --- /dev/null +++ b/src/strpool.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2007, Novell Inc. + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +#include <string.h> +#include "util.h" +#include "strpool.h" + +#define STRING_BLOCK 2047 +#define STRINGSPACE_BLOCK 65535 + +void +stringpool_init (Stringpool *ss, const char *strs[]) +{ + unsigned totalsize = 0; + unsigned count; + // count number and total size of predefined strings + for (count = 0; strs[count]; count++) + totalsize += strlen(strs[count]) + 1; + + // alloc appropriate space + ss->stringspace = (char *)xmalloc((totalsize + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK); + ss->strings = (Offset *)xmalloc(((count + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset)); + + // now copy predefined strings into allocated space + ss->sstrings = 0; + for (count = 0; strs[count]; count++) + { + strcpy(ss->stringspace + ss->sstrings, strs[count]); + ss->strings[count] = ss->sstrings; + ss->sstrings += strlen(strs[count]) + 1; + } + ss->nstrings = count; +} + +Id +stringpool_str2id (Stringpool *ss, 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 STRID_NULL; + if (!*str) + return STRID_EMPTY; + + hashmask = ss->stringhashmask; + hashtbl = ss->stringhashtbl; + + // expand hashtable if needed + // + // + if (ss->nstrings * 2 > hashmask) + { + xfree(hashtbl); + + // realloc hash table + ss->stringhashmask = hashmask = mkmask(ss->nstrings + STRING_BLOCK); + ss->stringhashtbl = hashtbl = (Hashtable)xcalloc(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) // follow overflow chain + h = HASHCHAIN_NEXT(h, hh, hashmask); + hashtbl[h] = i; + } + } + + // compute hash and check for match + + h = strhash(str) & hashmask; + hh = HASHCHAIN_START; + while ((id = hashtbl[h]) != 0) // follow hash overflow chain + { + // break if string already hashed + if(!strcmp(ss->stringspace + ss->strings[id], str)) + break; + h = HASHCHAIN_NEXT(h, hh, hashmask); + } + if (id || !create) // exit here if string found + return id; + + // generate next id and save in table + id = ss->nstrings++; + hashtbl[h] = id; + + // + if ((id & STRING_BLOCK) == 0) + ss->strings = xrealloc(ss->strings, ((ss->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Hashval)); + // 'pointer' into stringspace is Offset of next free pos: sstrings + ss->strings[id] = ss->sstrings; + + space_needed = strlen(str) + 1; + + // resize string buffer if needed + if (((ss->sstrings + space_needed - 1) | STRINGSPACE_BLOCK) != ((ss->sstrings - 1) | STRINGSPACE_BLOCK)) + ss->stringspace = xrealloc(ss->stringspace, (ss->sstrings + space_needed + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK); + // copy new string into buffer + memcpy(ss->stringspace + ss->sstrings, str, space_needed); + // next free pos is behind new string + ss->sstrings += space_needed; + + return id; +} + +void +stringpool_shrink (Stringpool *ss) +{ + ss->stringspace = (char *)xrealloc(ss->stringspace, (ss->sstrings + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK); + ss->strings = (Offset *)xrealloc(ss->strings, ((ss->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset)); +} diff --git a/src/strpool.h b/src/strpool.h new file mode 100644 index 0000000..58f7edd --- /dev/null +++ b/src/strpool.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2007, Novell Inc. + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ +#ifndef STRINGPOOL_H +#define STRINGPOOL_H + +#include "pooltypes.h" +#include "hash.h" + +#define STRID_NULL 0 +#define STRID_EMPTY 1 + +struct _Stringpool +{ + Offset *strings; // table of offsets into stringspace, indexed by Id: Id -> Offset + int nstrings; // number of unique strings in stringspace + char *stringspace; // space for all unique strings: stringspace + Offset = string + Offset sstrings; // next free pos in stringspace + + Hashtable stringhashtbl; // hash table: (string ->) Hash -> Id + Hashmask stringhashmask; // modulo value for hash table (size of table - 1) +}; + +void stringpool_init (Stringpool *ss, const char *strs[]); +Id stringpool_str2id (Stringpool *ss, const char *str, int create); +void stringpool_shrink (Stringpool *ss); + +#endif |