Record problems into the transaction elements causing them
authorPanu Matilainen <pmatilai@redhat.com>
Fri, 12 Mar 2010 17:41:10 +0000 (19:41 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Fri, 12 Mar 2010 17:46:06 +0000 (19:46 +0200)
- 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

lib/depends.c
lib/rpmds.c
lib/rpmds.h
lib/rpmts.c
lib/rpmts_internal.h
lib/transaction.c

index b6bdf33..a82aff3 100644 (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);
index e8240fd..b90c266 100644 (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;
index e8b2a33..cbe30fe 100644 (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
@@ -332,18 +331,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
  * @param req          dependency set
index 1c4bc17..c9e63ca 100644 (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;
index f874e17..9480424 100644 (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. */
 
index 15e2215..d5f734b 100644 (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;
 }