Refcount dbiTags on db open+close, automatically free
authorPanu Matilainen <pmatilai@redhat.com>
Wed, 12 Mar 2008 11:20:47 +0000 (13:20 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Wed, 12 Mar 2008 11:20:47 +0000 (13:20 +0200)
- avoids rpmdb_internal include in rpmqv.c and memleak in API clients
- avoids having to export dbiTags(Max) at all

rpmdb/rpmdb.c
rpmdb/rpmdb_internal.h
rpmqv.c

index bde9374..f31a97f 100644 (file)
@@ -40,8 +40,14 @@ static int _db_filter_dups = 0;
 #define        _DBI_PERMS      0644
 #define        _DBI_MAJOR      -1
 
-rpmTag * dbiTags = NULL;
-rpmTag dbiTagsMax = 0;
+struct dbiTags_s {
+    rpmTag * tags;
+    rpmTag max;
+    int nlink;
+};
+
+/* XXX should dbitags be per-db instead? */
+static struct dbiTags_s dbiTags = { NULL, 0, 0 };
 
 /* We use this to comunicate back to the the rpm transaction
  *  what their install instance was on a rpmdbAdd().
@@ -128,9 +134,9 @@ static int dbiTagToDbix(rpmTag rpmtag)
 {
     int dbix;
 
-    if (dbiTags != NULL)
-    for (dbix = 0; dbix < dbiTagsMax; dbix++) {
-       if (rpmtag == dbiTags[dbix])
+    if (dbiTags.tags != NULL)
+    for (dbix = 0; dbix < dbiTags.max; dbix++) {
+       if (rpmtag == dbiTags.tags[dbix])
            return dbix;
     }
     return -1;
@@ -147,6 +153,11 @@ static void dbiTagsInit(void)
     char * o, * oe;
     rpmTag rpmtag;
 
+    dbiTags.nlink++;
+    if (dbiTags.tags != NULL && dbiTags.max > 0) {
+       return;
+    }
+
     dbiTagStr = rpmExpand("%{?_dbi_tags}", NULL);
     if (!(dbiTagStr && *dbiTagStr)) {
        dbiTagStr = _free(dbiTagStr);
@@ -154,12 +165,12 @@ static void dbiTagsInit(void)
     }
 
     /* Discard previous values. */
-    dbiTags = _free(dbiTags);
-    dbiTagsMax = 0;
+    dbiTags.tags = _free(dbiTags.tags);
+    dbiTags.max = 0;
 
     /* Always allocate package index */
-    dbiTags = xcalloc(1, sizeof(*dbiTags));
-    dbiTags[dbiTagsMax++] = RPMDBI_PACKAGES;
+    dbiTags.tags = xcalloc(1, sizeof(*dbiTags.tags));
+    dbiTags.tags[dbiTags.max++] = RPMDBI_PACKAGES;
 
     for (o = dbiTagStr; o && *o; o = oe) {
        while (*o && xisspace(*o))
@@ -183,13 +194,22 @@ static void dbiTagsInit(void)
        if (dbiTagToDbix(rpmtag) >= 0)
            continue;
 
-       dbiTags = xrealloc(dbiTags, (dbiTagsMax + 1) * sizeof(*dbiTags)); /* XXX memory leak */
-       dbiTags[dbiTagsMax++] = rpmtag;
+       dbiTags.tags = xrealloc(dbiTags.tags, (dbiTags.max + 1) * sizeof(*dbiTags.tags)); /* XXX memory leak */
+       dbiTags.tags[dbiTags.max++] = rpmtag;
     }
 
     dbiTagStr = _free(dbiTagStr);
 }
 
+static void dbiTagsFree(void)
+{
+    if (--dbiTags.nlink > 0) {
+       return;
+    }
+    dbiTags.tags = _free(dbiTags.tags);
+    dbiTags.max = 0;
+}
+
 #define        DB1vec          NULL
 #define        DB2vec          NULL
 
@@ -222,7 +242,7 @@ dbiIndex dbiOpen(rpmdb db, rpmTag rpmtag, unsigned int flags)
        return NULL;
 
     dbix = dbiTagToDbix(rpmtag);
-    if (dbix < 0 || dbix >= dbiTagsMax)
+    if (dbix < 0 || dbix >= dbiTags.max)
        return NULL;
 
     /* Is this index already open ? */
@@ -757,14 +777,14 @@ int rpmdbOpenAll(rpmdb db)
 
     if (db == NULL) return -2;
 
-    if (dbiTags != NULL)
-    for (dbix = 0; dbix < dbiTagsMax; dbix++) {
+    if (dbiTags.tags != NULL)
+    for (dbix = 0; dbix < dbiTags.max; dbix++) {
        if (db->_dbi[dbix] != NULL)
            continue;
        /* Filter out temporary databases */
-       if (isTemporaryDB(dbiTags[dbix])) 
+       if (isTemporaryDB(dbiTags.tags[dbix])) 
            continue;
-       (void) dbiOpen(db, dbiTags[dbix], db->db_flags);
+       (void) dbiOpen(db, dbiTags.tags[dbix], db->db_flags);
     }
     return rc;
 }
@@ -774,11 +794,11 @@ int rpmdbCloseDBI(rpmdb db, rpmTag rpmtag)
     int dbix;
     int rc = 0;
 
-    if (db == NULL || db->_dbi == NULL || dbiTags == NULL)
+    if (db == NULL || db->_dbi == NULL || dbiTags.tags == NULL)
        return 0;
 
-    for (dbix = 0; dbix < dbiTagsMax; dbix++) {
-       if (dbiTags[dbix] != rpmtag)
+    for (dbix = 0; dbix < dbiTags.max; dbix++) {
+       if (dbiTags.tags[dbix] != rpmtag)
            continue;
        if (db->_dbi[dbix] != NULL) {
            int xx;
@@ -832,6 +852,8 @@ int rpmdbClose(rpmdb db)
 
     db = _free(db);
 
+    dbiTagsFree();
+
 exit:
     (void) rpmsqEnable(-SIGHUP,        NULL);
     (void) rpmsqEnable(-SIGINT,        NULL);
@@ -915,7 +937,7 @@ rpmdb newRpmdb(const char * root,
     db->db_errpfx = rpmExpand( (epfx && *epfx ? epfx : _DB_ERRPFX), NULL);
     db->db_remove_env = 0;
     db->db_filter_dups = _db_filter_dups;
-    db->db_ndbi = dbiTagsMax;
+    db->db_ndbi = dbiTags.max;
     db->_dbi = xcalloc(db->db_ndbi, sizeof(*db->_dbi));
     db->nrefs = 0;
     return rpmdbLink(db, RPMDBG_M("rpmdbCreate"));
@@ -928,14 +950,10 @@ static int openDatabase(const char * prefix,
 {
     rpmdb db;
     int rc, xx;
-    static int _tags_initialized = 0;
     int justCheck = flags & RPMDB_FLAG_JUSTCHECK;
     int minimal = flags & RPMDB_FLAG_MINIMAL;
 
-    if (!_tags_initialized || dbiTagsMax == 0) {
-       dbiTagsInit();
-       _tags_initialized++;
-    }
+    dbiTagsInit();
 
     /* Insure that _dbapi has one of -1, 1, 2, or 3 */
     if (_dbapi < -1 || _dbapi > 4)
@@ -963,13 +981,13 @@ static int openDatabase(const char * prefix,
     {  int dbix;
 
        rc = 0;
-       if (dbiTags != NULL)
-       for (dbix = 0; rc == 0 && dbix < dbiTagsMax; dbix++) {
+       if (dbiTags.tags != NULL)
+       for (dbix = 0; rc == 0 && dbix < dbiTags.max; dbix++) {
            dbiIndex dbi;
            rpmTag rpmtag;
 
            /* Filter out temporary databases */
-           if (isTemporaryDB((rpmtag = dbiTags[dbix])))
+           if (isTemporaryDB((rpmtag = dbiTags.tags[dbix])))
                continue;
 
            dbi = dbiOpen(db, rpmtag, 0);
@@ -2466,8 +2484,8 @@ memset(data, 0, sizeof(*data));
     {  int dbix;
        dbiIndexItem rec = dbiIndexNewItem(hdrNum, 0);
 
-       if (dbiTags != NULL)
-       for (dbix = 0; dbix < dbiTagsMax; dbix++) {
+       if (dbiTags.tags != NULL)
+       for (dbix = 0; dbix < dbiTags.max; dbix++) {
            dbiIndex dbi;
            const char *av[1];
            const char ** rpmvals = NULL;
@@ -2478,7 +2496,7 @@ memset(data, 0, sizeof(*data));
            rpm_count_t i, j;
 
            dbi = NULL;
-           rpmtag = dbiTags[dbix];
+           rpmtag = dbiTags.tags[dbix];
 
            /* Filter out temporary databases */
            if (isTemporaryDB(rpmtag)) 
@@ -2820,8 +2838,8 @@ memset(data, 0, sizeof(*data));
        /* Save the header number for the current transaction. */
        myinstall_instance = hdrNum;
        
-       if (dbiTags != NULL)
-       for (dbix = 0; dbix < dbiTagsMax; dbix++) {
+       if (dbiTags.tags != NULL)
+       for (dbix = 0; dbix < dbiTags.max; dbix++) {
            const char *av[1];
            const char **rpmvals = NULL;
            rpmTagType rpmtype = 0;
@@ -2834,7 +2852,7 @@ memset(data, 0, sizeof(*data));
            rpmrc = RPMRC_NOTFOUND;
            dbi = NULL;
            requireFlags = NULL;
-           rpmtag = dbiTags[dbix];
+           rpmtag = dbiTags.tags[dbix];
 
            /* Filter out temporary databases */
            if (isTemporaryDB(rpmtag)) 
@@ -3277,9 +3295,9 @@ static int rpmdbRemoveDatabase(const char * prefix,
     switch (_dbapi) {
     case 4:
     case 3:
-       if (dbiTags != NULL)
-       for (i = 0; i < dbiTagsMax; i++) {
-           const char * base = rpmTagGetName(dbiTags[i]);
+       if (dbiTags.tags != NULL)
+       for (i = 0; i < dbiTags.max; i++) {
+           const char * base = rpmTagGetName(dbiTags.tags[i]);
            sprintf(filename, "%s/%s/%s", prefix, dbpath, base);
            (void)rpmCleanPath(filename);
            if (!rpmioFileExists(filename))
@@ -3342,13 +3360,13 @@ static int rpmdbMoveDatabase(const char * prefix,
     case 4:
         /* Fall through */
     case 3:
-       if (dbiTags != NULL)
-       for (i = 0; i < dbiTagsMax; i++) {
+       if (dbiTags.tags != NULL)
+       for (i = 0; i < dbiTags.max; i++) {
            const char * base;
            rpmTag rpmtag;
 
            /* Filter out temporary databases */
-           if (isTemporaryDB((rpmtag = dbiTags[i])))
+           if (isTemporaryDB((rpmtag = dbiTags.tags[i])))
                continue;
 
            base = rpmTagGetName(rpmtag);
index b69d4e3..d5f4050 100644 (file)
@@ -652,12 +652,6 @@ unsigned int dbiIndexRecordOffset(dbiIndexSet set, int recno);
  */
 unsigned int dbiIndexRecordFileNumber(dbiIndexSet set, int recno);
 
-/** \ingroup rpmdb
- * Tags for which rpmdb indices will be built.
- */
-extern rpmTag * dbiTags;
-extern rpmTag dbiTagsMax;
-
 #ifndef __APPLE__
 /**
  *  * Mergesort, same arguments as qsort(2).
diff --git a/rpmqv.c b/rpmqv.c
index 1db5f1e..1544ac8 100644 (file)
--- a/rpmqv.c
+++ b/rpmqv.c
@@ -20,8 +20,6 @@ const char *__progname;
 #include <rpm/rpmps.h>
 #include <rpm/rpmts.h>
 
-#include "rpmdb/rpmdb_internal.h"      /* XXX for freeing dbiTags */
-
 #ifdef IAM_RPMBT
 #include "build.h"
 #define GETOPT_REBUILD         1003
@@ -855,8 +853,6 @@ exit:
     /* keeps memory leak checkers quiet */
     rpmFreeFilesystems();
     rpmlogClose();
-    /* XXX FIXME: hide this in the api */
-    dbiTags = _free(dbiTags);
 
 #ifdef IAM_RPMQV
     qva->qva_queryFormat = _free(qva->qva_queryFormat);