support annex.jobs for clusters
This commit is contained in:
parent
818030e4d3
commit
cec2848e8a
6 changed files with 65 additions and 12 deletions
|
@ -53,9 +53,11 @@ proxyCluster clusteruuid proxydone servermode clientside protoerrhandler = do
|
||||||
-- nodes.
|
-- nodes.
|
||||||
let protocolversion = min maxProtocolVersion clientmaxversion
|
let protocolversion = min maxProtocolVersion clientmaxversion
|
||||||
selectnode <- clusterProxySelector clusteruuid protocolversion
|
selectnode <- clusterProxySelector clusteruuid protocolversion
|
||||||
|
concurrencyconfig <- getConcurrencyConfig
|
||||||
proxy proxydone proxymethods servermode clientside
|
proxy proxydone proxymethods servermode clientside
|
||||||
(fromClusterUUID clusteruuid)
|
(fromClusterUUID clusteruuid)
|
||||||
selectnode protocolversion othermsg protoerrhandler
|
selectnode concurrencyconfig protocolversion
|
||||||
|
othermsg protoerrhandler
|
||||||
withclientversion Nothing = proxydone
|
withclientversion Nothing = proxydone
|
||||||
|
|
||||||
clusterProxySelector :: ClusterUUID -> ProtocolVersion -> Annex ProxySelector
|
clusterProxySelector :: ClusterUUID -> ProtocolVersion -> Annex ProxySelector
|
||||||
|
|
|
@ -149,7 +149,7 @@ commandAction start = do
|
||||||
showEndMessage startmsg False
|
showEndMessage startmsg False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
{- Waits for all worker threads to finish and merges their AnnexStates
|
{- Waits for all worker thrneads to finish and merges their AnnexStates
|
||||||
- back into the current Annex's state.
|
- back into the current Annex's state.
|
||||||
-}
|
-}
|
||||||
finishCommandActions :: Annex ()
|
finishCommandActions :: Annex ()
|
||||||
|
|
|
@ -74,9 +74,11 @@ performProxy clientuuid servermode remote = do
|
||||||
let closer = do
|
let closer = do
|
||||||
closeRemoteSide remoteside
|
closeRemoteSide remoteside
|
||||||
p2pDone
|
p2pDone
|
||||||
|
concurrencyconfig <- noConcurrencyConfig
|
||||||
proxy closer proxymethods servermode clientside
|
proxy closer proxymethods servermode clientside
|
||||||
(Remote.uuid remote)
|
(Remote.uuid remote)
|
||||||
(singleProxySelector remoteside)
|
(singleProxySelector remoteside)
|
||||||
|
concurrencyconfig
|
||||||
protocolversion othermsg p2pErrHandler
|
protocolversion othermsg p2pErrHandler
|
||||||
withclientversion _ Nothing = p2pDone
|
withclientversion _ Nothing = p2pDone
|
||||||
|
|
||||||
|
|
53
P2P/Proxy.hs
53
P2P/Proxy.hs
|
@ -11,14 +11,20 @@
|
||||||
module P2P.Proxy where
|
module P2P.Proxy where
|
||||||
|
|
||||||
import Annex.Common
|
import Annex.Common
|
||||||
|
import qualified Annex
|
||||||
import P2P.Protocol
|
import P2P.Protocol
|
||||||
import P2P.IO
|
import P2P.IO
|
||||||
import Utility.Metered
|
import Utility.Metered
|
||||||
import Git.FilePath
|
import Git.FilePath
|
||||||
|
import Types.Concurrency
|
||||||
|
import Annex.Concurrent
|
||||||
|
|
||||||
import Data.Either
|
import Data.Either
|
||||||
import Control.Concurrent.STM
|
import Control.Concurrent.STM
|
||||||
|
import Control.Concurrent.Async
|
||||||
|
import qualified Control.Concurrent.MSem as MSem
|
||||||
import qualified Data.ByteString.Lazy as L
|
import qualified Data.ByteString.Lazy as L
|
||||||
|
import GHC.Conc
|
||||||
|
|
||||||
type ProtoCloser = Annex ()
|
type ProtoCloser = Annex ()
|
||||||
|
|
||||||
|
@ -141,6 +147,7 @@ proxy
|
||||||
-> ClientSide
|
-> ClientSide
|
||||||
-> UUID
|
-> UUID
|
||||||
-> ProxySelector
|
-> ProxySelector
|
||||||
|
-> ConcurrencyConfig
|
||||||
-> ProtocolVersion
|
-> ProtocolVersion
|
||||||
-- ^ Protocol version being spoken between the proxy and the
|
-- ^ Protocol version being spoken between the proxy and the
|
||||||
-- client. When there are multiple remotes, some may speak an
|
-- client. When there are multiple remotes, some may speak an
|
||||||
|
@ -149,7 +156,7 @@ proxy
|
||||||
-- ^ 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) remoteuuid proxyselector (ProtocolVersion protocolversion) othermessage protoerrhandler = do
|
proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remoteuuid proxyselector concurrencyconfig (ProtocolVersion protocolversion) othermessage protoerrhandler = do
|
||||||
case othermessage of
|
case othermessage of
|
||||||
Nothing -> protoerrhandler proxynextclientmessage $
|
Nothing -> protoerrhandler proxynextclientmessage $
|
||||||
client $ net $ sendMessage $ VERSION $ ProtocolVersion protocolversion
|
client $ net $ sendMessage $ VERSION $ ProtocolVersion protocolversion
|
||||||
|
@ -276,7 +283,7 @@ proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remo
|
||||||
protoerrhandler proxynextclientmessage $
|
protoerrhandler proxynextclientmessage $
|
||||||
client $ net $ sendMessage FAILURE
|
client $ net $ sendMessage FAILURE
|
||||||
handleREMOVE remotesides k message = do
|
handleREMOVE remotesides k message = do
|
||||||
v <- forM remotesides $ \r ->
|
v <- forMC concurrencyconfig remotesides $ \r ->
|
||||||
runRemoteSideOrSkipFailed r $ do
|
runRemoteSideOrSkipFailed r $ do
|
||||||
net $ sendMessage message
|
net $ sendMessage message
|
||||||
net receiveMessage >>= return . \case
|
net receiveMessage >>= return . \case
|
||||||
|
@ -370,7 +377,7 @@ proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remo
|
||||||
let alreadyhave = \case
|
let alreadyhave = \case
|
||||||
Right (Left _) -> True
|
Right (Left _) -> True
|
||||||
_ -> False
|
_ -> False
|
||||||
l <- forM remotesides initiate
|
l <- forMC concurrencyconfig remotesides initiate
|
||||||
if all alreadyhave l
|
if all alreadyhave l
|
||||||
then if protocolversion < 2
|
then if protocolversion < 2
|
||||||
then protoerrhandler proxynextclientmessage $
|
then protoerrhandler proxynextclientmessage $
|
||||||
|
@ -392,7 +399,7 @@ proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remo
|
||||||
let totallen = datalen + minoffset
|
let totallen = datalen + minoffset
|
||||||
-- Tell each remote how much data to expect, depending
|
-- Tell each remote how much data to expect, depending
|
||||||
-- on the remote's offset.
|
-- on the remote's offset.
|
||||||
rs <- forM remotes $ \remote@(remoteside, remoteoffset) ->
|
rs <- forMC concurrencyconfig remotes $ \remote@(remoteside, remoteoffset) ->
|
||||||
runRemoteSideOrSkipFailed remoteside $ do
|
runRemoteSideOrSkipFailed remoteside $ do
|
||||||
net $ sendMessage $ DATA $ Len $
|
net $ sendMessage $ DATA $ Len $
|
||||||
totallen - remoteoffset
|
totallen - remoteoffset
|
||||||
|
@ -409,7 +416,7 @@ proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remo
|
||||||
let (chunk, b') = L.splitAt chunksize b
|
let (chunk, b') = L.splitAt chunksize b
|
||||||
let chunklen = fromIntegral (L.length chunk)
|
let chunklen = fromIntegral (L.length chunk)
|
||||||
let !n' = n + chunklen
|
let !n' = n + chunklen
|
||||||
rs' <- forM rs $ \r@(remoteside, remoteoffset) ->
|
rs' <- forMC concurrencyconfig rs $ \r@(remoteside, remoteoffset) ->
|
||||||
if n >= remoteoffset
|
if n >= remoteoffset
|
||||||
then runRemoteSideOrSkipFailed remoteside $ do
|
then runRemoteSideOrSkipFailed remoteside $ do
|
||||||
net $ sendBytes (Len chunklen) chunk nullMeterUpdate
|
net $ sendBytes (Len chunklen) chunk nullMeterUpdate
|
||||||
|
@ -471,7 +478,7 @@ proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remo
|
||||||
net receiveMessage
|
net receiveMessage
|
||||||
where
|
where
|
||||||
finish a = do
|
finish a = do
|
||||||
storeduuids <- forM rs $ \r ->
|
storeduuids <- forMC concurrencyconfig rs $ \r ->
|
||||||
runRemoteSideOrSkipFailed r a >>= \case
|
runRemoteSideOrSkipFailed r a >>= \case
|
||||||
Just (Just resp) ->
|
Just (Just resp) ->
|
||||||
relayPUTRecord k r resp
|
relayPUTRecord k r resp
|
||||||
|
@ -492,3 +499,37 @@ proxy proxydone proxymethods servermode (ClientSide clientrunst clientconn) remo
|
||||||
<$> fromRepo (fromTopFilePath (asTopFilePath f))
|
<$> fromRepo (fromTopFilePath (asTopFilePath f))
|
||||||
getassociatedfile (ProtoAssociatedFile (AssociatedFile Nothing)) =
|
getassociatedfile (ProtoAssociatedFile (AssociatedFile Nothing)) =
|
||||||
return $ AssociatedFile Nothing
|
return $ AssociatedFile Nothing
|
||||||
|
|
||||||
|
data ConcurrencyConfig = ConcurrencyConfig Int (MSem.MSem Int)
|
||||||
|
|
||||||
|
noConcurrencyConfig :: Annex ConcurrencyConfig
|
||||||
|
noConcurrencyConfig = liftIO $ ConcurrencyConfig 1 <$> MSem.new 1
|
||||||
|
|
||||||
|
getConcurrencyConfig :: Annex ConcurrencyConfig
|
||||||
|
getConcurrencyConfig = (annexJobs <$> Annex.getGitConfig) >>= \case
|
||||||
|
NonConcurrent -> noConcurrencyConfig
|
||||||
|
Concurrent n -> go n
|
||||||
|
ConcurrentPerCpu -> go =<< liftIO getNumProcessors
|
||||||
|
where
|
||||||
|
go n = do
|
||||||
|
c <- liftIO getNumCapabilities
|
||||||
|
when (n > c) $
|
||||||
|
liftIO $ setNumCapabilities n
|
||||||
|
setConcurrency (ConcurrencyGitConfig (Concurrent n))
|
||||||
|
msem <- liftIO $ MSem.new n
|
||||||
|
return (ConcurrencyConfig n msem)
|
||||||
|
|
||||||
|
forMC :: ConcurrencyConfig -> [a] -> (a -> Annex b) -> Annex [b]
|
||||||
|
forMC _ (x:[]) a = do
|
||||||
|
r <- a x
|
||||||
|
return [r]
|
||||||
|
forMC (ConcurrencyConfig n msem) xs a
|
||||||
|
| n < 2 = forM xs a
|
||||||
|
| otherwise = do
|
||||||
|
runners <- forM xs $ \x ->
|
||||||
|
forkState $ bracketIO
|
||||||
|
(MSem.wait msem)
|
||||||
|
(const $ MSem.signal msem)
|
||||||
|
(const $ a x)
|
||||||
|
mapM id =<< liftIO (forConcurrently runners id)
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,13 @@ in the git-annex branch. That tells other repositories about the cluster.
|
||||||
Started proxying for node2
|
Started proxying for node2
|
||||||
Started proxying for node3
|
Started proxying for node3
|
||||||
|
|
||||||
|
Operations that affect multiple nodes of a cluster can often be sped up by
|
||||||
|
configuring annex.jobs in the repository that will serve the cluster to
|
||||||
|
clients. In the example above, the nodes are all disk bound, so operating
|
||||||
|
on more than one at a time will likely be faster.
|
||||||
|
|
||||||
|
$ git config annex.jobs cpus
|
||||||
|
|
||||||
## preferred content of clusters
|
## preferred content of clusters
|
||||||
|
|
||||||
The preferred content of the cluster can be configured. This tells
|
The preferred content of the cluster can be configured. This tells
|
||||||
|
@ -94,8 +101,8 @@ to do the configuration in a repository that has the cluster as a remote.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
git-annex wanted bigserver-mycluster standard
|
$ git-annex wanted bigserver-mycluster standard
|
||||||
git-annex group bigserver-mycluster archive
|
$ git-annex group bigserver-mycluster archive
|
||||||
|
|
||||||
By default, when a file is uploaded to a cluster, it is stored on every node of
|
By default, when a file is uploaded to a cluster, it is stored on every node of
|
||||||
the cluster. To control which nodes to store to, the [[preferred_content]] of
|
the cluster. To control which nodes to store to, the [[preferred_content]] of
|
||||||
|
|
|
@ -31,8 +31,6 @@ For June's work on [[design/passthrough_proxy]], remaining todos:
|
||||||
round-robin amoung remotes, and prefer to avoid using remotes that
|
round-robin amoung remotes, and prefer to avoid using remotes that
|
||||||
other git-annex processes are currently using.
|
other git-annex processes are currently using.
|
||||||
|
|
||||||
* Support annex.jobs for clusters.
|
|
||||||
|
|
||||||
* Basic proxying to special remote support (non-streaming).
|
* Basic proxying to special remote support (non-streaming).
|
||||||
|
|
||||||
* Support proxies-of-proxies better, eg foo-bar-baz.
|
* Support proxies-of-proxies better, eg foo-bar-baz.
|
||||||
|
@ -104,3 +102,6 @@ For June's work on [[design/passthrough_proxy]], remaining todos:
|
||||||
|
|
||||||
* On upload to cluster, send to nodes where its preferred content, and not
|
* On upload to cluster, send to nodes where its preferred content, and not
|
||||||
to other nodes. (done)
|
to other nodes. (done)
|
||||||
|
|
||||||
|
* Support annex.jobs for clusters. (done)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue