queue Uploads of newly added files to remotes
Added knownRemotes to DaemonStatus. This list is not entirely trivial to calculate, and having it here should make it easier to add/remove remotes on the fly later on. It did require plumbing the daemonstatus through to some more threads.
This commit is contained in:
parent
b0894f00c0
commit
83c66ccaf8
5 changed files with 58 additions and 27 deletions
|
@ -21,7 +21,8 @@
|
||||||
- until this is complete.
|
- until this is complete.
|
||||||
- Thread 5: committer
|
- Thread 5: committer
|
||||||
- Waits for changes to occur, and runs the git queue to update its
|
- Waits for changes to occur, and runs the git queue to update its
|
||||||
- index, then commits.
|
- index, then commits. Also queues Transfer events to send added
|
||||||
|
- files to other remotes.
|
||||||
- Thread 6: pusher
|
- Thread 6: pusher
|
||||||
- Waits for commits to be made, and pushes updated branches to remotes,
|
- Waits for commits to be made, and pushes updated branches to remotes,
|
||||||
- in parallel. (Forks a process for each git push.)
|
- in parallel. (Forks a process for each git push.)
|
||||||
|
@ -73,6 +74,7 @@ import Assistant.DaemonStatus
|
||||||
import Assistant.Changes
|
import Assistant.Changes
|
||||||
import Assistant.Commits
|
import Assistant.Commits
|
||||||
import Assistant.Pushes
|
import Assistant.Pushes
|
||||||
|
import Assistant.TransferQueue
|
||||||
import Assistant.Threads.Watcher
|
import Assistant.Threads.Watcher
|
||||||
import Assistant.Threads.Committer
|
import Assistant.Threads.Committer
|
||||||
import Assistant.Threads.Pusher
|
import Assistant.Threads.Pusher
|
||||||
|
@ -103,9 +105,10 @@ startDaemon assistant foreground
|
||||||
changechan <- newChangeChan
|
changechan <- newChangeChan
|
||||||
commitchan <- newCommitChan
|
commitchan <- newCommitChan
|
||||||
pushmap <- newFailedPushMap
|
pushmap <- newFailedPushMap
|
||||||
|
transferqueue <- newTransferQueue
|
||||||
mapM_ (void . forkIO)
|
mapM_ (void . forkIO)
|
||||||
[ commitThread st changechan commitchan
|
[ commitThread st changechan commitchan transferqueue dstatus
|
||||||
, pushThread st commitchan pushmap
|
, pushThread st dstatus commitchan pushmap
|
||||||
, pushRetryThread st pushmap
|
, pushRetryThread st pushmap
|
||||||
, mergeThread st
|
, mergeThread st
|
||||||
, transferWatcherThread st dstatus
|
, transferWatcherThread st dstatus
|
||||||
|
|
|
@ -11,13 +11,14 @@ import Common.Annex
|
||||||
import Assistant.ThreadedMonad
|
import Assistant.ThreadedMonad
|
||||||
import Utility.ThreadScheduler
|
import Utility.ThreadScheduler
|
||||||
import Utility.TempFile
|
import Utility.TempFile
|
||||||
|
import Logs.Transfer
|
||||||
|
import qualified Command.Sync
|
||||||
|
|
||||||
import Control.Concurrent
|
import Control.Concurrent
|
||||||
import System.Posix.Types
|
import System.Posix.Types
|
||||||
import Data.Time.Clock.POSIX
|
import Data.Time.Clock.POSIX
|
||||||
import Data.Time
|
import Data.Time
|
||||||
import System.Locale
|
import System.Locale
|
||||||
import Logs.Transfer
|
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
|
|
||||||
data DaemonStatus = DaemonStatus
|
data DaemonStatus = DaemonStatus
|
||||||
|
@ -31,6 +32,8 @@ data DaemonStatus = DaemonStatus
|
||||||
, lastSanityCheck :: Maybe POSIXTime
|
, lastSanityCheck :: Maybe POSIXTime
|
||||||
-- Currently running file content transfers
|
-- Currently running file content transfers
|
||||||
, currentTransfers :: M.Map Transfer TransferInfo
|
, currentTransfers :: M.Map Transfer TransferInfo
|
||||||
|
-- Ordered list of remotes to talk to.
|
||||||
|
, knownRemotes :: [Remote]
|
||||||
}
|
}
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
|
@ -43,6 +46,7 @@ newDaemonStatus = DaemonStatus
|
||||||
, sanityCheckRunning = False
|
, sanityCheckRunning = False
|
||||||
, lastSanityCheck = Nothing
|
, lastSanityCheck = Nothing
|
||||||
, currentTransfers = M.empty
|
, currentTransfers = M.empty
|
||||||
|
, knownRemotes = []
|
||||||
}
|
}
|
||||||
|
|
||||||
getDaemonStatus :: DaemonStatusHandle -> Annex DaemonStatus
|
getDaemonStatus :: DaemonStatusHandle -> Annex DaemonStatus
|
||||||
|
@ -59,10 +63,12 @@ startDaemonStatus = do
|
||||||
status <- liftIO $
|
status <- liftIO $
|
||||||
catchDefaultIO (readDaemonStatusFile file) newDaemonStatus
|
catchDefaultIO (readDaemonStatusFile file) newDaemonStatus
|
||||||
transfers <- M.fromList <$> getTransfers
|
transfers <- M.fromList <$> getTransfers
|
||||||
|
remotes <- Command.Sync.syncRemotes []
|
||||||
liftIO $ newMVar status
|
liftIO $ newMVar status
|
||||||
{ scanComplete = False
|
{ scanComplete = False
|
||||||
, sanityCheckRunning = False
|
, sanityCheckRunning = False
|
||||||
, currentTransfers = transfers
|
, currentTransfers = transfers
|
||||||
|
, knownRemotes = remotes
|
||||||
}
|
}
|
||||||
|
|
||||||
{- This thread wakes up periodically and writes the daemon status to disk. -}
|
{- This thread wakes up periodically and writes the daemon status to disk. -}
|
||||||
|
|
|
@ -12,6 +12,9 @@ import Assistant.Changes
|
||||||
import Assistant.Commits
|
import Assistant.Commits
|
||||||
import Assistant.ThreadedMonad
|
import Assistant.ThreadedMonad
|
||||||
import Assistant.Threads.Watcher
|
import Assistant.Threads.Watcher
|
||||||
|
import Assistant.TransferQueue
|
||||||
|
import Assistant.DaemonStatus
|
||||||
|
import Logs.Transfer
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import qualified Annex.Queue
|
import qualified Annex.Queue
|
||||||
import qualified Git.Command
|
import qualified Git.Command
|
||||||
|
@ -29,8 +32,8 @@ import qualified Data.Set as S
|
||||||
import Data.Either
|
import Data.Either
|
||||||
|
|
||||||
{- This thread makes git commits at appropriate times. -}
|
{- This thread makes git commits at appropriate times. -}
|
||||||
commitThread :: ThreadState -> ChangeChan -> CommitChan -> IO ()
|
commitThread :: ThreadState -> ChangeChan -> CommitChan -> TransferQueue -> DaemonStatusHandle -> IO ()
|
||||||
commitThread st changechan commitchan = runEvery (Seconds 1) $ do
|
commitThread st changechan commitchan transferqueue dstatus = runEvery (Seconds 1) $ do
|
||||||
-- We already waited one second as a simple rate limiter.
|
-- We already waited one second as a simple rate limiter.
|
||||||
-- Next, wait until at least one change is available for
|
-- Next, wait until at least one change is available for
|
||||||
-- processing.
|
-- processing.
|
||||||
|
@ -39,7 +42,7 @@ commitThread st changechan commitchan = runEvery (Seconds 1) $ do
|
||||||
time <- getCurrentTime
|
time <- getCurrentTime
|
||||||
if shouldCommit time changes
|
if shouldCommit time changes
|
||||||
then do
|
then do
|
||||||
readychanges <- handleAdds st changechan changes
|
readychanges <- handleAdds st changechan transferqueue dstatus changes
|
||||||
if shouldCommit time readychanges
|
if shouldCommit time readychanges
|
||||||
then do
|
then do
|
||||||
void $ tryIO $ runThreadState st commitStaged
|
void $ tryIO $ runThreadState st commitStaged
|
||||||
|
@ -97,8 +100,8 @@ shouldCommit now changes
|
||||||
- Any pending adds that are not ready yet are put back into the ChangeChan,
|
- Any pending adds that are not ready yet are put back into the ChangeChan,
|
||||||
- where they will be retried later.
|
- where they will be retried later.
|
||||||
-}
|
-}
|
||||||
handleAdds :: ThreadState -> ChangeChan -> [Change] -> IO [Change]
|
handleAdds :: ThreadState -> ChangeChan -> TransferQueue -> DaemonStatusHandle -> [Change] -> IO [Change]
|
||||||
handleAdds st changechan cs = returnWhen (null pendingadds) $ do
|
handleAdds st changechan transferqueue dstatus cs = returnWhen (null pendingadds) $ do
|
||||||
(postponed, toadd) <- partitionEithers <$>
|
(postponed, toadd) <- partitionEithers <$>
|
||||||
safeToAdd st pendingadds
|
safeToAdd st pendingadds
|
||||||
|
|
||||||
|
@ -110,7 +113,7 @@ handleAdds st changechan cs = returnWhen (null pendingadds) $ do
|
||||||
if (DirWatcher.eventsCoalesce || null added)
|
if (DirWatcher.eventsCoalesce || null added)
|
||||||
then return $ added ++ otherchanges
|
then return $ added ++ otherchanges
|
||||||
else do
|
else do
|
||||||
r <- handleAdds st changechan
|
r <- handleAdds st changechan transferqueue dstatus
|
||||||
=<< getChanges changechan
|
=<< getChanges changechan
|
||||||
return $ r ++ added ++ otherchanges
|
return $ r ++ added ++ otherchanges
|
||||||
where
|
where
|
||||||
|
@ -121,12 +124,12 @@ handleAdds st changechan cs = returnWhen (null pendingadds) $ do
|
||||||
| otherwise = a
|
| otherwise = a
|
||||||
|
|
||||||
add :: Change -> IO (Maybe Change)
|
add :: Change -> IO (Maybe Change)
|
||||||
add change@(PendingAddChange { keySource = ks }) = do
|
add change@(PendingAddChange { keySource = ks }) =
|
||||||
r <- catchMaybeIO $ sanitycheck ks $ runThreadState st $ do
|
liftM maybeMaybe $ catchMaybeIO $
|
||||||
showStart "add" $ keyFilename ks
|
sanitycheck ks $ runThreadState st $ do
|
||||||
handle (finishedChange change) (keyFilename ks)
|
showStart "add" $ keyFilename ks
|
||||||
=<< Command.Add.ingest ks
|
key <- Command.Add.ingest ks
|
||||||
return $ maybeMaybe r
|
handle (finishedChange change) (keyFilename ks) key
|
||||||
add _ = return Nothing
|
add _ = return Nothing
|
||||||
|
|
||||||
maybeMaybe (Just j@(Just _)) = j
|
maybeMaybe (Just j@(Just _)) = j
|
||||||
|
@ -141,6 +144,7 @@ handleAdds st changechan cs = returnWhen (null pendingadds) $ do
|
||||||
sha <- inRepo $
|
sha <- inRepo $
|
||||||
Git.HashObject.hashObject BlobObject link
|
Git.HashObject.hashObject BlobObject link
|
||||||
stageSymlink file sha
|
stageSymlink file sha
|
||||||
|
queueTransfers transferqueue dstatus key (Just file) Upload
|
||||||
showEndOk
|
showEndOk
|
||||||
return $ Just change
|
return $ Just change
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ module Assistant.Threads.Pusher where
|
||||||
import Common.Annex
|
import Common.Annex
|
||||||
import Assistant.Commits
|
import Assistant.Commits
|
||||||
import Assistant.Pushes
|
import Assistant.Pushes
|
||||||
|
import Assistant.DaemonStatus
|
||||||
import Assistant.ThreadedMonad
|
import Assistant.ThreadedMonad
|
||||||
import Assistant.Threads.Merger
|
import Assistant.Threads.Merger
|
||||||
import qualified Command.Sync
|
import qualified Command.Sync
|
||||||
|
@ -32,9 +33,8 @@ pushRetryThread st pushmap = runEvery (Seconds halfhour) $ do
|
||||||
halfhour = 1800
|
halfhour = 1800
|
||||||
|
|
||||||
{- This thread pushes git commits out to remotes soon after they are made. -}
|
{- This thread pushes git commits out to remotes soon after they are made. -}
|
||||||
pushThread :: ThreadState -> CommitChan -> FailedPushMap -> IO ()
|
pushThread :: ThreadState -> DaemonStatusHandle -> CommitChan -> FailedPushMap -> IO ()
|
||||||
pushThread st commitchan pushmap = do
|
pushThread st daemonstatus commitchan pushmap = do
|
||||||
remotes <- runThreadState st $ Command.Sync.syncRemotes []
|
|
||||||
runEvery (Seconds 2) $ do
|
runEvery (Seconds 2) $ do
|
||||||
-- We already waited two seconds as a simple rate limiter.
|
-- We already waited two seconds as a simple rate limiter.
|
||||||
-- Next, wait until at least one commit has been made
|
-- Next, wait until at least one commit has been made
|
||||||
|
@ -42,7 +42,10 @@ pushThread st commitchan pushmap = do
|
||||||
-- Now see if now's a good time to push.
|
-- Now see if now's a good time to push.
|
||||||
now <- getCurrentTime
|
now <- getCurrentTime
|
||||||
if shouldPush now commits
|
if shouldPush now commits
|
||||||
then pushToRemotes now st pushmap remotes
|
then do
|
||||||
|
remotes <- runThreadState st $
|
||||||
|
knownRemotes <$> getDaemonStatus daemonstatus
|
||||||
|
pushToRemotes now st pushmap remotes
|
||||||
else refillCommits commitchan commits
|
else refillCommits commitchan commits
|
||||||
|
|
||||||
{- Decide if now is a good time to push to remotes.
|
{- Decide if now is a good time to push to remotes.
|
||||||
|
|
|
@ -8,9 +8,10 @@
|
||||||
module Assistant.TransferQueue where
|
module Assistant.TransferQueue where
|
||||||
|
|
||||||
import Common.Annex
|
import Common.Annex
|
||||||
import Utility.TSet
|
import Assistant.DaemonStatus
|
||||||
import Logs.Transfer
|
import Logs.Transfer
|
||||||
import Types.Remote
|
import Types.Remote
|
||||||
|
import qualified Remote
|
||||||
|
|
||||||
import Control.Concurrent.STM
|
import Control.Concurrent.STM
|
||||||
|
|
||||||
|
@ -28,15 +29,29 @@ stubInfo f = TransferInfo
|
||||||
, associatedFile = f
|
, associatedFile = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{- Adds pending transfers to the end of the queue for some of the known
|
||||||
|
- remotes. (TBD: a smaller set of remotes that are sufficient to transfer to,
|
||||||
|
- rather than transferring to all.) -}
|
||||||
|
queueTransfers :: TransferQueue -> DaemonStatusHandle -> Key -> AssociatedFile -> Direction -> Annex ()
|
||||||
|
queueTransfers q daemonstatus k f direction =
|
||||||
|
mapM_ (liftIO . queueTransfer q f . gentransfer)
|
||||||
|
=<< knownRemotes <$> getDaemonStatus daemonstatus
|
||||||
|
where
|
||||||
|
gentransfer r = Transfer
|
||||||
|
{ transferDirection = direction
|
||||||
|
, transferKey = k
|
||||||
|
, transferRemote = Remote.uuid r
|
||||||
|
}
|
||||||
|
|
||||||
{- Adds a pending transfer to the end of the queue. -}
|
{- Adds a pending transfer to the end of the queue. -}
|
||||||
queueTransfer :: TransferQueue -> Transfer -> AssociatedFile -> IO ()
|
queueTransfer :: TransferQueue -> AssociatedFile -> Transfer -> IO ()
|
||||||
queueTransfer q transfer f = void $ atomically $
|
queueTransfer q f t = void $ atomically $
|
||||||
writeTChan q (transfer, stubInfo f)
|
writeTChan q (t, stubInfo f)
|
||||||
|
|
||||||
{- Adds a pending transfer to the start of the queue, to be processed next. -}
|
{- Adds a pending transfer to the start of the queue, to be processed next. -}
|
||||||
queueNextTransfer :: TransferQueue -> Transfer -> AssociatedFile -> IO ()
|
queueNextTransfer :: TransferQueue -> AssociatedFile -> Transfer -> IO ()
|
||||||
queueNextTransfer q transfer f = void $ atomically $
|
queueNextTransfer q f t = void $ atomically $
|
||||||
unGetTChan q (transfer, stubInfo f)
|
unGetTChan q (t, stubInfo f)
|
||||||
|
|
||||||
{- Blocks until a pending transfer is available in the queue. -}
|
{- Blocks until a pending transfer is available in the queue. -}
|
||||||
getNextTransfer :: TransferQueue -> IO (Transfer, TransferInfo)
|
getNextTransfer :: TransferQueue -> IO (Transfer, TransferInfo)
|
||||||
|
|
Loading…
Reference in a new issue