{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Network.QUIC.Recovery.Metrics (
updateRTT,
updateCC,
metricsUpdated,
setInitialCongestionWindow,
) where
import Data.Sequence (Seq)
import UnliftIO.STM
import Network.QUIC.Imports
import Network.QUIC.Qlog
import Network.QUIC.Recovery.Constants
import Network.QUIC.Recovery.Misc
import Network.QUIC.Recovery.Persistent
import Network.QUIC.Recovery.Types
import Network.QUIC.Types
updateRTT :: LDCC -> EncryptionLevel -> Microseconds -> Microseconds -> IO ()
updateRTT :: LDCC -> EncryptionLevel -> Microseconds -> Microseconds -> IO ()
updateRTT ldcc :: LDCC
ldcc@LDCC{Array EncryptionLevel (IORef Bool)
Array EncryptionLevel (IORef PeerPacketNumbers)
Array EncryptionLevel (IORef LossDetection)
Array EncryptionLevel (IORef SentPackets)
TVar (Maybe EncryptionLevel)
TVar TimerInfoQ
TVar CC
TVar SentPackets
IORef Bool
IORef PacketNumber
IORef (Maybe TimeoutKey)
IORef (Maybe TimerInfo)
IORef PeerPacketNumbers
IORef RTT
ConnState
PlainPacket -> IO ()
QLogger
ldccState :: ConnState
ldccQlogger :: QLogger
putRetrans :: PlainPacket -> IO ()
recoveryRTT :: IORef RTT
recoveryCC :: TVar CC
spaceDiscarded :: Array EncryptionLevel (IORef Bool)
sentPackets :: Array EncryptionLevel (IORef SentPackets)
lossDetection :: Array EncryptionLevel (IORef LossDetection)
timerKey :: IORef (Maybe TimeoutKey)
timerInfo :: IORef (Maybe TimerInfo)
lostCandidates :: TVar SentPackets
ptoPing :: TVar (Maybe EncryptionLevel)
speedingUp :: IORef Bool
pktNumPersistent :: IORef PacketNumber
peerPacketNumbers :: Array EncryptionLevel (IORef PeerPacketNumbers)
previousRTT1PPNs :: IORef PeerPacketNumbers
timerInfoQ :: TVar TimerInfoQ
ldccState :: LDCC -> ConnState
ldccQlogger :: LDCC -> QLogger
putRetrans :: LDCC -> PlainPacket -> IO ()
recoveryRTT :: LDCC -> IORef RTT
recoveryCC :: LDCC -> TVar CC
spaceDiscarded :: LDCC -> Array EncryptionLevel (IORef Bool)
sentPackets :: LDCC -> Array EncryptionLevel (IORef SentPackets)
lossDetection :: LDCC -> Array EncryptionLevel (IORef LossDetection)
timerKey :: LDCC -> IORef (Maybe TimeoutKey)
timerInfo :: LDCC -> IORef (Maybe TimerInfo)
lostCandidates :: LDCC -> TVar SentPackets
ptoPing :: LDCC -> TVar (Maybe EncryptionLevel)
speedingUp :: LDCC -> IORef Bool
pktNumPersistent :: LDCC -> IORef PacketNumber
peerPacketNumbers :: LDCC -> Array EncryptionLevel (IORef PeerPacketNumbers)
previousRTT1PPNs :: LDCC -> IORef PeerPacketNumbers
timerInfoQ :: LDCC -> TVar TimerInfoQ
..} EncryptionLevel
lvl Microseconds
latestRTT0 Microseconds
ackDelay0 = LDCC -> IO () -> IO ()
metricsUpdated LDCC
ldcc (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Bool
firstTime <- IORef RTT -> (RTT -> (RTT, Bool)) -> IO Bool
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef RTT
recoveryRTT RTT -> (RTT, Bool)
update
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
firstTime (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
LDCC -> IO ()
setPktNumPersistent LDCC
ldcc
LDCC -> Debug -> IO ()
forall q. KeepQlog q => q -> Debug -> IO ()
qlogDebug LDCC
ldcc (Debug -> IO ()) -> Debug -> IO ()
forall a b. (a -> b) -> a -> b
$ LogStr -> Debug
Debug LogStr
"RTT first sample"
where
update :: RTT -> (RTT, Bool)
update rtt :: RTT
rtt@RTT{PacketNumber
Microseconds
latestRTT :: Microseconds
smoothedRTT :: Microseconds
rttvar :: Microseconds
minRTT :: Microseconds
maxAckDelay1RTT :: Microseconds
ptoCount :: PacketNumber
latestRTT :: RTT -> Microseconds
smoothedRTT :: RTT -> Microseconds
rttvar :: RTT -> Microseconds
minRTT :: RTT -> Microseconds
maxAckDelay1RTT :: RTT -> Microseconds
ptoCount :: RTT -> PacketNumber
..}
| Microseconds
latestRTT Microseconds -> Microseconds -> Bool
forall a. Eq a => a -> a -> Bool
== PacketNumber -> Microseconds
Microseconds PacketNumber
0 =
( RTT
rtt
{ latestRTT = latestRTT0
, minRTT = latestRTT0
, smoothedRTT = latestRTT0
, rttvar = latestRTT0 `unsafeShiftR` 1
}
, Bool
True
)
update rtt :: RTT
rtt@RTT{PacketNumber
Microseconds
latestRTT :: RTT -> Microseconds
smoothedRTT :: RTT -> Microseconds
rttvar :: RTT -> Microseconds
minRTT :: RTT -> Microseconds
maxAckDelay1RTT :: RTT -> Microseconds
ptoCount :: RTT -> PacketNumber
latestRTT :: Microseconds
smoothedRTT :: Microseconds
rttvar :: Microseconds
minRTT :: Microseconds
maxAckDelay1RTT :: Microseconds
ptoCount :: PacketNumber
..} =
( RTT
rtt
{ latestRTT = latestRTT0
, minRTT = minRTT'
, smoothedRTT = smoothedRTT'
, rttvar = rttvar'
}
, Bool
False
)
where
minRTT' :: Microseconds
minRTT' = Microseconds -> Microseconds -> Microseconds
forall a. Ord a => a -> a -> a
min Microseconds
minRTT Microseconds
latestRTT0
ackDelay :: Microseconds
ackDelay = Microseconds -> Microseconds -> Microseconds
forall a. Ord a => a -> a -> a
min Microseconds
ackDelay0 (Microseconds -> Microseconds) -> Microseconds -> Microseconds
forall a b. (a -> b) -> a -> b
$ Maybe EncryptionLevel -> Microseconds -> Microseconds
getMaxAckDelay (EncryptionLevel -> Maybe EncryptionLevel
forall a. a -> Maybe a
Just EncryptionLevel
lvl) Microseconds
maxAckDelay1RTT
adjustedRTT :: Microseconds
adjustedRTT
| Microseconds
latestRTT0 Microseconds -> Microseconds -> Bool
forall a. Ord a => a -> a -> Bool
>= Microseconds
minRTT Microseconds -> Microseconds -> Microseconds
forall a. Num a => a -> a -> a
+ Microseconds
ackDelay = Microseconds
latestRTT0 Microseconds -> Microseconds -> Microseconds
forall a. Num a => a -> a -> a
- Microseconds
ackDelay
| Bool
otherwise = Microseconds
latestRTT0
rttvar' :: Microseconds
rttvar' =
Microseconds
rttvar
Microseconds -> Microseconds -> Microseconds
forall a. Num a => a -> a -> a
- (Microseconds
rttvar Microseconds -> PacketNumber -> Microseconds
forall a. Bits a => a -> PacketNumber -> a
!>>. PacketNumber
2)
Microseconds -> Microseconds -> Microseconds
forall a. Num a => a -> a -> a
+ (Microseconds -> Microseconds
forall a. Num a => a -> a
abs (Microseconds
smoothedRTT Microseconds -> Microseconds -> Microseconds
forall a. Num a => a -> a -> a
- Microseconds
adjustedRTT) Microseconds -> PacketNumber -> Microseconds
forall a. Bits a => a -> PacketNumber -> a
!>>. PacketNumber
2)
smoothedRTT' :: Microseconds
smoothedRTT' =
Microseconds
smoothedRTT
Microseconds -> Microseconds -> Microseconds
forall a. Num a => a -> a -> a
- (Microseconds
smoothedRTT Microseconds -> PacketNumber -> Microseconds
forall a. Bits a => a -> PacketNumber -> a
!>>. PacketNumber
3)
Microseconds -> Microseconds -> Microseconds
forall a. Num a => a -> a -> a
+ (Microseconds
adjustedRTT Microseconds -> PacketNumber -> Microseconds
forall a. Bits a => a -> PacketNumber -> a
!>>. PacketNumber
3)
updateCC :: LDCC -> Seq SentPacket -> Bool -> IO ()
updateCC :: LDCC -> Seq SentPacket -> Bool -> IO ()
updateCC ldcc :: LDCC
ldcc@LDCC{Array EncryptionLevel (IORef Bool)
Array EncryptionLevel (IORef PeerPacketNumbers)
Array EncryptionLevel (IORef LossDetection)
Array EncryptionLevel (IORef SentPackets)
TVar (Maybe EncryptionLevel)
TVar TimerInfoQ
TVar CC
TVar SentPackets
IORef Bool
IORef PacketNumber
IORef (Maybe TimeoutKey)
IORef (Maybe TimerInfo)
IORef PeerPacketNumbers
IORef RTT
ConnState
PlainPacket -> IO ()
QLogger
ldccState :: LDCC -> ConnState
ldccQlogger :: LDCC -> QLogger
putRetrans :: LDCC -> PlainPacket -> IO ()
recoveryRTT :: LDCC -> IORef RTT
recoveryCC :: LDCC -> TVar CC
spaceDiscarded :: LDCC -> Array EncryptionLevel (IORef Bool)
sentPackets :: LDCC -> Array EncryptionLevel (IORef SentPackets)
lossDetection :: LDCC -> Array EncryptionLevel (IORef LossDetection)
timerKey :: LDCC -> IORef (Maybe TimeoutKey)
timerInfo :: LDCC -> IORef (Maybe TimerInfo)
lostCandidates :: LDCC -> TVar SentPackets
ptoPing :: LDCC -> TVar (Maybe EncryptionLevel)
speedingUp :: LDCC -> IORef Bool
pktNumPersistent :: LDCC -> IORef PacketNumber
peerPacketNumbers :: LDCC -> Array EncryptionLevel (IORef PeerPacketNumbers)
previousRTT1PPNs :: LDCC -> IORef PeerPacketNumbers
timerInfoQ :: LDCC -> TVar TimerInfoQ
ldccState :: ConnState
ldccQlogger :: QLogger
putRetrans :: PlainPacket -> IO ()
recoveryRTT :: IORef RTT
recoveryCC :: TVar CC
spaceDiscarded :: Array EncryptionLevel (IORef Bool)
sentPackets :: Array EncryptionLevel (IORef SentPackets)
lossDetection :: Array EncryptionLevel (IORef LossDetection)
timerKey :: IORef (Maybe TimeoutKey)
timerInfo :: IORef (Maybe TimerInfo)
lostCandidates :: TVar SentPackets
ptoPing :: TVar (Maybe EncryptionLevel)
speedingUp :: IORef Bool
pktNumPersistent :: IORef PacketNumber
peerPacketNumbers :: Array EncryptionLevel (IORef PeerPacketNumbers)
previousRTT1PPNs :: IORef PeerPacketNumbers
timerInfoQ :: TVar TimerInfoQ
..} Seq SentPacket
lostPackets Bool
isRecovery = do
Bool
persistent <- LDCC -> Seq SentPacket -> IO Bool
inPersistentCongestion LDCC
ldcc Seq SentPacket
lostPackets
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
persistent Bool -> Bool -> Bool
|| Bool -> Bool
not Bool
isRecovery) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
PacketNumber
minWindow <- LDCC -> IO PacketNumber
kMinimumWindow LDCC
ldcc
TimeMicrosecond
now <- IO TimeMicrosecond
getTimeMicrosecond
LDCC -> IO () -> IO ()
metricsUpdated LDCC
ldcc (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ STM () -> IO ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar CC -> (CC -> CC) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar CC
recoveryCC ((CC -> CC) -> STM ()) -> (CC -> CC) -> STM ()
forall a b. (a -> b) -> a -> b
$ \cc :: CC
cc@CC{PacketNumber
Maybe TimeMicrosecond
CCMode
bytesInFlight :: PacketNumber
congestionWindow :: PacketNumber
congestionRecoveryStartTime :: Maybe TimeMicrosecond
ssthresh :: PacketNumber
bytesAcked :: PacketNumber
numOfAckEliciting :: PacketNumber
ccMode :: CCMode
bytesInFlight :: CC -> PacketNumber
congestionWindow :: CC -> PacketNumber
congestionRecoveryStartTime :: CC -> Maybe TimeMicrosecond
ssthresh :: CC -> PacketNumber
bytesAcked :: CC -> PacketNumber
numOfAckEliciting :: CC -> PacketNumber
ccMode :: CC -> CCMode
..} ->
let halfWindow :: PacketNumber
halfWindow = PacketNumber -> PacketNumber -> PacketNumber
forall a. Ord a => a -> a -> a
max PacketNumber
minWindow (PacketNumber -> PacketNumber) -> PacketNumber -> PacketNumber
forall a b. (a -> b) -> a -> b
$ PacketNumber -> PacketNumber
kLossReductionFactor PacketNumber
congestionWindow
cwin :: PacketNumber
cwin
| Bool
persistent = PacketNumber
minWindow
| Bool
otherwise = PacketNumber
halfWindow
sst :: PacketNumber
sst = PacketNumber
halfWindow
mode :: CCMode
mode
| PacketNumber
cwin PacketNumber -> PacketNumber -> Bool
forall a. Ord a => a -> a -> Bool
< PacketNumber
sst = CCMode
SlowStart
| Bool
otherwise = CCMode
Recovery
in CC
cc
{ congestionRecoveryStartTime = Just now
, congestionWindow = cwin
, ssthresh = sst
, ccMode = mode
, bytesAcked = 0
}
CC{CCMode
ccMode :: CC -> CCMode
ccMode :: CCMode
ccMode} <- TVar CC -> IO CC
forall (m :: * -> *) a. MonadIO m => TVar a -> m a
readTVarIO TVar CC
recoveryCC
LDCC -> CCMode -> IO ()
forall q. KeepQlog q => q -> CCMode -> IO ()
qlogContestionStateUpdated LDCC
ldcc CCMode
ccMode
setInitialCongestionWindow :: LDCC -> Int -> IO ()
setInitialCongestionWindow :: LDCC -> PacketNumber -> IO ()
setInitialCongestionWindow ldcc :: LDCC
ldcc@LDCC{Array EncryptionLevel (IORef Bool)
Array EncryptionLevel (IORef PeerPacketNumbers)
Array EncryptionLevel (IORef LossDetection)
Array EncryptionLevel (IORef SentPackets)
TVar (Maybe EncryptionLevel)
TVar TimerInfoQ
TVar CC
TVar SentPackets
IORef Bool
IORef PacketNumber
IORef (Maybe TimeoutKey)
IORef (Maybe TimerInfo)
IORef PeerPacketNumbers
IORef RTT
ConnState
PlainPacket -> IO ()
QLogger
ldccState :: LDCC -> ConnState
ldccQlogger :: LDCC -> QLogger
putRetrans :: LDCC -> PlainPacket -> IO ()
recoveryRTT :: LDCC -> IORef RTT
recoveryCC :: LDCC -> TVar CC
spaceDiscarded :: LDCC -> Array EncryptionLevel (IORef Bool)
sentPackets :: LDCC -> Array EncryptionLevel (IORef SentPackets)
lossDetection :: LDCC -> Array EncryptionLevel (IORef LossDetection)
timerKey :: LDCC -> IORef (Maybe TimeoutKey)
timerInfo :: LDCC -> IORef (Maybe TimerInfo)
lostCandidates :: LDCC -> TVar SentPackets
ptoPing :: LDCC -> TVar (Maybe EncryptionLevel)
speedingUp :: LDCC -> IORef Bool
pktNumPersistent :: LDCC -> IORef PacketNumber
peerPacketNumbers :: LDCC -> Array EncryptionLevel (IORef PeerPacketNumbers)
previousRTT1PPNs :: LDCC -> IORef PeerPacketNumbers
timerInfoQ :: LDCC -> TVar TimerInfoQ
ldccState :: ConnState
ldccQlogger :: QLogger
putRetrans :: PlainPacket -> IO ()
recoveryRTT :: IORef RTT
recoveryCC :: TVar CC
spaceDiscarded :: Array EncryptionLevel (IORef Bool)
sentPackets :: Array EncryptionLevel (IORef SentPackets)
lossDetection :: Array EncryptionLevel (IORef LossDetection)
timerKey :: IORef (Maybe TimeoutKey)
timerInfo :: IORef (Maybe TimerInfo)
lostCandidates :: TVar SentPackets
ptoPing :: TVar (Maybe EncryptionLevel)
speedingUp :: IORef Bool
pktNumPersistent :: IORef PacketNumber
peerPacketNumbers :: Array EncryptionLevel (IORef PeerPacketNumbers)
previousRTT1PPNs :: IORef PeerPacketNumbers
timerInfoQ :: TVar TimerInfoQ
..} PacketNumber
pktSiz = LDCC -> IO () -> IO ()
metricsUpdated LDCC
ldcc (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
STM () -> IO ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
TVar CC -> (CC -> CC) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar CC
recoveryCC ((CC -> CC) -> STM ()) -> (CC -> CC) -> STM ()
forall a b. (a -> b) -> a -> b
$ \CC
cc ->
CC
cc
{ congestionWindow = kInitialWindow pktSiz
}
metricsUpdated :: LDCC -> IO () -> IO ()
metricsUpdated :: LDCC -> IO () -> IO ()
metricsUpdated ldcc :: LDCC
ldcc@LDCC{Array EncryptionLevel (IORef Bool)
Array EncryptionLevel (IORef PeerPacketNumbers)
Array EncryptionLevel (IORef LossDetection)
Array EncryptionLevel (IORef SentPackets)
TVar (Maybe EncryptionLevel)
TVar TimerInfoQ
TVar CC
TVar SentPackets
IORef Bool
IORef PacketNumber
IORef (Maybe TimeoutKey)
IORef (Maybe TimerInfo)
IORef PeerPacketNumbers
IORef RTT
ConnState
PlainPacket -> IO ()
QLogger
ldccState :: LDCC -> ConnState
ldccQlogger :: LDCC -> QLogger
putRetrans :: LDCC -> PlainPacket -> IO ()
recoveryRTT :: LDCC -> IORef RTT
recoveryCC :: LDCC -> TVar CC
spaceDiscarded :: LDCC -> Array EncryptionLevel (IORef Bool)
sentPackets :: LDCC -> Array EncryptionLevel (IORef SentPackets)
lossDetection :: LDCC -> Array EncryptionLevel (IORef LossDetection)
timerKey :: LDCC -> IORef (Maybe TimeoutKey)
timerInfo :: LDCC -> IORef (Maybe TimerInfo)
lostCandidates :: LDCC -> TVar SentPackets
ptoPing :: LDCC -> TVar (Maybe EncryptionLevel)
speedingUp :: LDCC -> IORef Bool
pktNumPersistent :: LDCC -> IORef PacketNumber
peerPacketNumbers :: LDCC -> Array EncryptionLevel (IORef PeerPacketNumbers)
previousRTT1PPNs :: LDCC -> IORef PeerPacketNumbers
timerInfoQ :: LDCC -> TVar TimerInfoQ
ldccState :: ConnState
ldccQlogger :: QLogger
putRetrans :: PlainPacket -> IO ()
recoveryRTT :: IORef RTT
recoveryCC :: TVar CC
spaceDiscarded :: Array EncryptionLevel (IORef Bool)
sentPackets :: Array EncryptionLevel (IORef SentPackets)
lossDetection :: Array EncryptionLevel (IORef LossDetection)
timerKey :: IORef (Maybe TimeoutKey)
timerInfo :: IORef (Maybe TimerInfo)
lostCandidates :: TVar SentPackets
ptoPing :: TVar (Maybe EncryptionLevel)
speedingUp :: IORef Bool
pktNumPersistent :: IORef PacketNumber
peerPacketNumbers :: Array EncryptionLevel (IORef PeerPacketNumbers)
previousRTT1PPNs :: IORef PeerPacketNumbers
timerInfoQ :: TVar TimerInfoQ
..} IO ()
body = do
RTT
rtt0 <- IORef RTT -> IO RTT
forall a. IORef a -> IO a
readIORef IORef RTT
recoveryRTT
CC
cc0 <- TVar CC -> IO CC
forall (m :: * -> *) a. MonadIO m => TVar a -> m a
readTVarIO TVar CC
recoveryCC
IO ()
body
RTT
rtt1 <- IORef RTT -> IO RTT
forall a. IORef a -> IO a
readIORef IORef RTT
recoveryRTT
CC
cc1 <- TVar CC -> IO CC
forall (m :: * -> *) a. MonadIO m => TVar a -> m a
readTVarIO TVar CC
recoveryCC
let ~[(String, PacketNumber)]
diff =
[Maybe (String, PacketNumber)] -> [(String, PacketNumber)]
forall a. [Maybe a] -> [a]
catMaybes
[ String
-> Microseconds -> Microseconds -> Maybe (String, PacketNumber)
forall {a}.
a -> Microseconds -> Microseconds -> Maybe (a, PacketNumber)
time String
"min_rtt" (RTT -> Microseconds
minRTT RTT
rtt0) (RTT -> Microseconds
minRTT RTT
rtt1)
, String
-> Microseconds -> Microseconds -> Maybe (String, PacketNumber)
forall {a}.
a -> Microseconds -> Microseconds -> Maybe (a, PacketNumber)
time String
"smoothed_rtt" (RTT -> Microseconds
smoothedRTT RTT
rtt0) (RTT -> Microseconds
smoothedRTT RTT
rtt1)
, String
-> Microseconds -> Microseconds -> Maybe (String, PacketNumber)
forall {a}.
a -> Microseconds -> Microseconds -> Maybe (a, PacketNumber)
time String
"latest_rtt" (RTT -> Microseconds
latestRTT RTT
rtt0) (RTT -> Microseconds
latestRTT RTT
rtt1)
, String
-> Microseconds -> Microseconds -> Maybe (String, PacketNumber)
forall {a}.
a -> Microseconds -> Microseconds -> Maybe (a, PacketNumber)
time String
"rtt_variance" (RTT -> Microseconds
rttvar RTT
rtt0) (RTT -> Microseconds
rttvar RTT
rtt1)
, String
-> PacketNumber -> PacketNumber -> Maybe (String, PacketNumber)
forall {b} {a}. Eq b => a -> b -> b -> Maybe (a, b)
numb String
"pto_count" (RTT -> PacketNumber
ptoCount RTT
rtt0) (RTT -> PacketNumber
ptoCount RTT
rtt1)
, String
-> PacketNumber -> PacketNumber -> Maybe (String, PacketNumber)
forall {b} {a}. Eq b => a -> b -> b -> Maybe (a, b)
numb String
"bytes_in_flight" (CC -> PacketNumber
bytesInFlight CC
cc0) (CC -> PacketNumber
bytesInFlight CC
cc1)
, String
-> PacketNumber -> PacketNumber -> Maybe (String, PacketNumber)
forall {b} {a}. Eq b => a -> b -> b -> Maybe (a, b)
numb String
"congestion_window" (CC -> PacketNumber
congestionWindow CC
cc0) (CC -> PacketNumber
congestionWindow CC
cc1)
, String
-> PacketNumber -> PacketNumber -> Maybe (String, PacketNumber)
forall {b} {a}. Eq b => a -> b -> b -> Maybe (a, b)
numb String
"ssthresh" (CC -> PacketNumber
ssthresh CC
cc0) (CC -> PacketNumber
ssthresh CC
cc1)
]
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([(String, PacketNumber)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(String, PacketNumber)]
diff) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ LDCC -> MetricsDiff -> IO ()
forall q. KeepQlog q => q -> MetricsDiff -> IO ()
qlogMetricsUpdated LDCC
ldcc (MetricsDiff -> IO ()) -> MetricsDiff -> IO ()
forall a b. (a -> b) -> a -> b
$ [(String, PacketNumber)] -> MetricsDiff
MetricsDiff [(String, PacketNumber)]
diff
where
time :: a -> Microseconds -> Microseconds -> Maybe (a, PacketNumber)
time a
tag (Microseconds PacketNumber
v0) (Microseconds PacketNumber
v1)
| PacketNumber
v0 PacketNumber -> PacketNumber -> Bool
forall a. Eq a => a -> a -> Bool
== PacketNumber
v1 = Maybe (a, PacketNumber)
forall a. Maybe a
Nothing
| Bool
otherwise = (a, PacketNumber) -> Maybe (a, PacketNumber)
forall a. a -> Maybe a
Just (a
tag, PacketNumber
v1)
numb :: a -> b -> b -> Maybe (a, b)
numb a
tag b
v0 b
v1
| b
v0 b -> b -> Bool
forall a. Eq a => a -> a -> Bool
== b
v1 = Maybe (a, b)
forall a. Maybe a
Nothing
| Bool
otherwise = (a, b) -> Maybe (a, b)
forall a. a -> Maybe a
Just (a
tag, b
v1)