{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecordWildCards #-}
module Ouroboros.Network.PeerSelection.LocalRootPeers
(
LocalRootPeers (..)
, invariant
, empty
, null
, size
, member
, target
, fromGroups
, toGroups
, toGroupSets
, toMap
, keysSet
, clampToLimit
) where
import Prelude hiding (null)
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Set (Set)
import qualified Data.Set as Set
import Ouroboros.Network.PeerSelection.Types
data LocalRootPeers peeraddr =
LocalRootPeers
(Map peeraddr PeerAdvertise)
[(Int, Set peeraddr)]
deriving LocalRootPeers peeraddr -> LocalRootPeers peeraddr -> Bool
(LocalRootPeers peeraddr -> LocalRootPeers peeraddr -> Bool)
-> (LocalRootPeers peeraddr -> LocalRootPeers peeraddr -> Bool)
-> Eq (LocalRootPeers peeraddr)
forall peeraddr.
Eq peeraddr =>
LocalRootPeers peeraddr -> LocalRootPeers peeraddr -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LocalRootPeers peeraddr -> LocalRootPeers peeraddr -> Bool
$c/= :: forall peeraddr.
Eq peeraddr =>
LocalRootPeers peeraddr -> LocalRootPeers peeraddr -> Bool
== :: LocalRootPeers peeraddr -> LocalRootPeers peeraddr -> Bool
$c== :: forall peeraddr.
Eq peeraddr =>
LocalRootPeers peeraddr -> LocalRootPeers peeraddr -> Bool
Eq
instance (Show peeraddr, Ord peeraddr) => Show (LocalRootPeers peeraddr) where
show :: LocalRootPeers peeraddr -> String
show LocalRootPeers peeraddr
lrps = String
"fromGroups " String -> ShowS
forall a. [a] -> [a] -> [a]
++ [(Int, Map peeraddr PeerAdvertise)] -> String
forall a. Show a => a -> String
show (LocalRootPeers peeraddr -> [(Int, Map peeraddr PeerAdvertise)]
forall peeraddr.
Ord peeraddr =>
LocalRootPeers peeraddr -> [(Int, Map peeraddr PeerAdvertise)]
toGroups LocalRootPeers peeraddr
lrps)
invariant :: Ord peeraddr => LocalRootPeers peeraddr -> Bool
invariant :: LocalRootPeers peeraddr -> Bool
invariant (LocalRootPeers Map peeraddr PeerAdvertise
m [(Int, Set peeraddr)]
gs) =
[Set peeraddr] -> Set peeraddr
forall (f :: * -> *) a. (Foldable f, Ord a) => f (Set a) -> Set a
Set.unions [ Set peeraddr
g | (Int
_, Set peeraddr
g) <- [(Int, Set peeraddr)]
gs ] Set peeraddr -> Set peeraddr -> Bool
forall a. Eq a => a -> a -> Bool
== Map peeraddr PeerAdvertise -> Set peeraddr
forall k a. Map k a -> Set k
Map.keysSet Map peeraddr PeerAdvertise
m
Bool -> Bool -> Bool
&& Map peeraddr PeerAdvertise -> Int
forall k a. Map k a -> Int
Map.size Map peeraddr PeerAdvertise
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [ Set peeraddr -> Int
forall a. Set a -> Int
Set.size Set peeraddr
g | (Int
_, Set peeraddr
g) <- [(Int, Set peeraddr)]
gs ]
Bool -> Bool -> Bool
&& [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and [ Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
t Bool -> Bool -> Bool
&& Int
t Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Set peeraddr -> Int
forall a. Set a -> Int
Set.size Set peeraddr
g | (Int
t, Set peeraddr
g) <- [(Int, Set peeraddr)]
gs ]
empty :: LocalRootPeers peeraddr
empty :: LocalRootPeers peeraddr
empty = Map peeraddr PeerAdvertise
-> [(Int, Set peeraddr)] -> LocalRootPeers peeraddr
forall peeraddr.
Map peeraddr PeerAdvertise
-> [(Int, Set peeraddr)] -> LocalRootPeers peeraddr
LocalRootPeers Map peeraddr PeerAdvertise
forall k a. Map k a
Map.empty []
null :: LocalRootPeers peeraddr -> Bool
null :: LocalRootPeers peeraddr -> Bool
null (LocalRootPeers Map peeraddr PeerAdvertise
m [(Int, Set peeraddr)]
_) = Map peeraddr PeerAdvertise -> Bool
forall k a. Map k a -> Bool
Map.null Map peeraddr PeerAdvertise
m
size :: LocalRootPeers peeraddr -> Int
size :: LocalRootPeers peeraddr -> Int
size (LocalRootPeers Map peeraddr PeerAdvertise
m [(Int, Set peeraddr)]
_) = Map peeraddr PeerAdvertise -> Int
forall k a. Map k a -> Int
Map.size Map peeraddr PeerAdvertise
m
member :: Ord peeraddr => peeraddr -> LocalRootPeers peeraddr -> Bool
member :: peeraddr -> LocalRootPeers peeraddr -> Bool
member peeraddr
p (LocalRootPeers Map peeraddr PeerAdvertise
m [(Int, Set peeraddr)]
_) = peeraddr -> Map peeraddr PeerAdvertise -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.member peeraddr
p Map peeraddr PeerAdvertise
m
target :: LocalRootPeers peeraddr -> Int
target :: LocalRootPeers peeraddr -> Int
target (LocalRootPeers Map peeraddr PeerAdvertise
_ [(Int, Set peeraddr)]
gs) = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [ Int
t | (Int
t, Set peeraddr
_) <- [(Int, Set peeraddr)]
gs ]
toMap :: LocalRootPeers peeraddr -> Map peeraddr PeerAdvertise
toMap :: LocalRootPeers peeraddr -> Map peeraddr PeerAdvertise
toMap (LocalRootPeers Map peeraddr PeerAdvertise
m [(Int, Set peeraddr)]
_) = Map peeraddr PeerAdvertise
m
keysSet :: LocalRootPeers peeraddr -> Set peeraddr
keysSet :: LocalRootPeers peeraddr -> Set peeraddr
keysSet (LocalRootPeers Map peeraddr PeerAdvertise
m [(Int, Set peeraddr)]
_) = Map peeraddr PeerAdvertise -> Set peeraddr
forall k a. Map k a -> Set k
Map.keysSet Map peeraddr PeerAdvertise
m
toGroupSets :: LocalRootPeers peeraddr -> [(Int, Set peeraddr)]
toGroupSets :: LocalRootPeers peeraddr -> [(Int, Set peeraddr)]
toGroupSets (LocalRootPeers Map peeraddr PeerAdvertise
_ [(Int, Set peeraddr)]
gs) = [(Int, Set peeraddr)]
gs
fromGroups :: Ord peeraddr
=> [(Int, Map peeraddr PeerAdvertise)]
-> LocalRootPeers peeraddr
fromGroups :: [(Int, Map peeraddr PeerAdvertise)] -> LocalRootPeers peeraddr
fromGroups =
(\[(Int, Map peeraddr PeerAdvertise)]
gs -> let m' :: Map peeraddr PeerAdvertise
m' = [Map peeraddr PeerAdvertise] -> Map peeraddr PeerAdvertise
forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
f (Map k a) -> Map k a
Map.unions [ Map peeraddr PeerAdvertise
g | (Int
_, Map peeraddr PeerAdvertise
g) <- [(Int, Map peeraddr PeerAdvertise)]
gs ]
gs' :: [(Int, Set peeraddr)]
gs' = [ (Int
t, Map peeraddr PeerAdvertise -> Set peeraddr
forall k a. Map k a -> Set k
Map.keysSet Map peeraddr PeerAdvertise
g) | (Int
t, Map peeraddr PeerAdvertise
g) <- [(Int, Map peeraddr PeerAdvertise)]
gs ]
in Map peeraddr PeerAdvertise
-> [(Int, Set peeraddr)] -> LocalRootPeers peeraddr
forall peeraddr.
Map peeraddr PeerAdvertise
-> [(Int, Set peeraddr)] -> LocalRootPeers peeraddr
LocalRootPeers Map peeraddr PeerAdvertise
m' [(Int, Set peeraddr)]
gs')
([(Int, Map peeraddr PeerAdvertise)] -> LocalRootPeers peeraddr)
-> ([(Int, Map peeraddr PeerAdvertise)]
-> [(Int, Map peeraddr PeerAdvertise)])
-> [(Int, Map peeraddr PeerAdvertise)]
-> LocalRootPeers peeraddr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set peeraddr
-> [(Int, Map peeraddr PeerAdvertise)]
-> [(Int, Map peeraddr PeerAdvertise)]
forall k a. Ord k => Set k -> [(Int, Map k a)] -> [(Int, Map k a)]
establishStructureInvariant Set peeraddr
forall a. Set a
Set.empty
where
establishStructureInvariant :: Set k -> [(Int, Map k a)] -> [(Int, Map k a)]
establishStructureInvariant !Set k
_ [] = []
establishStructureInvariant !Set k
acc ((Int
t, Map k a
g): [(Int, Map k a)]
gs)
| Int
t' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 = (Int
t', Map k a
g') (Int, Map k a) -> [(Int, Map k a)] -> [(Int, Map k a)]
forall a. a -> [a] -> [a]
: Set k -> [(Int, Map k a)] -> [(Int, Map k a)]
establishStructureInvariant Set k
acc' [(Int, Map k a)]
gs
| Bool
otherwise = Set k -> [(Int, Map k a)] -> [(Int, Map k a)]
establishStructureInvariant Set k
acc' [(Int, Map k a)]
gs
where
!g' :: Map k a
g' = Map k a
g Map k a -> Set k -> Map k a
forall k a. Ord k => Map k a -> Set k -> Map k a
`Map.withoutKeys` Set k
acc
!t' :: Int
t' = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
t (Map k a -> Int
forall k a. Map k a -> Int
Map.size Map k a
g')
!acc' :: Set k
acc' = Set k
acc Set k -> Set k -> Set k
forall a. Semigroup a => a -> a -> a
<> Map k a -> Set k
forall k a. Map k a -> Set k
Map.keysSet Map k a
g
toGroups :: Ord peeraddr
=> LocalRootPeers peeraddr
-> [(Int, Map peeraddr PeerAdvertise)]
toGroups :: LocalRootPeers peeraddr -> [(Int, Map peeraddr PeerAdvertise)]
toGroups (LocalRootPeers Map peeraddr PeerAdvertise
m [(Int, Set peeraddr)]
gs) =
[ (Int
t, (peeraddr -> PeerAdvertise)
-> Set peeraddr -> Map peeraddr PeerAdvertise
forall k a. (k -> a) -> Set k -> Map k a
Map.fromSet (Map peeraddr PeerAdvertise
m Map peeraddr PeerAdvertise -> peeraddr -> PeerAdvertise
forall k a. Ord k => Map k a -> k -> a
Map.!) Set peeraddr
g)
| (Int
t, Set peeraddr
g) <- [(Int, Set peeraddr)]
gs ]
clampToLimit :: Ord peeraddr
=> Int
-> LocalRootPeers peeraddr
-> LocalRootPeers peeraddr
clampToLimit :: Int -> LocalRootPeers peeraddr -> LocalRootPeers peeraddr
clampToLimit Int
totalLimit (LocalRootPeers Map peeraddr PeerAdvertise
m [(Int, Set peeraddr)]
gs0) =
let gs' :: [(Int, Set peeraddr)]
gs' = Int -> [(Int, Set peeraddr)] -> [(Int, Set peeraddr)]
forall a. Int -> [(Int, Set a)] -> [(Int, Set a)]
limitTotalSize Int
0 [(Int, Set peeraddr)]
gs0
m' :: Map peeraddr PeerAdvertise
m' = Map peeraddr PeerAdvertise
m Map peeraddr PeerAdvertise
-> Set peeraddr -> Map peeraddr PeerAdvertise
forall k a. Ord k => Map k a -> Set k -> Map k a
`Map.restrictKeys` [Set peeraddr] -> Set peeraddr
forall (f :: * -> *) a. (Foldable f, Ord a) => f (Set a) -> Set a
Set.unions [ Set peeraddr
g | (Int
_, Set peeraddr
g) <- [(Int, Set peeraddr)]
gs' ]
in Map peeraddr PeerAdvertise
-> [(Int, Set peeraddr)] -> LocalRootPeers peeraddr
forall peeraddr.
Map peeraddr PeerAdvertise
-> [(Int, Set peeraddr)] -> LocalRootPeers peeraddr
LocalRootPeers Map peeraddr PeerAdvertise
m' [(Int, Set peeraddr)]
gs'
where
limitTotalSize :: Int -> [(Int, Set a)] -> [(Int, Set a)]
limitTotalSize !Int
_ [] = []
limitTotalSize !Int
n ((Int
t, Set a
g) : [(Int, Set a)]
gs)
| Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
totalLimit
= []
| let n' :: Int
n' = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Set a -> Int
forall a. Set a -> Int
Set.size Set a
g
, Int
n' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
totalLimit
= (Int
t, Set a
g) (Int, Set a) -> [(Int, Set a)] -> [(Int, Set a)]
forall a. a -> [a] -> [a]
: Int -> [(Int, Set a)] -> [(Int, Set a)]
limitTotalSize Int
n' [(Int, Set a)]
gs
| Bool
otherwise
, let !g' :: Set a
g' = Int -> Set a -> Set a
forall a. Int -> Set a -> Set a
Set.take (Int
totalLimit Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n) Set a
g
!t' :: Int
t' = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
t (Set a -> Int
forall a. Set a -> Int
Set.size Set a
g')
= (Int
t', Set a
g') (Int, Set a) -> [(Int, Set a)] -> [(Int, Set a)]
forall a. a -> [a] -> [a]
: []