The following commit has been merged in the master branch:
commit 66fae0bda4c7afa60682c8d7bee6261922c45116
Author: Raphaël Hertzog <[email protected]>
Date:   Fri Jan 28 12:29:40 2011 +0100

    libdpkg: Add new multiarch aware in-core database functions
    
    The new functions are:
    
    - pkg_db_find_set(name)
    - pkg_db_find_pkg(name, arch)
    - pkg_db_iter_next_set(i)
    - pkg_db_iter_next_pkg(i)
    - pkg_db_count_set()
    - pkg_db_count_pkg()
    
    And rework the legacy functions pkg_db_count(), pkg_db_find(name) and
    pkg_db_iter_next(name) to work on top of the new functions.
    
    The pkg_db_find_pkg() function is just a compatibility stub for now,
    so that there's no point in time when dpkg can load multiple package
    instances but not save them to disk, which would imply losing data.
    
    Sponsored-by: Linaro Limited
    
    Signed-off-by: Guillem Jover <[email protected]>

diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h
index db46e11..c75b0a5 100644
--- a/lib/dpkg/dpkg-db.h
+++ b/lib/dpkg/dpkg-db.h
@@ -267,11 +267,17 @@ void pkgbin_blank(struct pkgbin *pifp);
 bool pkg_is_informative(struct pkginfo *pkg, struct pkgbin *info);
 
 struct pkginfo *pkg_db_find(const char *name);
+struct pkgset *pkg_db_find_set(const char *name);
+struct pkginfo *pkg_db_find_pkg(const char *name, const struct dpkg_arch 
*arch);
 int pkg_db_count(void);
+int pkg_db_count_set(void);
+int pkg_db_count_pkg(void);
 void pkg_db_reset(void);
 
 struct pkgiterator *pkg_db_iter_new(void);
 struct pkginfo *pkg_db_iter_next(struct pkgiterator *iter);
+struct pkgset *pkg_db_iter_next_set(struct pkgiterator *iter);
+struct pkginfo *pkg_db_iter_next_pkg(struct pkgiterator *iter);
 void pkg_db_iter_free(struct pkgiterator *iter);
 
 void pkg_db_report(FILE *);
diff --git a/lib/dpkg/libdpkg.Versions b/lib/dpkg/libdpkg.Versions
index d6722bb..86a4152 100644
--- a/lib/dpkg/libdpkg.Versions
+++ b/lib/dpkg/libdpkg.Versions
@@ -219,10 +219,16 @@ LIBDPKG_PRIVATE {
 
        # Package in-core database functions
        pkg_db_find;
+       pkg_db_find_set;
+       pkg_db_find_pkg;
        pkg_db_count;
+       pkg_db_count_set;
+       pkg_db_count_pkg;
        pkg_db_reset;
        pkg_db_iter_new;
        pkg_db_iter_next;
+       pkg_db_iter_next_set;
+       pkg_db_iter_next_pkg;
        pkg_db_iter_free;
 
        # Package on-disk database functions
diff --git a/lib/dpkg/pkg-db.c b/lib/dpkg/pkg-db.c
index 29b0faf..2d3f22b 100644
--- a/lib/dpkg/pkg-db.c
+++ b/lib/dpkg/pkg-db.c
@@ -3,6 +3,8 @@
  * pkg-db.c - Low level package database routines (hash tables, etc.)
  *
  * Copyright © 1995 Ian Jackson <[email protected]>
+ * Copyright © 2011 Linaro Limited
+ * Copyright © 2011 Raphaël Hertzog <[email protected]>
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -37,7 +39,7 @@
 #define BINS 8191
 
 static struct pkgset *bins[BINS];
-static int npackages;
+static int npkg, nset;
 
 #define FNV_offset_basis 2166136261ul
 #define FNV_mixing_prime 16777619ul
@@ -57,8 +59,24 @@ static unsigned int hash(const char *name) {
   return h;
 }
 
-struct pkginfo *
-pkg_db_find(const char *inname)
+/**
+ * Return the package set with the given name.
+ *
+ * If the package already exists in the internal database, then it returns
+ * the existing structure. Otherwise it allocates a new one and will return
+ * it. The actual name associated to the package set is a lowercase version
+ * of the name given in parameter.
+ *
+ * A package set (struct pkgset) can be composed of multiple package instances
+ * (struct pkginfo) where each instance is distinguished by its architecture
+ * (as recorded in pkg.installed.architecture and pkg.available.architecture).
+ *
+ * @param inname Name of the package set.
+ *
+ * @return The package set.
+ */
+struct pkgset *
+pkg_db_find_set(const char *inname)
 {
   struct pkgset **pointerp, *newpkg;
   char *name = m_strdup(inname), *p;
@@ -71,7 +89,7 @@ pkg_db_find(const char *inname)
     pointerp= &(*pointerp)->next;
   if (*pointerp) {
     free(name);
-    return &(*pointerp)->pkg;
+    return *pointerp;
   }
 
   newpkg = nfmalloc(sizeof(struct pkgset));
@@ -79,16 +97,65 @@ pkg_db_find(const char *inname)
   newpkg->name= nfstrsave(name);
   newpkg->next= NULL;
   *pointerp= newpkg;
-  npackages++;
+  nset++;
+  npkg++;
 
   free(name);
-  return &newpkg->pkg;
+  return newpkg;
+}
+
+/**
+ * Return the package instance with the given name and architecture.
+ *
+ * @param name The package name.
+ * @param arch The requested architecture.
+ *
+ * @return The package instance.
+ */
+struct pkginfo *
+pkg_db_find_pkg(const char *name, const struct dpkg_arch *arch)
+{
+  struct pkgset *set;
+  struct pkginfo *pkg;
+
+  set = pkg_db_find_set(name);
+  pkg = &set->pkg;
+
+  return pkg;
+}
+
+struct pkginfo *
+pkg_db_find(const char *name)
+{
+  return pkg_db_find_pkg(name, NULL);
+}
+
+/**
+ * Return the number of package sets available in the database.
+ *
+ * @return The number of package sets.
+ */
+int
+pkg_db_count_set(void)
+{
+  return nset;
+}
+
+/**
+ * Return the number of package instances available in the database.
+ *
+ * @return The number of package instances.
+ */
+int
+pkg_db_count_pkg(void)
+{
+  return npkg;
 }
 
 int
 pkg_db_count(void)
 {
-  return npackages;
+  return nset;
 }
 
 struct pkgiterator {
@@ -96,6 +163,13 @@ struct pkgiterator {
   int nbinn;
 };
 
+/**
+ * Create a new package iterator.
+ *
+ * It can iterate either over package sets or over package instances.
+ *
+ * @return The iterator.
+ */
 struct pkgiterator *
 pkg_db_iter_new(void)
 {
@@ -106,8 +180,52 @@ pkg_db_iter_new(void)
   return i;
 }
 
+/**
+ * Return the next package set in the database.
+ *
+ * If no further package set is available, it will return NULL.
+ *
+ * @name iter The iterator.
+ *
+ * @return A package set.
+ */
+struct pkgset *
+pkg_db_iter_next_set(struct pkgiterator *iter)
+{
+  struct pkgset *set;
+
+  while (!iter->pigp) {
+    if (iter->nbinn >= BINS)
+      return NULL;
+    if (bins[iter->nbinn])
+      iter->pigp = &bins[iter->nbinn]->pkg;
+    iter->nbinn++;
+  }
+
+  set = iter->pigp->set;
+  if (set->next)
+    iter->pigp = &set->next->pkg;
+  else
+    iter->pigp = NULL;
+
+  return set;
+}
+
+/**
+ * Return the next package instance in the database.
+ *
+ * If no further package instance is available, it will return NULL. Note
+ * that it will return all instances of a given package set in sequential
+ * order. The first instance for a given package set will always correspond
+ * to the native architecture even if that package is not installed or
+ * available.
+ *
+ * @name i The iterator.
+ *
+ * @return A package instance.
+ */
 struct pkginfo *
-pkg_db_iter_next(struct pkgiterator *i)
+pkg_db_iter_next_pkg(struct pkgiterator *i)
 {
   struct pkginfo *r;
 
@@ -129,6 +247,17 @@ pkg_db_iter_next(struct pkgiterator *i)
   return r;
 }
 
+struct pkginfo *
+pkg_db_iter_next(struct pkgiterator *iter)
+{
+  return pkg_db_iter_next_pkg(iter);
+}
+
+/**
+ * Free the package database iterator.
+ *
+ * @name i The iterator.
+ */
 void
 pkg_db_iter_free(struct pkgiterator *i)
 {
@@ -142,7 +271,8 @@ pkg_db_reset(void)
 
   dpkg_arch_reset_list();
   nffreeall();
-  npackages= 0;
+  nset = 0;
+  npkg = 0;
   for (i=0; i<BINS; i++) bins[i]= NULL;
 }
 
@@ -153,14 +283,15 @@ pkg_db_report(FILE *file)
   struct pkgset *pkg;
   int *freq;
 
-  freq= m_malloc(sizeof(int)*npackages+1);
-  for (i=0; i<=npackages; i++) freq[i]= 0;
+  freq = m_malloc(sizeof(int) * nset + 1);
+  for (i = 0; i <= nset; i++)
+    freq[i] = 0;
   for (i=0; i<BINS; i++) {
     for (c=0, pkg= bins[i]; pkg; c++, pkg= pkg->next);
     fprintf(file,"bin %5d has %7d\n",i,c);
     freq[c]++;
   }
-  for (i=npackages; i>0 && freq[i]==0; i--);
+  for (i = nset; i > 0 && freq[i] == 0; i--);
   while (i >= 0) {
     fprintf(file, "size %7d occurs %5d times\n", i, freq[i]);
     i--;

-- 
dpkg's main repository


-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to