Add infastructure for global transaction set string pool
authorPanu Matilainen <pmatilai@redhat.com>
Wed, 12 Sep 2012 10:37:54 +0000 (13:37 +0300)
committerPanu Matilainen <pmatilai@redhat.com>
Wed, 12 Sep 2012 10:37:54 +0000 (13:37 +0300)
- Add a pool pointer to to ts members struct and a getter function
- Grab the global pool for rpmte dependency- and file info creation,
  if its NULL then the sets will use private pools of their own.
- Add the (currently) required magic voodoo rain-dance to freeze and
  unfreeze the pool as necessary wrt new element additions: for
  current rpmal and fingerprinting to work, the string pointers
  must be immovable.
- This is infrastructure only: nothing creates the global pool yet,
  so everything is still using private pools.

lib/depends.c
lib/rpmte.c
lib/rpmts.c
lib/rpmts.h
lib/rpmts_internal.h
lib/transaction.c

index 2ee7e0d..e852344 100644 (file)
@@ -101,6 +101,10 @@ static int removePackage(rpmts ts, Header h, rpmte depends)
         return 0;
     }
 
+    /* Ensure pool is writable */
+    if (tsmem->addedPackages != NULL)
+       rpmstrPoolUnfreeze(tsmem->pool);
+
     p = rpmteNew(ts, h, TR_REMOVED, NULL, NULL);
     if (p == NULL)
        return 1;
@@ -320,6 +324,9 @@ rpmal rpmtsCreateAl(rpmts ts, rpmElementTypes types)
        rpmte p;
        rpmtsi pi;
 
+       /* Required for now to lock string pointers in memory */
+       rpmstrPoolFreeze(rpmtsPool(ts));
+
        al = rpmalCreate((rpmtsNElements(ts) / 4) + 1, rpmtsFlags(ts),
                                rpmtsColor(ts), rpmtsPrefColor(ts));
        pi = rpmtsiInit(ts);
@@ -356,6 +363,10 @@ int rpmtsAddInstallElement(rpmts ts, Header h,
            goto exit;
     }
 
+    /* Ensure pool is writable */
+    if (tsmem->addedPackages != NULL)
+       rpmstrPoolUnfreeze(tsmem->pool);
+
     p = rpmteNew(ts, h, TR_ADDED, key, relocs);
     if (p == NULL) {
        ec = 1;
index 38a89f2..8e85052 100644 (file)
@@ -99,7 +99,7 @@ static rpmfi getFI(rpmte p, Header h)
            rpmRelocateFileList(p->relocs, p->nrelocs, p->fs, h);
        }
     }
-    return rpmfiNew(NULL, h, RPMTAG_BASENAMES, fiflags);
+    return rpmfiNewPool(rpmtsPool(p->ts), h, RPMTAG_BASENAMES, fiflags);
 }
 
 /* stupid bubble sort, but it's probably faster here */
@@ -203,6 +203,7 @@ static void buildRelocs(rpmte p, Header h, rpmRelocation *relocs)
  */
 static int addTE(rpmte p, Header h, fnpyKey key, rpmRelocation * relocs)
 {
+    rpmstrPool tspool = rpmtsPool(p->ts);
     struct rpmtd_s colls, bnames;
     int rc = 1; /* assume failure */
 
@@ -241,12 +242,13 @@ static int addTE(rpmte p, Header h, fnpyKey key, rpmRelocation * relocs)
     p->pkgFileSize = 0;
     p->headerSize = headerSizeof(h, HEADER_MAGIC_NO);
 
+    /* XXX thisds not in global pool yet, but not strictly needed either */
     p->thisds = rpmdsThis(h, RPMTAG_PROVIDENAME, RPMSENSE_EQUAL);
-    p->provides = rpmdsNew(h, RPMTAG_PROVIDENAME, 0);
-    p->requires = rpmdsNew(h, RPMTAG_REQUIRENAME, 0);
-    p->conflicts = rpmdsNew(h, RPMTAG_CONFLICTNAME, 0);
-    p->obsoletes = rpmdsNew(h, RPMTAG_OBSOLETENAME, 0);
-    p->order = rpmdsNew(h, RPMTAG_ORDERNAME, 0);
+    p->provides = rpmdsNewPool(tspool, h, RPMTAG_PROVIDENAME, 0);
+    p->requires = rpmdsNewPool(tspool, h, RPMTAG_REQUIRENAME, 0);
+    p->conflicts = rpmdsNewPool(tspool, h, RPMTAG_CONFLICTNAME, 0);
+    p->obsoletes = rpmdsNewPool(tspool, h, RPMTAG_OBSOLETENAME, 0);
+    p->order = rpmdsNewPool(tspool, h, RPMTAG_ORDERNAME, 0);
 
     /* Relocation needs to know file count before rpmfiNew() */
     headerGet(h, RPMTAG_BASENAMES, &bnames, HEADERGET_MINMEM);
index abf8a2b..c8ecb9c 100644 (file)
@@ -584,6 +584,8 @@ void rpmtsEmpty(rpmts ts)
     }
 
     tsmem->orderCount = 0;
+    /* XXX emptying would be sufficient... */
+    tsmem->pool = rpmstrPoolFree(tsmem->pool);
     removedHashEmpty(tsmem->removedPackages);
     return;
 }
@@ -927,6 +929,12 @@ tsMembers rpmtsMembers(rpmts ts)
     return (ts != NULL) ? ts->members : NULL;
 }
 
+rpmstrPool rpmtsPool(rpmts ts)
+{
+    tsMembers tsmem = rpmtsMembers(ts);
+    return (tsmem != NULL) ? tsmem->pool : NULL;
+}
+
 rpmts rpmtsCreate(void)
 {
     rpmts ts;
@@ -974,6 +982,7 @@ rpmts rpmtsCreate(void)
     }
 
     tsmem = xcalloc(1, sizeof(*ts->members));
+    tsmem->pool = NULL;
     tsmem->delta = 5;
     tsmem->addedPackages = NULL;
     tsmem->removedPackages = removedHashCreate(128, uintId, uintCmp, NULL, NULL);
index 0b8d970..2f0dcaf 100644 (file)
@@ -527,6 +527,13 @@ int rpmtsSetNotifyCallback(rpmts ts,
 rpmts rpmtsCreate(void);
 
 /** \ingroup rpmts
+ * Return transaction global string pool handle
+ * @param ts           transaction set
+ * @return             string pool handle (weak ref)
+ */
+rpmstrPool rpmtsPool(rpmts ts);
+
+/** \ingroup rpmts
  * Add package to be installed to transaction set.
  *
  * The transaction set is checked for duplicate package names.
index 5d3240c..a942910 100644 (file)
@@ -2,6 +2,7 @@
 #define _RPMTS_INTERNAL_H
 
 #include <rpm/rpmts.h>
+#include <rpm/rpmstrpool.h>
 
 #include "lib/rpmal.h"         /* XXX availablePackage */
 #include "lib/fprint.h"
@@ -11,6 +12,7 @@ typedef struct diskspaceInfo_s * rpmDiskSpaceInfo;
 
 /* Transaction set elements information */
 typedef struct tsMembers_s {
+    rpmstrPool pool;           /*!< Global string pool */
     removedHash removedPackages;       /*!< Set of packages being removed. */
     rpmal addedPackages;       /*!< Set of packages being installed. */
 
index bbe29a5..6240777 100644 (file)
@@ -1475,6 +1475,7 @@ static int rpmtsProcess(rpmts ts)
 int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
 {
     int rc = -1; /* assume failure */
+    tsMembers tsmem = rpmtsMembers(ts);
     rpmlock lock = NULL;
     rpmps tsprobs = NULL;
     /* Force default 022 umask during transaction for consistent results */
@@ -1521,7 +1522,6 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
 
      /* If unfiltered problems exist, free memory and return. */
     if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS) || (rpmpsNumProblems(tsprobs))) {
-       tsMembers tsmem = rpmtsMembers(ts);
        rc = tsmem->orderCount;
        goto exit;
     }
@@ -1530,6 +1530,14 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
     tsprobs = rpmpsFree(tsprobs);
     rpmtsCleanProblems(ts);
 
+    /*
+     * Free up the global string pool unless we expect it to be needed
+     * again. During the transaction, private pools will be used for
+     * rpmfi's etc.
+     */
+    if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS)))
+       tsmem->pool = rpmstrPoolFree(tsmem->pool);
+
     /* Actually install and remove packages, get final exit code */
     rc = rpmtsProcess(ts) ? -1 : 0;