Merge branch 'bwlimit'
This commit is contained in:
commit
fc9abca231
16 changed files with 149 additions and 47 deletions
|
@ -461,8 +461,9 @@ importKeys remote importtreeconfig importcontent thirdpartypopulated importablec
|
||||||
, providedMimeEncoding = Nothing
|
, providedMimeEncoding = Nothing
|
||||||
, providedLinkType = Nothing
|
, providedLinkType = Nothing
|
||||||
}
|
}
|
||||||
|
let bwlimit = remoteAnnexBwLimit (Remote.gitconfig remote)
|
||||||
islargefile <- checkMatcher' matcher mi mempty
|
islargefile <- checkMatcher' matcher mi mempty
|
||||||
metered Nothing sz $ const $ if islargefile
|
metered Nothing sz bwlimit $ const $ if islargefile
|
||||||
then doimportlarge importkey cidmap db loc cid sz f
|
then doimportlarge importkey cidmap db loc cid sz f
|
||||||
else doimportsmall cidmap db loc cid sz
|
else doimportsmall cidmap db loc cid sz
|
||||||
|
|
||||||
|
@ -557,11 +558,12 @@ importKeys remote importtreeconfig importcontent thirdpartypopulated importablec
|
||||||
Left e -> do
|
Left e -> do
|
||||||
warning (show e)
|
warning (show e)
|
||||||
return Nothing
|
return Nothing
|
||||||
|
let bwlimit = remoteAnnexBwLimit (Remote.gitconfig remote)
|
||||||
checkDiskSpaceToGet tmpkey Nothing $
|
checkDiskSpaceToGet tmpkey Nothing $
|
||||||
notifyTransfer Download af $
|
notifyTransfer Download af $
|
||||||
download' (Remote.uuid remote) tmpkey af Nothing stdRetry $ \p ->
|
download' (Remote.uuid remote) tmpkey af Nothing stdRetry $ \p ->
|
||||||
withTmp tmpkey $ \tmpfile ->
|
withTmp tmpkey $ \tmpfile ->
|
||||||
metered (Just p) tmpkey $
|
metered (Just p) tmpkey bwlimit $
|
||||||
const (rundownload tmpfile)
|
const (rundownload tmpfile)
|
||||||
where
|
where
|
||||||
tmpkey = importKey cid sz
|
tmpkey = importKey cid sz
|
||||||
|
|
|
@ -22,7 +22,7 @@ import Control.Monad.IO.Class (MonadIO)
|
||||||
detectStalls :: (Monad m, MonadIO m) => Maybe StallDetection -> TVar (Maybe BytesProcessed) -> m () -> m ()
|
detectStalls :: (Monad m, MonadIO m) => Maybe StallDetection -> TVar (Maybe BytesProcessed) -> m () -> m ()
|
||||||
detectStalls Nothing _ _ = noop
|
detectStalls Nothing _ _ = noop
|
||||||
detectStalls (Just StallDetectionDisabled) _ _ = noop
|
detectStalls (Just StallDetectionDisabled) _ _ = noop
|
||||||
detectStalls (Just (StallDetection minsz duration)) metervar onstall =
|
detectStalls (Just (StallDetection (BwRate minsz duration))) metervar onstall =
|
||||||
detectStalls' minsz duration metervar onstall Nothing
|
detectStalls' minsz duration metervar onstall Nothing
|
||||||
detectStalls (Just ProbeStallDetection) metervar onstall = do
|
detectStalls (Just ProbeStallDetection) metervar onstall = do
|
||||||
-- Only do stall detection once the progress is confirmed to be
|
-- Only do stall detection once the progress is confirmed to be
|
||||||
|
|
|
@ -96,7 +96,7 @@ youtubeDl' url workdir p uo
|
||||||
-- with the size, which is why it's important the
|
-- with the size, which is why it's important the
|
||||||
-- meter is passed into commandMeter'
|
-- meter is passed into commandMeter'
|
||||||
let unknownsize = Nothing :: Maybe FileSize
|
let unknownsize = Nothing :: Maybe FileSize
|
||||||
ok <- metered (Just p) unknownsize $ \meter meterupdate ->
|
ok <- metered (Just p) unknownsize Nothing $ \meter meterupdate ->
|
||||||
liftIO $ commandMeter'
|
liftIO $ commandMeter'
|
||||||
parseYoutubeDlProgress oh (Just meter) meterupdate cmd opts
|
parseYoutubeDlProgress oh (Just meter) meterupdate cmd opts
|
||||||
(\pr -> pr { cwd = Just workdir })
|
(\pr -> pr { cwd = Just workdir })
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
git-annex (8.20210904) UNRELEASED; urgency=medium
|
git-annex (8.20210904) UNRELEASED; urgency=medium
|
||||||
|
|
||||||
|
* Added annex.bwlimit and remote.name.annex-bwlimit config to limit
|
||||||
|
the bandwidth of transfers. It works for git remotes and many
|
||||||
|
but not all special remotes.
|
||||||
* Bug fix: Git configs such as annex.verify were incorrectly overriding
|
* Bug fix: Git configs such as annex.verify were incorrectly overriding
|
||||||
per-remote git configs such as remote.name.annex-verify.
|
per-remote git configs such as remote.name.annex-verify.
|
||||||
(Reversion in version 4.20130323)
|
(Reversion in version 4.20130323)
|
||||||
|
|
|
@ -192,7 +192,7 @@ perform o file addunlockedmatcher = withOtherTmp $ \tmpdir -> do
|
||||||
}
|
}
|
||||||
ld <- lockDown cfg (fromRawFilePath file)
|
ld <- lockDown cfg (fromRawFilePath file)
|
||||||
let sizer = keySource <$> ld
|
let sizer = keySource <$> ld
|
||||||
v <- metered Nothing sizer $ \_meter meterupdate ->
|
v <- metered Nothing sizer Nothing $ \_meter meterupdate ->
|
||||||
ingestAdd (checkGitIgnoreOption o) meterupdate ld
|
ingestAdd (checkGitIgnoreOption o) meterupdate ld
|
||||||
finish v
|
finish v
|
||||||
where
|
where
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{- git-annex progress output
|
{- git-annex progress output
|
||||||
-
|
-
|
||||||
- Copyright 2010-2020 Joey Hess <id@joeyh.name>
|
- Copyright 2010-2021 Joey Hess <id@joeyh.name>
|
||||||
-
|
-
|
||||||
- Licensed under the GNU AGPL version 3 or higher.
|
- Licensed under the GNU AGPL version 3 or higher.
|
||||||
-}
|
-}
|
||||||
|
@ -18,6 +18,7 @@ import Types
|
||||||
import Types.Messages
|
import Types.Messages
|
||||||
import Types.Key
|
import Types.Key
|
||||||
import Types.KeySource
|
import Types.KeySource
|
||||||
|
import Types.StallDetection (BwRate(..))
|
||||||
import Utility.InodeCache
|
import Utility.InodeCache
|
||||||
import qualified Messages.JSON as JSON
|
import qualified Messages.JSON as JSON
|
||||||
import Messages.Concurrent
|
import Messages.Concurrent
|
||||||
|
@ -72,11 +73,12 @@ metered
|
||||||
:: MeterSize sizer
|
:: MeterSize sizer
|
||||||
=> Maybe MeterUpdate
|
=> Maybe MeterUpdate
|
||||||
-> sizer
|
-> sizer
|
||||||
|
-> Maybe BwRate
|
||||||
-> (Meter -> MeterUpdate -> Annex a)
|
-> (Meter -> MeterUpdate -> Annex a)
|
||||||
-> Annex a
|
-> Annex a
|
||||||
metered othermeter sizer a = withMessageState $ \st -> do
|
metered othermeterupdate sizer bwlimit a = withMessageState $ \st -> do
|
||||||
sz <- getMeterSize sizer
|
sz <- getMeterSize sizer
|
||||||
metered' st setclear othermeter sz showOutput a
|
metered' st setclear othermeterupdate sz bwlimit showOutput a
|
||||||
where
|
where
|
||||||
setclear c = Annex.changeState $ \st -> st
|
setclear c = Annex.changeState $ \st -> st
|
||||||
{ Annex.output = (Annex.output st) { clearProgressMeter = c } }
|
{ Annex.output = (Annex.output st) { clearProgressMeter = c } }
|
||||||
|
@ -90,11 +92,12 @@ metered'
|
||||||
-- NormalOutput.
|
-- NormalOutput.
|
||||||
-> Maybe MeterUpdate
|
-> Maybe MeterUpdate
|
||||||
-> Maybe TotalSize
|
-> Maybe TotalSize
|
||||||
|
-> Maybe BwRate
|
||||||
-> m ()
|
-> m ()
|
||||||
-- ^ this should run showOutput
|
-- ^ this should run showOutput
|
||||||
-> (Meter -> MeterUpdate -> m a)
|
-> (Meter -> MeterUpdate -> m a)
|
||||||
-> m a
|
-> m a
|
||||||
metered' st setclear othermeter msize showoutput a = go st
|
metered' st setclear othermeterupdate msize bwlimit showoutput a = go st
|
||||||
where
|
where
|
||||||
go (MessageState { outputType = QuietOutput }) = nometer
|
go (MessageState { outputType = QuietOutput }) = nometer
|
||||||
go (MessageState { outputType = NormalOutput, concurrentOutputEnabled = False }) = do
|
go (MessageState { outputType = NormalOutput, concurrentOutputEnabled = False }) = do
|
||||||
|
@ -105,7 +108,7 @@ metered' st setclear othermeter msize showoutput a = go st
|
||||||
setclear clear
|
setclear clear
|
||||||
m <- liftIO $ rateLimitMeterUpdate consoleratelimit meter $
|
m <- liftIO $ rateLimitMeterUpdate consoleratelimit meter $
|
||||||
updateMeter meter
|
updateMeter meter
|
||||||
r <- a meter (combinemeter m)
|
r <- a meter =<< mkmeterupdate m
|
||||||
setclear noop
|
setclear noop
|
||||||
liftIO clear
|
liftIO clear
|
||||||
return r
|
return r
|
||||||
|
@ -116,7 +119,7 @@ metered' st setclear othermeter msize showoutput a = go st
|
||||||
in Regions.setConsoleRegion r ('\n' : s)
|
in Regions.setConsoleRegion r ('\n' : s)
|
||||||
m <- liftIO $ rateLimitMeterUpdate consoleratelimit meter $
|
m <- liftIO $ rateLimitMeterUpdate consoleratelimit meter $
|
||||||
updateMeter meter
|
updateMeter meter
|
||||||
a meter (combinemeter m)
|
a meter =<< mkmeterupdate m
|
||||||
go (MessageState { outputType = JSONOutput jsonoptions })
|
go (MessageState { outputType = JSONOutput jsonoptions })
|
||||||
| jsonProgress jsonoptions = do
|
| jsonProgress jsonoptions = do
|
||||||
let buf = jsonBuffer st
|
let buf = jsonBuffer st
|
||||||
|
@ -124,7 +127,7 @@ metered' st setclear othermeter msize showoutput a = go st
|
||||||
JSON.progress buf msize' (meterBytesProcessed new)
|
JSON.progress buf msize' (meterBytesProcessed new)
|
||||||
m <- liftIO $ rateLimitMeterUpdate jsonratelimit meter $
|
m <- liftIO $ rateLimitMeterUpdate jsonratelimit meter $
|
||||||
updateMeter meter
|
updateMeter meter
|
||||||
a meter (combinemeter m)
|
a meter =<< mkmeterupdate m
|
||||||
| otherwise = nometer
|
| otherwise = nometer
|
||||||
go (MessageState { outputType = SerializedOutput h _ }) = do
|
go (MessageState { outputType = SerializedOutput h _ }) = do
|
||||||
liftIO $ outputSerialized h BeginProgressMeter
|
liftIO $ outputSerialized h BeginProgressMeter
|
||||||
|
@ -144,16 +147,21 @@ metered' st setclear othermeter msize showoutput a = go st
|
||||||
meterBytesProcessed new
|
meterBytesProcessed new
|
||||||
m <- liftIO $ rateLimitMeterUpdate minratelimit meter $
|
m <- liftIO $ rateLimitMeterUpdate minratelimit meter $
|
||||||
updateMeter meter
|
updateMeter meter
|
||||||
a meter (combinemeter m)
|
(a meter =<< mkmeterupdate m)
|
||||||
`finally` (liftIO $ outputSerialized h EndProgressMeter)
|
`finally` (liftIO $ outputSerialized h EndProgressMeter)
|
||||||
nometer = do
|
nometer = do
|
||||||
dummymeter <- liftIO $ mkMeter Nothing $
|
dummymeter <- liftIO $ mkMeter Nothing $
|
||||||
\_ _ _ _ -> return ()
|
\_ _ _ _ -> return ()
|
||||||
a dummymeter (combinemeter (const noop))
|
a dummymeter =<< mkmeterupdate (const noop)
|
||||||
|
|
||||||
combinemeter m = case othermeter of
|
mkmeterupdate m =
|
||||||
Nothing -> m
|
let mu = case othermeterupdate of
|
||||||
Just om -> combineMeterUpdate m om
|
Nothing -> m
|
||||||
|
Just om -> combineMeterUpdate m om
|
||||||
|
in case bwlimit of
|
||||||
|
Nothing -> return mu
|
||||||
|
Just (BwRate sz duration) -> liftIO $
|
||||||
|
bwLimitMeterUpdate sz duration mu
|
||||||
|
|
||||||
consoleratelimit = 0.2
|
consoleratelimit = 0.2
|
||||||
|
|
||||||
|
@ -164,7 +172,7 @@ metered' st setclear othermeter msize showoutput a = go st
|
||||||
{- Poll file size to display meter. -}
|
{- Poll file size to display meter. -}
|
||||||
meteredFile :: FilePath -> Maybe MeterUpdate -> Key -> Annex a -> Annex a
|
meteredFile :: FilePath -> Maybe MeterUpdate -> Key -> Annex a -> Annex a
|
||||||
meteredFile file combinemeterupdate key a =
|
meteredFile file combinemeterupdate key a =
|
||||||
metered combinemeterupdate key $ \_ p ->
|
metered combinemeterupdate key Nothing $ \_ p ->
|
||||||
watchFileSize file p a
|
watchFileSize file p a
|
||||||
|
|
||||||
{- Progress dots. -}
|
{- Progress dots. -}
|
||||||
|
|
|
@ -68,7 +68,7 @@ relaySerializedOutput getso sendsor meterreport runannex = go Nothing
|
||||||
let setclear = const noop
|
let setclear = const noop
|
||||||
-- Display a progress meter while running, until
|
-- Display a progress meter while running, until
|
||||||
-- the meter ends or a final value is returned.
|
-- the meter ends or a final value is returned.
|
||||||
metered' ost setclear Nothing Nothing (runannex showOutput)
|
metered' ost setclear Nothing Nothing Nothing (runannex showOutput)
|
||||||
(\meter meterupdate -> loop (Just (meter, meterupdate)))
|
(\meter meterupdate -> loop (Just (meter, meterupdate)))
|
||||||
>>= \case
|
>>= \case
|
||||||
Right r -> return (Right r)
|
Right r -> return (Right r)
|
||||||
|
|
|
@ -550,6 +550,7 @@ copyFromRemote'' repo forcersync r st@(State connpool _ _ _ _) key file dest met
|
||||||
| not $ Git.repoIsUrl repo = guardUsable repo (giveup "cannot access remote") $ do
|
| not $ Git.repoIsUrl repo = guardUsable repo (giveup "cannot access remote") $ do
|
||||||
u <- getUUID
|
u <- getUUID
|
||||||
hardlink <- wantHardLink
|
hardlink <- wantHardLink
|
||||||
|
let bwlimit = remoteAnnexBwLimit (gitconfig r)
|
||||||
-- run copy from perspective of remote
|
-- run copy from perspective of remote
|
||||||
onLocalFast st $ Annex.Content.prepSendAnnex' key >>= \case
|
onLocalFast st $ Annex.Content.prepSendAnnex' key >>= \case
|
||||||
Just (object, check) -> do
|
Just (object, check) -> do
|
||||||
|
@ -559,7 +560,7 @@ copyFromRemote'' repo forcersync r st@(State connpool _ _ _ _) key file dest met
|
||||||
copier <- mkFileCopier hardlink st
|
copier <- mkFileCopier hardlink st
|
||||||
(ok, v) <- runTransfer (Transfer Download u (fromKey id key))
|
(ok, v) <- runTransfer (Transfer Download u (fromKey id key))
|
||||||
file Nothing stdRetry $ \p ->
|
file Nothing stdRetry $ \p ->
|
||||||
metered (Just (combineMeterUpdate p meterupdate)) key $ \_ p' ->
|
metered (Just (combineMeterUpdate p meterupdate)) key bwlimit $ \_ p' ->
|
||||||
copier object dest key p' checksuccess vc
|
copier object dest key p' checksuccess vc
|
||||||
if ok
|
if ok
|
||||||
then return v
|
then return v
|
||||||
|
@ -572,6 +573,7 @@ copyFromRemote'' repo forcersync r st@(State connpool _ _ _ _) key file dest met
|
||||||
then return v
|
then return v
|
||||||
else giveup "failed to retrieve content from remote"
|
else giveup "failed to retrieve content from remote"
|
||||||
else P2PHelper.retrieve
|
else P2PHelper.retrieve
|
||||||
|
(gitconfig r)
|
||||||
(\p -> Ssh.runProto r connpool (return (False, UnVerified)) (fallback p))
|
(\p -> Ssh.runProto r connpool (return (False, UnVerified)) (fallback p))
|
||||||
key file dest meterupdate vc
|
key file dest meterupdate vc
|
||||||
| otherwise = giveup "copying from non-ssh, non-http remote not supported"
|
| otherwise = giveup "copying from non-ssh, non-http remote not supported"
|
||||||
|
@ -680,7 +682,7 @@ copyToRemote' repo r st@(State connpool duc _ _ _) key file meterupdate
|
||||||
, giveup "remote does not have expected annex.uuid value"
|
, giveup "remote does not have expected annex.uuid value"
|
||||||
)
|
)
|
||||||
| Git.repoIsSsh repo = commitOnCleanup repo r st $
|
| Git.repoIsSsh repo = commitOnCleanup repo r st $
|
||||||
P2PHelper.store
|
P2PHelper.store (gitconfig r)
|
||||||
(Ssh.runProto r connpool (return False) . copyremotefallback)
|
(Ssh.runProto r connpool (return False) . copyremotefallback)
|
||||||
key file meterupdate
|
key file meterupdate
|
||||||
|
|
||||||
|
@ -694,6 +696,7 @@ copyToRemote' repo r st@(State connpool duc _ _ _) key file meterupdate
|
||||||
checkio <- Annex.withCurrentState check
|
checkio <- Annex.withCurrentState check
|
||||||
u <- getUUID
|
u <- getUUID
|
||||||
hardlink <- wantHardLink
|
hardlink <- wantHardLink
|
||||||
|
let bwlimit = remoteAnnexBwLimit (gitconfig r)
|
||||||
-- run copy from perspective of remote
|
-- run copy from perspective of remote
|
||||||
res <- onLocalFast st $ ifM (Annex.Content.inAnnex key)
|
res <- onLocalFast st $ ifM (Annex.Content.inAnnex key)
|
||||||
( return True
|
( return True
|
||||||
|
@ -705,7 +708,7 @@ copyToRemote' repo r st@(State connpool duc _ _ _) key file meterupdate
|
||||||
Just err -> giveup err
|
Just err -> giveup err
|
||||||
Nothing -> return True
|
Nothing -> return True
|
||||||
res <- logStatusAfter key $ Annex.Content.getViaTmp rsp verify key file $ \dest ->
|
res <- logStatusAfter key $ Annex.Content.getViaTmp rsp verify key file $ \dest ->
|
||||||
metered (Just (combineMeterUpdate meterupdate p)) key $ \_ p' ->
|
metered (Just (combineMeterUpdate meterupdate p)) key bwlimit $ \_ p' ->
|
||||||
copier object (fromRawFilePath dest) key p' checksuccess verify
|
copier object (fromRawFilePath dest) key p' checksuccess verify
|
||||||
Annex.Content.saveState True
|
Annex.Content.saveState True
|
||||||
return res
|
return res
|
||||||
|
|
|
@ -31,19 +31,21 @@ type ProtoConnRunner c = forall a. P2P.Proto a -> ClosableConnection c -> Annex
|
||||||
-- the pool when done.
|
-- the pool when done.
|
||||||
type WithConn a c = (ClosableConnection c -> Annex (ClosableConnection c, a)) -> Annex a
|
type WithConn a c = (ClosableConnection c -> Annex (ClosableConnection c, a)) -> Annex a
|
||||||
|
|
||||||
store :: (MeterUpdate -> ProtoRunner Bool) -> Key -> AssociatedFile -> MeterUpdate -> Annex ()
|
store :: RemoteGitConfig -> (MeterUpdate -> ProtoRunner Bool) -> Key -> AssociatedFile -> MeterUpdate -> Annex ()
|
||||||
store runner k af p = do
|
store gc runner k af p = do
|
||||||
let sizer = KeySizer k (fmap (toRawFilePath . fst) <$> prepSendAnnex k)
|
let sizer = KeySizer k (fmap (toRawFilePath . fst) <$> prepSendAnnex k)
|
||||||
metered (Just p) sizer $ \_ p' ->
|
let bwlimit = remoteAnnexBwLimit gc
|
||||||
|
metered (Just p) sizer bwlimit $ \_ p' ->
|
||||||
runner p' (P2P.put k af p') >>= \case
|
runner p' (P2P.put k af p') >>= \case
|
||||||
Just True -> return ()
|
Just True -> return ()
|
||||||
Just False -> giveup "Transfer failed"
|
Just False -> giveup "Transfer failed"
|
||||||
Nothing -> remoteUnavail
|
Nothing -> remoteUnavail
|
||||||
|
|
||||||
retrieve :: (MeterUpdate -> ProtoRunner (Bool, Verification)) -> Key -> AssociatedFile -> FilePath -> MeterUpdate -> VerifyConfig -> Annex Verification
|
retrieve :: RemoteGitConfig -> (MeterUpdate -> ProtoRunner (Bool, Verification)) -> Key -> AssociatedFile -> FilePath -> MeterUpdate -> VerifyConfig -> Annex Verification
|
||||||
retrieve runner k af dest p verifyconfig = do
|
retrieve gc runner k af dest p verifyconfig = do
|
||||||
iv <- startVerifyKeyContentIncrementally verifyconfig k
|
iv <- startVerifyKeyContentIncrementally verifyconfig k
|
||||||
metered (Just p) k $ \m p' ->
|
let bwlimit = remoteAnnexBwLimit gc
|
||||||
|
metered (Just p) k bwlimit $ \m p' ->
|
||||||
runner p' (P2P.get dest k iv af m p') >>= \case
|
runner p' (P2P.get dest k iv af m p') >>= \case
|
||||||
Just (True, v) -> return v
|
Just (True, v) -> return v
|
||||||
Just (False, _) -> giveup "Transfer failed"
|
Just (False, _) -> giveup "Transfer failed"
|
||||||
|
|
|
@ -261,8 +261,9 @@ specialRemote' cfg c storer retriever remover checkpresent baser = encr
|
||||||
chunkconfig = chunkConfig cfg
|
chunkconfig = chunkConfig cfg
|
||||||
|
|
||||||
displayprogress p k srcfile a
|
displayprogress p k srcfile a
|
||||||
| displayProgress cfg =
|
| displayProgress cfg = do
|
||||||
metered (Just p) (KeySizer k (pure (fmap toRawFilePath srcfile))) (const a)
|
let bwlimit = remoteAnnexBwLimit (gitconfig baser)
|
||||||
|
metered (Just p) (KeySizer k (pure (fmap toRawFilePath srcfile))) bwlimit (const a)
|
||||||
| otherwise = a p
|
| otherwise = a p
|
||||||
|
|
||||||
withBytes :: ContentSource -> (L.ByteString -> Annex a) -> Annex a
|
withBytes :: ContentSource -> (L.ByteString -> Annex a) -> Annex a
|
||||||
|
|
|
@ -55,8 +55,8 @@ chainGen addr r u rc gc rs = do
|
||||||
{ uuid = u
|
{ uuid = u
|
||||||
, cost = cst
|
, cost = cst
|
||||||
, name = Git.repoDescribe r
|
, name = Git.repoDescribe r
|
||||||
, storeKey = store (const protorunner)
|
, storeKey = store gc (const protorunner)
|
||||||
, retrieveKeyFile = retrieve (const protorunner)
|
, retrieveKeyFile = retrieve gc (const protorunner)
|
||||||
, retrieveKeyFileCheap = Nothing
|
, retrieveKeyFileCheap = Nothing
|
||||||
, retrievalSecurityPolicy = RetrievalAllKeysSecure
|
, retrievalSecurityPolicy = RetrievalAllKeysSecure
|
||||||
, removeKey = remove protorunner
|
, removeKey = remove protorunner
|
||||||
|
|
|
@ -339,6 +339,7 @@ data RemoteGitConfig = RemoteGitConfig
|
||||||
, remoteAnnexForwardRetry :: Maybe Integer
|
, remoteAnnexForwardRetry :: Maybe Integer
|
||||||
, remoteAnnexRetryDelay :: Maybe Seconds
|
, remoteAnnexRetryDelay :: Maybe Seconds
|
||||||
, remoteAnnexStallDetection :: Maybe StallDetection
|
, remoteAnnexStallDetection :: Maybe StallDetection
|
||||||
|
, remoteAnnexBwLimit :: Maybe BwRate
|
||||||
, remoteAnnexAllowUnverifiedDownloads :: Bool
|
, remoteAnnexAllowUnverifiedDownloads :: Bool
|
||||||
, remoteAnnexConfigUUID :: Maybe UUID
|
, remoteAnnexConfigUUID :: Maybe UUID
|
||||||
|
|
||||||
|
@ -404,8 +405,11 @@ extractRemoteGitConfig r remotename = do
|
||||||
, remoteAnnexRetryDelay = Seconds
|
, remoteAnnexRetryDelay = Seconds
|
||||||
<$> getmayberead "retrydelay"
|
<$> getmayberead "retrydelay"
|
||||||
, remoteAnnexStallDetection =
|
, remoteAnnexStallDetection =
|
||||||
either (const Nothing) id . parseStallDetection
|
either (const Nothing) Just . parseStallDetection
|
||||||
=<< getmaybe "stalldetection"
|
=<< getmaybe "stalldetection"
|
||||||
|
, remoteAnnexBwLimit = do
|
||||||
|
sz <- readSize dataUnits =<< getmaybe "bwlimit"
|
||||||
|
return (BwRate sz (Duration 1))
|
||||||
, remoteAnnexAllowUnverifiedDownloads = (== Just "ACKTHPPT") $
|
, remoteAnnexAllowUnverifiedDownloads = (== Just "ACKTHPPT") $
|
||||||
getmaybe ("security-allow-unverified-downloads")
|
getmaybe ("security-allow-unverified-downloads")
|
||||||
, remoteAnnexConfigUUID = toUUID <$> getmaybe "config-uuid"
|
, remoteAnnexConfigUUID = toUUID <$> getmaybe "config-uuid"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{- types for stall detection
|
{- types for stall detection and banwdith rates
|
||||||
-
|
-
|
||||||
- Copyright 2020-2021 Joey Hess <id@joeyh.name>
|
- Copyright 2020-2021 Joey Hess <id@joeyh.name>
|
||||||
-
|
-
|
||||||
|
@ -13,7 +13,7 @@ import Utility.Misc
|
||||||
import Git.Config
|
import Git.Config
|
||||||
|
|
||||||
data StallDetection
|
data StallDetection
|
||||||
= StallDetection ByteSize Duration
|
= StallDetection BwRate
|
||||||
-- ^ Unless the given number of bytes have been sent over the given
|
-- ^ Unless the given number of bytes have been sent over the given
|
||||||
-- amount of time, there's a stall.
|
-- amount of time, there's a stall.
|
||||||
| ProbeStallDetection
|
| ProbeStallDetection
|
||||||
|
@ -22,21 +22,29 @@ data StallDetection
|
||||||
| StallDetectionDisabled
|
| StallDetectionDisabled
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
|
data BwRate = BwRate ByteSize Duration
|
||||||
|
deriving (Show)
|
||||||
|
|
||||||
-- Parse eg, "0KiB/60s"
|
-- Parse eg, "0KiB/60s"
|
||||||
--
|
--
|
||||||
-- Also, it can be set to "true" (or other git config equivilants)
|
-- Also, it can be set to "true" (or other git config equivilants)
|
||||||
-- to enable ProbeStallDetection.
|
-- to enable ProbeStallDetection.
|
||||||
-- And "false" (and other git config equivilants) explicitly
|
-- And "false" (and other git config equivilants) explicitly
|
||||||
-- disable stall detection.
|
-- disable stall detection.
|
||||||
parseStallDetection :: String -> Either String (Maybe StallDetection)
|
parseStallDetection :: String -> Either String StallDetection
|
||||||
parseStallDetection s = case isTrueFalse s of
|
parseStallDetection s = case isTrueFalse s of
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
let (bs, ds) = separate (== '/') s
|
v <- parseBwRate s
|
||||||
b <- maybe
|
Right (StallDetection v)
|
||||||
(Left $ "Unable to parse stall detection amount " ++ bs)
|
Just True -> Right ProbeStallDetection
|
||||||
Right
|
Just False -> Right StallDetectionDisabled
|
||||||
(readSize dataUnits bs)
|
|
||||||
d <- parseDuration ds
|
parseBwRate :: String -> Either String BwRate
|
||||||
return (Just (StallDetection b d))
|
parseBwRate s = do
|
||||||
Just True -> Right (Just ProbeStallDetection)
|
let (bs, ds) = separate (== '/') s
|
||||||
Just False -> Right (Just StallDetectionDisabled)
|
b <- maybe
|
||||||
|
(Left $ "Unable to parse bandwidth amount " ++ bs)
|
||||||
|
Right
|
||||||
|
(readSize dataUnits bs)
|
||||||
|
d <- parseDuration ds
|
||||||
|
Right (BwRate b d)
|
||||||
|
|
|
@ -37,6 +37,7 @@ module Utility.Metered (
|
||||||
demeterCommandEnv,
|
demeterCommandEnv,
|
||||||
avoidProgress,
|
avoidProgress,
|
||||||
rateLimitMeterUpdate,
|
rateLimitMeterUpdate,
|
||||||
|
bwLimitMeterUpdate,
|
||||||
Meter,
|
Meter,
|
||||||
mkMeter,
|
mkMeter,
|
||||||
setMeterTotalSize,
|
setMeterTotalSize,
|
||||||
|
@ -51,6 +52,7 @@ import Utility.Percentage
|
||||||
import Utility.DataUnits
|
import Utility.DataUnits
|
||||||
import Utility.HumanTime
|
import Utility.HumanTime
|
||||||
import Utility.SimpleProtocol as Proto
|
import Utility.SimpleProtocol as Proto
|
||||||
|
import Utility.ThreadScheduler
|
||||||
|
|
||||||
import qualified Data.ByteString.Lazy as L
|
import qualified Data.ByteString.Lazy as L
|
||||||
import qualified Data.ByteString as S
|
import qualified Data.ByteString as S
|
||||||
|
@ -380,6 +382,42 @@ rateLimitMeterUpdate delta (Meter totalsizev _ _ _) meterupdate = do
|
||||||
meterupdate n
|
meterupdate n
|
||||||
else putMVar lastupdate prev
|
else putMVar lastupdate prev
|
||||||
|
|
||||||
|
-- | Bandwidth limiting by inserting a delay at the point that a meter is
|
||||||
|
-- updated.
|
||||||
|
--
|
||||||
|
-- This will only work when the actions that use bandwidth are run in the
|
||||||
|
-- same process and thread as the call to the MeterUpdate.
|
||||||
|
--
|
||||||
|
-- For example, if the desired bandwidth is 100kb/s, and over the past
|
||||||
|
-- 1/10th of a second, 30kb was sent, then the current bandwidth is
|
||||||
|
-- 300kb/s, 3x as fast as desired. So, after getting the next chunk,
|
||||||
|
-- pause for twice as long as it took to get it.
|
||||||
|
bwLimitMeterUpdate :: ByteSize -> Duration -> MeterUpdate -> IO MeterUpdate
|
||||||
|
bwLimitMeterUpdate bwlimit duration meterupdate
|
||||||
|
| bwlimit <= 0 = return meterupdate
|
||||||
|
| otherwise = do
|
||||||
|
nowtime <- getPOSIXTime
|
||||||
|
mv <- newMVar (nowtime, 0)
|
||||||
|
return (mu mv)
|
||||||
|
where
|
||||||
|
mu mv n@(BytesProcessed i) = do
|
||||||
|
endtime <- getPOSIXTime
|
||||||
|
(starttime, previ) <- takeMVar mv
|
||||||
|
|
||||||
|
let runtime = endtime - starttime
|
||||||
|
let currbw = fromIntegral (i - previ) / runtime
|
||||||
|
let pausescale = if currbw > bwlimit'
|
||||||
|
then (currbw / bwlimit') - 1
|
||||||
|
else 0
|
||||||
|
unboundDelay (floor (runtime * pausescale * msecs))
|
||||||
|
meterupdate n
|
||||||
|
|
||||||
|
nowtime <- getPOSIXTime
|
||||||
|
putMVar mv (nowtime, i)
|
||||||
|
|
||||||
|
bwlimit' = fromIntegral (bwlimit * durationSeconds duration)
|
||||||
|
msecs = fromIntegral oneSecond
|
||||||
|
|
||||||
data Meter = Meter (MVar (Maybe TotalSize)) (MVar MeterState) (MVar String) DisplayMeter
|
data Meter = Meter (MVar (Maybe TotalSize)) (MVar MeterState) (MVar String) DisplayMeter
|
||||||
|
|
||||||
data MeterState = MeterState
|
data MeterState = MeterState
|
||||||
|
|
|
@ -1384,6 +1384,18 @@ Remotes are configured using these settings in `.git/config`.
|
||||||
When making multiple retries of the same transfer, the delay
|
When making multiple retries of the same transfer, the delay
|
||||||
doubles after each retry. (default 1)
|
doubles after each retry. (default 1)
|
||||||
|
|
||||||
|
* `remote.<name>.annex-bwlimit`, `annex.bwlimit`
|
||||||
|
|
||||||
|
This can be used to limit how much bandwidth is used for a transfer
|
||||||
|
from or to a remote.
|
||||||
|
|
||||||
|
For example, to limit transfers to 1 mebibyte per second:
|
||||||
|
`git config annex.bwlimit "1MiB"`
|
||||||
|
|
||||||
|
This will work with many remotes, including git remotes, but not
|
||||||
|
for remotes where the transfer is run by a separate program than
|
||||||
|
git-annex.
|
||||||
|
|
||||||
* `remote.<name>.annex-stalldetecton`, `annex.stalldetection`
|
* `remote.<name>.annex-stalldetecton`, `annex.stalldetection`
|
||||||
|
|
||||||
Configuring this lets stalled or too-slow transfers be detected, and
|
Configuring this lets stalled or too-slow transfers be detected, and
|
||||||
|
|
|
@ -10,5 +10,26 @@ works, it will probably work to put the delay in there. --[[Joey]]
|
||||||
|
|
||||||
[[confirmed]]
|
[[confirmed]]
|
||||||
|
|
||||||
> Implmentation in progress in the `bwlimit` branch. Seems to work, but see
|
> Implemented and works well.
|
||||||
> commit message for what still needs to be done. --[[Joey]]
|
>
|
||||||
|
> A local git remote, when resuming an interrupted
|
||||||
|
> transfer, has to hash the file (with default annex.verify settings),
|
||||||
|
> and that hashing updates the progress bar, and so the bwlimit can kick
|
||||||
|
> in and slow down that initial hashing, before any data copying begins.
|
||||||
|
> This seems perhaps ok; if you've bwlimited a local git remote,
|
||||||
|
> remote you're wanting to limit disk IO. Only reason it might not be ok
|
||||||
|
> is if the intent is to limit IO to the disk containing the remote
|
||||||
|
> but not the one containing the annex repo. (This also probably
|
||||||
|
> holds for the directory special remote.)
|
||||||
|
>
|
||||||
|
> Other remotes, including git over ssh, when resuming don't have that
|
||||||
|
> problem. Looks like chunked special remotes narrowly avoid it, just
|
||||||
|
> because their implementation choose to not do incremental verification
|
||||||
|
> when resuming. It might be worthwhile to differentiate between progress
|
||||||
|
> updates for incremental verification setup and for actual transfers, and
|
||||||
|
> only rate limit the latter, just to avoid fragility in the code.
|
||||||
|
> I have not done so yet though, and am closing this..
|
||||||
|
> --[[Joey]]
|
||||||
|
|
||||||
|
[[done]]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue