[PATCH] Rewrite action sort so it works correctly.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Action sort previously had several holes in it. Instead
of trying to fix it, I rewrote it. It works at least as
well as the old version in my testing.
---
 storage/devicetree.py |  231 ++++++++++++++++++++++++++++---------------------
 1 files changed, 133 insertions(+), 98 deletions(-)

diff --git a/storage/devicetree.py b/storage/devicetree.py
index 84fcc8a..b0694e5 100644
--- a/storage/devicetree.py
+++ b/storage/devicetree.py
@@ -330,114 +330,149 @@ class DeviceTree(object):
 
     def processActions(self, dryRun=None):
         """ Execute all registered actions. """
-        def cmpActions(x, y):
-            """
-                < 1 => x < y
-                  0 => x == y
-                > 1 => x > y
-
-                FIXME: this is unmanageable.
-            """
-	    #log.debug("%s | %s" % (x, y))
-
-            # destroy actions come first
-            if x.isDestroy() and not y.isDestroy():
-		#log.debug("x is destroy -- x first")
-                return -1
-            elif y.isDestroy() and not x.isDestroy():
-		#log.debug("y is destroy -- y first")
-                return 1
-            elif x.isDestroy() and y.isDestroy():
-                # outermost/youngest first
-                if x.device.dependsOn(y.device):
-                    #log.debug("x depends on y -- x first")
-                    return -1
-                elif y.device.dependsOn(x.device):
-                    #log.debug("y depends on x -- y first")
-                    return 1
-                # filesystem destruction must precede device destruction
-                elif x.isFormat() and not y.isFormat():
-		    #log.debug("x is format -- x first")
-                    return -1
-                elif y.isFormat() and not x.isFormat():
-                    #log.debug("y is format -- y first")
-                    return 1
-
-            # resize actions come next
-            if x.isResize() and not y.isResize():
-		#log.debug("x is resize -- x first")
-                return -1
-            elif y.isResize() and not x.isResize():
-	        #log.debug("y is resize -- y first")
-                return 1
-            elif x.isResize() and y.isResize():
-                if x.isGrow() and y.isGrow():
-                    # for grow, devices come first, root down
-                    if x.isDevice() and not y.isDevice():
-                        #log.debug("x is device -- x first")
-                        return -1
-                    elif y.isDevice() and not x.isDevice():
-			#log.debug("y is device -- y first")
-                        return 1
+        # in most cases the actions will already be sorted because of the
+        # rules for registration, but let's not rely on that
+        def cmpActions(a1, a2):
+            ret = 0
+            if a1.isDestroy() and a2.isDestroy():
+                if a1.device.path == a2.device.path:
+                    # if it's the same device, destroy the format first
+                    if a1.isFormat() and a2.isFormat():
+                        ret = 0
+                    elif a1.isFormat() and not a2.isFormat():
+                        ret = -1
+                    elif not a1.isFormat() and a2.isFormat():
+                        ret = 1
+                elif a1.device.dependsOn(a2.device):
+                    ret = -1
+                elif a2.device.dependsOn(a1.device):
+                    ret = 1
+                # generally destroy partitions after lvs, vgs, &c
+                elif isinstance(a1.device, PartitionDevice) and \
+                     isinstance(a2.device, PartitionDevice):
+                    ret = cmp(a2.device.name, a1.device.name)
+                elif isinstance(a1.device, PartitionDevice) and \
+                     not isinstance(a2.device, DiskDevice):
+                    ret = 1
+                elif isinstance(a2.device, PartitionDevice) and \
+                     not isinstance(a1.device, DiskDevice):
+                    ret = -1
+                else:
+                    ret = cmp(a2.device.name, a1.device.name)
+            elif a1.isDestroy():
+                ret = -1
+            elif a2.isDestroy():
+                ret = 1
+            elif a1.isResize() and a2.isResize():
+                if a1.device.path == a2.device.path:
+                    if a1.obj and a2.obj:
+                        ret = 0
+                    elif a1.isFormat() and not a2.isFormat():
+                        # same path, one device, one format
+                        if a1.isGrow():
+                            ret = 1
+                        else:
+                            ret = -1
+                    elif not a1.isFormat() and a2.isFormat():
+                        # same path, one device, one format
+                        if a1.isGrow():
+                            ret = -1
+                        else:
+                            ret = 1
                     else:
-                        # innermost/oldest first
-                        if x.device.dependsOn(y.device):
-			    #log.debug("x depends on y -- y first")
-                            return 1
-                        elif y.device.dependsOn(x.device):
-		            #log.debug("y depends on x -- x first")
-                            return -1
-                elif x.isShrink() and y.isShrink():
-                    # for shrink, filesystems come first, leaves up
-                    if x.isFormat() and not y.isFormat():
-		        #log.debug("x is format -- x first")
-                        return -1
-                    elif y.isFormat() and not x.isFormat():
-                        #log.debug("y is format -- y first")
-                        return 1
+                        ret = cmp(a1.device.name, a2.device.name)
+                elif a1.device.dependsOn(a2.device):
+                    if a1.isGrow():
+                        ret = 1
+                    else:
+                        ret = -1
+                elif a2.device.dependsOn(a1.device):
+                    if a1.isGrow():
+                        ret = -1
+                    else:
+                        ret = 1
+                elif isinstance(a1.device, PartitionDevice) and \
+                     isinstance(a2.device, PartitionDevice):
+                    ret = cmp(a1.device.name, a2.device.name)
+                elif isinstance(a1.device, PartitionDevice) and \
+                     not isinstance(a2.device, DiskDevice):
+                    if a1.isGrow():
+                        ret = -1
+                    else:
+                        ret = 1
+                elif isinstance(a2.device, PartitionDevice) and \
+                     not isinstance(a1.device, DiskDevice):
+                    if a2.isGrow():
+                        ret = 1
+                    else:
+                        ret = -1
+                else:
+                    ret = cmp(a1.device.name, a2.device.name)
+            elif a1.isResize():
+                ret = -1
+            elif a2.isResize():
+                ret = 1
+            elif a1.isCreate() and a2.isCreate():
+                if a1.device.path == a2.device.path:
+                    if a1.obj == a2.obj:
+                        ret = 0
+                    if a1.isFormat():
+                        ret = 1
+                    elif a2.isFormat():
+                        ret = -1
                     else:
-                        # outermost/youngest first
-                        if x.device.dependsOn(y.device):
-			    #log.debug("x depends on y -- x first")
-                            return -1
-                        elif y.device.dependsOn(x.device):
-                            #log.debug("y depends on x -- y first")
-                            return 1
+                        ret = cmp(a1.device.name, a2.device.name)
+                elif a1.device.dependsOn(a2.device):
+                    ret = 1
+                elif a2.device.dependsOn(a1.device):
+                    ret = -1
+                # generally create partitions before other device types
+                elif isinstance(a1.device, PartitionDevice) and \
+                     isinstance(a2.device, PartitionDevice):
+                    ret = cmp(a1.device.name, a2.device.name)
+                elif isinstance(a1.device, PartitionDevice) and \
+                     not isinstance(a2.device, DiskDevice):
+                    ret = -1
+                elif isinstance(a2.device, PartitionDevice) and \
+                     not isinstance(a1.device, DiskDevice):
+                    ret = 1
                 else:
-                    # we don't care about grow action -v- shrink action
-                    # since they should be unrelated
-		    #log.debug("we don't care")
-                    return 0
-
-            # create actions come last
-            if x.isCreate() and y.isCreate():
-                # innermost/oldest first
-                if x.device.dependsOn(y.device):
-		    #log.debug("x depends on y")
-                    return 1
-                elif y.device.dependsOn(x.device):
-		    #log.debug("y depends on x")
-                    return -1
-                # devices first, root down
-                elif x.isDevice() and not y.isDevice():
-		    #log.debug("x is a device")
-                    return -1
-                elif y.isDevice() and not x.isDevice():
-		    #log.debug("y is a device")
-                    return 1
-
-	    #log.debug("no decision")
-            return 0
+                    ret = cmp(a1.device.name, a2.device.name)
+            elif a1.isCreate():
+                ret = -1
+            elif a2.isCreate():
+                ret = 1
+            elif a1.isMigrate() and a2.isMigrate():
+                if a1.device.path == a2.device.path:
+                    ret = 0
+                elif a1.device.dependsOn(a2.device):
+                    ret = 1
+                elif a2.device.dependsOn(a1.device):
+                    ret = -1
+                elif isinstance(a1.device, PartitionDevice) and \
+                     isinstance(a2.device, PartitionDevice):
+                    ret = cmp(a1.device.name, a2.device.name)
+                else:
+                    ret = cmp(a1.device.name, a2.device.name)
+            else:
+                ret = cmp(a1.device.name, a2.device.name)
+
+            log.debug("cmp: %d -- %s | %s" % (ret, a1, a2))
+            return ret
 
-        # in most cases the actions will already be sorted because of the
-        # rules for registration, but let's not rely on that
         for action in self._actions:
             log.debug("action: %s" % action)
+
         log.debug("pruning action queue...")
         self.pruneActions()
         for action in self._actions:
             log.debug("action: %s" % action)
-        #self._actions.sort(cmpActions)
+
+        log.debug("sorting actions...")
+        self._actions.sort(cmp=cmpActions)
+        for action in self._actions:
+            log.debug("action: %s" % action)
+
         self.teardownAll()
         for action in self._actions:
             log.info("executing action: %s" % action)
-- 
1.6.0.6

_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/anaconda-devel-list

[Index of Archives]     [Kickstart]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]
  Powered by Linux