preparing for cluster node selection
Support selecting what remote to proxy for each top-level P2P protocol message. This only needs to be extended now to support fanout to multiple nodes for PUT and REMOVE, and with a remote that fails for LOCKCONTENT and UNLOCKCONTENT. But a good first step would be to implement CHECKPRESENT and GET for clusters. Both should select a node that actually does have the content. That will allow a cluster to work for GET even when location tracking is out of date.
This commit is contained in:
parent
291280ced2
commit
7a839a983a
2 changed files with 89 additions and 72 deletions
|
@ -67,15 +67,17 @@ performProxy clientuuid servermode remote = do
|
||||||
where
|
where
|
||||||
withclientversion clientside (Just (clientmaxversion, othermsg)) = do
|
withclientversion clientside (Just (clientmaxversion, othermsg)) = do
|
||||||
remoteside <- proxySshRemoteSide clientmaxversion remote
|
remoteside <- proxySshRemoteSide clientmaxversion remote
|
||||||
proxy p2pDone proxymethods servermode clientside remoteside
|
protocolversion <- either (const (min P2P.maxProtocolVersion clientmaxversion)) id
|
||||||
othermsg p2pErrHandler
|
<$> runRemoteSide remoteside
|
||||||
|
(P2P.net P2P.getProtocolVersion)
|
||||||
|
let closer = do
|
||||||
|
closeRemoteSide remoteside
|
||||||
|
p2pDone
|
||||||
|
proxy closer proxyMethods servermode clientside
|
||||||
|
(const $ return remoteside)
|
||||||
|
protocolversion othermsg p2pErrHandler
|
||||||
withclientversion _ Nothing = p2pDone
|
withclientversion _ Nothing = p2pDone
|
||||||
|
|
||||||
proxymethods = ProxyMethods
|
|
||||||
{ removedContent = \u k -> logChange k u InfoMissing
|
|
||||||
, addedContent = \u k -> logChange k u InfoPresent
|
|
||||||
}
|
|
||||||
|
|
||||||
performProxyCluster :: UUID -> ClusterUUID -> P2P.ServerMode -> CommandPerform
|
performProxyCluster :: UUID -> ClusterUUID -> P2P.ServerMode -> CommandPerform
|
||||||
performProxyCluster clientuuid clusteruuid servermode = do
|
performProxyCluster clientuuid clusteruuid servermode = do
|
||||||
clientside <- proxyClientSide clientuuid
|
clientside <- proxyClientSide clientuuid
|
||||||
|
@ -84,9 +86,18 @@ performProxyCluster clientuuid clusteruuid servermode = do
|
||||||
p2pErrHandler
|
p2pErrHandler
|
||||||
where
|
where
|
||||||
withclientversion clientside (Just (clientmaxversion, othermsg)) = do
|
withclientversion clientside (Just (clientmaxversion, othermsg)) = do
|
||||||
giveup "TODO"
|
let protocolversion = min P2P.maxProtocolVersion clientmaxversion
|
||||||
|
let selectnode = giveup "FIXME" -- FIXME
|
||||||
|
proxy p2pDone proxyMethods servermode clientside selectnode
|
||||||
|
protocolversion othermsg p2pErrHandler
|
||||||
withclientversion _ Nothing = p2pDone
|
withclientversion _ Nothing = p2pDone
|
||||||
|
|
||||||
|
proxyMethods :: ProxyMethods
|
||||||
|
proxyMethods = ProxyMethods
|
||||||
|
{ removedContent = \u k -> logChange k u InfoMissing
|
||||||
|
, addedContent = \u k -> logChange k u InfoPresent
|
||||||
|
}
|
||||||
|
|
||||||
proxyClientSide :: UUID -> Annex ClientSide
|
proxyClientSide :: UUID -> Annex ClientSide
|
||||||
proxyClientSide clientuuid = do
|
proxyClientSide clientuuid = do
|
||||||
clientrunst <- liftIO (mkRunState $ Serving clientuuid Nothing)
|
clientrunst <- liftIO (mkRunState $ Serving clientuuid Nothing)
|
||||||
|
|
122
P2P/Proxy.hs
122
P2P/Proxy.hs
|
@ -32,6 +32,24 @@ mkRemoteSide remoteuuid remoteconnect = RemoteSide
|
||||||
<*> pure remoteconnect
|
<*> pure remoteconnect
|
||||||
<*> liftIO (atomically newEmptyTMVar)
|
<*> liftIO (atomically newEmptyTMVar)
|
||||||
|
|
||||||
|
runRemoteSide :: RemoteSide -> Proto a -> Annex (Either ProtoFailure a)
|
||||||
|
runRemoteSide remoteside a =
|
||||||
|
liftIO (atomically $ tryReadTMVar $ remoteTMVar remoteside) >>= \case
|
||||||
|
Just (runst, conn, _closer) -> liftIO $ runNetProto runst conn a
|
||||||
|
Nothing -> remoteConnect remoteside >>= \case
|
||||||
|
Just (runst, conn, closer) -> do
|
||||||
|
liftIO $ atomically $ putTMVar
|
||||||
|
(remoteTMVar remoteside)
|
||||||
|
(runst, conn, closer)
|
||||||
|
liftIO $ runNetProto runst conn a
|
||||||
|
Nothing -> giveup "Unable to connect to remote."
|
||||||
|
|
||||||
|
closeRemoteSide :: RemoteSide -> Annex ()
|
||||||
|
closeRemoteSide remoteside =
|
||||||
|
liftIO (atomically $ tryReadTMVar $ remoteTMVar remoteside) >>= \case
|
||||||
|
Just (_, _, closer) -> closer
|
||||||
|
Nothing -> return ()
|
||||||
|
|
||||||
{- To keep this module limited to P2P protocol actions,
|
{- To keep this module limited to P2P protocol actions,
|
||||||
- all other actions that a proxy needs to do are provided
|
- all other actions that a proxy needs to do are provided
|
||||||
- here. -}
|
- here. -}
|
||||||
|
@ -95,42 +113,20 @@ proxy
|
||||||
-> ProxyMethods
|
-> ProxyMethods
|
||||||
-> ServerMode
|
-> ServerMode
|
||||||
-> ClientSide
|
-> ClientSide
|
||||||
-> RemoteSide
|
-> (Message -> Annex RemoteSide)
|
||||||
|
-> ProtocolVersion
|
||||||
-> Maybe Message
|
-> Maybe Message
|
||||||
-- ^ non-VERSION message that was received from the client when
|
-- ^ non-VERSION message that was received from the client when
|
||||||
-- negotiating protocol version, and has not been responded to yet
|
-- negotiating protocol version, and has not been responded to yet
|
||||||
-> ProtoErrorHandled r
|
-> ProtoErrorHandled r
|
||||||
proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remoteside othermessage protoerrhandler = do
|
proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) getremoteside protocolversion othermessage protoerrhandler = do
|
||||||
case othermessage of
|
case othermessage of
|
||||||
|
Nothing -> protoerrhandler proxynextclientmessage $
|
||||||
|
client $ net $ sendMessage $ VERSION protocolversion
|
||||||
Just message -> proxyclientmessage (Just message)
|
Just message -> proxyclientmessage (Just message)
|
||||||
Nothing -> do
|
|
||||||
v <- protocolversion
|
|
||||||
protoerrhandler proxynextclientmessage $
|
|
||||||
client $ net $ sendMessage $ VERSION v
|
|
||||||
where
|
where
|
||||||
client = liftIO . runNetProto clientrunst clientconn
|
client = liftIO . runNetProto clientrunst clientconn
|
||||||
|
|
||||||
remote a = liftIO (atomically $ tryReadTMVar $ remoteTMVar remoteside) >>= \case
|
|
||||||
Just (runst, conn, _closer) -> liftIO $ runNetProto runst conn a
|
|
||||||
Nothing -> remoteConnect remoteside >>= \case
|
|
||||||
Just (runst, conn, closer) -> do
|
|
||||||
liftIO $ atomically $ putTMVar
|
|
||||||
(remoteTMVar remoteside)
|
|
||||||
(runst, conn, closer)
|
|
||||||
liftIO $ runNetProto runst conn a
|
|
||||||
Nothing -> giveup "Unable to connect to remote."
|
|
||||||
|
|
||||||
closeremote = liftIO (atomically $ tryReadTMVar $ remoteTMVar remoteside) >>= \case
|
|
||||||
Just (_, _, closer) -> closer
|
|
||||||
Nothing -> return ()
|
|
||||||
|
|
||||||
proxydone' = do
|
|
||||||
closeremote
|
|
||||||
proxydone
|
|
||||||
|
|
||||||
protocolversion = either (const defaultProtocolVersion) id
|
|
||||||
<$> remote (net getProtocolVersion)
|
|
||||||
|
|
||||||
proxynextclientmessage () = protoerrhandler proxyclientmessage $
|
proxynextclientmessage () = protoerrhandler proxyclientmessage $
|
||||||
client (net receiveMessage)
|
client (net receiveMessage)
|
||||||
|
|
||||||
|
@ -140,21 +136,28 @@ proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remo
|
||||||
protoerrhandler proxynextclientmessage $
|
protoerrhandler proxynextclientmessage $
|
||||||
client notallowed
|
client notallowed
|
||||||
|
|
||||||
proxyclientmessage Nothing = proxydone'
|
proxyclientmessage Nothing = proxydone
|
||||||
proxyclientmessage (Just message) = case message of
|
proxyclientmessage (Just message) = case message of
|
||||||
CHECKPRESENT _ ->
|
CHECKPRESENT _ -> do
|
||||||
proxyresponse message (const proxynextclientmessage)
|
remoteside <- getremoteside message
|
||||||
LOCKCONTENT _ ->
|
proxyresponse remoteside message (const proxynextclientmessage)
|
||||||
proxyresponse message (const proxynextclientmessage)
|
LOCKCONTENT _ -> do
|
||||||
UNLOCKCONTENT ->
|
remoteside <- getremoteside message
|
||||||
proxynoresponse message proxynextclientmessage
|
proxyresponse remoteside message (const proxynextclientmessage)
|
||||||
REMOVE k ->
|
UNLOCKCONTENT -> do
|
||||||
|
remoteside <- getremoteside message
|
||||||
|
proxynoresponse remoteside message proxynextclientmessage
|
||||||
|
REMOVE k -> do
|
||||||
|
remoteside <- getremoteside message
|
||||||
servermodechecker checkREMOVEServerMode $
|
servermodechecker checkREMOVEServerMode $
|
||||||
handleREMOVE k message
|
handleREMOVE remoteside k message
|
||||||
GET _ _ _ -> handleGET message
|
GET _ _ _ -> do
|
||||||
PUT _ k ->
|
remoteside <- getremoteside message
|
||||||
|
handleGET remoteside message
|
||||||
|
PUT _ k -> do
|
||||||
|
remoteside <- getremoteside message
|
||||||
servermodechecker checkPUTServerMode $
|
servermodechecker checkPUTServerMode $
|
||||||
handlePUT k message
|
handlePUT remoteside k message
|
||||||
-- These messages involve the git repository, not the
|
-- These messages involve the git repository, not the
|
||||||
-- annex. So they affect the git repository of the proxy,
|
-- annex. So they affect the git repository of the proxy,
|
||||||
-- not the remote.
|
-- not the remote.
|
||||||
|
@ -162,7 +165,7 @@ proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remo
|
||||||
servermodechecker (checkCONNECTServerMode service) $
|
servermodechecker (checkCONNECTServerMode service) $
|
||||||
-- P2P protocol does not continue after
|
-- P2P protocol does not continue after
|
||||||
-- relaying from git.
|
-- relaying from git.
|
||||||
protoerrhandler (\() -> proxydone') $
|
protoerrhandler (\() -> proxydone) $
|
||||||
client $ net $ relayService service
|
client $ net $ relayService service
|
||||||
NOTIFYCHANGE -> protoerr
|
NOTIFYCHANGE -> protoerr
|
||||||
-- Messages that the client should only send after one of
|
-- Messages that the client should only send after one of
|
||||||
|
@ -186,14 +189,15 @@ proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remo
|
||||||
|
|
||||||
-- Send a message to the remote, send its response back to the
|
-- Send a message to the remote, send its response back to the
|
||||||
-- client, and pass it to the continuation.
|
-- client, and pass it to the continuation.
|
||||||
proxyresponse message a = getresponse remote message $ \resp ->
|
proxyresponse remoteside message a =
|
||||||
|
getresponse (runRemoteSide remoteside) message $ \resp ->
|
||||||
protoerrhandler (a resp) $
|
protoerrhandler (a resp) $
|
||||||
client $ net $ sendMessage resp
|
client $ net $ sendMessage resp
|
||||||
|
|
||||||
-- Send a message to the remote, that it will not respond to.
|
-- Send a message to the remote, that it will not respond to.
|
||||||
proxynoresponse message a =
|
proxynoresponse remoteside message a =
|
||||||
protoerrhandler a $
|
protoerrhandler a $
|
||||||
remote $ net $ sendMessage message
|
runRemoteSide remoteside $ net $ sendMessage message
|
||||||
|
|
||||||
-- Send a message to the endpoint and get back its response.
|
-- Send a message to the endpoint and get back its response.
|
||||||
getresponse endpoint message handleresp =
|
getresponse endpoint message handleresp =
|
||||||
|
@ -205,7 +209,7 @@ proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remo
|
||||||
withresp a (Just resp) = a resp
|
withresp a (Just resp) = a resp
|
||||||
-- Whichever of the remote or client the message was read from
|
-- Whichever of the remote or client the message was read from
|
||||||
-- hung up.
|
-- hung up.
|
||||||
withresp _ Nothing = proxydone'
|
withresp _ Nothing = proxydone
|
||||||
|
|
||||||
-- Read a message from one party, send it to the other,
|
-- Read a message from one party, send it to the other,
|
||||||
-- and then pass the message to the continuation.
|
-- and then pass the message to the continuation.
|
||||||
|
@ -219,36 +223,38 @@ proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remo
|
||||||
_ <- client $ net $ sendMessage (ERROR "protocol error")
|
_ <- client $ net $ sendMessage (ERROR "protocol error")
|
||||||
giveup "protocol error"
|
giveup "protocol error"
|
||||||
|
|
||||||
handleREMOVE k message =
|
handleREMOVE remoteside k message =
|
||||||
proxyresponse message $ \resp () -> do
|
proxyresponse remoteside message $ \resp () -> do
|
||||||
case resp of
|
case resp of
|
||||||
SUCCESS -> removedContent proxymethods
|
SUCCESS -> removedContent proxymethods
|
||||||
(remoteUUID remoteside) k
|
(remoteUUID remoteside) k
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
proxynextclientmessage ()
|
proxynextclientmessage ()
|
||||||
|
|
||||||
handleGET message = getresponse remote message $ withDATA relayGET
|
handleGET remoteside message = getresponse (runRemoteSide remoteside) message $
|
||||||
|
withDATA (relayGET remoteside)
|
||||||
|
|
||||||
handlePUT k message = getresponse remote message $ \resp -> case resp of
|
handlePUT remoteside k message =
|
||||||
|
getresponse (runRemoteSide remoteside) message $ \resp -> case resp of
|
||||||
ALREADY_HAVE -> protoerrhandler proxynextclientmessage $
|
ALREADY_HAVE -> protoerrhandler proxynextclientmessage $
|
||||||
client $ net $ sendMessage resp
|
client $ net $ sendMessage resp
|
||||||
PUT_FROM _ ->
|
PUT_FROM _ ->
|
||||||
getresponse client resp $ withDATA (relayPUT k)
|
getresponse client resp $ withDATA (relayPUT remoteside k)
|
||||||
_ -> protoerr
|
_ -> protoerr
|
||||||
|
|
||||||
withDATA a message@(DATA len) = a len message
|
withDATA a message@(DATA len) = a len message
|
||||||
withDATA _ _ = protoerr
|
withDATA _ _ = protoerr
|
||||||
|
|
||||||
relayGET len = relayDATAStart client $
|
relayGET remoteside len = relayDATAStart client $
|
||||||
relayDATACore len remote client $
|
relayDATACore len (runRemoteSide remoteside) client $
|
||||||
relayDATAFinish remote client $
|
relayDATAFinish (runRemoteSide remoteside) client $
|
||||||
relayonemessage client remote $
|
relayonemessage client (runRemoteSide remoteside) $
|
||||||
const proxynextclientmessage
|
const proxynextclientmessage
|
||||||
|
|
||||||
relayPUT k len = relayDATAStart remote $
|
relayPUT remoteside k len = relayDATAStart (runRemoteSide remoteside) $
|
||||||
relayDATACore len client remote $
|
relayDATACore len client (runRemoteSide remoteside) $
|
||||||
relayDATAFinish client remote $
|
relayDATAFinish client (runRemoteSide remoteside) $
|
||||||
relayonemessage remote client finished
|
relayonemessage (runRemoteSide remoteside) client finished
|
||||||
where
|
where
|
||||||
finished resp () = do
|
finished resp () = do
|
||||||
case resp of
|
case resp of
|
||||||
|
@ -266,7 +272,7 @@ proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remo
|
||||||
send b = protoerrhandler finishget $
|
send b = protoerrhandler finishget $
|
||||||
y $ net $ sendBytes len b nullMeterUpdate
|
y $ net $ sendBytes len b nullMeterUpdate
|
||||||
|
|
||||||
relayDATAFinish x y sendsuccessfailure () = protocolversion >>= \case
|
relayDATAFinish x y sendsuccessfailure () = case protocolversion of
|
||||||
ProtocolVersion 0 -> sendsuccessfailure
|
ProtocolVersion 0 -> sendsuccessfailure
|
||||||
-- Protocol version 1 has a VALID or
|
-- Protocol version 1 has a VALID or
|
||||||
-- INVALID message after the data.
|
-- INVALID message after the data.
|
||||||
|
|
Loading…
Reference in a new issue