Major API/ABI cleanup bringing performance improvements and fixes.

These are the core interfaces in the new API:

rpool - Interface to interact with the repository pool.
rindex - Interface to interact with repository indexes.
pkgdb - Interface to interact with local packages.
transaction - Interface to interact with a transaction.

This also brings new repository index format, making the index file
per architecture and being incompatible with previous versions.

The transaction frequency flush option has been removed, and due to
the nature of package states it was causing more harm than good.

More changes coming soon, but the API shall remain stable from now on.
This commit is contained in:
Juan RP
2012-11-30 07:11:51 +01:00
parent 16e18313da
commit 63c1883201
57 changed files with 1437 additions and 2640 deletions

View File

@@ -31,378 +31,89 @@
#include "xbps_api_impl.h"
/**
* @file lib/plist_find.c
* @brief PropertyList generic routines
* @defgroup plist PropertyList generic functions
*
* These functions manipulate plist files and objects shared by almost
* all library functions.
*/
static prop_dictionary_t
find_pkg_in_array(struct xbps_handle *xhp,
prop_array_t array,
const char *str,
bool bypattern,
bool virtual,
const char *targetarch)
get_pkg_in_array(prop_array_t array, const char *str, bool virtual)
{
prop_object_iterator_t iter;
prop_object_t obj = NULL;
const char *pkgver, *dpkgn, *arch;
bool chkarch;
assert(prop_object_type(array) == PROP_TYPE_ARRAY);
assert(str != NULL);
iter = prop_array_iterator(array);
if (iter == NULL)
return NULL;
while ((obj = prop_object_iterator_next(iter))) {
chkarch = prop_dictionary_get_cstring_nocopy(obj,
"architecture", &arch);
if (chkarch && !xbps_pkg_arch_match(xhp, arch, targetarch))
continue;
const char *pkgver, *dpkgn;
size_t i;
bool found = false;
for (i = 0; i < prop_array_count(array); i++) {
obj = prop_array_get(array, i);
if (virtual) {
/*
* Check if package pattern matches
* any virtual package version in dictionary.
*/
if (xbps_match_virtual_pkg_in_dict(obj, str, bypattern))
if (xbps_pkgpattern_version(str))
found = xbps_match_virtual_pkg_in_dict(obj, str, true);
else
found = xbps_match_virtual_pkg_in_dict(obj, str, false);
if (found)
break;
} else if (bypattern) {
/*
* Check if package pattern matches the
* pkgver string object in dictionary.
*/
} else if (xbps_pkgpattern_version(str)) {
/* ,atch by pattern against pkgver */
if (!prop_dictionary_get_cstring_nocopy(obj,
"pkgver", &pkgver))
continue;
if (xbps_pkgpattern_match(pkgver, str))
if (xbps_pkgpattern_match(pkgver, str)) {
found = true;
break;
}
} else if (xbps_pkg_version(str)) {
/* match by exact pkgver */
if (!prop_dictionary_get_cstring_nocopy(obj,
"pkgver", &pkgver))
continue;
if (strcmp(str, pkgver) == 0) {
found = true;
break;
}
} else {
/* match by pkgname */
if (!prop_dictionary_get_cstring_nocopy(obj,
"pkgname", &dpkgn))
continue;
if (strcmp(dpkgn, str) == 0)
if (strcmp(dpkgn, str) == 0) {
found = true;
break;
}
}
prop_object_iterator_release(iter);
if (obj == NULL) {
errno = ENOENT;
return NULL;
}
return obj;
}
prop_dictionary_t
xbps_find_pkg_in_array_by_name(struct xbps_handle *xhp,
prop_array_t array,
const char *name,
const char *targetarch)
{
return find_pkg_in_array(xhp, array, name, false, false, targetarch);
}
prop_dictionary_t
xbps_find_pkg_in_array_by_pattern(struct xbps_handle *xhp,
prop_array_t array,
const char *pattern,
const char *targetarch)
{
return find_pkg_in_array(xhp, array, pattern, true, false, targetarch);
}
prop_dictionary_t
xbps_find_pkg_in_array_by_pkgver(struct xbps_handle *xhp,
prop_array_t array,
const char *pkgver,
const char *targetarch)
{
prop_object_iterator_t iter;
prop_object_t obj = NULL;
const char *rpkgver, *arch;
bool chkarch, found = false;
assert(prop_object_type(array) == PROP_TYPE_ARRAY);
assert(pkgver != NULL);
iter = prop_array_iterator(array);
if (iter == NULL)
return NULL;
while ((obj = prop_object_iterator_next(iter))) {
chkarch = prop_dictionary_get_cstring_nocopy(obj,
"architecture", &arch);
if (!prop_dictionary_get_cstring_nocopy(obj,
"pkgver", &rpkgver))
continue;
if (chkarch && !xbps_pkg_arch_match(xhp, arch, targetarch))
continue;
if (strcmp(pkgver, rpkgver) == 0) {
found = true;
break;
}
}
prop_object_iterator_release(iter);
if (found)
return obj;
return NULL;
}
prop_dictionary_t
xbps_find_virtualpkg_in_array_by_name(struct xbps_handle *xhp,
prop_array_t array,
const char *name)
{
return find_pkg_in_array(xhp, array, name, false, true, NULL);
}
prop_dictionary_t
xbps_find_virtualpkg_in_array_by_pattern(struct xbps_handle *xhp,
prop_array_t array,
const char *pattern)
{
return find_pkg_in_array(xhp, array, pattern, true, true, NULL);
}
static const char *
find_virtualpkg_user_in_conf(struct xbps_handle *xhp,
const char *vpkg,
bool bypattern)
{
const char *vpkgver, *pkg = NULL;
char *vpkgname = NULL, *tmp;
size_t i, j, cnt;
if (xhp->cfg == NULL)
return NULL;
if ((cnt = cfg_size(xhp->cfg, "virtual-package")) == 0) {
/* no virtual packages configured */
return NULL;
}
for (i = 0; i < cnt; i++) {
cfg_t *sec = cfg_getnsec(xhp->cfg, "virtual-package", i);
for (j = 0; j < cfg_size(sec, "targets"); j++) {
tmp = NULL;
vpkgver = cfg_getnstr(sec, "targets", j);
if (strchr(vpkgver, '_') == NULL) {
tmp = xbps_xasprintf("%s_1", vpkgver);
vpkgname = xbps_pkg_name(tmp);
free(tmp);
} else {
vpkgname = xbps_pkg_name(vpkgver);
}
if (vpkgname == NULL)
break;
if (bypattern) {
if (!xbps_pkgpattern_match(vpkgver, vpkg)) {
free(vpkgname);
continue;
}
} else {
if (strcmp(vpkg, vpkgname)) {
free(vpkgname);
continue;
}
}
/* virtual package matched in conffile */
pkg = cfg_title(sec);
xbps_dbg_printf(xhp,
"matched vpkg in conf `%s' for %s\n",
pkg, vpkg);
free(vpkgname);
break;
}
}
return pkg;
}
static prop_dictionary_t
find_virtualpkg_user_in_array(struct xbps_handle *xhp,
prop_array_t array,
const char *str,
bool bypattern)
{
const char *vpkgname;
assert(prop_object_type(array) == PROP_TYPE_ARRAY);
assert(str != NULL);
vpkgname = find_virtualpkg_user_in_conf(xhp, str, bypattern);
if (vpkgname == NULL)
return NULL;
return find_pkg_in_array(xhp, array, vpkgname, false, false, NULL);
return found ? obj : NULL;
}
prop_dictionary_t HIDDEN
xbps_find_virtualpkg_conf_in_array_by_name(struct xbps_handle *xhp,
prop_array_t array,
const char *name)
xbps_find_pkg_in_array(prop_array_t a, const char *s)
{
return find_virtualpkg_user_in_array(xhp, array, name, false);
assert(prop_object_type(a) == PROP_TYPE_ARRAY);
assert(s);
return get_pkg_in_array(a, s, false);
}
prop_dictionary_t HIDDEN
xbps_find_virtualpkg_conf_in_array_by_pattern(struct xbps_handle *xhp,
prop_array_t array,
const char *p)
xbps_find_virtualpkg_in_array(struct xbps_handle *x,
prop_array_t a,
const char *s)
{
return find_virtualpkg_user_in_array(xhp, array, p, true);
}
prop_dictionary_t pkgd;
const char *vpkg;
bool bypattern = false;
static prop_dictionary_t
find_pkg_in_dict(struct xbps_handle *xhp,
prop_dictionary_t d,
const char *key,
const char *str,
bool bypattern,
bool virtual)
{
prop_array_t array;
assert(x);
assert(prop_object_type(a) == PROP_TYPE_ARRAY);
assert(s);
assert(prop_object_type(d) == PROP_TYPE_DICTIONARY);
assert(str != NULL);
assert(key != NULL);
if (xbps_pkgpattern_version(s))
bypattern = true;
array = prop_dictionary_get(d, key);
if (prop_object_type(array) != PROP_TYPE_ARRAY)
return NULL;
return find_pkg_in_array(xhp, array, str, bypattern, virtual, NULL);
}
prop_dictionary_t
xbps_find_pkg_in_dict_by_name(struct xbps_handle *xhp,
prop_dictionary_t d,
const char *key,
const char *pkgname)
{
return find_pkg_in_dict(xhp, d, key, pkgname, false, false);
}
prop_dictionary_t
xbps_find_pkg_in_dict_by_pattern(struct xbps_handle *xhp,
prop_dictionary_t d,
const char *key,
const char *pattern)
{
return find_pkg_in_dict(xhp, d, key, pattern, true, false);
}
prop_dictionary_t
xbps_find_pkg_in_dict_by_pkgver(struct xbps_handle *xhp,
prop_dictionary_t d,
const char *key,
const char *pkgver)
{
prop_array_t array;
assert(d != NULL);
assert(key != NULL);
assert(pkgver != NULL);
array = prop_dictionary_get(d, key);
if (array == NULL)
return NULL;
return xbps_find_pkg_in_array_by_pkgver(xhp, array, pkgver, NULL);
}
prop_dictionary_t
xbps_find_virtualpkg_in_dict_by_name(struct xbps_handle *xhp,
prop_dictionary_t d,
const char *key,
const char *name)
{
return find_pkg_in_dict(xhp, d, key, name, false, true);
}
prop_dictionary_t
xbps_find_virtualpkg_in_dict_by_pattern(struct xbps_handle *xhp,
prop_dictionary_t d,
const char *key,
const char *pattern)
{
return find_pkg_in_dict(xhp, d, key, pattern, true, true);
}
static prop_dictionary_t
find_pkgd_installed(struct xbps_handle *xhp,
const char *str,
bool bypattern,
bool virtual)
{
prop_dictionary_t pkgd = NULL;
pkg_state_t state = 0;
int rv;
assert(str != NULL);
if ((rv = xbps_pkgdb_init(xhp)) != 0) {
if (rv != ENOENT) {
xbps_dbg_printf(xhp, "%s: couldn't initialize "
"pkgdb: %s\n", strerror(rv));
return NULL;
} else if (rv == ENOENT)
return NULL;
if ((vpkg = vpkg_user_conf(x, s, bypattern))) {
if ((pkgd = get_pkg_in_array(a, vpkg, true)))
return pkgd;
}
/* try normal pkg */
if (virtual == false) {
pkgd = find_pkg_in_array(xhp, xhp->pkgdb, str,
bypattern, false, NULL);
} else {
/* virtual pkg set by user in conf */
pkgd = find_virtualpkg_user_in_array(xhp, xhp->pkgdb,
str, bypattern);
if (pkgd == NULL) {
/* any virtual pkg in array matching pattern */
pkgd = find_pkg_in_array(xhp, xhp->pkgdb,
str, bypattern, true, NULL);
}
}
/* pkg not found */
if (pkgd == NULL)
return NULL;
if (xbps_pkg_state_dictionary(pkgd, &state) != 0)
return NULL;
switch (state) {
case XBPS_PKG_STATE_INSTALLED:
case XBPS_PKG_STATE_UNPACKED:
return pkgd;
/* NOTREACHED */
default:
/* not fully installed */
errno = ENOENT;
break;
}
return NULL;
}
prop_dictionary_t
xbps_find_pkg_dict_installed(struct xbps_handle *xhp,
const char *str,
bool bypattern)
{
return find_pkgd_installed(xhp, str, bypattern, false);
}
prop_dictionary_t
xbps_find_virtualpkg_dict_installed(struct xbps_handle *xhp,
const char *str,
bool bypattern)
{
return find_pkgd_installed(xhp, str, bypattern, true);
return get_pkg_in_array(a, s, true);
}