1 {-| Module describing a node.
3 All updates are functional (copy-based) and return a new node with
9 Node(failN1, idx, f_mem, f_dsk, p_mem, p_dsk, slist, plist, p_rem)
12 -- ** Finalization after data loading
15 -- * Instance (re)location
27 import Text.Printf (printf)
29 import qualified Container
30 import qualified Instance
31 import qualified PeerMap
35 data Node = Node { t_mem :: Double -- ^ total memory (Mib)
36 , f_mem :: Int -- ^ free memory (MiB)
37 , t_dsk :: Double -- ^ total disk space (MiB)
38 , f_dsk :: Int -- ^ free disk space (MiB)
39 , plist :: [Int] -- ^ list of primary instance indices
40 , slist :: [Int] -- ^ list of secondary instance indices
41 , idx :: Int -- ^ internal index for book-keeping
42 , peers:: PeerMap.PeerMap -- ^ primary node to instance
44 , failN1:: Bool -- ^ whether the node has failed n1
45 , maxRes :: Int -- ^ maximum memory needed for
46 -- failover by primaries of this node
52 {- | Create a new node.
54 The index and the peers maps are empty, and will be need to be update
55 later via the 'setIdx' and 'buildPeers' functions.
58 create :: String -> String -> String -> String -> Node
59 create mem_t_init mem_f_init dsk_t_init dsk_f_init =
60 let mem_t = read mem_t_init
61 mem_f = read mem_f_init
62 dsk_t = read dsk_t_init
63 dsk_f = read dsk_f_init
67 t_mem = read mem_t_init,
68 f_mem = read mem_f_init,
69 t_dsk = read dsk_t_init,
70 f_dsk = read dsk_f_init,
75 peers = PeerMap.empty,
77 p_mem = (fromIntegral mem_f) / (fromIntegral mem_t),
78 p_dsk = (fromIntegral dsk_f) / (fromIntegral dsk_t),
82 -- | Changes the index.
83 -- This is used only during the building of the data structures.
84 setIdx :: Node -> Int -> Node
85 setIdx t i = t {idx = i}
87 -- | Given the rmem, free memory and disk, computes the failn1 status.
88 computeFailN1 :: Int -> Int -> Int -> Bool
89 computeFailN1 new_rmem new_mem new_dsk =
90 new_mem <= new_rmem || new_dsk <= 0
92 -- | Given the new free memory and disk, fail if any of them is below zero.
93 failHealth :: Int -> Int -> Bool
94 failHealth new_mem new_dsk = new_mem <= 0 || new_dsk <= 0
96 -- | Computes the maximum reserved memory for peers from a peer map.
97 computeMaxRes :: PeerMap.PeerMap -> PeerMap.Elem
98 computeMaxRes new_peers = PeerMap.maxElem new_peers
100 -- | Builds the peer map for a given node.
101 buildPeers :: Node -> Container.Container Instance.Instance -> Int -> Node
102 buildPeers t il num_nodes =
104 (\i_idx -> let inst = Container.find i_idx il
105 in (Instance.pnode inst, Instance.mem inst))
107 pmap = PeerMap.accumArray (+) 0 (0, num_nodes - 1) mdata
108 new_rmem = computeMaxRes pmap
109 new_failN1 = computeFailN1 new_rmem (f_mem t) (f_dsk t)
110 new_prem = (fromIntegral new_rmem) / (t_mem t)
111 in t {peers=pmap, failN1 = new_failN1, maxRes = new_rmem, p_rem = new_prem}
113 -- | Removes a primary instance.
114 removePri :: Node -> Instance.Instance -> Node
116 let iname = Instance.idx inst
117 new_plist = delete iname (plist t)
118 new_mem = f_mem t + Instance.mem inst
119 new_dsk = f_dsk t + Instance.dsk inst
120 new_mp = (fromIntegral new_mem) / (t_mem t)
121 new_dp = (fromIntegral new_dsk) / (t_dsk t)
122 new_failn1 = computeFailN1 (maxRes t) new_mem new_dsk
123 in t {plist = new_plist, f_mem = new_mem, f_dsk = new_dsk,
124 failN1 = new_failn1, p_mem = new_mp, p_dsk = new_dp}
126 -- | Removes a secondary instance.
127 removeSec :: Node -> Instance.Instance -> Node
129 let iname = Instance.idx inst
130 pnode = Instance.pnode inst
131 new_slist = delete iname (slist t)
132 new_dsk = f_dsk t + Instance.dsk inst
134 old_peem = PeerMap.find pnode old_peers
135 new_peem = old_peem - (Instance.mem inst)
136 new_peers = PeerMap.add pnode new_peem old_peers
138 new_rmem = if old_peem < old_rmem then
141 computeMaxRes new_peers
142 new_prem = (fromIntegral new_rmem) / (t_mem t)
143 new_failn1 = computeFailN1 new_rmem (f_mem t) new_dsk
144 new_dp = (fromIntegral new_dsk) / (t_dsk t)
145 in t {slist = new_slist, f_dsk = new_dsk, peers = new_peers,
146 failN1 = new_failn1, maxRes = new_rmem, p_dsk = new_dp,
149 -- | Adds a primary instance.
150 addPri :: Node -> Instance.Instance -> Maybe Node
152 let iname = Instance.idx inst
153 new_mem = f_mem t - Instance.mem inst
154 new_dsk = f_dsk t - Instance.dsk inst
155 new_failn1 = computeFailN1 (maxRes t) new_mem new_dsk in
156 if (failHealth new_mem new_dsk) || (new_failn1 && not (failN1 t)) then
159 let new_plist = iname:(plist t)
160 new_mp = (fromIntegral new_mem) / (t_mem t)
161 new_dp = (fromIntegral new_dsk) / (t_dsk t)
163 Just t {plist = new_plist, f_mem = new_mem, f_dsk = new_dsk,
164 failN1 = new_failn1, p_mem = new_mp, p_dsk = new_dp}
166 -- | Adds a secondary instance.
167 addSec :: Node -> Instance.Instance -> Int -> Maybe Node
169 let iname = Instance.idx inst
172 new_dsk = f_dsk t - Instance.dsk inst
173 new_peem = PeerMap.find pdx old_peers + Instance.mem inst
174 new_peers = PeerMap.add pdx new_peem old_peers
175 new_rmem = max (maxRes t) new_peem
176 new_prem = (fromIntegral new_rmem) / (t_mem t)
177 new_failn1 = computeFailN1 new_rmem old_mem new_dsk in
178 if (failHealth old_mem new_dsk) || (new_failn1 && not (failN1 t)) then
181 let new_slist = iname:(slist t)
182 new_dp = (fromIntegral new_dsk) / (t_dsk t)
184 Just t {slist = new_slist, f_dsk = new_dsk,
185 peers = new_peers, failN1 = new_failn1,
186 maxRes = new_rmem, p_dsk = new_dp,
189 -- | Add a primary instance to a node without other updates
190 setPri :: Node -> Int -> Node
191 setPri t idx = t { plist = idx:(plist t) }
193 -- | Add a secondary instance to a node without other updates
194 setSec :: Node -> Int -> Node
195 setSec t idx = t { slist = idx:(slist t) }
197 -- | Simple converter to string.
198 str :: Node -> String
200 printf ("Node %d (mem=%5d MiB, disk=%5.2f GiB)\n Primaries:" ++
201 " %s\nSecondaries: %s")
202 (idx t) (f_mem t) ((f_dsk t) `div` 1024)
203 (commaJoin (map show (plist t)))
204 (commaJoin (map show (slist t)))
206 -- | String converter for the node list functionality.
207 list :: Int -> String -> Node -> String
215 printf " %c %-*s %5d %5d %5d %3d %3d %.5f %.5f"
216 (if fn then '*' else ' ')
217 mname n (f_mem t) (maxRes t) ((f_dsk t) `div` 1024)
218 (length pl) (length sl)