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]