Exclude components which are equal to zero from the computation sum
on compile time by using Maybe monad to wrap optimal value computation
function.

Signed-off-by: Oleg Ponomarev <[email protected]>
---
 src/Ganeti/HTools/Cluster/MetricsComponents.hs | 17 ++++-------------
 src/Ganeti/HTools/Cluster/MetricsTH.hs         | 18 +++++++++++++-----
 2 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/src/Ganeti/HTools/Cluster/MetricsComponents.hs 
b/src/Ganeti/HTools/Cluster/MetricsComponents.hs
index e946b51..85f20ee 100644
--- a/src/Ganeti/HTools/Cluster/MetricsComponents.hs
+++ b/src/Ganeti/HTools/Cluster/MetricsComponents.hs
@@ -53,10 +53,6 @@ import qualified Ganeti.HTools.PeerMap as P
 import Ganeti.HTools.Types
 import Ganeti.Utils.Statistics
 
--- | Coefficient that is used for optimal value computation.
--- reservedMemRTotal :: Double
--- reservedMemRTotal = 0.25
-
 -- | Type alias decreasing table size below
 type D = Double
 
@@ -119,7 +115,7 @@ sumComp nm w on f = MetricComponent { name = nm
                                     , fromNodeType = [t| Double |]
                                     , statisticsType = [t| SumStat |]
                                     , forOnlineNodes = on
-                                    , optimalValue = [| zeroOptValueFunc |]
+                                    , optimalValue = Nothing
                                     }
 
 -- | Function to be used as a short MetricComponent constructor for StdDevStat.
@@ -130,7 +126,7 @@ stdDevComp nm w on f = MetricComponent { name = nm
                                        , fromNodeType = [t| Double |]
                                        , statisticsType = [t| StdDevStat |]
                                        , forOnlineNodes = on
-                                       , optimalValue = [| zeroOptValueFunc |]
+                                       , optimalValue = Nothing
                                        }
 
 -- | Function to be used as a short MetricComponent constructor for MapStat.
@@ -141,14 +137,9 @@ mapComp nm w on f = MetricComponent { name = nm
                                     , fromNodeType = [t| MapData |]
                                     , statisticsType = [t| MapStat |]
                                     , forOnlineNodes = on
-                                    , optimalValue = [| zeroOptValueFunc |]
+                                    , optimalValue = Nothing
                                     }
 
--- | Function is supposed to be used in MericComponent.hs as a most widepread
--- optimalValue function
-zeroOptValueFunc :: Node.List -> Double
-zeroOptValueFunc _ = 0
-
 -- | Weight of reservedMemRTotal component
 wReservedMemRTotal :: Double
 wReservedMemRTotal = 0.25
@@ -161,7 +152,7 @@ reservedMemRTotal = MetricComponent
   , fromNodeType = [t| Double |]
   , statisticsType = [t| SumStat |]
   , forOnlineNodes = True
-  , optimalValue = [| reservedMemRTotalOptValue |]
+  , optimalValue = Just [| reservedMemRTotalOptValue |]
   }
 
 -- | Computes theoretical opimal value for reservedMemRTotal component
diff --git a/src/Ganeti/HTools/Cluster/MetricsTH.hs 
b/src/Ganeti/HTools/Cluster/MetricsTH.hs
index 67bf9e6..1e2265f 100644
--- a/src/Ganeti/HTools/Cluster/MetricsTH.hs
+++ b/src/Ganeti/HTools/Cluster/MetricsTH.hs
@@ -42,6 +42,7 @@ module Ganeti.HTools.Cluster.MetricsTH
   ) where
 
 import Data.List (partition)
+import Data.Maybe (mapMaybe)
 import Language.Haskell.TH
 import Text.Printf (printf)
 
@@ -63,8 +64,9 @@ data MetricComponent = MetricComponent
                              -- should be defined
   , forOnlineNodes :: Bool   -- ^ Whether this component should be calculated
                              -- for online or offline nodes
-  , optimalValue   :: Q Exp  -- ^ Quasi quoted function obtaining optimal
-                             -- value of such component (Node.List -> Double)
+  , optimalValue   :: Maybe ExpQ  -- ^ Maybe quasi quoted function obtaining
+                                  -- optimal value of such component
+                                  -- (Node.List -> Double)
   }
 
 -- | Declares all functions and data types implemented in template haskell
@@ -240,16 +242,22 @@ showClusterStatisticsDecl components = do
   fun_d <- funD fname [clause [varP lp, varP cs] (normalB result) []]
   return [sig_d, fun_d]
 
+
 -- | Generates (optimalCVScore :: Node.List -> Double) declaration for metric
 -- components given. The function computes the lower bound of the cluster
 -- score, i.e., the sum of the minimal values for all cluster score values that
--- are not 0 on a perfectly balanced cluster.
+-- are not 0 on a perfectly balanced cluster. Components which optimal values
+-- are not 0 have Nothing as optimaLValue component
 optimalCVScoreDecl :: [MetricComponent] -> Q [Dec]
 optimalCVScoreDecl components = do
   nl <- newName "nl"
-  let comp c = appE (optimalValue c) $ varE nl
-      stat = appE [| sum :: [Double] -> Double |] . listE $ map comp components
+  let stat =
+        foldl (addVal nl) [| 0 :: Double |] $ mapMaybe optimalValue components
       fname = mkName "optimalCVScore"
   sig_d <- sigD fname ((arrowT `appT` [t| Node.List |]) `appT` [t| Double |])
   fun_d <- funD fname [clause [varP nl] (normalB stat) []]
   return [sig_d, fun_d]
+  where
+    addVal :: Name -> ExpQ -> ExpQ -> ExpQ
+    addVal nl cur f = appTwice [| (+) :: Double -> Double -> Double |]
+                               cur . appE f $ varE nl
-- 
1.9.1

Reply via email to