summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Assistant/Alert.hs6
-rw-r--r--Assistant/ScanRemotes.hs24
-rw-r--r--Assistant/Sync.hs4
-rw-r--r--Assistant/Threads/TransferScanner.hs56
4 files changed, 42 insertions, 48 deletions
diff --git a/Assistant/Alert.hs b/Assistant/Alert.hs
index bc20b59ff..c66621836 100644
--- a/Assistant/Alert.hs
+++ b/Assistant/Alert.hs
@@ -214,10 +214,10 @@ syncAlert rs = baseActivityAlert
, alertPriority = Low
}
-scanAlert :: Remote -> Alert
-scanAlert r = baseActivityAlert
+scanAlert :: [Remote] -> Alert
+scanAlert rs = baseActivityAlert
{ alertHeader = Just $ tenseWords
- [Tensed "Scanning" "Scanned", showRemotes [r]]
+ [Tensed "Scanning" "Scanned", showRemotes rs]
, alertBlockDisplay = True
, alertPriority = Low
}
diff --git a/Assistant/ScanRemotes.hs b/Assistant/ScanRemotes.hs
index bfe953803..661c98095 100644
--- a/Assistant/ScanRemotes.hs
+++ b/Assistant/ScanRemotes.hs
@@ -26,21 +26,15 @@ type ScanRemoteMap = TMVar (M.Map Remote ScanInfo)
newScanRemoteMap :: IO ScanRemoteMap
newScanRemoteMap = atomically newEmptyTMVar
-{- Blocks until there is a remote that needs to be scanned.
- - Processes higher priority remotes first. -}
-getScanRemote :: ScanRemoteMap -> IO (Remote, ScanInfo)
-getScanRemote v = atomically $ do
- m <- takeTMVar v
- let l = reverse $ sortBy (compare `on` scanPriority . snd) $ M.toList m
- case l of
- [] -> retry -- should never happen
- (ret@(r, _):_) -> do
- let m' = M.delete r m
- unless (M.null m') $
- putTMVar v m'
- return ret
-
-{- Adds new remotes that need scanning to the map. -}
+{- Blocks until there is a remote or remotes that need to be scanned.
+ -
+ - The list has higher priority remotes listed first. -}
+getScanRemote :: ScanRemoteMap -> IO [(Remote, ScanInfo)]
+getScanRemote v = atomically $
+ reverse . sortBy (compare `on` scanPriority . snd) . M.toList
+ <$> takeTMVar v
+
+{- Adds new remotes that need scanning. -}
addScanRemotes :: ScanRemoteMap -> Bool -> [Remote] -> IO ()
addScanRemotes _ _ [] = noop
addScanRemotes v full rs = atomically $ do
diff --git a/Assistant/Sync.hs b/Assistant/Sync.hs
index 35b300f39..499fc960c 100644
--- a/Assistant/Sync.hs
+++ b/Assistant/Sync.hs
@@ -28,8 +28,8 @@ import qualified Data.Map as M
-
- First gets git in sync, and then prepares any necessary file transfers.
-
- - An expensive full scan is queued when the git-annex branches of the
- - remotes have diverged from the local git-annex branch. Otherwise,
+ - An expensive full scan is queued when the git-annex branches of some of
+ - the remotes have diverged from the local git-annex branch. Otherwise,
- it's sufficient to requeue failed transfers.
-}
reconnectRemotes :: ThreadName -> ThreadState -> DaemonStatusHandle -> ScanRemoteMap -> [Remote] -> IO ()
diff --git a/Assistant/Threads/TransferScanner.hs b/Assistant/Threads/TransferScanner.hs
index e5191956e..b4ceac17d 100644
--- a/Assistant/Threads/TransferScanner.hs
+++ b/Assistant/Threads/TransferScanner.hs
@@ -36,13 +36,13 @@ transferScannerThread st dstatus scanremotes transferqueue = do
where
go scanned = do
threadDelaySeconds (Seconds 2)
- (r, info) <- getScanRemote scanremotes
- if fullScan info || not (S.member r scanned)
+ (rs, infos) <- unzip <$> getScanRemote scanremotes
+ if any fullScan infos || any (`S.notMember` scanned) rs
then do
- expensiveScan st dstatus transferqueue r
- go (S.insert r scanned)
+ expensiveScan st dstatus transferqueue rs
+ go (S.union scanned (S.fromList rs))
else do
- failedTransferScan st dstatus transferqueue r
+ mapM_ (failedTransferScan st dstatus transferqueue) rs
go scanned
{- All available remotes are scanned in full on startup,
- for multiple reasons, including:
@@ -92,39 +92,39 @@ failedTransferScan st dstatus transferqueue r = do
dequeue t = void $ runThreadState st $ inRepo $
liftIO . tryIO . removeFile . failedTransferFile t
-{- This is a expensive scan through the full git work tree.
+{- This is a expensive scan through the full git work tree, finding
+ - files to download from or upload to any of the remotes.
-
- The scan is blocked when the transfer queue gets too large. -}
-expensiveScan :: ThreadState -> DaemonStatusHandle -> TransferQueue -> Remote -> IO ()
-expensiveScan st dstatus transferqueue r = do
- liftIO $ debug thisThread ["starting scan of", show r]
- void $ alertWhile dstatus (scanAlert r) $ do
+expensiveScan :: ThreadState -> DaemonStatusHandle -> TransferQueue -> [Remote] -> IO ()
+expensiveScan st dstatus transferqueue rs = do
+ liftIO $ debug thisThread ["starting scan of", show rs]
+ void $ alertWhile dstatus (scanAlert rs) $ do
g <- runThreadState st $ fromRepo id
files <- LsFiles.inRepo [] g
go files
return True
- liftIO $ debug thisThread ["finished scan of", show r]
+ liftIO $ debug thisThread ["finished scan of", show rs]
where
go [] = noop
go (f:fs) = do
- v <- runThreadState st $ whenAnnexed check f
- case v of
- Nothing -> noop
- Just t -> do
- debug thisThread ["queuing", show t]
- enqueue f t
+ mapM_ (enqueue f) =<< catMaybes <$> runThreadState st
+ (ifAnnexed f findtransfers $ return [])
go fs
- where
- check _ (key, _) = ifM (inAnnex key)
- ( helper key Upload False =<< remoteHas r key
- , helper key Download True =<< remoteHas r key
- )
- helper key direction x y
- | x == y = return $ Just $
- Transfer direction (Remote.uuid r) key
- | otherwise = return Nothing
-
- enqueue f t = queueTransferWhenSmall transferqueue dstatus (Just f) t r
+ enqueue f (r, t) = do
+ debug thisThread ["queuing", show t]
+ queueTransferWhenSmall transferqueue dstatus (Just f) t r
+ findtransfers (key, _) = do
+ locs <- loggedLocations key
+ let use a = return $ map (a key locs) rs
+ ifM (inAnnex key)
+ ( use $ check Upload False
+ , use $ check Download True
+ )
+ check direction want key locs r
+ | (Remote.uuid r `elem` locs) == want = Just $
+ (r, Transfer direction (Remote.uuid r) key)
+ | otherwise = Nothing
remoteHas :: Remote -> Key -> Annex Bool
remoteHas r key = elem