char *sp; /* pointer into string space */
Id *idmap; /* map of repo Ids to pool Ids */
Id id, type;
- unsigned int hashmask, h;
- int hh;
- Id *hashtbl;
+ Hashval hashmask, h, hh;
+ Hashtable hashtbl;
Id name, evr, did;
int relflags;
Reldep *ran;
/******* Part 1: string IDs *****************************************/
- sizeid = read_u32(&data); /* size of string+Id space */
+ sizeid = read_u32(&data); /* size of string space */
/*
* read strings and Ids
*/
if (!(flags & REPO_LOCALPOOL))
- spool = &pool->ss;
+ {
+ spool = &pool->ss;
+ /* alloc max needed string buffer and string pointers, will shrink again later */
+#if 0
+ spool->stringspace = solv_realloc(spool->stringspace, spool->sstrings + sizeid + 1);
+ spool->strings = solv_realloc2(spool->strings, spool->nstrings + numid, sizeof(Offset));
+#else
+ spool->sstrings += sizeid + 1;
+ spool->nstrings += numid;
+ stringpool_shrink(spool); /* we misuse stringpool_shrink so that the correct BLOCK factor is used */
+ spool->sstrings -= sizeid + 1;
+ spool->nstrings -= numid;
+#endif
+ }
else
{
data.localpool = 1;
spool = &data.spool;
- spool->stringspace = solv_malloc(7);
+ spool->stringspace = solv_malloc(7 + sizeid + 1);
+ spool->strings = solv_malloc2(numid < 2 ? 2 : numid, sizeof(Offset));
strcpy(spool->stringspace, "<NULL>");
spool->sstrings = 7;
- spool->nstrings = 0;
+ spool->nstrings = 1;
+ spool->strings[0] = 0; /* <NULL> */
}
- /* alloc string buffer */
- spool->stringspace = solv_realloc(spool->stringspace, spool->sstrings + sizeid + 1);
- /* alloc string offsets (Id -> Offset into string space) */
- spool->strings = solv_realloc2(spool->strings, spool->nstrings + numid, sizeof(Offset));
-
- strsp = spool->stringspace;
- str = spool->strings; /* array of offsets into strsp, indexed by Id */
-
- /* point to _BEHIND_ already allocated string/Id space */
- strsp += spool->sstrings;
-
/*
- * read new repo at end of pool
+ * read string data and append to old string space
*/
+ strsp = spool->stringspace + spool->sstrings; /* append new entries */
if ((solvflags & SOLV_FLAG_PREFIX_POOL) == 0)
{
if (sizeid && fread(strsp, sizeid, 1, fp) != 1)
- return pool_error(pool, SOLV_ERROR_EOF, "read error while reading strings");
+ {
+ repodata_freedata(&data);
+ return pool_error(pool, SOLV_ERROR_EOF, "read error while reading strings");
+ }
}
else
{
int freesp = sizeid;
if (pfsize && fread(prefix, pfsize, 1, fp) != 1)
- {
+ {
solv_free(prefix);
- return pool_error(pool, SOLV_ERROR_EOF, "read error while reading strings");
+ repodata_freedata(&data);
+ return pool_error(pool, SOLV_ERROR_EOF, "read error while reading strings");
}
for (i = 1; i < numid; i++)
{
if (freesp < 0)
{
solv_free(prefix);
+ repodata_freedata(&data);
return pool_error(pool, SOLV_ERROR_OVERFLOW, "overflow while expanding strings");
}
if (same)
}
solv_free(prefix);
if (freesp != 0)
- return pool_error(pool, SOLV_ERROR_CORRUPT, "expanding strings size mismatch");
+ {
+ repodata_freedata(&data);
+ return pool_error(pool, SOLV_ERROR_CORRUPT, "expanding strings size mismatch");
+ }
}
strsp[sizeid] = 0; /* make string space \0 terminated */
sp = strsp;
+ /* now merge */
+ str = spool->strings; /* array of offsets into strsp, indexed by Id */
if ((flags & REPO_LOCALPOOL) != 0)
{
- /* no shared pool, thus no idmap and no unification */
+ /* no shared pool, thus no idmap and no unification needed */
idmap = 0;
- spool->nstrings = numid;
- str[0] = 0;
+ spool->nstrings = numid < 2 ? 2 : numid; /* make sure we have at least id 0 and 1 */
if (*sp)
{
- /* we need the '' for directories */
+ /* we need id 1 to be '' for directories */
+ repodata_freedata(&data);
return pool_error(pool, SOLV_ERROR_CORRUPT, "store strings don't start with an empty string");
}
for (i = 1; i < spool->nstrings; i++)
{
- if (sp >= strsp + sizeid)
- return pool_error(pool, SOLV_ERROR_OVERFLOW, "not enough strings");
+ if (sp >= strsp + sizeid && numid >= 2)
+ {
+ repodata_freedata(&data);
+ return pool_error(pool, SOLV_ERROR_OVERFLOW, "not enough strings");
+ }
str[i] = sp - spool->stringspace;
sp += strlen(sp) + 1;
}
}
else
{
+ Offset oldsstrings = spool->sstrings;
+
/* 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));
{
if (sp >= strsp + sizeid)
{
- solv_free(hashtbl);
solv_free(idmap);
+ spool->nstrings = oldnstrings;
+ spool->sstrings = oldsstrings;
+ stringpool_freehash(spool);
+ repodata_freedata(&data);
return pool_error(pool, SOLV_ERROR_OVERFLOW, "not enough strings %d %d", i, numid);
}
if (!*sp) /* empty string */
spool->stringhashtbl = solv_free(spool->stringhashtbl);
spool->stringhashmask = 0;
}
+ stringpool_shrink(spool); /* vacuum */
}
- pool_shrink_strings(pool); /* vacuum */
/******* Part 2: Relation IDs ***************************************/
data.incoredata = solv_realloc(data.incoredata, data.incoredatalen);
data.incoredatafree = 0;
}
+ solv_free(idmap);
for (i = 1; i < numkeys; i++)
if (keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET)
}
data.lastverticaloffset = fileoffset;
pagesize = read_u32(&data);
- data.error = repopagestore_read_or_setup_pages(&data.store, data.fp, pagesize, fileoffset);
- if (data.error == SOLV_ERROR_EOF)
- pool_error(pool, data.error, "repopagestore setup: unexpected EOF");
- else if (data.error)
- pool_error(pool, data.error, "repopagestore setup failed");
- }
- else
- {
- /* no longer needed */
- data.fp = 0;
+ if (!data.error)
+ {
+ data.error = repopagestore_read_or_setup_pages(&data.store, data.fp, pagesize, fileoffset);
+ if (data.error == SOLV_ERROR_EOF)
+ pool_error(pool, data.error, "repopagestore setup: unexpected EOF");
+ else if (data.error)
+ pool_error(pool, data.error, "repopagestore setup failed");
+ }
}
- solv_free(idmap);
+ data.fp = 0; /* no longer needed */
if (data.error)
{
- /* XXX: free repodata? */
- return data.error;
+ i = data.error;
+ repodata_freedata(&data);
+ return i;
}
if (parent)