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_disk, p_mem, p_dsk, slist, plist)
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 :: Int -- ^ total memory (Mib)
36 , f_mem :: Int -- ^ free memory (MiB)
37 , t_disk :: Int -- ^ total disk space (MiB)
38 , f_disk :: 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
51 {- | Create a new node.
53 The index and the peers maps are empty, and will be need to be update
54 later via the 'setIdx' and 'buildPeers' functions.
57 create :: String -> String -> String -> String -> Node
58 create mem_t_init mem_f_init disk_t_init disk_f_init =
59 let mem_t = read mem_t_init
60 mem_f = read mem_f_init
61 disk_t = read disk_t_init
62 disk_f = read disk_f_init
66 t_mem = read mem_t_init,
67 f_mem = read mem_f_init,
68 t_disk = read disk_t_init,
69 f_disk = read disk_f_init,
74 peers = PeerMap.empty,
76 p_mem = (fromIntegral mem_f) / (fromIntegral mem_t),
77 p_dsk = (fromIntegral disk_f) / (fromIntegral disk_t)
80 -- | Changes the index.
81 -- This is used only during the building of the data structures.
82 setIdx :: Node -> Int -> Node
83 setIdx t i = t {idx = i}
85 -- | Given the rmem, free memory and disk, computes the failn1 status.
86 computeFailN1 :: Int -> Int -> Int -> Bool
87 computeFailN1 new_rmem new_mem new_disk =
88 new_mem <= new_rmem || new_disk <= 0
90 -- | Computes the maximum reserved memory for peers from a peer map.
91 computeMaxRes :: PeerMap.PeerMap -> PeerMap.Elem
92 computeMaxRes new_peers = PeerMap.maxElem new_peers
94 -- | Builds the peer map for a given node.
95 buildPeers :: Node -> Container.Container Instance.Instance -> Int -> Node
96 buildPeers t il num_nodes =
98 (\i_idx -> let inst = Container.find i_idx il
99 in (Instance.pnode inst, Instance.mem inst))
101 pmap = PeerMap.accumArray (+) 0 (0, num_nodes - 1) mdata
102 new_rmem = computeMaxRes pmap
103 new_failN1 = computeFailN1 new_rmem (f_mem t) (f_disk t)
104 in t {peers=pmap, failN1 = new_failN1, maxRes = new_rmem}
106 -- | Removes a primary instance.
107 removePri :: Node -> Instance.Instance -> Node
109 let iname = Instance.idx inst
110 new_plist = delete iname (plist t)
111 new_mem = f_mem t + Instance.mem inst
112 new_disk = f_disk t + Instance.disk inst
113 new_mp = (fromIntegral new_mem) / (fromIntegral $ t_mem t)
114 new_dp = (fromIntegral new_disk) / (fromIntegral $ t_disk t)
115 new_failn1 = computeFailN1 (maxRes t) new_mem new_disk
116 in t {plist = new_plist, f_mem = new_mem, f_disk = new_disk,
117 failN1 = new_failn1, p_mem = new_mp, p_dsk = new_dp}
119 -- | Removes a secondary instance.
120 removeSec :: Node -> Instance.Instance -> Node
122 let iname = Instance.idx inst
123 pnode = Instance.pnode inst
124 new_slist = delete iname (slist t)
125 new_disk = f_disk t + Instance.disk inst
127 old_peem = PeerMap.find pnode old_peers
128 new_peem = old_peem - (Instance.mem inst)
129 new_peers = PeerMap.add pnode new_peem old_peers
131 new_rmem = if old_peem < old_rmem then
134 computeMaxRes new_peers
135 new_failn1 = computeFailN1 new_rmem (f_mem t) new_disk
136 new_dp = (fromIntegral new_disk) / (fromIntegral $ t_disk t)
137 in t {slist = new_slist, f_disk = new_disk, peers = new_peers,
138 failN1 = new_failn1, maxRes = new_rmem, p_dsk = new_dp}
140 -- | Adds a primary instance.
141 addPri :: Node -> Instance.Instance -> Maybe Node
143 let iname = Instance.idx inst
144 new_mem = f_mem t - Instance.mem inst
145 new_disk = f_disk t - Instance.disk inst
146 new_failn1 = computeFailN1 (maxRes t) new_mem new_disk in
150 let new_plist = iname:(plist t)
151 new_mp = (fromIntegral new_mem) / (fromIntegral $ t_mem t)
152 new_dp = (fromIntegral new_disk) / (fromIntegral $ t_disk t)
154 Just t {plist = new_plist, f_mem = new_mem, f_disk = new_disk,
155 failN1 = new_failn1, p_mem = new_mp, p_dsk = new_dp}
157 -- | Adds a secondary instance.
158 addSec :: Node -> Instance.Instance -> Int -> Maybe Node
160 let iname = Instance.idx inst
162 new_disk = f_disk t - Instance.disk inst
163 new_peem = PeerMap.find pdx old_peers + Instance.mem inst
164 new_peers = PeerMap.add pdx new_peem old_peers
165 new_rmem = max (maxRes t) new_peem
166 new_failn1 = computeFailN1 new_rmem (f_mem t) new_disk in
170 let new_slist = iname:(slist t)
171 new_dp = (fromIntegral new_disk) / (fromIntegral $ t_disk t)
173 Just t {slist = new_slist, f_disk = new_disk,
174 peers = new_peers, failN1 = new_failn1,
175 maxRes = new_rmem, p_dsk = new_dp}
177 -- | Add a primary instance to a node without other updates
178 setPri :: Node -> Int -> Node
179 setPri t idx = t { plist = idx:(plist t) }
181 -- | Add a secondary instance to a node without other updates
182 setSec :: Node -> Int -> Node
183 setSec t idx = t { slist = idx:(slist t) }
185 -- | Simple converter to string.
186 str :: Node -> String
188 printf ("Node %d (mem=%5d MiB, disk=%5.2f GiB)\n Primaries:" ++
189 " %s\nSecondaries: %s")
190 (idx t) (f_mem t) ((f_disk t) `div` 1024)
191 (commaJoin (map show (plist t)))
192 (commaJoin (map show (slist t)))
194 -- | String converter for the node list functionality.
195 list :: String -> Node -> String
202 printf " %s(%d)\t%5d\t%5d\t%3d\t%3d\t%s\t%s\t%.5f\t%.5f"
203 n (idx t) (f_mem t) ((f_disk t) `div` 1024)
204 (length pl) (length sl)
205 (commaJoin (map show pl))
206 (commaJoin (map show sl))