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

Reply via email to