summaryrefslogtreecommitdiff
path: root/rpmio
diff options
context:
space:
mode:
authorFlorian Festi <ffesti@redhat.com>2012-09-28 10:23:03 +0300
committerPanu Matilainen <pmatilai@redhat.com>2012-09-28 10:37:05 +0300
commitbdb966b4df1a882f9c1f84393666277bec98080c (patch)
treee21eb49492468fc65058fa7f8e52e32767f67a6a /rpmio
parentb81b4a35240f16fa8b45156b0151fab9e130a8e8 (diff)
downloadlibrpm-tizen-bdb966b4df1a882f9c1f84393666277bec98080c.tar.gz
librpm-tizen-bdb966b4df1a882f9c1f84393666277bec98080c.tar.bz2
librpm-tizen-bdb966b4df1a882f9c1f84393666277bec98080c.zip
Make string pool strings static in memory
- Use multiple chunks that get allocated as old ones get filled up instead of reallocating, store direct pointers to the strings in the id array. - This prevents nasty surprises when previously retrieved pointer to a pool string goes invalid underneath us due to somebody adding a new string, and restores former rpm API behavior: string pointers retrieved from eg rpmds and rpmfi are valid for the entire lifetime of those objects.
Diffstat (limited to 'rpmio')
-rw-r--r--rpmio/rpmstrpool.c89
1 files changed, 56 insertions, 33 deletions
diff --git a/rpmio/rpmstrpool.c b/rpmio/rpmstrpool.c
index 6adab0beb..5264a9c9b 100644
--- a/rpmio/rpmstrpool.c
+++ b/rpmio/rpmstrpool.c
@@ -4,6 +4,7 @@
#include <rpm/rpmstrpool.h>
#include "debug.h"
+#define STRDATA_CHUNKS 1024
#define STRDATA_CHUNK 65536
#define STROFFS_CHUNK 2048
/* XXX this is ridiculously small... */
@@ -25,12 +26,15 @@ struct poolHash_s {
};
struct rpmstrPool_s {
- size_t * offs; /* offsets into data area */
+ char ** offs; /* pointers into data area */
rpmsid offs_size; /* largest offset index */;
rpmsid offs_alloced; /* offsets allocation size */
- char * data; /* string data area */
- size_t data_size; /* string data area size */
- size_t data_alloced; /* string data area allocation size */
+
+ char ** chunks; /* memory chunks for storing the strings */
+ size_t chunks_size; /* current chunk */
+ size_t chunks_allocated; /* allocated size of the chunks array */
+ size_t chunk_allocated; /* size of the current chunk */
+
poolHash hash; /* string -> sid hash table */
int frozen; /* are new id additions allowed? */
int nrefs; /* refcount */
@@ -221,6 +225,17 @@ static void rpmstrPoolRehash(rpmstrPool pool)
rpmstrPool rpmstrPoolCreate(void)
{
rpmstrPool pool = xcalloc(1, sizeof(*pool));
+
+ pool->offs_alloced = STROFFS_CHUNK;
+ pool->offs = xcalloc(pool->offs_alloced, sizeof(*pool->offs));
+
+ pool->chunks_allocated = STRDATA_CHUNKS;
+ pool->chunks = xcalloc(pool->chunks_allocated, sizeof(*pool->chunks));
+ pool->chunks_size = 1;
+ pool->chunk_allocated = STRDATA_CHUNK;
+ pool->offs[1] = xcalloc(1, pool->chunk_allocated);
+ pool->chunks[pool->chunks_size] = pool->offs[1];
+
rpmstrPoolRehash(pool);
pool->nrefs = 1;
return pool;
@@ -236,7 +251,10 @@ rpmstrPool rpmstrPoolFree(rpmstrPool pool)
poolHashPrintStats(pool);
poolHashFree(pool->hash);
free(pool->offs);
- free(pool->data);
+ for (int i=1;i<=pool->chunks_size;i++) {
+ pool->chunks[i] = _free(pool->chunks[i]);
+ }
+ free(pool->chunks);
free(pool);
}
}
@@ -253,18 +271,12 @@ rpmstrPool rpmstrPoolLink(rpmstrPool pool)
void rpmstrPoolFreeze(rpmstrPool pool, int keephash)
{
if (pool && !pool->frozen) {
- /*
- * realloc() might require rehashing even when downsizing,
- * dont bother unless we're also discarding the hash.
- */
if (!keephash) {
pool->hash = poolHashFree(pool->hash);
- pool->data_alloced = pool->data_size;
- pool->data = xrealloc(pool->data, pool->data_alloced);
- pool->offs_alloced = pool->offs_size + 1;
- pool->offs = xrealloc(pool->offs,
- pool->offs_alloced * sizeof(*pool->offs));
}
+ pool->offs_alloced = pool->offs_size + 2; /* space for end marker */
+ pool->offs = xrealloc(pool->offs,
+ pool->offs_alloced * sizeof(*pool->offs));
pool->frozen = 1;
}
}
@@ -283,29 +295,42 @@ static rpmsid rpmstrPoolPut(rpmstrPool pool, const char *s, size_t slen, unsigne
{
char *t = NULL;
size_t ssize = slen + 1;
-
- if (ssize > pool->data_alloced - pool->data_size) {
- size_t need = pool->data_size + ssize;
- size_t alloced = pool->data_alloced;
-
- while (alloced < need)
- alloced += STRDATA_CHUNK;
-
- pool->data = xrealloc(pool->data, alloced);
- pool->data_alloced = alloced;
- }
+ size_t chunk_used;
pool->offs_size += 1;
- if (pool->offs_alloced <= pool->offs_size) {
+ /* need one extra for end of string */
+ /* and one extra to mark the end of the chunk */
+ if (pool->offs_alloced <= pool->offs_size + 2) {
pool->offs_alloced += STROFFS_CHUNK;
pool->offs = xrealloc(pool->offs,
pool->offs_alloced * sizeof(*pool->offs));
}
- t = memcpy(pool->data + pool->data_size, s, slen);
+ chunk_used = pool->offs[pool->offs_size] - pool->chunks[pool->chunks_size];
+ if (ssize + 1 > pool->chunk_allocated - chunk_used) {
+ /* check size of ->chunks */
+ pool->chunks_size += 1;
+ if (pool->chunks_size >= pool->chunks_allocated) {
+ pool->chunks_allocated += pool->chunks_allocated;
+ pool->chunks = xrealloc(pool->chunks,
+ pool->chunks_allocated * sizeof(*pool->chunks));
+ }
+
+ /* Check if string is bigger than chunks */
+ if (ssize > pool->chunk_allocated) {
+ pool->chunk_allocated = 2 * ssize;
+ }
+
+ /* Dummy entry for end of last string*/
+ pool->offs_size += 1;
+
+ pool->offs[pool->offs_size] = xcalloc(1, pool->chunk_allocated);
+ pool->chunks[pool->chunks_size] = pool->offs[pool->offs_size];
+ }
+
+ t = memcpy(pool->offs[pool->offs_size], s, slen);
t[slen] = '\0';
- pool->offs[pool->offs_size] = pool->data_size;
- pool->data_size += ssize;
+ pool->offs[pool->offs_size+1] = t + ssize;
poolHashAddHEntry(pool, t, hash, pool->offs_size);
@@ -373,7 +398,7 @@ const char * rpmstrPoolStr(rpmstrPool pool, rpmsid sid)
{
const char *s = NULL;
if (pool && sid > 0 && sid <= pool->offs_size)
- s = pool->data + pool->offs[sid];
+ s = pool->offs[sid];
return s;
}
@@ -381,9 +406,7 @@ size_t rpmstrPoolStrlen(rpmstrPool pool, rpmsid sid)
{
size_t slen = 0;
if (pool && sid <= pool->offs_size) {
- size_t end = (sid < pool->offs_size) ? pool->offs[sid + 1] :
- pool->data_size;
- slen = end - pool->offs[sid] - 1;
+ slen = pool->offs[sid+1] - pool->offs[sid] - 1;
}
return slen;
}