commit d55c7e85ac87be0529d2d84f8ed0f72c18f31e8f
Merge: 3a366d6 6a2114c
Author: Brian Foley <[email protected]>
Date: Tue Aug 16 13:14:32 2016 +0100
Merge branch 'stable-2.16' into stable-2.17
* stable-2.16
Improve error reporting in _VerifyClientCertificates
Simplify some inscrutable map/map/ifilter/zip code
Avoid overuse of operator in watcher *.py
Sprinkle some more list comprehensions
Replace map/partial with list comprehension
Replace uses of map/lambda with more Pythonic code
Replace map(operator.attrgetter, ...) uses
Fix typos in gnt-cluster man page
Hide errors for expected inotify failures in unittest
Add gnt-instance rename --force option
Improve documentation for gnt-instance failover
Allow master failover to ignore offline nodes
Fix LogicalVolume code to work with older /sbin/lvs
Shorten verifyMasterVote failure message
Adding a confirmation before gnt-node --offline no
Removed unnecessary dependency from rpc in cli
Refactor cli exception to its appropriate module
Clean-up of code and fix of pylint warnings
Use fork instead of spawnv in the watcher
Make 'make pep8' happy
Manually fix merge conflicts in src/Ganeti/Utils.py
Signed-off-by: Brian Foley <[email protected]>
diff --cc src/Ganeti/Utils.hs
index 42a8db9,47f65c1..0c2a0ac
--- a/src/Ganeti/Utils.hs
+++ b/src/Ganeti/Utils.hs
@@@ -97,16 -96,10 +97,17 @@@ module Ganeti.Util
, ensurePermissions
, ordNub
, isSubsequenceOf
+ , maxBy
+ , threadDelaySeconds
+ , monotoneFind
+ , iterateJust
+ , partitionM
+ , frequency
) where
-import Control.Applicative
+import Prelude ()
+import Ganeti.Prelude
+
import Control.Concurrent
import Control.Exception (try, bracket)
import Control.Monad
@@@ -116,17 -110,7 +117,19 @@@ import Data.Char (toUpper, isAlphaNum,
import qualified Data.Either as E
import Data.Function (on)
import Data.IORef
-import Data.List
+#if MIN_VERSION_base(4,8,0)
+import Data.List hiding (isSubsequenceOf)
+#else
+import Data.List ( intercalate
+ , find
+ , foldl'
++ , group
+ , transpose
++ , sort
+ , sortBy
+ , isPrefixOf
+ , maximumBy)
+#endif
import qualified Data.Map as M
import Data.Maybe (fromMaybe)
import qualified Data.Set as S
@@@ -846,41 -820,7 +849,46 @@@ isSubsequenceOf _ [
isSubsequenceOf a@(x:a') (y:b) | x == y = isSubsequenceOf a' b
| otherwise = isSubsequenceOf a b
+-- | Compute the maximum of two elements by a given order.
+-- As opposed to using `maximumBy`, is function is guaranteed
+-- to be total, as the signature enforces a non-empty list of
+-- arguments.
+maxBy :: (a -> a -> Ordering) -> a -> a -> a
+maxBy ord a b = maximumBy ord [a, b]
+
+-- | Given a predicate that is monotone on a list, find the
+-- first list entry where it holds, if any. Use the monotonicity
+-- property to evaluate the property at as few places as possible,
+-- guided by the heuristics provided.
+monotoneFind :: ([a] -> Int) -> (a -> Bool) -> [a] -> Maybe a
+monotoneFind heuristics p xs =
+ let count = heuristics xs
+ in case () of
+ _ | x:xs' <- drop count xs
+ -> if p x
+ then (`mplus` Just x) . monotoneFind heuristics p
+ $ take count xs
+ else monotoneFind heuristics p xs'
+ _ | x:xs' <- xs
+ -> if p x
+ then Just x
+ else monotoneFind heuristics p xs'
+ _ -> Nothing
+
+-- | Iterate a function as long as it returns Just values, collecting
+-- all the Justs that where obtained.
+iterateJust :: (a -> Maybe a) -> a -> [a]
+iterateJust f a = a : maybe [] (iterateJust f) (f a)
+
+-- | A version of partition with a monadic predicate
+-- Implementation taken from David Fox's Extras package.
+partitionM :: (Monad m) => (a -> m Bool) -> [a] -> m ([a], [a])
+partitionM p xs = foldM f ([], []) xs
+ where f (a, b) x = do
+ pv <- p x
+ return $ if pv then (x : a, b) else (a, x : b)
++
+ -- | Returns a list of tuples of elements and the number of times they occur
+ -- in a list
+ frequency :: Ord t => [t] -> [(Int, t)]
+ frequency xs = map (\x -> (length x, head x)) . group . sort $ xs