<commit_before>{-| Module describing a node.

    All updates are functional (copy-based) and return a new node with
    updated value.
-}

module Ganeti.HTools.Node
    (
      Node(failN1, idx, t_mem, n_mem, f_mem, t_dsk, f_dsk,
           p_mem, p_dsk, p_rem,
           plist, slist, offline)
    -- * Constructor
    , create
    -- ** Finalization after data loading
    , buildPeers
    , setIdx
    , setOffline
    , setXmem
    , setFmem
    -- * Instance (re)location
    , removePri
    , removeSec
    , addPri
    , addSec
    , setPri
    , setSec
    -- * Formatting
    , list
    ) where

import Data.List
import Text.Printf (printf)

import qualified Ganeti.HTools.Container as Container
import qualified Ganeti.HTools.Instance as Instance
import qualified Ganeti.HTools.PeerMap as PeerMap

import Ganeti.HTools.Utils

data Node = Node { t_mem :: Double -- ^ total memory (MiB)
                 , n_mem :: Int    -- ^ node memory (MiB)
                 , f_mem :: Int    -- ^ free memory (MiB)
                 , x_mem :: Int    -- ^ unaccounted memory (MiB)
                 , t_dsk :: Double -- ^ total disk space (MiB)
                 , f_dsk :: Int    -- ^ free disk space (MiB)
                 , plist :: [Int]  -- ^ list of primary instance indices
                 , slist :: [Int]  -- ^ list of secondary instance indices
                 , idx :: Int      -- ^ internal index for book-keeping
                 , peers :: PeerMap.PeerMap -- ^ pnode to instance mapping
                 , failN1:: Bool   -- ^ whether the node has failed n1
                 , r_mem :: Int    -- ^ maximum memory needed for
                                   -- failover by primaries of this node
                 , p_mem :: Double -- ^ percent of free memory
                 , p_dsk :: Double -- ^ percent of free disk
                 , p_rem :: Double -- ^ percent of reserved memory
                 , offline :: Bool -- ^ whether the node should not be used
                                   -- for allocations and skipped from
                                   -- score computations
  } deriving (Show)

{- | Create a new node.

The index and the peers maps are empty, and will be need to be update
later via the 'setIdx' and 'buildPeers' functions.

-}
create :: Double -> Int -> Int -> Double -> Int -> Node
create mem_t_init mem_n_init mem_f_init dsk_t_init dsk_f_init =
    Node
    {
      t_mem = mem_t_init,
      n_mem = mem_n_init,
      f_mem = mem_f_init,
      t_dsk = dsk_t_init,
      f_dsk = dsk_f_init,
      plist = [],
      slist = [],
      failN1 = True,
      idx = -1,
      peers = PeerMap.empty,
      r_mem = 0,
      p_mem = (fromIntegral mem_f_init) / mem_t_init,
      p_dsk = (fromIntegral dsk_f_init) / dsk_t_init,
      p_rem = 0,
      offline = False,
      x_mem = 0
    }

-- | Changes the index.
-- This is used only during the building of the data structures.
setIdx :: Node -> Int -> Node
setIdx t i = t {idx = i}

-- | Sets the offline attribute
setOffline :: Node -> Bool -> Node
setOffline t val = t { offline = val }

-- | Sets the unnaccounted memory
setXmem :: Node -> Int -> Node
setXmem t val = t { x_mem = val }

-- | Sets the free memory
setFmem :: Node -> Int -> Node
setFmem t val = t { f_mem = val }

-- | Given the rmem, free memory and disk, computes the failn1 status.
computeFailN1 :: Int -> Int -> Int -> Bool
computeFailN1 new_rmem new_mem new_dsk =
    new_mem <= new_rmem || new_dsk <= 0

-- | Given the new free memory and disk, fail if any of them is below zero.
failHealth :: Int -> Int -> Bool
failHealth new_mem new_dsk = new_mem <= 0 || new_dsk <= 0<commit_msg>Update all needed node fields on f_mem change<commit_after>{-| Module describing a node.

    All updates are functional (copy-based) and return a new node with
    updated value.
-}

module Ganeti.HTools.Node
    (
      Node(failN1, idx, t_mem, n_mem, f_mem, t_dsk, f_dsk,
           p_mem, p_dsk, p_rem,
           plist, slist, offline)
    -- * Constructor
    , create
    -- ** Finalization after data loading
    , buildPeers
    , setIdx
    , setOffline
    , setXmem
    , setFmem
    -- * Instance (re)location
    , removePri
    , removeSec
    , addPri
    , addSec
    , setPri
    , setSec
    -- * Formatting
    , list
    ) where

import Data.List
import Text.Printf (printf)

import qualified Ganeti.HTools.Container as Container
import qualified Ganeti.HTools.Instance as Instance
import qualified Ganeti.HTools.PeerMap as PeerMap

import Ganeti.HTools.Utils

data Node = Node { t_mem :: Double -- ^ total memory (MiB)
                 , n_mem :: Int    -- ^ node memory (MiB)
                 , f_mem :: Int    -- ^ free memory (MiB)
                 , x_mem :: Int    -- ^ unaccounted memory (MiB)
                 , t_dsk :: Double -- ^ total disk space (MiB)
                 , f_dsk :: Int    -- ^ free disk space (MiB)
                 , plist :: [Int]  -- ^ list of primary instance indices
                 , slist :: [Int]  -- ^ list of secondary instance indices
                 , idx :: Int      -- ^ internal index for book-keeping
                 , peers :: PeerMap.PeerMap -- ^ pnode to instance mapping
                 , failN1:: Bool   -- ^ whether the node has failed n1
                 , r_mem :: Int    -- ^ maximum memory needed for
                                   -- failover by primaries of this node
                 , p_mem :: Double -- ^ percent of free memory
                 , p_dsk :: Double -- ^ percent of free disk
                 , p_rem :: Double -- ^ percent of reserved memory
                 , offline :: Bool -- ^ whether the node should not be used
                                   -- for allocations and skipped from
                                   -- score computations
  } deriving (Show)

{- | Create a new node.

The index and the peers maps are empty, and will be need to be update
later via the 'setIdx' and 'buildPeers' functions.

-}
create :: Double -> Int -> Int -> Double -> Int -> Node
create mem_t_init mem_n_init mem_f_init dsk_t_init dsk_f_init =
    Node
    {
      t_mem = mem_t_init,
      n_mem = mem_n_init,
      f_mem = mem_f_init,
      t_dsk = dsk_t_init,
      f_dsk = dsk_f_init,
      plist = [],
      slist = [],
      failN1 = True,
      idx = -1,
      peers = PeerMap.empty,
      r_mem = 0,
      p_mem = (fromIntegral mem_f_init) / mem_t_init,
      p_dsk = (fromIntegral dsk_f_init) / dsk_t_init,
      p_rem = 0,
      offline = False,
      x_mem = 0
    }

-- | Changes the index.
-- This is used only during the building of the data structures.
setIdx :: Node -> Int -> Node
setIdx t i = t {idx = i}

-- | Sets the offline attribute
setOffline :: Node -> Bool -> Node
setOffline t val = t { offline = val }

-- | Sets the unnaccounted memory
setXmem :: Node -> Int -> Node
setXmem t val = t { x_mem = val }

-- | Sets the free memory
setFmem :: Node -> Int -> Node
setFmem t new_mem =
    let new_n1 = computeFailN1 (r_mem t) new_mem (f_dsk t)
        new_mp = (fromIntegral new_mem) / (t_mem t)
    in
      t { f_mem = new_mem, failN1 = new_n1, p_mem = new_mp }

-- | Given the rmem, free memory and disk, computes the failn1 status.
computeFailN1 :: Int -> Int -> Int -> Bool
computeFailN1 new_rmem new_mem new_dsk =
    new_mem <= new_rmem || new_dsk <= 0

-- | Given the new free memory and disk, fail if any of them is below zero.
failHealth :: Int -> Int -> Bool
failHealth new_mem new_dsk = new_mem <= 0 || new_dsk <= 0
{'fraction_non_alphanumeric': 0.09811774128954746, 'fraction_numerical': 0.004271792818048324, 'mean_word_length': 1.8335854765506807, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3997792', 'n_tokens_mistral': 2405, 'n_tokens_neox': 2332, 'n_words': 792}