Record failure of install/erase into transaction elements
authorPanu Matilainen <pmatilai@redhat.com>
Tue, 25 Nov 2008 09:46:20 +0000 (11:46 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Wed, 26 Nov 2008 15:35:12 +0000 (17:35 +0200)
- add rpmteMarkFailed() (internal) and rpmteFailed() methods to rpmte
- skip any elements marked as failed in rpmtsProcess()
- this is fairly close to the previous "now mostly broken" hack, except
  we remember more than one failure so it's slightly better and it's
  possible to do much better by making rpmteMarkFailed() smarter

lib/rpmte.c
lib/rpmte.h
lib/rpmte_internal.h
lib/transaction.c

index ef1a4be..154c01b 100644 (file)
@@ -659,3 +659,26 @@ int rpmteClose(rpmte te, rpmts ts)
     }
     return rc;
 }
+
+int rpmteMarkFailed(rpmte te, rpmts ts)
+{
+    rpmtsi pi = rpmtsiInit(ts);
+    int rc = 0;
+    rpmte p;
+    rpmalKey key = rpmteAddedKey(te);
+
+    te->failed = 1;
+    /* XXX we can do a much better here than this... */
+    while ((p = rpmtsiNext(pi, TR_REMOVED))) {
+       if (rpmteDependsOnKey(p) == key) {
+           p->failed = 1;
+       }
+    }
+    rpmtsiFree(pi);
+    return rc;
+}
+
+int rpmteFailed(rpmte te)
+{
+    return (te != NULL) ? te->failed : -1;
+}
index c1136b4..32ece3b 100644 (file)
@@ -348,6 +348,13 @@ FD_t rpmteFd(rpmte te);
 fnpyKey rpmteKey(rpmte te);
 
 /** \ingroup rpmte
+ * Return failed status of transaction element.
+ * @param te           transaction element
+ * @return             1 if transaction element (or its parents) failed
+ */
+int rpmteFailed(rpmte te);
+
+/** \ingroup rpmte
  * Retrieve dependency tag set from transaction element.
  * @param te           transaction element
  * @param tag          dependency tag
index 3d8903e..5b7c5c2 100644 (file)
@@ -65,6 +65,7 @@ struct rpmte_s {
 #define RPMTE_HAVE_PRETRANS    (1 << 0)
 #define RPMTE_HAVE_POSTTRANS   (1 << 1)
     int transscripts;          /*!< pre/posttrans script existence */
+    int failed;                        /*!< (parent) install/erase failed */
 
     rpmalKey pkgKey;
 };
@@ -85,5 +86,7 @@ int rpmteOpen(rpmte te, rpmts ts);
 RPM_GNUC_INTERNAL
 int rpmteClose(rpmte te, rpmts ts);
 
+RPM_GNUC_INTERNAL
+int rpmteMarkFailed(rpmte te, rpmts ts);
 #endif /* _RPMTE_INTERNAL_H */
 
index 30f4660..88e8257 100644 (file)
@@ -893,24 +893,28 @@ static int runTransScripts(rpmts ts, rpmTag stag)
  */
 static int rpmtsProcess(rpmts ts)
 {
-    rpmalKey lastFailKey = (rpmalKey)-2;       /* erased packages have -1 */
     rpmtsi pi; rpmte p;
     int rc = 0;
 
     pi = rpmtsiInit(ts);
     while ((p = rpmtsiNext(pi, 0)) != NULL) {
-       rpmalKey pkgKey;
        rpmpsm psm;
        rpmfi fi;
        int async;
+       int failed = 0;
        rpmElementType tetype = rpmteType(p);
        rpmtsOpX op = (tetype == TR_ADDED) ? RPMTS_OP_INSTALL : RPMTS_OP_ERASE;
 
        rpmlog(RPMLOG_DEBUG, "========== +++ %s %s-%s 0x%x\n",
                rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
 
-       if ((fi = rpmtsiFi(pi)) == NULL)
-           continue;   /* XXX can't happen */
+       if (rpmteFailed(p) || (fi = rpmtsiFi(pi)) == NULL) {
+           /* XXX this should be a warning, need a better message though */
+           rpmlog(RPMLOG_DEBUG, "element %s marked as failed, skipping\n",
+                                       rpmteNEVRA(p));
+           rc++;
+           continue;
+       }
        
        psm = rpmpsmNew(ts, p, fi);
        async = (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1) ? 1 : 0);
@@ -919,7 +923,6 @@ static int rpmtsProcess(rpmts ts)
        (void) rpmswEnter(rpmtsOp(ts, op), 0);
        switch (tetype) {
        case TR_ADDED:
-           pkgKey = rpmteAddedKey(p);
            if (rpmteOpen(p, ts)) {
                /*
                 * XXX Sludge necessary to tranfer existing fstates/actions
@@ -930,14 +933,12 @@ static int rpmtsProcess(rpmts ts)
                rpmpsmSetFI(psm, p->fi);
 
                if (rpmpsmStage(psm, PSM_PKGINSTALL)) {
-                   rc++;
-                   lastFailKey = pkgKey;
+                   failed = 1;
                }
                rpmteClose(p, ts);
                
            } else {
-               rc++;
-               lastFailKey = pkgKey;
+               failed = 1;
            }
            break;
        case TR_REMOVED:
@@ -945,13 +946,16 @@ static int rpmtsProcess(rpmts ts)
             * XXX This has always been a hack, now mostly broken.
             * If install failed, then we shouldn't erase.
             */
-           if (rpmteDependsOnKey(p) != lastFailKey) {
-               if (rpmpsmStage(psm, PSM_PKGERASE)) {
-                   rc++;
-               }
+           if (rpmpsmStage(psm, PSM_PKGERASE)) {
+               failed = 1;
            }
            break;
        }
+       if (failed) {
+           rpmteMarkFailed(p, ts);
+           rc++;
+       }
+       
        (void) rpmswExit(rpmtsOp(ts, op), 0);
        (void) rpmdbSync(rpmtsGetRdb(ts));