Allow keeping hash table around on pool freeze, adjust callers
authorPanu Matilainen <pmatilai@redhat.com>
Wed, 12 Sep 2012 13:47:43 +0000 (16:47 +0300)
committerPanu Matilainen <pmatilai@redhat.com>
Wed, 12 Sep 2012 16:17:20 +0000 (19:17 +0300)
- Pool id -> string always works with a frozen pool, but in some cases
  we'll need to go the other way, allow caller to specify whether
  string -> id lookups should be possible on frozen pool.
- On glibc, realloc() to smaller size doesn't move the data but on
  other platforms (including valgrind) it can and does move, which
  would require a full rehash. For now, just leave all the data
  alone unless we're also freeing the hash, the memory savings
  isn't much for a global pool (which is where this matters)

lib/depends.c
lib/rpmds.c
lib/rpmfi.c
rpmio/rpmstrpool.c
rpmio/rpmstrpool.h

index 79d86d8..b9d87d9 100644 (file)
@@ -330,7 +330,7 @@ rpmal rpmtsCreateAl(rpmts ts, rpmElementTypes types)
        rpmstrPool tspool = rpmtsPool(ts);
 
        /* Required for now to lock string pointers in memory */
-       rpmstrPoolFreeze(tspool);
+       rpmstrPoolFreeze(tspool, 1);
 
        al = rpmalCreate(tspool, (rpmtsNElements(ts) / 4) + 1, rpmtsFlags(ts),
                                rpmtsColor(ts), rpmtsPrefColor(ts));
index dcf2c39..3b7a836 100644 (file)
@@ -212,7 +212,7 @@ rpmds rpmdsNewPool(rpmstrPool pool, Header h, rpmTagVal tagN, int flags)
 
        /* freeze the pool to save memory, but only if private pool */
        if (ds->pool != pool)
-           rpmstrPoolFreeze(ds->pool);
+           rpmstrPoolFreeze(ds->pool, 0);
     }
 
 exit:
@@ -310,7 +310,7 @@ static rpmds singleDS(rpmTagVal tagN, const char * N, const char * EVR,
 
     /* freeze the pool on success to save memory */
     if (ds != NULL)
-       rpmstrPoolFreeze(ds->pool);
+       rpmstrPoolFreeze(ds->pool, 0);
 
     /* free or unlink: ds now owns the reference */
     rpmstrPoolFree(pool);
@@ -989,7 +989,7 @@ int rpmdsRpmlib(rpmds * dsp, const void * tblp)
        rpmdsFree(ds);
     }
     if (*dsp)
-       rpmstrPoolFreeze((*dsp)->pool);
+       rpmstrPoolFreeze((*dsp)->pool, 0);
     return rc;
 }
 
index 6f61b70..826b0d2 100644 (file)
@@ -1253,7 +1253,7 @@ rpmfi rpmfiNewPool(rpmstrPool pool, Header h, rpmTagVal tagN, rpmfiFlags flags)
 
            /* freeze the pool to save memory, but only if private pool */
            if (fi->pool != pool)
-               rpmstrPoolFreeze(fi->pool);
+               rpmstrPoolFreeze(fi->pool, 0);
 
            fi->h = (fi->fiflags & RPMFI_KEEPHEADER) ? headerLink(h) : NULL;
        } else {
index 38b676c..5792471 100644 (file)
@@ -25,6 +25,7 @@ struct rpmstrPool_s {
     size_t data_size;          /* string data area size */
     size_t data_alloced;       /* string data area allocation size */
     strHash hash;              /* string -> sid hash table */
+    int frozen;                        /* are new id additions allowed? */
     int nrefs;                 /* refcount */
 };
 
@@ -58,28 +59,38 @@ rpmstrPool rpmstrPoolLink(rpmstrPool pool)
     return pool;
 }
 
-void rpmstrPoolFreeze(rpmstrPool pool)
+void rpmstrPoolFreeze(rpmstrPool pool, int keephash)
 {
-    if (pool && pool->hash) {
-       pool->hash = strHashFree(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));
+    if (pool && !pool->frozen) {
+       /*
+        * realloc() might require rehashing even when downsizing,
+        * dont bother unless we're also discarding the hash.
+        */
+       if (!keephash) {
+           pool->hash = strHashFree(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->frozen = 1;
     }
 }
 
 void rpmstrPoolUnfreeze(rpmstrPool pool)
 {
-    if (pool && pool->hash == NULL) {
-       int sizehint = (pool->offs_size / 2) - 1;
-       if (sizehint < STRHASH_INITSIZE)
-           sizehint = STRHASH_INITSIZE;
-       pool->hash = strHashCreate(sizehint, rstrhash, strcmp, NULL, NULL);
-       for (int i = 1; i < pool->offs_size; i++) {
-           strHashAddEntry(pool->hash, rpmstrPoolStr(pool, i), i);
+    if (pool) {
+       if (pool->hash == NULL) {
+           int sizehint = (pool->offs_size / 2) - 1;
+           if (sizehint < STRHASH_INITSIZE)
+               sizehint = STRHASH_INITSIZE;
+           pool->hash = strHashCreate(sizehint, rstrhash, strcmp, NULL, NULL);
+           for (int i = 1; i < pool->offs_size; i++) {
+               strHashAddEntry(pool->hash, rpmstrPoolStr(pool, i), i);
+           }
        }
+       pool->frozen = 0;
     }
 }
 
@@ -130,7 +141,7 @@ rpmsid rpmstrPoolIdn(rpmstrPool pool, const char *s, size_t slen, int create)
        rpmsid *sids;
        if (strHashGetHEntry(pool->hash, s, hash, &sids, NULL, NULL)) {
            sid = sids[0];
-       } else if (create) {
+       } else if (create && !pool->frozen) {
            sid = rpmstrPoolPut(pool, s, slen, hash);
        }
     }
index 958a470..67e1620 100644 (file)
@@ -18,8 +18,8 @@ rpmstrPool rpmstrPoolFree(rpmstrPool sidpool);
 /* reference a string pool */
 rpmstrPool rpmstrPoolLink(rpmstrPool sidpool);
 
-/* freeze pool to free memory */
-void rpmstrPoolFreeze(rpmstrPool sidpool);
+/* freeze pool to free memory (keephash required for string -> id lookups) */
+void rpmstrPoolFreeze(rpmstrPool sidpool, int keephash);
 
 /* unfreeze pool (ie recreate hash table) */
 void rpmstrPoolUnfreeze(rpmstrPool sidpool);