Hi, I'm working on a way to pass per-architecture package counts to scriptlets [1]. Jeff Johnson suggested creating a new database index for this purpose [2].
Attached are two patches against Fedora 9's rpm. The first adds a Namearch index to the RPM database. The second uses Namearch to implement a new rpmlib function, rpmdbCountPackagesArch. A few observations about patch 1, from testing on Fedora 9 i386: - A new tag type, RPMTAG_NAMEARCH, is introduced. It does not represent a real header tag; it's only used in rpmdb.c to maintain the Namearch index. - An RPM database rebuild is required. - The time it takes to rebuild the database is not affected by the addition of the new index. - /var/lib/rpm/Namearch on my machine is 84K. - Namearch does not index headers that have NULL arch tags, like GPG key entries. Patch 2 observations: - rpmdbCountPackagesArch matches rpmdbCountPackages's performance. - rpmdbCountPackages's performance is not affected by this patch. - If the Namearch index is not present (i.e. if rpm --rebuilddb has not been run yet) rpmdbCountPackagesArch produces incorrect results. These patches form the basis for whatever mechanism we choose to pass the new information to scriptlets, whether it be re-using the existing $1 and $2 arguments, adding additional arguments or introducing new environment variables. That's a subject for another thread though. For now I'd like feedback on these initial patches. Tom 1. https://bugzilla.redhat.com/show_bug.cgi?id=340391 2. https://lists.dulug.duke.edu/pipermail/rpm-devel/2007-February/002075.html
diff -up rpm-4.4.2.3/lib/rpmlib.h.namearch-index rpm-4.4.2.3/lib/rpmlib.h --- rpm-4.4.2.3/lib/rpmlib.h.namearch-index 2008-06-27 12:21:48.000000000 -0400 +++ rpm-4.4.2.3/lib/rpmlib.h 2008-06-27 12:21:48.000000000 -0400 @@ -448,6 +448,7 @@ typedef enum rpmTag_e { RPMTAG_CVSID = 1163, /* s */ #define RPMTAG_SVNID RPMTAG_CVSID /* s */ RPMTAG_TRIGGERPREIN = 1171, /*!< internal */ + RPMTAG_NAMEARCH = 1172, /* s */ /[EMAIL PROTECTED]@*/ RPMTAG_FIRSTFREE_TAG /*!< internal */ diff -up rpm-4.4.2.3/macros.in.namearch-index rpm-4.4.2.3/macros.in --- rpm-4.4.2.3/macros.in.namearch-index 2008-06-27 12:21:48.000000000 -0400 +++ rpm-4.4.2.3/macros.in 2008-06-27 12:21:48.000000000 -0400 @@ -600,7 +600,7 @@ print (t)\ %{nil} # The list of tags for which indices will be built. -%_dbi_tags Packages:Name:Basenames:Group:Requirename:Providename:Conflictname:Triggername:Dirnames:Requireversion:Provideversion:Installtid:Sigmd5:Sha1header:Filemd5s:Depends:Pubkeys +%_dbi_tags Packages:Name:Basenames:Group:Requirename:Providename:Conflictname:Triggername:Dirnames:Requireversion:Provideversion:Installtid:Sigmd5:Sha1header:Filemd5s:Depends:Pubkeys:Namearch # "Packages" should have shared/exclusive fcntl(2) lock using "lockdbfd". %_dbi_config_Packages %{_dbi_htconfig} lockdbfd diff -up rpm-4.4.2.3/rpmdb/rpmdb.c.namearch-index rpm-4.4.2.3/rpmdb/rpmdb.c --- rpm-4.4.2.3/rpmdb/rpmdb.c.namearch-index 2008-04-01 03:28:22.000000000 -0400 +++ rpm-4.4.2.3/rpmdb/rpmdb.c 2008-06-27 12:21:48.000000000 -0400 @@ -118,6 +118,42 @@ static inline pbm_set * PBM_REALLOC(pbm_ /[EMAIL PROTECTED] =retalias [EMAIL PROTECTED]/ } +static char * createNamearchTag(Header h, HGE_t hge, HFD_t hfd) +{ + const char ** rpmnamevals = NULL; + const char * name = NULL; + int namelen = 0; + const char ** rpmarchvals = NULL; + const char * arch = NULL; + int archlen = 0; + char * rpmval = NULL; + + hge(h, RPMTAG_NAME, NULL, (void **) &rpmnamevals, NULL); + if (rpmnamevals == NULL) + return NULL; + name = (const char *) rpmnamevals; + namelen = strlen(name); + + hge(h, RPMTAG_ARCH, NULL, (void **) &rpmarchvals, NULL); + if (rpmarchvals == NULL) { + hfd(rpmnamevals, RPM_STRING_TYPE); + return NULL; + } + arch = (const char *) rpmarchvals; + archlen = strlen(arch); + + rpmval = (char *) xmalloc(namelen + archlen + 2); + memcpy(rpmval, name, namelen); + rpmval[namelen] = ' '; + memcpy(rpmval + namelen + 1, arch, archlen); + rpmval[namelen + archlen + 1] = '\0'; + + hfd(rpmnamevals, RPM_STRING_TYPE); + hfd(rpmarchvals, RPM_STRING_TYPE); + + return rpmval; +} + /** * Convert hex to binary nibble. * @param c hex character @@ -181,7 +217,7 @@ static void dbiTagsInit(void) { /[EMAIL PROTECTED]@*/ static const char * const _dbiTagStr_default = - "Packages:Name:Basenames:Group:Requirename:Providename:Conflictname:Triggername:Dirnames:Requireversion:Provideversion:Installtid:Sigmd5:Sha1header:Filemd5s:Depends:Pubkeys"; + "Packages:Name:Basenames:Group:Requirename:Providename:Conflictname:Triggername:Dirnames:Requireversion:Provideversion:Installtid:Sigmd5:Sha1header:Filemd5s:Depends:Pubkeys:Namearch"; char * dbiTagStr = NULL; char * o, * oe; int rpmtag; @@ -2735,8 +2795,16 @@ if (dbiByteSwapped(dbi) == 1) } /[EMAIL PROTECTED]@*/ - if (!hge(h, rpmtag, &rpmtype, (void **) &rpmvals, &rpmcnt)) - continue; + if (rpmtag == RPMTAG_NAMEARCH) { + rpmvals = (const char **) createNamearchTag(h, hge, hfd); + if (rpmvals == NULL) + continue; + rpmtype = RPM_STRING_TYPE; + rpmcnt = 1; + } else { + if (!hge(h, rpmtag, &rpmtype, (void **) &rpmvals, &rpmcnt)) + continue; + } dbi = dbiOpen(db, rpmtag, 0); if (dbi != NULL) { @@ -3155,6 +3223,13 @@ data->size = 0; xx = hge(h, rpmtag, &rpmtype, (void **)&rpmvals, &rpmcnt); xx = hge(h, RPMTAG_REQUIREFLAGS, NULL, (void **)&requireFlags, NULL); /[EMAIL PROTECTED]@*/ break; + case RPMTAG_NAMEARCH: + rpmvals = (const char **) createNamearchTag(h, hge, hfd); + if (rpmvals == NULL) + continue; + rpmtype = RPM_STRING_TYPE; + rpmcnt = 1; + /[EMAIL PROTECTED]@*/ break; default: xx = hge(h, rpmtag, &rpmtype, (void **)&rpmvals, &rpmcnt); /[EMAIL PROTECTED]@*/ break;
diff -up rpm-4.4.2.3/rpmdb/rpmdb.c.namearch-count rpm-4.4.2.3/rpmdb/rpmdb.c --- rpm-4.4.2.3/rpmdb/rpmdb.c.namearch-count 2008-06-27 12:21:48.000000000 -0400 +++ rpm-4.4.2.3/rpmdb/rpmdb.c 2008-06-27 12:21:48.000000000 -0400 @@ -1387,7 +1387,7 @@ if (rc == 0) } /* XXX python/upgrade.c, install.c, uninstall.c */ -int rpmdbCountPackages(rpmdb db, const char * name) +static int rpmdbCountIndex(rpmdb db, rpmTag rpmtype, const char * str) { DBC * dbcursor = NULL; DBT * key = alloca(sizeof(*key)); @@ -1402,14 +1402,14 @@ DBT * data = alloca(sizeof(*data)); memset(key, 0, sizeof(*key)); memset(data, 0, sizeof(*data)); - dbi = dbiOpen(db, RPMTAG_NAME, 0); + dbi = dbiOpen(db, rpmtype, 0); if (dbi == NULL) return 0; /[EMAIL PROTECTED]@*/ -key->data = (void *) name; +key->data = (void *) str; /[EMAIL PROTECTED]@*/ -key->size = strlen(name); +key->size = strlen(str); xx = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, 0); rc = dbiGet(dbi, dbcursor, key, data, DB_SET); @@ -1446,6 +1446,30 @@ key->size = strlen(name); return rc; } +int rpmdbCountPackages(rpmdb db, const char * name) +{ + return rpmdbCountIndex(db, RPMTAG_NAME, name); +} + +int rpmdbCountPackagesArch(rpmdb db, const char * name, const char * arch) +{ + char * namearch = NULL; + int count = 0; + int namelen = 0; + int archlen = 0; + + namelen = strlen(name); + archlen = strlen(arch); + namearch = (char *) xmalloc(namelen + archlen + 2); + memcpy(namearch, name, namelen); + namearch[namelen] = ' '; + memcpy(namearch + namelen + 1, arch, archlen); + namearch[namelen + archlen + 1] = '\0'; + count = rpmdbCountIndex(db, RPMTAG_NAMEARCH, namearch); + _free(namearch); + return count; +} + /** * Attempt partial matches on name[-version[-release]] strings. * @param dbi index database handle (always RPMTAG_NAME) diff -up rpm-4.4.2.3/rpmdb/rpmdb.h.namearch-count rpm-4.4.2.3/rpmdb/rpmdb.h --- rpm-4.4.2.3/rpmdb/rpmdb.h.namearch-count 2008-04-01 03:28:22.000000000 -0400 +++ rpm-4.4.2.3/rpmdb/rpmdb.h 2008-06-27 12:21:48.000000000 -0400 @@ -932,6 +932,17 @@ int rpmdbCountPackages(/[EMAIL PROTECTED]@*/ rpmdb /[EMAIL PROTECTED] db, rpmGlobalMacroContext, fileSystem, internalState @*/; /** \ingroup rpmdb + * Return number of instances per architecture of package in rpm + * database. + * @param db rpm database + * @param name rpm package name + * @param arch rpm package architecture + * @return number of instances + */ +int rpmdbCountPackagesArch(/[EMAIL PROTECTED]@*/ rpmdb db, const char * name, + const char * arch); + +/** \ingroup rpmdb * Return header join key for current position of rpm database iterator. * @param mi rpm database iterator * @return current header join key
_______________________________________________ Rpm-maint mailing list Rpm-maint@lists.rpm.org https://lists.rpm.org/mailman/listinfo/rpm-maint