generalized ExternalState to not be limited to a ExternalAddonProcess
Idea is for ASYNC extension, it will instead contain methods that communicate with the thread that handles all communication with the external process.
This commit is contained in:
parent
5f4228dc2b
commit
3f8c808bd7
2 changed files with 48 additions and 33 deletions
|
@ -12,7 +12,7 @@ module Remote.External (remote) where
|
||||||
import Remote.External.Types
|
import Remote.External.Types
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import Annex.Common
|
import Annex.Common
|
||||||
import Annex.ExternalAddonProcess
|
import qualified Annex.ExternalAddonProcess as AddonProcess
|
||||||
import Types.Remote
|
import Types.Remote
|
||||||
import Types.Export
|
import Types.Export
|
||||||
import Types.CleanupActions
|
import Types.CleanupActions
|
||||||
|
@ -504,13 +504,26 @@ handleRequest' st external req mp responsehandler
|
||||||
setDownloader (show uri) OtherDownloader
|
setDownloader (show uri) OtherDownloader
|
||||||
|
|
||||||
sendMessage :: Sendable m => ExternalState -> m -> Annex ()
|
sendMessage :: Sendable m => ExternalState -> m -> Annex ()
|
||||||
sendMessage st m = liftIO $ do
|
sendMessage st m = liftIO $ externalSend st line
|
||||||
protocolDebug (externalAddonProcess st) True line
|
where
|
||||||
|
line = unwords $ formatMessage m
|
||||||
|
|
||||||
|
sendMessageAddonProcess :: AddonProcess.ExternalAddonProcess -> String -> IO ()
|
||||||
|
sendMessageAddonProcess p line = do
|
||||||
|
AddonProcess.protocolDebug p True line
|
||||||
hPutStrLn h line
|
hPutStrLn h line
|
||||||
hFlush h
|
hFlush h
|
||||||
where
|
where
|
||||||
line = unwords $ formatMessage m
|
h = AddonProcess.externalSend p
|
||||||
h = externalSend (externalAddonProcess st)
|
|
||||||
|
receiveMessageAddonProcess :: AddonProcess.ExternalAddonProcess -> IO (Maybe String)
|
||||||
|
receiveMessageAddonProcess p = do
|
||||||
|
v <- catchMaybeIO $ hGetLine $ AddonProcess.externalReceive p
|
||||||
|
maybe noop (AddonProcess.protocolDebug p False) v
|
||||||
|
return v
|
||||||
|
|
||||||
|
shutdownAddonProcess :: AddonProcess.ExternalAddonProcess -> Bool -> IO ()
|
||||||
|
shutdownAddonProcess = AddonProcess.externalShutdown
|
||||||
|
|
||||||
{- A response handler can yeild a result, or it can request that another
|
{- A response handler can yeild a result, or it can request that another
|
||||||
- message be consumed from the external. -}
|
- message be consumed from the external. -}
|
||||||
|
@ -535,23 +548,21 @@ receiveMessage
|
||||||
-> (ExceptionalMessage -> Maybe (Annex a))
|
-> (ExceptionalMessage -> Maybe (Annex a))
|
||||||
-> Annex a
|
-> Annex a
|
||||||
receiveMessage st external handleresponse handlerequest handleexceptional =
|
receiveMessage st external handleresponse handlerequest handleexceptional =
|
||||||
go =<< liftIO (catchMaybeIO $ hGetLine $ externalReceive $ externalAddonProcess st)
|
go =<< liftIO (externalReceive st)
|
||||||
where
|
where
|
||||||
go Nothing = protocolError False ""
|
go Nothing = protocolError False ""
|
||||||
go (Just s) = do
|
go (Just s) = case parseMessage s :: Maybe Response of
|
||||||
liftIO $ protocolDebug (externalAddonProcess st) False s
|
Just resp -> case handleresponse resp of
|
||||||
case parseMessage s :: Maybe Response of
|
Nothing -> protocolError True s
|
||||||
Just resp -> case handleresponse resp of
|
Just callback -> callback >>= \case
|
||||||
Nothing -> protocolError True s
|
Result a -> return a
|
||||||
Just callback -> callback >>= \case
|
GetNextMessage handleresponse' ->
|
||||||
Result a -> return a
|
receiveMessage st external handleresponse' handlerequest handleexceptional
|
||||||
GetNextMessage handleresponse' ->
|
Nothing -> case parseMessage s :: Maybe RemoteRequest of
|
||||||
receiveMessage st external handleresponse' handlerequest handleexceptional
|
Just req -> maybe (protocolError True s) id (handlerequest req)
|
||||||
Nothing -> case parseMessage s :: Maybe RemoteRequest of
|
Nothing -> case parseMessage s :: Maybe ExceptionalMessage of
|
||||||
Just req -> maybe (protocolError True s) id (handlerequest req)
|
Just msg -> maybe (protocolError True s) id (handleexceptional msg)
|
||||||
Nothing -> case parseMessage s :: Maybe ExceptionalMessage of
|
Nothing -> protocolError False s
|
||||||
Just msg -> maybe (protocolError True s) id (handleexceptional msg)
|
|
||||||
Nothing -> protocolError False s
|
|
||||||
protocolError parsed s = giveup $ "external special remote protocol error, unexpectedly received \"" ++ s ++ "\" " ++
|
protocolError parsed s = giveup $ "external special remote protocol error, unexpectedly received \"" ++ s ++ "\" " ++
|
||||||
if parsed
|
if parsed
|
||||||
then "(command not allowed at this time)"
|
then "(command not allowed at this time)"
|
||||||
|
@ -571,7 +582,7 @@ receiveMessage st external handleresponse handlerequest handleexceptional =
|
||||||
withExternalState :: External -> (ExternalState -> Annex a) -> Annex a
|
withExternalState :: External -> (ExternalState -> Annex a) -> Annex a
|
||||||
withExternalState external a = do
|
withExternalState external a = do
|
||||||
st <- get
|
st <- get
|
||||||
r <- a st `onException` liftIO (externalShutdown (externalAddonProcess st) True)
|
r <- a st `onException` liftIO (externalShutdown st True)
|
||||||
put st -- only when no exception is thrown
|
put st -- only when no exception is thrown
|
||||||
return r
|
return r
|
||||||
where
|
where
|
||||||
|
@ -597,9 +608,9 @@ startExternal external = do
|
||||||
n <- succ <$> readTVar (externalLastPid external)
|
n <- succ <$> readTVar (externalLastPid external)
|
||||||
writeTVar (externalLastPid external) n
|
writeTVar (externalLastPid external) n
|
||||||
return n
|
return n
|
||||||
startExternalAddonProcess basecmd pid >>= \case
|
AddonProcess.startExternalAddonProcess basecmd pid >>= \case
|
||||||
Left (ProgramFailure err) -> giveup err
|
Left (AddonProcess.ProgramFailure err) -> giveup err
|
||||||
Left (ProgramNotInstalled err) ->
|
Left (AddonProcess.ProgramNotInstalled err) ->
|
||||||
case (lookupName (unparsedRemoteConfig (externalDefaultConfig external)), remoteAnnexReadOnly <$> externalGitConfig external) of
|
case (lookupName (unparsedRemoteConfig (externalDefaultConfig external)), remoteAnnexReadOnly <$> externalGitConfig external) of
|
||||||
(Just rname, Just True) -> giveup $ unlines
|
(Just rname, Just True) -> giveup $ unlines
|
||||||
[ err
|
[ err
|
||||||
|
@ -614,7 +625,9 @@ startExternal external = do
|
||||||
ccv <- liftIO $ newTVarIO id
|
ccv <- liftIO $ newTVarIO id
|
||||||
pv <- liftIO $ newTVarIO Unprepared
|
pv <- liftIO $ newTVarIO Unprepared
|
||||||
let st = ExternalState
|
let st = ExternalState
|
||||||
{ externalAddonProcess = p
|
{ externalSend = sendMessageAddonProcess p
|
||||||
|
, externalReceive = receiveMessageAddonProcess p
|
||||||
|
, externalShutdown = shutdownAddonProcess p
|
||||||
, externalPrepared = pv
|
, externalPrepared = pv
|
||||||
, externalConfig = cv
|
, externalConfig = cv
|
||||||
, externalConfigChanges = ccv
|
, externalConfigChanges = ccv
|
||||||
|
@ -644,7 +657,7 @@ startExternal external = do
|
||||||
stopExternal :: External -> Annex ()
|
stopExternal :: External -> Annex ()
|
||||||
stopExternal external = liftIO $ do
|
stopExternal external = liftIO $ do
|
||||||
l <- atomically $ swapTVar (externalState external) []
|
l <- atomically $ swapTVar (externalState external) []
|
||||||
mapM_ (flip (externalShutdown . externalAddonProcess) False) l
|
mapM_ (flip externalShutdown False) l
|
||||||
|
|
||||||
checkVersion :: ExternalState -> RemoteRequest -> Maybe (Annex ())
|
checkVersion :: ExternalState -> RemoteRequest -> Maybe (Annex ())
|
||||||
checkVersion st (VERSION v) = Just $
|
checkVersion st (VERSION v) = Just $
|
||||||
|
|
16
Remote/External/Types.hs
vendored
16
Remote/External/Types.hs
vendored
|
@ -34,7 +34,6 @@ module Remote.External.Types (
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Annex.Common
|
import Annex.Common
|
||||||
import Annex.ExternalAddonProcess
|
|
||||||
import Types.StandardGroups (PreferredContentExpression)
|
import Types.StandardGroups (PreferredContentExpression)
|
||||||
import Utility.Metered (BytesProcessed(..))
|
import Utility.Metered (BytesProcessed(..))
|
||||||
import Types.Transfer (Direction(..))
|
import Types.Transfer (Direction(..))
|
||||||
|
@ -75,12 +74,15 @@ newExternal externaltype u c gc rs = liftIO $ External
|
||||||
|
|
||||||
type ExternalType = String
|
type ExternalType = String
|
||||||
|
|
||||||
data ExternalState = ExternalState
|
data ExternalState
|
||||||
{ externalAddonProcess :: ExternalAddonProcess
|
= ExternalState
|
||||||
, externalPrepared :: TVar PrepareStatus
|
{ externalSend :: String -> IO ()
|
||||||
, externalConfig :: TVar ParsedRemoteConfig
|
, externalReceive :: IO (Maybe String)
|
||||||
, externalConfigChanges :: TVar (RemoteConfig -> RemoteConfig)
|
, externalShutdown :: Bool -> IO ()
|
||||||
}
|
, externalPrepared :: TVar PrepareStatus
|
||||||
|
, externalConfig :: TVar ParsedRemoteConfig
|
||||||
|
, externalConfigChanges :: TVar (RemoteConfig -> RemoteConfig)
|
||||||
|
}
|
||||||
|
|
||||||
type PID = Int
|
type PID = Int
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue