{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Ouroboros.Network.Server.ConnectionTable
( ConnectionTable
, ConnectionTableRef (..)
, ConnectionDirection (..)
, ValencyCounter
, newConnectionTableSTM
, newConnectionTable
, refConnectionSTM
, refConnection
, addConnection
, removeConnectionSTM
, removeConnection
, newValencyCounter
, addValencyCounter
, remValencyCounter
, waitValencyCounter
, readValencyCounter
) where
import Control.Concurrent.Class.MonadSTM.Strict
import Control.Monad (when)
import Data.Map.Strict qualified as M
import Data.Set (Set)
import Data.Set qualified as S
import Network.Socket qualified as Socket
import Text.Printf
data ConnectionTable m addr = ConnectionTable {
forall (m :: * -> *) addr.
ConnectionTable m addr
-> StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable :: StrictTVar m (M.Map (addr,ConnectionDirection) (ConnectionTableEntry m addr))
, forall (m :: * -> *) addr.
ConnectionTable m addr -> StrictTVar m Int
ctLastRefId :: StrictTVar m Int
}
data ValencyCounter m = ValencyCounter {
forall (m :: * -> *). ValencyCounter m -> Int
vcId :: Int
, forall (m :: * -> *). ValencyCounter m -> StrictTVar m Int
vcRef :: StrictTVar m Int
}
data ConnectionDirection = ConnectionInbound | ConnectionOutbound
deriving (ConnectionDirection -> ConnectionDirection -> Bool
(ConnectionDirection -> ConnectionDirection -> Bool)
-> (ConnectionDirection -> ConnectionDirection -> Bool)
-> Eq ConnectionDirection
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ConnectionDirection -> ConnectionDirection -> Bool
== :: ConnectionDirection -> ConnectionDirection -> Bool
$c/= :: ConnectionDirection -> ConnectionDirection -> Bool
/= :: ConnectionDirection -> ConnectionDirection -> Bool
Eq, Eq ConnectionDirection
Eq ConnectionDirection =>
(ConnectionDirection -> ConnectionDirection -> Ordering)
-> (ConnectionDirection -> ConnectionDirection -> Bool)
-> (ConnectionDirection -> ConnectionDirection -> Bool)
-> (ConnectionDirection -> ConnectionDirection -> Bool)
-> (ConnectionDirection -> ConnectionDirection -> Bool)
-> (ConnectionDirection
-> ConnectionDirection -> ConnectionDirection)
-> (ConnectionDirection
-> ConnectionDirection -> ConnectionDirection)
-> Ord ConnectionDirection
ConnectionDirection -> ConnectionDirection -> Bool
ConnectionDirection -> ConnectionDirection -> Ordering
ConnectionDirection -> ConnectionDirection -> ConnectionDirection
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ConnectionDirection -> ConnectionDirection -> Ordering
compare :: ConnectionDirection -> ConnectionDirection -> Ordering
$c< :: ConnectionDirection -> ConnectionDirection -> Bool
< :: ConnectionDirection -> ConnectionDirection -> Bool
$c<= :: ConnectionDirection -> ConnectionDirection -> Bool
<= :: ConnectionDirection -> ConnectionDirection -> Bool
$c> :: ConnectionDirection -> ConnectionDirection -> Bool
> :: ConnectionDirection -> ConnectionDirection -> Bool
$c>= :: ConnectionDirection -> ConnectionDirection -> Bool
>= :: ConnectionDirection -> ConnectionDirection -> Bool
$cmax :: ConnectionDirection -> ConnectionDirection -> ConnectionDirection
max :: ConnectionDirection -> ConnectionDirection -> ConnectionDirection
$cmin :: ConnectionDirection -> ConnectionDirection -> ConnectionDirection
min :: ConnectionDirection -> ConnectionDirection -> ConnectionDirection
Ord, Int -> ConnectionDirection -> ShowS
[ConnectionDirection] -> ShowS
ConnectionDirection -> String
(Int -> ConnectionDirection -> ShowS)
-> (ConnectionDirection -> String)
-> ([ConnectionDirection] -> ShowS)
-> Show ConnectionDirection
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ConnectionDirection -> ShowS
showsPrec :: Int -> ConnectionDirection -> ShowS
$cshow :: ConnectionDirection -> String
show :: ConnectionDirection -> String
$cshowList :: [ConnectionDirection] -> ShowS
showList :: [ConnectionDirection] -> ShowS
Show)
newValencyCounter
:: MonadSTM m
=> ConnectionTable m addr
-> Int
-> STM m (ValencyCounter m)
newValencyCounter :: forall (m :: * -> *) addr.
MonadSTM m =>
ConnectionTable m addr -> Int -> STM m (ValencyCounter m)
newValencyCounter ConnectionTable m addr
tbl Int
valency = do
lr <- StrictTVar m Int -> STM m Int
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar (StrictTVar m Int -> STM m Int) -> StrictTVar m Int -> STM m Int
forall a b. (a -> b) -> a -> b
$ ConnectionTable m addr -> StrictTVar m Int
forall (m :: * -> *) addr.
ConnectionTable m addr -> StrictTVar m Int
ctLastRefId ConnectionTable m addr
tbl
let !lr' = Int
lr Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
writeTVar (ctLastRefId tbl) lr'
v <- newTVar valency
return $ ValencyCounter lr' v
instance Ord (ValencyCounter m) where
compare :: ValencyCounter m -> ValencyCounter m -> Ordering
compare ValencyCounter m
a ValencyCounter m
b = Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (ValencyCounter m -> Int
forall (m :: * -> *). ValencyCounter m -> Int
vcId ValencyCounter m
a) (ValencyCounter m -> Int
forall (m :: * -> *). ValencyCounter m -> Int
vcId ValencyCounter m
b)
instance Eq (ValencyCounter m) where
== :: ValencyCounter m -> ValencyCounter m -> Bool
(==) ValencyCounter m
a ValencyCounter m
b = ValencyCounter m -> Int
forall (m :: * -> *). ValencyCounter m -> Int
vcId ValencyCounter m
a Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== ValencyCounter m -> Int
forall (m :: * -> *). ValencyCounter m -> Int
vcId ValencyCounter m
b
readValencyCounter :: MonadSTM m => ValencyCounter m -> STM m Int
readValencyCounter :: forall (m :: * -> *). MonadSTM m => ValencyCounter m -> STM m Int
readValencyCounter ValencyCounter m
vc = StrictTVar m Int -> STM m Int
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar (StrictTVar m Int -> STM m Int) -> StrictTVar m Int -> STM m Int
forall a b. (a -> b) -> a -> b
$ ValencyCounter m -> StrictTVar m Int
forall (m :: * -> *). ValencyCounter m -> StrictTVar m Int
vcRef ValencyCounter m
vc
data ConnectionTableEntry m addr = ConnectionTableEntry {
forall (m :: * -> *) addr.
ConnectionTableEntry m addr -> Set (ValencyCounter m)
cteRefs :: !(Set (ValencyCounter m))
, forall (m :: * -> *) addr. ConnectionTableEntry m addr -> Set addr
cteLocalAddresses :: !(Set addr)
}
data ConnectionTableRef =
ConnectionTableCreate
| ConnectionTableExist
| ConnectionTableDuplicate
deriving Int -> ConnectionTableRef -> ShowS
[ConnectionTableRef] -> ShowS
ConnectionTableRef -> String
(Int -> ConnectionTableRef -> ShowS)
-> (ConnectionTableRef -> String)
-> ([ConnectionTableRef] -> ShowS)
-> Show ConnectionTableRef
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ConnectionTableRef -> ShowS
showsPrec :: Int -> ConnectionTableRef -> ShowS
$cshow :: ConnectionTableRef -> String
show :: ConnectionTableRef -> String
$cshowList :: [ConnectionTableRef] -> ShowS
showList :: [ConnectionTableRef] -> ShowS
Show
addValencyCounter :: MonadSTM m => ValencyCounter m -> STM m ()
addValencyCounter :: forall (m :: * -> *). MonadSTM m => ValencyCounter m -> STM m ()
addValencyCounter ValencyCounter m
vc = StrictTVar m Int -> (Int -> Int) -> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> (a -> a) -> STM m ()
modifyTVar (ValencyCounter m -> StrictTVar m Int
forall (m :: * -> *). ValencyCounter m -> StrictTVar m Int
vcRef ValencyCounter m
vc) (\Int
r -> Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
remValencyCounter :: MonadSTM m => ValencyCounter m -> STM m ()
remValencyCounter :: forall (m :: * -> *). MonadSTM m => ValencyCounter m -> STM m ()
remValencyCounter ValencyCounter m
vc = StrictTVar m Int -> (Int -> Int) -> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> (a -> a) -> STM m ()
modifyTVar (ValencyCounter m -> StrictTVar m Int
forall (m :: * -> *). ValencyCounter m -> StrictTVar m Int
vcRef ValencyCounter m
vc) (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
waitValencyCounter :: MonadSTM m => ValencyCounter m -> STM m ()
waitValencyCounter :: forall (m :: * -> *). MonadSTM m => ValencyCounter m -> STM m ()
waitValencyCounter ValencyCounter m
vc = do
v <- StrictTVar m Int -> STM m Int
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar (StrictTVar m Int -> STM m Int) -> StrictTVar m Int -> STM m Int
forall a b. (a -> b) -> a -> b
$ ValencyCounter m -> StrictTVar m Int
forall (m :: * -> *). ValencyCounter m -> StrictTVar m Int
vcRef ValencyCounter m
vc
when (v <= 0)
retry
newConnectionTableSTM :: MonadSTM m => STM m (ConnectionTable m addr)
newConnectionTableSTM :: forall (m :: * -> *) addr.
MonadSTM m =>
STM m (ConnectionTable m addr)
newConnectionTableSTM = do
tbl <- Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> STM
m
(StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)))
forall (m :: * -> *) a. MonadSTM m => a -> STM m (StrictTVar m a)
newTVar Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
forall k a. Map k a
M.empty
li <- newTVar 0
return $ ConnectionTable tbl li
newConnectionTable :: MonadSTM m => m (ConnectionTable m addr)
newConnectionTable :: forall (m :: * -> *) addr. MonadSTM m => m (ConnectionTable m addr)
newConnectionTable = STM m (ConnectionTable m addr) -> m (ConnectionTable m addr)
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically STM m (ConnectionTable m addr)
forall (m :: * -> *) addr.
MonadSTM m =>
STM m (ConnectionTable m addr)
newConnectionTableSTM
addConnection
:: forall m addr.
( MonadSTM m
, Ord addr
)
=> ConnectionTable m addr
-> addr
-> addr
-> ConnectionDirection
-> Maybe (ValencyCounter m)
-> STM m ()
addConnection :: forall (m :: * -> *) addr.
(MonadSTM m, Ord addr) =>
ConnectionTable m addr
-> addr
-> addr
-> ConnectionDirection
-> Maybe (ValencyCounter m)
-> STM m ()
addConnection ConnectionTable{StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable :: forall (m :: * -> *) addr.
ConnectionTable m addr
-> StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable :: StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable} addr
remoteAddr addr
localAddr ConnectionDirection
dir Maybe (ValencyCounter m)
ref_m = do
StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
-> STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
-> (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)))
-> STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
forall a b. STM m a -> (a -> STM m b) -> STM m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr)))
-> (addr, ConnectionDirection)
-> Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
forall (f :: * -> *) k a.
(Functor f, Ord k) =>
(Maybe a -> f (Maybe a)) -> k -> Map k a -> f (Map k a)
M.alterF Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr))
fn (addr
remoteAddr,ConnectionDirection
dir) STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
-> (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> STM m ())
-> STM m ()
forall a b. STM m a -> (a -> STM m b) -> STM m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
-> Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable
where
fn :: Maybe (ConnectionTableEntry m addr) -> STM m (Maybe (ConnectionTableEntry m addr))
fn :: Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr))
fn Maybe (ConnectionTableEntry m addr)
Nothing = do
refs <- case Maybe (ValencyCounter m)
ref_m of
Just ValencyCounter m
ref -> do
ValencyCounter m -> STM m ()
forall (m :: * -> *). MonadSTM m => ValencyCounter m -> STM m ()
addValencyCounter ValencyCounter m
ref
Set (ValencyCounter m) -> STM m (Set (ValencyCounter m))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Set (ValencyCounter m) -> STM m (Set (ValencyCounter m)))
-> Set (ValencyCounter m) -> STM m (Set (ValencyCounter m))
forall a b. (a -> b) -> a -> b
$ ValencyCounter m -> Set (ValencyCounter m)
forall a. a -> Set a
S.singleton ValencyCounter m
ref
Maybe (ValencyCounter m)
Nothing -> Set (ValencyCounter m) -> STM m (Set (ValencyCounter m))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return Set (ValencyCounter m)
forall a. Set a
S.empty
return $ Just $ ConnectionTableEntry refs (S.singleton localAddr)
fn (Just ConnectionTableEntry m addr
cte) = do
let refs' :: Set (ValencyCounter m)
refs' = case Maybe (ValencyCounter m)
ref_m of
Just ValencyCounter m
ref -> ValencyCounter m
-> Set (ValencyCounter m) -> Set (ValencyCounter m)
forall a. Ord a => a -> Set a -> Set a
S.insert ValencyCounter m
ref (ConnectionTableEntry m addr -> Set (ValencyCounter m)
forall (m :: * -> *) addr.
ConnectionTableEntry m addr -> Set (ValencyCounter m)
cteRefs ConnectionTableEntry m addr
cte)
Maybe (ValencyCounter m)
Nothing -> ConnectionTableEntry m addr -> Set (ValencyCounter m)
forall (m :: * -> *) addr.
ConnectionTableEntry m addr -> Set (ValencyCounter m)
cteRefs ConnectionTableEntry m addr
cte
(ValencyCounter m -> STM m ())
-> Set (ValencyCounter m) -> STM m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ValencyCounter m -> STM m ()
forall (m :: * -> *). MonadSTM m => ValencyCounter m -> STM m ()
addValencyCounter Set (ValencyCounter m)
refs'
Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr)))
-> Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr))
forall a b. (a -> b) -> a -> b
$ ConnectionTableEntry m addr -> Maybe (ConnectionTableEntry m addr)
forall a. a -> Maybe a
Just (ConnectionTableEntry m addr
-> Maybe (ConnectionTableEntry m addr))
-> ConnectionTableEntry m addr
-> Maybe (ConnectionTableEntry m addr)
forall a b. (a -> b) -> a -> b
$ ConnectionTableEntry m addr
cte {
cteRefs = refs'
, cteLocalAddresses = S.insert localAddr (cteLocalAddresses cte)
}
_dumpConnectionTable
:: ConnectionTable IO Socket.SockAddr
-> IO ()
_dumpConnectionTable :: ConnectionTable IO SockAddr -> IO ()
_dumpConnectionTable ConnectionTable{StrictTVar
IO
(Map
(SockAddr, ConnectionDirection) (ConnectionTableEntry IO SockAddr))
ctTable :: forall (m :: * -> *) addr.
ConnectionTable m addr
-> StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable :: StrictTVar
IO
(Map
(SockAddr, ConnectionDirection) (ConnectionTableEntry IO SockAddr))
ctTable} = do
tbl <- STM
IO
(Map
(SockAddr, ConnectionDirection) (ConnectionTableEntry IO SockAddr))
-> IO
(Map
(SockAddr, ConnectionDirection) (ConnectionTableEntry IO SockAddr))
forall a. HasCallStack => STM IO a -> IO a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM
IO
(Map
(SockAddr, ConnectionDirection) (ConnectionTableEntry IO SockAddr))
-> IO
(Map
(SockAddr, ConnectionDirection)
(ConnectionTableEntry IO SockAddr)))
-> STM
IO
(Map
(SockAddr, ConnectionDirection) (ConnectionTableEntry IO SockAddr))
-> IO
(Map
(SockAddr, ConnectionDirection) (ConnectionTableEntry IO SockAddr))
forall a b. (a -> b) -> a -> b
$ StrictTVar
IO
(Map
(SockAddr, ConnectionDirection) (ConnectionTableEntry IO SockAddr))
-> STM
IO
(Map
(SockAddr, ConnectionDirection) (ConnectionTableEntry IO SockAddr))
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar StrictTVar
IO
(Map
(SockAddr, ConnectionDirection) (ConnectionTableEntry IO SockAddr))
ctTable
printf "Dumping Table:\n"
mapM_ dumpTableEntry (M.toList tbl)
where
dumpTableEntry :: ((Socket.SockAddr, ConnectionDirection), ConnectionTableEntry IO Socket.SockAddr) -> IO ()
dumpTableEntry :: ((SockAddr, ConnectionDirection), ConnectionTableEntry IO SockAddr)
-> IO ()
dumpTableEntry ((SockAddr
remoteAddr, ConnectionDirection
dir), ConnectionTableEntry IO SockAddr
ce) = do
refs <- (ValencyCounter IO -> IO Int) -> [ValencyCounter IO] -> IO [Int]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (STM Int -> IO Int
STM IO Int -> IO Int
forall a. HasCallStack => STM IO a -> IO a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM Int -> IO Int)
-> (ValencyCounter IO -> STM Int) -> ValencyCounter IO -> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StrictTVar IO Int -> STM Int
StrictTVar IO Int -> STM IO Int
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar (StrictTVar IO Int -> STM Int)
-> (ValencyCounter IO -> StrictTVar IO Int)
-> ValencyCounter IO
-> STM Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ValencyCounter IO -> StrictTVar IO Int
forall (m :: * -> *). ValencyCounter m -> StrictTVar m Int
vcRef) (Set (ValencyCounter IO) -> [ValencyCounter IO]
forall a. Set a -> [a]
S.elems (Set (ValencyCounter IO) -> [ValencyCounter IO])
-> Set (ValencyCounter IO) -> [ValencyCounter IO]
forall a b. (a -> b) -> a -> b
$ ConnectionTableEntry IO SockAddr -> Set (ValencyCounter IO)
forall (m :: * -> *) addr.
ConnectionTableEntry m addr -> Set (ValencyCounter m)
cteRefs ConnectionTableEntry IO SockAddr
ce)
let rids = (ValencyCounter IO -> Int) -> [ValencyCounter IO] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ValencyCounter IO -> Int
forall (m :: * -> *). ValencyCounter m -> Int
vcId ([ValencyCounter IO] -> [Int]) -> [ValencyCounter IO] -> [Int]
forall a b. (a -> b) -> a -> b
$ Set (ValencyCounter IO) -> [ValencyCounter IO]
forall a. Set a -> [a]
S.elems (Set (ValencyCounter IO) -> [ValencyCounter IO])
-> Set (ValencyCounter IO) -> [ValencyCounter IO]
forall a b. (a -> b) -> a -> b
$ ConnectionTableEntry IO SockAddr -> Set (ValencyCounter IO)
forall (m :: * -> *) addr.
ConnectionTableEntry m addr -> Set (ValencyCounter m)
cteRefs ConnectionTableEntry IO SockAddr
ce
refids = [Int] -> [Int] -> [(Int, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
rids [Int]
refs
printf "Remote Address: %s\nLocal Addresses %s\nDirection %s\nReferenses %s\n"
(show remoteAddr) (show $ cteLocalAddresses ce) (show dir) (show refids)
removeConnectionSTM
:: forall m addr.
( MonadSTM m
, Ord addr
)
=> ConnectionTable m addr
-> addr
-> addr
-> ConnectionDirection
-> STM m ()
removeConnectionSTM :: forall (m :: * -> *) addr.
(MonadSTM m, Ord addr) =>
ConnectionTable m addr
-> addr -> addr -> ConnectionDirection -> STM m ()
removeConnectionSTM ConnectionTable{StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable :: forall (m :: * -> *) addr.
ConnectionTable m addr
-> StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable :: StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable} addr
remoteAddr addr
localAddr ConnectionDirection
dir =
StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
-> STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
-> (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)))
-> STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
forall a b. STM m a -> (a -> STM m b) -> STM m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr)))
-> (addr, ConnectionDirection)
-> Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
forall (f :: * -> *) k a.
(Functor f, Ord k) =>
(Maybe a -> f (Maybe a)) -> k -> Map k a -> f (Map k a)
M.alterF Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr))
fn (addr
remoteAddr, ConnectionDirection
dir) STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
-> (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> STM m ())
-> STM m ()
forall a b. STM m a -> (a -> STM m b) -> STM m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
-> Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable
where
fn :: Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr))
fn :: Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr))
fn Maybe (ConnectionTableEntry m addr)
Nothing = Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (ConnectionTableEntry m addr)
forall a. Maybe a
Nothing
fn (Just ConnectionTableEntry{Set (ValencyCounter m)
cteRefs :: forall (m :: * -> *) addr.
ConnectionTableEntry m addr -> Set (ValencyCounter m)
cteRefs :: Set (ValencyCounter m)
cteRefs, Set addr
cteLocalAddresses :: forall (m :: * -> *) addr. ConnectionTableEntry m addr -> Set addr
cteLocalAddresses :: Set addr
cteLocalAddresses}) = do
(ValencyCounter m -> STM m ())
-> Set (ValencyCounter m) -> STM m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ValencyCounter m -> STM m ()
forall (m :: * -> *). MonadSTM m => ValencyCounter m -> STM m ()
remValencyCounter Set (ValencyCounter m)
cteRefs
let localAddresses' :: Set addr
localAddresses' = addr -> Set addr -> Set addr
forall a. Ord a => a -> Set a -> Set a
S.delete addr
localAddr Set addr
cteLocalAddresses
if Set addr -> Bool
forall a. Set a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Set addr
localAddresses'
then Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (ConnectionTableEntry m addr)
forall a. Maybe a
Nothing
else Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr))
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr)))
-> Maybe (ConnectionTableEntry m addr)
-> STM m (Maybe (ConnectionTableEntry m addr))
forall a b. (a -> b) -> a -> b
$ ConnectionTableEntry m addr -> Maybe (ConnectionTableEntry m addr)
forall a. a -> Maybe a
Just (ConnectionTableEntry m addr
-> Maybe (ConnectionTableEntry m addr))
-> ConnectionTableEntry m addr
-> Maybe (ConnectionTableEntry m addr)
forall a b. (a -> b) -> a -> b
$ Set (ValencyCounter m) -> Set addr -> ConnectionTableEntry m addr
forall (m :: * -> *) addr.
Set (ValencyCounter m) -> Set addr -> ConnectionTableEntry m addr
ConnectionTableEntry Set (ValencyCounter m)
cteRefs Set addr
localAddresses'
removeConnection
:: forall m addr.
( MonadSTM m
, Ord addr
)
=> ConnectionTable m addr
-> addr
-> addr
-> ConnectionDirection
-> m ()
removeConnection :: forall (m :: * -> *) addr.
(MonadSTM m, Ord addr) =>
ConnectionTable m addr
-> addr -> addr -> ConnectionDirection -> m ()
removeConnection ConnectionTable m addr
tbl addr
remoteAddr addr
localAddr ConnectionDirection
dir = STM m () -> m ()
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> STM m () -> m ()
forall a b. (a -> b) -> a -> b
$ ConnectionTable m addr
-> addr -> addr -> ConnectionDirection -> STM m ()
forall (m :: * -> *) addr.
(MonadSTM m, Ord addr) =>
ConnectionTable m addr
-> addr -> addr -> ConnectionDirection -> STM m ()
removeConnectionSTM ConnectionTable m addr
tbl addr
remoteAddr addr
localAddr ConnectionDirection
dir
refConnectionSTM
:: ( MonadSTM m
, Ord addr
)
=> ConnectionTable m addr
-> addr
-> ConnectionDirection
-> ValencyCounter m
-> STM m ConnectionTableRef
refConnectionSTM :: forall (m :: * -> *) addr.
(MonadSTM m, Ord addr) =>
ConnectionTable m addr
-> addr
-> ConnectionDirection
-> ValencyCounter m
-> STM m ConnectionTableRef
refConnectionSTM ConnectionTable{StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable :: forall (m :: * -> *) addr.
ConnectionTable m addr
-> StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable :: StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable} addr
remoteAddr ConnectionDirection
dir ValencyCounter m
refVar = do
tbl <- StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
-> STM
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable
case M.lookup (remoteAddr, dir) tbl of
Maybe (ConnectionTableEntry m addr)
Nothing -> ConnectionTableRef -> STM m ConnectionTableRef
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ConnectionTableRef
ConnectionTableCreate
Just ConnectionTableEntry m addr
cte ->
if ValencyCounter m -> Set (ValencyCounter m) -> Bool
forall a. Ord a => a -> Set a -> Bool
S.member ValencyCounter m
refVar (Set (ValencyCounter m) -> Bool) -> Set (ValencyCounter m) -> Bool
forall a b. (a -> b) -> a -> b
$ ConnectionTableEntry m addr -> Set (ValencyCounter m)
forall (m :: * -> *) addr.
ConnectionTableEntry m addr -> Set (ValencyCounter m)
cteRefs ConnectionTableEntry m addr
cte
then ConnectionTableRef -> STM m ConnectionTableRef
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ConnectionTableRef
ConnectionTableDuplicate
else do
let refs' :: Set (ValencyCounter m)
refs' = ValencyCounter m
-> Set (ValencyCounter m) -> Set (ValencyCounter m)
forall a. Ord a => a -> Set a -> Set a
S.insert ValencyCounter m
refVar (ConnectionTableEntry m addr -> Set (ValencyCounter m)
forall (m :: * -> *) addr.
ConnectionTableEntry m addr -> Set (ValencyCounter m)
cteRefs ConnectionTableEntry m addr
cte)
(ValencyCounter m -> STM m ()) -> [ValencyCounter m] -> STM m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ValencyCounter m -> STM m ()
forall (m :: * -> *). MonadSTM m => ValencyCounter m -> STM m ()
addValencyCounter ([ValencyCounter m] -> STM m ()) -> [ValencyCounter m] -> STM m ()
forall a b. (a -> b) -> a -> b
$ Set (ValencyCounter m) -> [ValencyCounter m]
forall a. Set a -> [a]
S.toList Set (ValencyCounter m)
refs'
StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
-> Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar
m (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr))
ctTable (Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> STM m ())
-> Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> STM m ()
forall a b. (a -> b) -> a -> b
$ (addr, ConnectionDirection)
-> ConnectionTableEntry m addr
-> Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
-> Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert (addr
remoteAddr, ConnectionDirection
dir)
(ConnectionTableEntry m addr
cte { cteRefs = refs'}) Map (addr, ConnectionDirection) (ConnectionTableEntry m addr)
tbl
ConnectionTableRef -> STM m ConnectionTableRef
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return ConnectionTableRef
ConnectionTableExist
refConnection
:: ( MonadSTM m
, Ord addr
)
=> ConnectionTable m addr
-> addr
-> ConnectionDirection
-> ValencyCounter m
-> m ConnectionTableRef
refConnection :: forall (m :: * -> *) addr.
(MonadSTM m, Ord addr) =>
ConnectionTable m addr
-> addr
-> ConnectionDirection
-> ValencyCounter m
-> m ConnectionTableRef
refConnection ConnectionTable m addr
tbl addr
remoteAddr ConnectionDirection
dir ValencyCounter m
refVar =
STM m ConnectionTableRef -> m ConnectionTableRef
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m ConnectionTableRef -> m ConnectionTableRef)
-> STM m ConnectionTableRef -> m ConnectionTableRef
forall a b. (a -> b) -> a -> b
$ ConnectionTable m addr
-> addr
-> ConnectionDirection
-> ValencyCounter m
-> STM m ConnectionTableRef
forall (m :: * -> *) addr.
(MonadSTM m, Ord addr) =>
ConnectionTable m addr
-> addr
-> ConnectionDirection
-> ValencyCounter m
-> STM m ConnectionTableRef
refConnectionSTM ConnectionTable m addr
tbl addr
remoteAddr ConnectionDirection
dir ValencyCounter m
refVar