diff --git a/lib/backend/db3.c b/lib/backend/db3.c index ed6815c79..4b5500ed0 100644 --- a/lib/backend/db3.c +++ b/lib/backend/db3.c @@ -350,21 +350,27 @@ dbiIndexType dbiType(dbiIndex dbi) return dbi->dbi_type; } -int dbiStat(dbiIndex dbi, unsigned int flags) +int dbiNumKeys(dbiIndex dbi, int fast) { DB * db = dbi->dbi_db; - DB_TXN * txnid = NULL; - int rc = 0; + int rc, nkeys = -1; + void *sp = NULL; - assert(db != NULL); - if (flags) - flags = DB_FAST_STAT; - else - flags = 0; - dbi->dbi_stats = _free(dbi->dbi_stats); - rc = db->stat(db, txnid, &dbi->dbi_stats, flags); + rc = db->stat(db, dbi->dbi_txnid, &sp, fast ? DB_FAST_STAT : 0); rc = cvtdberr(dbi, "db->stat", rc, _debug); - return rc; + + if (rc == 0 && sp) { + if (dbi->dbi_dbtype == DB_HASH) { + DB_HASH_STAT *hash = sp; + nkeys = hash->hash_nkeys; + } else if (dbi->dbi_dbtype == DB_BTREE) { + DB_BTREE_STAT *btree = sp; + nkeys = btree->bt_nkeys; + } + free(sp); + } + + return nkeys; } int dbiVerify(dbiIndex dbi, unsigned int flags) diff --git a/lib/backend/dbconfig.c b/lib/backend/dbconfig.c index 750c67a5c..aaa5cef6d 100644 --- a/lib/backend/dbconfig.c +++ b/lib/backend/dbconfig.c @@ -119,7 +119,6 @@ static const struct poptOption rdbOptions[] = { dbiIndex dbiFree(dbiIndex dbi) { if (dbi) { - dbi->dbi_stats = _free(dbi->dbi_stats); dbi = _free(dbi); } return dbi; diff --git a/lib/backend/dbi.h b/lib/backend/dbi.h index 4990cfad5..3bae2a425 100644 --- a/lib/backend/dbi.h +++ b/lib/backend/dbi.h @@ -49,7 +49,6 @@ struct _dbiIndex { DB * dbi_db; /*!< Berkeley DB * handle */ DB_TXN * dbi_txnid; /*!< Bekerley DB_TXN * transaction id */ - void * dbi_stats; /*!< Berkeley db statistics */ }; /** \ingroup dbi @@ -197,13 +196,13 @@ RPM_GNUC_INTERNAL int dbiByteSwapped(dbiIndex dbi); /** \ingroup dbi - * Is database byte swapped? + * Return number of keys in index * @param dbi index database handle - * @param flags DB_FAST_STAT or 0 - * @return 0 on success + * @param fast fast, cached estimate or slow but accurate? + * @return number of keys in index, -1 on error */ RPM_GNUC_INTERNAL -int dbiStat(dbiIndex dbi, unsigned int flags); +int dbiNumKeys(dbiIndex dbi, int fast); /** \ingroup dbi * Type of dbi (primary data / index) diff --git a/lib/rpmdb.c b/lib/rpmdb.c index e324667eb..d15403ab8 100644 --- a/lib/rpmdb.c +++ b/lib/rpmdb.c @@ -178,20 +178,15 @@ static dbiIndex rpmdbOpenIndex(rpmdb db, rpmTag rpmtag, unsigned int flags) if (dbi != NULL && rc == 0) { db->_dbi[dbix] = dbi; + /* Grab a fast estimate of package count for allocation */ if (rpmtag == RPMDBI_PACKAGES && db->db_bits == NULL) { - db->db_nbits = 1024; - if (!dbiStat(dbi, DB_FAST_STAT)) { - DB_HASH_STAT * hash = (DB_HASH_STAT *)dbi->dbi_stats; - if (hash) - db->db_nbits += hash->hash_nkeys; - } + int nkeys = dbiNumKeys(dbi, 1); + db->db_nbits = 1024 + (nkeys > 0 ? nkeys : 0); db->db_bits = PBM_ALLOC(db->db_nbits); } - } -#ifdef HAVE_DB_H - else + } else { dbi = dbiFree(dbi); -#endif + } /* FIX: db->_dbi may be NULL */ return dbi; @@ -687,6 +682,13 @@ int rpmdbClose(rpmdb db) int xx; if (db->_dbi[dbix] == NULL) continue; + + /* Force full statistics generation at package db close */ + if (dbiTags[dbix] == RPMDBI_PACKAGES && + (db->db_mode & O_ACCMODE) != O_RDONLY) { + (void) dbiNumKeys(db->_dbi[dbix], 0); + } + xx = dbiClose(db->_dbi[dbix], 0); if (xx && rc == 0) rc = xx; db->_dbi[dbix] = NULL;