Record problems into the transaction elements causing them

- Any problem found in transaction processing is caused, or at least
  triggered by, some transaction element. Having the problems in
  elements lets API users easily determine which package caused which
  problem instead of having to parse problem strings in vain.
- No problem set stored in transaction set itself now, rpmtsProblems() API p
  reserved by making it collect problems from our transaction elements
  into a new set. The problem set fiddling in rpmtsRun() wrt %pretrans
  and all is a bit crazy - always was, now its just more visible...
- Make rpmtsCheck() pass the associated transaction elements into
  the lower level functions. rpmdsProblem() removed from API, it's
  not particularly useful outside rpmtsCheck() internals.
- rpmts struct is now opaque within depends.c except for solve callback
- This breaks --badreloc, need to figure out something saner for the
  problem filtering
This commit is contained in:
Panu Matilainen 2010-03-12 19:41:10 +02:00
parent 1d98830819
commit e696b409fe
6 changed files with 69 additions and 121 deletions

View File

@ -14,6 +14,7 @@
#include <rpm/rpmfi.h>
#include "lib/rpmts_internal.h"
#include "lib/rpmte_internal.h"
#include "debug.h"
@ -466,6 +467,7 @@ exit:
/**
* Check added requires/conflicts against against installed+added packages.
* @param ts transaction set
* @param te related transaction element
* @param pkgNEVRA package name-version-release.arch
* @param requires Requires: dependencies (or NULL)
* @param conflicts Conflicts: dependencies (or NULL)
@ -473,8 +475,8 @@ exit:
* @param tscolor color bits for transaction set (0 disables)
* @param adding dependency is from added package set?
*/
static void checkPackageDeps(rpmts ts, depCache dcache, const char * pkgNEVRA,
rpmds requires, rpmds conflicts,
static void checkPackageDeps(rpmts ts, depCache dcache, rpmte te,
const char * pkgNEVRA, rpmds requires, rpmds conflicts,
const char * depName, rpm_color_t tscolor, int adding)
{
rpm_color_t dscolor;
@ -491,7 +493,7 @@ static void checkPackageDeps(rpmts ts, depCache dcache, const char * pkgNEVRA,
continue;
if (unsatisfiedDepend(ts, dcache, requires, adding) == 1)
rpmdsProblem(ts->probs, pkgNEVRA, requires, NULL, adding);
rpmteAddDepProblem(te, pkgNEVRA, requires, NULL, adding);
}
conflicts = rpmdsInit(conflicts);
@ -506,7 +508,7 @@ static void checkPackageDeps(rpmts ts, depCache dcache, const char * pkgNEVRA,
continue;
if (unsatisfiedDepend(ts, dcache, conflicts, adding) == 0)
rpmdsProblem(ts->probs, pkgNEVRA, conflicts, NULL, adding);
rpmteAddDepProblem(te, pkgNEVRA, conflicts, NULL, adding);
}
}
@ -519,8 +521,8 @@ static void checkPackageDeps(rpmts ts, depCache dcache, const char * pkgNEVRA,
* @param mi rpm database iterator
* @param adding dependency is from added package set?
*/
static void checkPackageSet(rpmts ts, depCache dcache, const char * dep,
rpmdbMatchIterator mi, int adding)
static void checkPackageSet(rpmts ts, depCache dcache, rpmte te,
const char * dep, rpmdbMatchIterator mi, int adding)
{
tsMembers tsmem = rpmtsMembers(ts);
Header h;
@ -534,7 +536,7 @@ static void checkPackageSet(rpmts ts, depCache dcache, const char * dep,
(void) rpmdsSetNoPromote(requires, _rpmds_nopromote);
(void) rpmdsSetNoPromote(conflicts, _rpmds_nopromote);
checkPackageDeps(ts, dcache, pkgNEVRA, requires, conflicts, dep, 0, adding);
checkPackageDeps(ts, dcache, te, pkgNEVRA, requires, conflicts, dep, 0, adding);
conflicts = rpmdsFree(conflicts);
requires = rpmdsFree(requires);
pkgNEVRA = _free(pkgNEVRA);
@ -546,10 +548,11 @@ static void checkPackageSet(rpmts ts, depCache dcache, const char * dep,
* @param ts transaction set
* @param dep requires name
*/
static void checkDependentPackages(rpmts ts, depCache dcache, const char * dep)
static void checkDependentPackages(rpmts ts, depCache dcache,
rpmte te, const char * dep)
{
rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMTAG_REQUIRENAME, dep, 0);
checkPackageSet(ts, dcache, dep, mi, 0);
checkPackageSet(ts, dcache, te, dep, mi, 0);
rpmdbFreeIterator(mi);
}
@ -558,10 +561,11 @@ static void checkDependentPackages(rpmts ts, depCache dcache, const char * dep)
* @param ts transaction set
* @param dep conflicts name
*/
static void checkDependentConflicts(rpmts ts, depCache dcache, const char * dep)
static void checkDependentConflicts(rpmts ts, depCache dcache,
rpmte te, const char * dep)
{
rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMTAG_CONFLICTNAME, dep, 0);
checkPackageSet(ts, dcache, dep, mi, 1);
checkPackageSet(ts, dcache, te, dep, mi, 1);
rpmdbFreeIterator(mi);
}
@ -585,9 +589,6 @@ int rpmtsCheck(rpmts ts)
closeatexit = 1;
}
ts->probs = rpmpsFree(ts->probs);
ts->probs = rpmpsCreate();
rpmalMakeIndex(tsmem->addedPackages);
/* XXX FIXME: figure some kind of heuristic for the cache size */
@ -604,7 +605,7 @@ int rpmtsCheck(rpmts ts)
rpmlog(RPMLOG_DEBUG, "========== +++ %s %s/%s 0x%x\n",
rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
checkPackageDeps(ts, dcache, rpmteNEVRA(p),
checkPackageDeps(ts, dcache, p, rpmteNEVRA(p),
rpmteDS(p, RPMTAG_REQUIRENAME),
rpmteDS(p, RPMTAG_CONFLICTNAME),
NULL,
@ -612,7 +613,7 @@ int rpmtsCheck(rpmts ts)
/* Adding: check provides key against conflicts matches. */
while (rpmdsNext(provides) >= 0) {
checkDependentConflicts(ts, dcache, rpmdsN(provides));
checkDependentConflicts(ts, dcache, p, rpmdsN(provides));
}
}
pi = rpmtsiFree(pi);
@ -630,12 +631,12 @@ int rpmtsCheck(rpmts ts)
/* Erasing: check provides against requiredby matches. */
while (rpmdsNext(provides) >= 0) {
checkDependentPackages(ts, dcache, rpmdsN(provides));
checkDependentPackages(ts, dcache, p, rpmdsN(provides));
}
/* Erasing: check filename against requiredby matches. */
while (rpmfiNext(fi) >= 0) {
checkDependentPackages(ts, dcache, rpmfiFN(fi));
checkDependentPackages(ts, dcache, p, rpmfiFN(fi));
}
}
pi = rpmtsiFree(pi);

View File

@ -797,32 +797,6 @@ exit:
return result;
}
void rpmdsProblem(rpmps ps, const char * pkgNEVR, const rpmds ds,
const fnpyKey * suggestedKeys, int adding)
{
const char * DNEVR = rpmdsDNEVR(ds);
const char * EVR = rpmdsEVR(ds);
rpmProblemType type;
fnpyKey key;
if (ps == NULL) return;
if (EVR == NULL) EVR = "?EVR?";
if (DNEVR == NULL) DNEVR = "? ?N? ?OP? ?EVR?";
rpmlog(RPMLOG_DEBUG, "package %s has unsatisfied %s: %s\n",
pkgNEVR, ds->Type, DNEVR+2);
switch ((unsigned)DNEVR[0]) {
case 'C': type = RPMPROB_CONFLICT; break;
default:
case 'R': type = RPMPROB_REQUIRES; break;
}
key = (suggestedKeys ? suggestedKeys[0] : NULL);
rpmpsAppend(ps, type, pkgNEVR, key, NULL, NULL, DNEVR, adding);
}
int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote)
{
rpmds provides = NULL;

View File

@ -322,7 +322,6 @@ int rpmdsMerge(rpmds * dsp, rpmds ods);
**/
int rpmdsSearch(rpmds ds, rpmds ods);
/** \ingroup rpmds
* Compare two versioned dependency ranges, looking for overlap.
* @param A 1st dependency
@ -331,18 +330,6 @@ int rpmdsSearch(rpmds ds, rpmds ods);
*/
int rpmdsCompare(const rpmds A, const rpmds B);
/** \ingroup rpmds
* Report a Requires: or Conflicts: dependency problem.
* @param ps transaction set problems
* @param pkgNEVR package name/epoch/version/release
* @param ds dependency set
* @param suggestedKeys filename or python object address
* @param adding dependency problem is from added package set?
*/
void rpmdsProblem(rpmps ps, const char * pkgNEVR, const rpmds ds,
const fnpyKey * suggestedKeys,
int adding);
/** \ingroup rpmds
* Compare package provides dependencies from header with a single dependency.
* @param h header

View File

@ -476,19 +476,34 @@ int rpmtsSetSolveCallback(rpmts ts,
rpmps rpmtsProblems(rpmts ts)
{
rpmps ps = NULL;
if (ts) {
if (ts->probs)
ps = rpmpsLink(ts->probs, RPMDBG_M("rpmtsProblems"));
rpmps ps = rpmpsCreate();
rpmtsi pi = rpmtsiInit(ts);
rpmte p;
/* XXX TODO this cries for rpmpsMerge() */
while ((p = rpmtsiNext(pi, 0)) != NULL) {
rpmps teprobs = rpmteProblems(p);
if (teprobs) {
rpmpsi psi = rpmpsInitIterator(teprobs);
while (rpmpsNextIterator(psi) >= 0) {
rpmProblem prob = rpmpsGetProblem(psi);
rpmpsAppendProblem(ps, prob);
}
rpmpsFreeIterator(psi);
rpmpsFree(teprobs);
}
}
pi = rpmtsiFree(pi);
return ps;
}
void rpmtsCleanProblems(rpmts ts)
{
if (ts && ts->probs) {
ts->probs = rpmpsFree(ts->probs);
}
rpmte p;
rpmtsi pi = rpmtsiInit(ts);
while ((p = rpmtsiNext(pi, 0)) != NULL)
rpmteCleanProblems(p);
pi = rpmtsiFree(pi);
}
void rpmtsClean(rpmts ts)
@ -921,8 +936,6 @@ rpmts rpmtsCreate(void)
ts->selinuxEnabled = is_selinux_enabled();
ts->probs = NULL;
ts->keyring = NULL;
ts->nrefs = 0;

View File

@ -37,7 +37,6 @@ struct rpmts_s {
rpmCallbackFunction notify; /*!< Callback function. */
rpmCallbackData notifyData; /*!< Callback private data. */
rpmps probs; /*!< Current problems in transaction. */
rpmprobFilterFlags ignoreSet;
/*!< Bits to filter current problems. */

View File

@ -260,20 +260,17 @@ static void rpmtsUpdateDSIrpmDBSize(const rpmte p,
static void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te)
{
rpmDiskSpaceInfo dsi = ts->dsi;
rpmps ps;
if (dsi == NULL || !dsi->bsize)
return;
if (rpmfiFC(rpmteFI(te)) <= 0)
return;
ps = rpmtsProblems(ts);
for (; dsi->bsize; dsi++) {
if (dsi->bavail >= 0 && adj_fs_blocks(dsi->bneeded) > dsi->bavail) {
if (dsi->bneeded > dsi->obneeded) {
rpmpsAppend(ps, RPMPROB_DISKSPACE,
rpmteNEVRA(te), rpmteKey(te),
rpmteAddProblem(te, RPMPROB_DISKSPACE,
dsi->mntPoint, NULL, NULL,
(adj_fs_blocks(dsi->bneeded) - dsi->bavail) * dsi->bsize);
dsi->obneeded = dsi->bneeded;
@ -282,15 +279,13 @@ static void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te)
if (dsi->iavail >= 0 && adj_fs_blocks(dsi->ineeded) > dsi->iavail) {
if (dsi->ineeded > dsi->oineeded) {
rpmpsAppend(ps, RPMPROB_DISKNODES,
rpmteNEVRA(te), rpmteKey(te),
rpmteAddProblem(te, RPMPROB_DISKNODES,
dsi->mntPoint, NULL, NULL,
(adj_fs_blocks(dsi->ineeded) - dsi->iavail));
dsi->oineeded = dsi->ineeded;
}
}
}
ps = rpmpsFree(ps);
}
static void rpmtsFreeDSI(rpmts ts){
@ -361,14 +356,9 @@ static int handleInstInstalledFile(const rpmts ts, rpmte p, rpmfi fi,
if (rConflicts) {
char *altNEVR = headerGetAsString(otherHeader, RPMTAG_NEVRA);
rpmps ps = rpmtsProblems(ts);
rpmpsAppend(ps, RPMPROB_FILE_CONFLICT,
rpmteNEVRA(p), rpmteKey(p),
rpmfiDN(fi), rpmfiBN(fi),
altNEVR,
0);
rpmteAddProblem(p, RPMPROB_FILE_CONFLICT,
rpmfiDN(fi), rpmfiBN(fi), altNEVR, 0);
free(altNEVR);
rpmpsFree(ps);
}
/* Save file identifier to mark as state REPLACED. */
@ -398,7 +388,6 @@ static int handleInstInstalledFile(const rpmts ts, rpmte p, rpmfi fi,
static void handleOverlappedFiles(rpmts ts, rpmFpHash ht, rpmte p, rpmfi fi)
{
rpm_loff_t fixupSize = 0;
rpmps ps;
const char * fn;
int i, j;
rpm_color_t tscolor = rpmtsColor(ts);
@ -406,7 +395,6 @@ static void handleOverlappedFiles(rpmts ts, rpmFpHash ht, rpmte p, rpmfi fi)
rpmfs fs = rpmteGetFileStates(p);
rpmfs otherFs;
ps = rpmtsProblems(ts);
fi = rpmfiInit(fi, 0);
while ((i = rpmfiNext(fi)) >= 0) {
rpm_color_t oFColor, FColor;
@ -538,11 +526,8 @@ assert(otherFi != NULL);
done = 1;
}
if (rConflicts) {
rpmpsAppend(ps, RPMPROB_NEW_FILE_CONFLICT,
rpmteNEVRA(p), rpmteKey(p),
fn, NULL,
rpmteNEVRA(otherTe),
0);
rpmteAddProblem(p, RPMPROB_NEW_FILE_CONFLICT,
fn, NULL, rpmteNEVRA(otherTe), 0);
}
}
@ -604,7 +589,6 @@ assert(otherFi != NULL);
fixupSize, rpmfsGetAction(fs, i));
}
ps = rpmpsFree(ps);
}
/**
@ -613,7 +597,7 @@ assert(otherFi != NULL);
* @param h installed header
* @param ps problem set
*/
static void ensureOlder(const rpmte p, const Header h, rpmps ps)
static void ensureOlder(const rpmte p, const Header h)
{
rpmsenseFlags reqFlags = (RPMSENSE_LESS | RPMSENSE_EQUAL);
rpmds req;
@ -621,8 +605,7 @@ static void ensureOlder(const rpmte p, const Header h, rpmps ps)
req = rpmdsSingle(RPMTAG_REQUIRENAME, rpmteN(p), rpmteEVR(p), reqFlags);
if (rpmdsNVRMatchesDep(h, req, _rpmds_nopromote) == 0) {
char * altNEVR = headerGetAsString(h, RPMTAG_NEVRA);
rpmpsAppend(ps, RPMPROB_OLDPACKAGE, rpmteNEVRA(p), rpmteKey(p),
NULL, NULL, altNEVR, 0);
rpmteAddProblem(p, RPMPROB_OLDPACKAGE, NULL, NULL, altNEVR, 0);
free(altNEVR);
}
rpmdsFree(req);
@ -1070,7 +1053,6 @@ static rpmps checkProblems(rpmts ts)
{
rpm_color_t tscolor = rpmtsColor(ts);
rpmprobFilterFlags probFilter = rpmtsFilterFlags(ts);
rpmps ps = rpmpsCreate();
rpmtsi pi = rpmtsiInit(ts);
rpmte p;
@ -1079,21 +1061,18 @@ static rpmps checkProblems(rpmts ts)
rpmlog(RPMLOG_DEBUG, "sanity checking %d elements\n", rpmtsNElements(ts));
while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
rpmdbMatchIterator mi;
rpmpsi psi;
if (!(probFilter & RPMPROB_FILTER_IGNOREARCH) && badArch(rpmteA(p)))
rpmpsAppend(ps, RPMPROB_BADARCH, rpmteNEVRA(p), rpmteKey(p),
rpmteA(p), NULL, NULL, 0);
rpmteAddProblem(p, RPMPROB_BADARCH, rpmteA(p), NULL, NULL, 0);
if (!(probFilter & RPMPROB_FILTER_IGNOREOS) && badOs(rpmteO(p)))
rpmpsAppend(ps, RPMPROB_BADOS, rpmteNEVRA(p), rpmteKey(p),
rpmteO(p), NULL, NULL, 0);
rpmteAddProblem(p, RPMPROB_BADOS, rpmteO(p), NULL, NULL, 0);
if (!(probFilter & RPMPROB_FILTER_OLDPACKAGE)) {
Header h;
mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
while ((h = rpmdbNextIterator(mi)) != NULL)
ensureOlder(p, h, ps);
ensureOlder(p, h);
mi = rpmdbFreeIterator(mi);
}
@ -1107,27 +1086,14 @@ static rpmps checkProblems(rpmts ts)
rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP, rpmteO(p));
}
while (rpmdbNextIterator(mi) != NULL) {
rpmpsAppend(ps, RPMPROB_PKG_INSTALLED,
rpmteNEVRA(p), rpmteKey(p),
NULL, NULL,
NULL, 0);
break;
if (rpmdbNextIterator(mi) != NULL) {
rpmteAddProblem(p, RPMPROB_PKG_INSTALLED, NULL, NULL, NULL, 0);
}
mi = rpmdbFreeIterator(mi);
}
/* XXX rpmte problems can only be relocation problems atm */
if (!(probFilter & RPMPROB_FILTER_FORCERELOCATE)) {
psi = rpmpsInitIterator(rpmteProblems(p));
while (rpmpsNextIterator(psi) >= 0) {
rpmpsAppendProblem(ps, rpmpsGetProblem(psi));
}
rpmpsFreeIterator(psi);
}
}
pi = rpmtsiFree(pi);
return ps;
return rpmtsProblems(ts);
}
/*
@ -1254,7 +1220,6 @@ static int rpmtsSetup(rpmts ts, rpmprobFilterFlags ignoreSet)
}
ts->ignoreSet = ignoreSet;
ts->probs = rpmpsFree(ts->probs);
{ char * currDir = rpmGetCwd();
rpmtsSetCurrDir(ts, currDir);
@ -1411,6 +1376,7 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
{
int rc = -1; /* assume failure */
void * lock = NULL;
rpmps tsprobs = NULL;
/* XXX programmer error segfault avoidance. */
if (rpmtsNElements(ts) <= 0) {
@ -1430,31 +1396,38 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
}
/* Check package set for problems */
ts->probs = checkProblems(ts);
tsprobs = checkProblems(ts);
/* Run pre-transaction scripts, but only if there are no known
* problems up to this point and not disabled otherwise. */
if (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_NOPRE))
|| (rpmpsNumProblems(ts->probs) &&
(okProbs == NULL || rpmpsTrim(ts->probs, okProbs))))) {
|| (rpmpsNumProblems(tsprobs) &&
(okProbs == NULL || rpmpsTrim(tsprobs, okProbs))))) {
rpmlog(RPMLOG_DEBUG, "running pre-transaction scripts\n");
runTransScripts(ts, RPMTAG_PRETRANS);
}
tsprobs = rpmpsFree(tsprobs);
/* Compute file disposition for each package in transaction set. */
if (rpmtsPrepare(ts)) {
goto exit;
}
/* Check again for problems (now including file conflicts, duh */
tsprobs = rpmtsProblems(ts);
/* If unfiltered problems exist, free memory and return. */
if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS) ||
(rpmpsNumProblems(ts->probs) &&
(okProbs == NULL || rpmpsTrim(ts->probs, okProbs)))) {
(rpmpsNumProblems(tsprobs) &&
(okProbs == NULL || rpmpsTrim(tsprobs, okProbs)))) {
tsMembers tsmem = rpmtsMembers(ts);
rc = tsmem->orderCount;
goto exit;
}
/* Free up memory taken by problem sets */
tsprobs = rpmpsFree(tsprobs);
rpmtsCleanProblems(ts);
/* Actually install and remove packages, get final exit code */
rc = rpmtsProcess(ts) ? -1 : 0;
@ -1468,6 +1441,7 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
(void) rpmtsFinish(ts);
exit:
tsprobs = rpmpsFree(tsprobs);
rpmtsFreeLock(lock);
return rc;
}