root / Ganeti / HTools / PeerMap.hs @ 9188aeef
History | View | Annotate | Download (2.2 kB)
1 |
{-| |
---|---|
2 |
Module abstracting the peer map implementation. |
3 |
|
4 |
This is abstracted separately since the speed of peermap updates can |
5 |
be a significant part of the total runtime, and as such changing the |
6 |
implementation should be easy in case it's needed. |
7 |
|
8 |
-} |
9 |
|
10 |
module Ganeti.HTools.PeerMap |
11 |
( PeerMap |
12 |
, Key |
13 |
, Elem |
14 |
, empty |
15 |
, accumArray |
16 |
, Ganeti.HTools.PeerMap.find |
17 |
, add |
18 |
, remove |
19 |
, maxElem |
20 |
) where |
21 |
|
22 |
import Data.Maybe (fromMaybe) |
23 |
import Data.List |
24 |
import Data.Function |
25 |
import Data.Ord |
26 |
|
27 |
import Ganeti.HTools.Types |
28 |
|
29 |
type Key = Ndx |
30 |
type Elem = Int |
31 |
type PeerMap = [(Key, Elem)] |
32 |
|
33 |
-- * Initialization functions |
34 |
|
35 |
-- | Create a new empty map. |
36 |
empty :: PeerMap |
37 |
empty = [] |
38 |
|
39 |
-- | Our reverse-compare function. |
40 |
pmCompare :: (Key, Elem) -> (Key, Elem) -> Ordering |
41 |
pmCompare a b = (compare `on` snd) b a |
42 |
|
43 |
-- | Add or update (via a custom function) an element. |
44 |
addWith :: (Elem -> Elem -> Elem) -> Key -> Elem -> PeerMap -> PeerMap |
45 |
addWith fn k v lst = |
46 |
let r = lookup k lst |
47 |
in |
48 |
case r of |
49 |
Nothing -> insertBy pmCompare (k, v) lst |
50 |
Just o -> insertBy pmCompare (k, fn o v) (remove k lst) |
51 |
|
52 |
-- | Create a PeerMap from an association list, with possible duplicates |
53 |
accumArray :: (Elem -> Elem -> Elem) -- ^ function used to merge the elements |
54 |
-> [(Key, Elem)] -- ^ source data |
55 |
-> PeerMap -- ^ results |
56 |
accumArray fn lst = |
57 |
case lst of |
58 |
[] -> empty |
59 |
(k, v):xs -> addWith fn k v $ accumArray fn xs |
60 |
|
61 |
-- * Basic operations |
62 |
|
63 |
-- | Returns either the value for a key or zero if not found |
64 |
find :: Key -> PeerMap -> Elem |
65 |
find k c = fromMaybe 0 $ lookup k c |
66 |
|
67 |
-- | Add an element to a peermap, overwriting the previous value |
68 |
add :: Key -> Elem -> PeerMap -> PeerMap |
69 |
add k v c = addWith (flip const) k v c |
70 |
|
71 |
-- | Remove an element from a peermap |
72 |
remove :: Key -> PeerMap -> PeerMap |
73 |
remove k c = case c of |
74 |
[] -> [] |
75 |
(x@(x', _)):xs -> if k == x' then xs |
76 |
else x:(remove k xs) |
77 |
|
78 |
-- | Find the maximum element. |
79 |
-- |
80 |
-- Since this is a sorted list, we just get the value at the head of |
81 |
-- the list, or zero for a null list |
82 |
maxElem :: PeerMap -> Elem |
83 |
maxElem c = if null c then 0 else snd . head $ c |