avoid double-connect to unreachable ssh remote
When git-annex-shell p2pstdio fails with 255, it's because the ssh server is not reachable. Avoid running the fallback action in this case, since it would just try a second time to connect, and presumably fail. Note that the closed P2PSshConnection will not be stored in the pool, so the next request tries again to connect. This is just the right behavior; when the remote becomes reachable again, the same git-annex process will start using it. This commit was sponsored by Ole-Morten Duesund on Patreon.
This commit is contained in:
parent
e36ceb7448
commit
c3df5d1f10
6 changed files with 43 additions and 37 deletions
|
@ -342,7 +342,7 @@ inAnnex rmt (State connpool duc) key
|
|||
)
|
||||
checkremote =
|
||||
let fallback = Ssh.inAnnex r key
|
||||
in P2PHelper.checkpresent (Ssh.runProto rmt connpool fallback) key
|
||||
in P2PHelper.checkpresent (Ssh.runProto rmt connpool (cantCheck rmt) fallback) key
|
||||
checklocal = ifM duc
|
||||
( guardUsable r (cantCheck r) $
|
||||
maybe (cantCheck r) return
|
||||
|
@ -384,7 +384,7 @@ dropKey r (State connpool duc) key
|
|||
| Git.repoIsHttp (repo r) = giveup "dropping from http remote not supported"
|
||||
| otherwise = commitOnCleanup r $ do
|
||||
let fallback = Ssh.dropKey (repo r) key
|
||||
P2PHelper.remove (Ssh.runProto r connpool fallback) key
|
||||
P2PHelper.remove (Ssh.runProto r connpool False fallback) key
|
||||
|
||||
lockKey :: Remote -> State -> Key -> (VerifiedCopy -> Annex r) -> Annex r
|
||||
lockKey r (State connpool duc) key callback
|
||||
|
@ -471,7 +471,7 @@ copyFromRemote' forcersync r (State connpool _) key file dest meterupdate
|
|||
| Git.repoIsSsh (repo r) = if forcersync
|
||||
then unVerified fallback
|
||||
else P2PHelper.retrieve
|
||||
(Ssh.runProto r connpool fallback)
|
||||
(Ssh.runProto r connpool False fallback)
|
||||
key file dest meterupdate
|
||||
| otherwise = giveup "copying from non-ssh, non-http remote not supported"
|
||||
where
|
||||
|
@ -572,7 +572,7 @@ copyToRemote r (State connpool duc) key file meterupdate
|
|||
)
|
||||
| Git.repoIsSsh (repo r) = commitOnCleanup r $
|
||||
P2PHelper.store
|
||||
(Ssh.runProto r connpool copyremotefallback)
|
||||
(Ssh.runProto r connpool False copyremotefallback)
|
||||
key file meterupdate
|
||||
|
||||
| otherwise = giveup "copying to non-ssh repo not supported"
|
||||
|
|
|
@ -189,12 +189,12 @@ contentLockedMarker = "OK"
|
|||
type P2PSshConnection = P2P.ClosableConnection
|
||||
(P2P.RunState, P2P.P2PConnection, ProcessHandle)
|
||||
|
||||
closeP2PSshConnection :: P2PSshConnection -> IO P2PSshConnection
|
||||
closeP2PSshConnection P2P.ClosedConnection = return P2P.ClosedConnection
|
||||
closeP2PSshConnection :: P2PSshConnection -> IO (P2PSshConnection, Maybe ExitCode)
|
||||
closeP2PSshConnection P2P.ClosedConnection = return (P2P.ClosedConnection, Nothing)
|
||||
closeP2PSshConnection (P2P.OpenConnection (_st, conn, pid)) = do
|
||||
P2P.closeConnection conn
|
||||
void $ waitForProcess pid
|
||||
return P2P.ClosedConnection
|
||||
exitcode <- waitForProcess pid
|
||||
return (P2P.ClosedConnection, Just exitcode)
|
||||
|
||||
-- Pool of connections over ssh to git-annex-shell p2pstdio.
|
||||
type P2PSshConnectionPool = TVar (Maybe P2PSshConnectionPoolState)
|
||||
|
@ -270,17 +270,26 @@ openP2PSshConnection r connpool = do
|
|||
Right (Right (Just theiruuid)) | theiruuid == uuid r ->
|
||||
return $ Just c
|
||||
_ -> do
|
||||
void $ closeP2PSshConnection c
|
||||
rememberunsupported
|
||||
return Nothing
|
||||
(cclosed, exitcode) <- closeP2PSshConnection c
|
||||
-- ssh exits 255 when unable to connect to
|
||||
-- server. Return a closed connection in
|
||||
-- this case, to avoid the fallback action
|
||||
-- being run instead, which would mean a
|
||||
-- second connection attempt to this server
|
||||
-- that is down.
|
||||
if exitcode == Just (ExitFailure 255)
|
||||
then return (Just cclosed)
|
||||
else do
|
||||
rememberunsupported
|
||||
return Nothing
|
||||
rememberunsupported = atomically $
|
||||
modifyTVar' connpool $
|
||||
maybe (Just P2PSshUnsupported) Just
|
||||
|
||||
-- Runs a P2P Proto action on a remote when it supports that,
|
||||
-- otherwise the fallback action.
|
||||
runProto :: Remote -> P2PSshConnectionPool -> Annex a -> P2P.Proto a -> Annex (Maybe a)
|
||||
runProto r connpool fallback proto = Just <$>
|
||||
runProto :: Remote -> P2PSshConnectionPool -> a -> Annex a -> P2P.Proto a -> Annex (Maybe a)
|
||||
runProto r connpool bad fallback proto = Just <$>
|
||||
(getP2PSshConnection r connpool >>= maybe fallback go)
|
||||
where
|
||||
go c = do
|
||||
|
@ -290,9 +299,8 @@ runProto r connpool fallback proto = Just <$>
|
|||
liftIO $ storeP2PSshConnection connpool c'
|
||||
return res
|
||||
-- Running the proto failed, either due to a protocol
|
||||
-- error or a network error, so discard the
|
||||
-- connection, and run the fallback.
|
||||
Nothing -> fallback
|
||||
-- error or a network error.
|
||||
Nothing -> return bad
|
||||
|
||||
runProtoConn :: P2P.Proto a -> P2PSshConnection -> Annex (P2PSshConnection, Maybe a)
|
||||
runProtoConn _ P2P.ClosedConnection = return (P2P.ClosedConnection, Nothing)
|
||||
|
@ -303,7 +311,7 @@ runProtoConn a conn@(P2P.OpenConnection (runst, c, _pid)) = do
|
|||
-- usable, so close it.
|
||||
Left e -> do
|
||||
warning $ "Lost connection (" ++ e ++ ")"
|
||||
conn' <- liftIO $ closeP2PSshConnection conn
|
||||
conn' <- fst <$> liftIO (closeP2PSshConnection conn)
|
||||
return (conn', Nothing)
|
||||
|
||||
-- Allocates a P2P ssh connection from the pool, and runs the action with it,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue