first pass at assistant knowing about export remotes
Split exportRemotes out from syncDataRemotes; the parts of the assistant that upload keys and drop keys from remotes don't apply to exports, because those operations are not supported. Some parts of the assistant and webapp do operate on both syncDataRemotes and exportRemotes. Particularly when downloading from either of them. Added a downloadRemotes that combines both. With this, the assistant should download from exports, but it won't yet upload changes to them. This commit was sponsored by Fernando Jimenez on Patreon.
This commit is contained in:
parent
28eba8e9c6
commit
46d19648ee
6 changed files with 40 additions and 26 deletions
|
@ -20,6 +20,7 @@ import Logs.TimeStamp
|
||||||
import qualified Remote
|
import qualified Remote
|
||||||
import qualified Types.Remote as Remote
|
import qualified Types.Remote as Remote
|
||||||
import Config.DynamicConfig
|
import Config.DynamicConfig
|
||||||
|
import Annex.Export
|
||||||
|
|
||||||
import Control.Concurrent.STM
|
import Control.Concurrent.STM
|
||||||
import System.Posix.Types
|
import System.Posix.Types
|
||||||
|
@ -53,15 +54,18 @@ calcSyncRemotes = do
|
||||||
alive <- trustExclude DeadTrusted (map Remote.uuid rs)
|
alive <- trustExclude DeadTrusted (map Remote.uuid rs)
|
||||||
let good r = Remote.uuid r `elem` alive
|
let good r = Remote.uuid r `elem` alive
|
||||||
let syncable = filter good rs
|
let syncable = filter good rs
|
||||||
syncdata <- filterM (not <$$> liftIO . getDynamicConfig . remoteAnnexIgnore . Remote.gitconfig) $
|
contentremotes <- filterM (not <$$> liftIO . getDynamicConfig . remoteAnnexIgnore . Remote.gitconfig) $
|
||||||
filter (\r -> Remote.uuid r /= NoUUID) $
|
filter (\r -> Remote.uuid r /= NoUUID) $
|
||||||
filter (not . Remote.isXMPPRemote) syncable
|
filter (not . Remote.isXMPPRemote) syncable
|
||||||
|
let (exportremotes, dataremotes) = partition (exportTree . Remote.config) contentremotes
|
||||||
|
|
||||||
return $ \dstatus -> dstatus
|
return $ \dstatus -> dstatus
|
||||||
{ syncRemotes = syncable
|
{ syncRemotes = syncable
|
||||||
, syncGitRemotes = filter Remote.gitSyncableRemote syncable
|
, syncGitRemotes = filter Remote.gitSyncableRemote syncable
|
||||||
, syncDataRemotes = syncdata
|
, syncDataRemotes = dataremotes
|
||||||
, syncingToCloudRemote = any iscloud syncdata
|
, exportRemotes = exportremotes
|
||||||
|
, downloadRemotes = contentremotes
|
||||||
|
, syncingToCloudRemote = any iscloud contentremotes
|
||||||
}
|
}
|
||||||
where
|
where
|
||||||
iscloud r = not (Remote.readonly r) && Remote.availability r == Remote.GloballyAvailable
|
iscloud r = not (Remote.readonly r) && Remote.availability r == Remote.GloballyAvailable
|
||||||
|
|
|
@ -29,7 +29,7 @@ glacierThread = namedThread "Glacier" $ runEvery (Seconds 3600) <~> go
|
||||||
where
|
where
|
||||||
isglacier r = Remote.remotetype r == Glacier.remote
|
isglacier r = Remote.remotetype r == Glacier.remote
|
||||||
go = do
|
go = do
|
||||||
rs <- filter isglacier . syncDataRemotes <$> getDaemonStatus
|
rs <- filter isglacier . downloadRemotes <$> getDaemonStatus
|
||||||
forM_ rs $ \r ->
|
forM_ rs $ \r ->
|
||||||
check r =<< liftAnnex (getFailedTransfers $ Remote.uuid r)
|
check r =<< liftAnnex (getFailedTransfers $ Remote.uuid r)
|
||||||
check _ [] = noop
|
check _ [] = noop
|
||||||
|
|
|
@ -78,7 +78,7 @@ transferScannerThread urlrenderer = namedThread "TransferScanner" $ do
|
||||||
-}
|
-}
|
||||||
startupScan = do
|
startupScan = do
|
||||||
reconnectRemotes =<< syncGitRemotes <$> getDaemonStatus
|
reconnectRemotes =<< syncGitRemotes <$> getDaemonStatus
|
||||||
addScanRemotes True =<< syncDataRemotes <$> getDaemonStatus
|
addScanRemotes True =<< scannableRemotes
|
||||||
|
|
||||||
{- This is a cheap scan for failed transfers involving a remote. -}
|
{- This is a cheap scan for failed transfers involving a remote. -}
|
||||||
failedTransferScan :: Remote -> Assistant ()
|
failedTransferScan :: Remote -> Assistant ()
|
||||||
|
@ -157,25 +157,30 @@ expensiveScan urlrenderer rs = batch <~> do
|
||||||
(AssociatedFile (Just f)) t r
|
(AssociatedFile (Just f)) t r
|
||||||
findtransfers f unwanted key = do
|
findtransfers f unwanted key = do
|
||||||
let af = AssociatedFile (Just f)
|
let af = AssociatedFile (Just f)
|
||||||
{- The syncable remotes may have changed since this
|
|
||||||
- scan began. -}
|
|
||||||
syncrs <- syncDataRemotes <$> getDaemonStatus
|
|
||||||
locs <- liftAnnex $ loggedLocations key
|
locs <- liftAnnex $ loggedLocations key
|
||||||
present <- liftAnnex $ inAnnex key
|
present <- liftAnnex $ inAnnex key
|
||||||
|
let slocs = S.fromList locs
|
||||||
|
|
||||||
|
{- The remotes may have changed since this scan began. -}
|
||||||
|
syncrs <- syncDataRemotes <$> getDaemonStatus
|
||||||
|
let use l a = mapMaybe (a key slocs) . l <$> getDaemonStatus
|
||||||
|
|
||||||
liftAnnex $ handleDropsFrom locs syncrs
|
liftAnnex $ handleDropsFrom locs syncrs
|
||||||
"expensive scan found too many copies of object"
|
"expensive scan found too many copies of object"
|
||||||
present key af [] callCommandAction
|
present key af [] callCommandAction
|
||||||
liftAnnex $ do
|
|
||||||
let slocs = S.fromList locs
|
|
||||||
let use a = return $ mapMaybe (a key slocs) syncrs
|
|
||||||
ts <- if present
|
ts <- if present
|
||||||
then filterM (wantSend True (Just key) af . Remote.uuid . fst)
|
then liftAnnex . filterM (wantSend True (Just key) af . Remote.uuid . fst)
|
||||||
=<< use (genTransfer Upload False)
|
=<< use syncDataRemotes (genTransfer Upload False)
|
||||||
else ifM (wantGet True (Just key) af)
|
else ifM (liftAnnex $ wantGet True (Just key) af)
|
||||||
( use (genTransfer Download True) , return [] )
|
( use downloadRemotes (genTransfer Download True) , return [] )
|
||||||
let unwanted' = S.difference unwanted slocs
|
let unwanted' = S.difference unwanted slocs
|
||||||
return (unwanted', ts)
|
return (unwanted', ts)
|
||||||
|
|
||||||
|
-- Both syncDataRemotes and exportRemotes can be scanned.
|
||||||
|
-- The downloadRemotes list contains both.
|
||||||
|
scannableRemotes :: Assistant [Remote]
|
||||||
|
scannableRemotes = downloadRemotes <$> getDaemonStatus
|
||||||
|
|
||||||
genTransfer :: Direction -> Bool -> Key -> S.Set UUID -> Remote -> Maybe (Remote, Transfer)
|
genTransfer :: Direction -> Bool -> Key -> S.Set UUID -> Remote -> Maybe (Remote, Transfer)
|
||||||
genTransfer direction want key slocs r
|
genTransfer direction want key slocs r
|
||||||
| direction == Upload && Remote.readonly r = Nothing
|
| direction == Upload && Remote.readonly r = Nothing
|
||||||
|
|
|
@ -66,9 +66,7 @@ queueTransfersMatching matching reason schedule k f direction
|
||||||
| otherwise = go
|
| otherwise = go
|
||||||
where
|
where
|
||||||
go = do
|
go = do
|
||||||
|
rs <- liftAnnex . selectremotes =<< getDaemonStatus
|
||||||
rs <- liftAnnex . selectremotes
|
|
||||||
=<< syncDataRemotes <$> getDaemonStatus
|
|
||||||
let matchingrs = filter (matching . Remote.uuid) rs
|
let matchingrs = filter (matching . Remote.uuid) rs
|
||||||
if null matchingrs
|
if null matchingrs
|
||||||
then do
|
then do
|
||||||
|
@ -78,20 +76,21 @@ queueTransfersMatching matching reason schedule k f direction
|
||||||
forM_ matchingrs $ \r ->
|
forM_ matchingrs $ \r ->
|
||||||
enqueue reason schedule (gentransfer r) (stubInfo f r)
|
enqueue reason schedule (gentransfer r) (stubInfo f r)
|
||||||
return True
|
return True
|
||||||
selectremotes rs
|
selectremotes st
|
||||||
{- Queue downloads from all remotes that
|
{- Queue downloads from all remotes that
|
||||||
- have the key. The list of remotes is ordered with
|
- have the key. The list of remotes is ordered with
|
||||||
- cheapest first. More expensive ones will only be tried
|
- cheapest first. More expensive ones will only be tried
|
||||||
- if downloading from a cheap one fails. -}
|
- if downloading from a cheap one fails. -}
|
||||||
| direction == Download = do
|
| direction == Download = do
|
||||||
s <- locs
|
s <- locs
|
||||||
return $ filter (inset s) rs
|
return $ filter (inset s) (downloadRemotes st)
|
||||||
{- Upload to all remotes that want the content and don't
|
{- Upload to all remotes that want the content and don't
|
||||||
- already have it. -}
|
- already have it. -}
|
||||||
| otherwise = do
|
| otherwise = do
|
||||||
s <- locs
|
s <- locs
|
||||||
filterM (wantSend True (Just k) f . Remote.uuid) $
|
filterM (wantSend True (Just k) f . Remote.uuid) $
|
||||||
filter (\r -> not (inset s r || Remote.readonly r)) rs
|
filter (\r -> not (inset s r || Remote.readonly r))
|
||||||
|
(syncDataRemotes st)
|
||||||
where
|
where
|
||||||
locs = S.fromList <$> Remote.keyLocations k
|
locs = S.fromList <$> Remote.keyLocations k
|
||||||
inset s r = S.member (Remote.uuid r) s
|
inset s r = S.member (Remote.uuid r) s
|
||||||
|
@ -114,7 +113,7 @@ queueDeferredDownloads :: Reason -> Schedule -> Assistant ()
|
||||||
queueDeferredDownloads reason schedule = do
|
queueDeferredDownloads reason schedule = do
|
||||||
q <- getAssistant transferQueue
|
q <- getAssistant transferQueue
|
||||||
l <- liftIO $ atomically $ readTList (deferreddownloads q)
|
l <- liftIO $ atomically $ readTList (deferreddownloads q)
|
||||||
rs <- syncDataRemotes <$> getDaemonStatus
|
rs <- downloadRemotes <$> getDaemonStatus
|
||||||
left <- filterM (queue rs) l
|
left <- filterM (queue rs) l
|
||||||
unless (null left) $
|
unless (null left) $
|
||||||
liftIO $ atomically $ appendTList (deferreddownloads q) left
|
liftIO $ atomically $ appendTList (deferreddownloads q) left
|
||||||
|
|
|
@ -49,6 +49,10 @@ data DaemonStatus = DaemonStatus
|
||||||
, syncGitRemotes :: [Remote]
|
, syncGitRemotes :: [Remote]
|
||||||
-- Ordered list of remotes to sync data with
|
-- Ordered list of remotes to sync data with
|
||||||
, syncDataRemotes :: [Remote]
|
, syncDataRemotes :: [Remote]
|
||||||
|
-- Ordered list of remotes to export to
|
||||||
|
, exportRemotes :: [Remote]
|
||||||
|
-- Ordered list of remotes that data can be downloaded from
|
||||||
|
, downloadRemotes :: [Remote]
|
||||||
-- Are we syncing to any cloud remotes?
|
-- Are we syncing to any cloud remotes?
|
||||||
, syncingToCloudRemote :: Bool
|
, syncingToCloudRemote :: Bool
|
||||||
-- Set of uuids of remotes that are currently connected.
|
-- Set of uuids of remotes that are currently connected.
|
||||||
|
@ -97,6 +101,8 @@ newDaemonStatus = DaemonStatus
|
||||||
<*> pure []
|
<*> pure []
|
||||||
<*> pure []
|
<*> pure []
|
||||||
<*> pure []
|
<*> pure []
|
||||||
|
<*> pure []
|
||||||
|
<*> pure []
|
||||||
<*> pure False
|
<*> pure False
|
||||||
<*> pure S.empty
|
<*> pure S.empty
|
||||||
<*> pure Nothing
|
<*> pure Nothing
|
||||||
|
|
|
@ -72,7 +72,7 @@ deleteCurrentRepository :: Handler Html
|
||||||
deleteCurrentRepository = dangerPage $ do
|
deleteCurrentRepository = dangerPage $ do
|
||||||
reldir <- fromJust . relDir <$> liftH getYesod
|
reldir <- fromJust . relDir <$> liftH getYesod
|
||||||
havegitremotes <- haveremotes syncGitRemotes
|
havegitremotes <- haveremotes syncGitRemotes
|
||||||
havedataremotes <- haveremotes syncDataRemotes
|
havedataremotes <- haveremotes downloadRemotes
|
||||||
((result, form), enctype) <- liftH $
|
((result, form), enctype) <- liftH $
|
||||||
runFormPostNoToken $ renderBootstrap3 bootstrapFormLayout $
|
runFormPostNoToken $ renderBootstrap3 bootstrapFormLayout $
|
||||||
sanityVerifierAForm $ SanityVerifier magicphrase
|
sanityVerifierAForm $ SanityVerifier magicphrase
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue