fix transfers of key with no associated file

Several places assumed this would not happen, and when the AssociatedFile
was Nothing, did nothing.

As part of this, preferred content checks pass the Key around.

Note that checkMatcher is sometimes now called with Just Key and Just File.
It currently constructs a FileMatcher, ignoring the Key. However, if it
constructed a FileKeyMatcher, which contained both, then it might be
possible to speed up parts of Limit, which currently call the somewhat
expensive lookupFileKey to get the Key.

I have not made this optimisation yet, because I am not sure if the key is
always the same. Will need some significant checking to satisfy myself
that's the case..
This commit is contained in:
Joey Hess 2014-01-23 16:37:08 -04:00
parent 90bc6e3137
commit 3518c586cf
13 changed files with 79 additions and 64 deletions

View file

@ -11,6 +11,7 @@ import Common.Annex
import Logs.Trust import Logs.Trust
import Config.NumCopies import Config.NumCopies
import Types.Remote (uuid) import Types.Remote (uuid)
import Types.Key (key2file)
import qualified Remote import qualified Remote
import qualified Command.Drop import qualified Command.Drop
import Command import Command
@ -43,15 +44,14 @@ type Reason = String
- or commandAction. - or commandAction.
-} -}
handleDropsFrom :: [UUID] -> [Remote] -> Reason -> Bool -> Key -> AssociatedFile -> Maybe Remote -> CommandActionRunner -> Annex () handleDropsFrom :: [UUID] -> [Remote] -> Reason -> Bool -> Key -> AssociatedFile -> Maybe Remote -> CommandActionRunner -> Annex ()
handleDropsFrom _ _ _ _ _ Nothing _ _ = noop handleDropsFrom locs rs reason fromhere key afile knownpresentremote runner = do
handleDropsFrom locs rs reason fromhere key (Just afile) knownpresentremote runner = do
fs <- ifM isDirect fs <- ifM isDirect
( do ( do
l <- associatedFilesRelative key l <- associatedFilesRelative key
if null l if null l
then return [afile] then return $ maybe [] (:[]) afile
else return l else return l
, return [afile] , return $ maybe [] (:[]) afile
) )
n <- getcopies fs n <- getcopies fs
if fromhere && checkcopies n Nothing if fromhere && checkcopies n Nothing
@ -60,7 +60,9 @@ handleDropsFrom locs rs reason fromhere key (Just afile) knownpresentremote runn
where where
getcopies fs = do getcopies fs = do
(untrusted, have) <- trustPartition UnTrusted locs (untrusted, have) <- trustPartition UnTrusted locs
numcopies <- maximum <$> mapM getFileNumCopies fs numcopies <- if null fs
then getNumCopies
else maximum <$> mapM getFileNumCopies fs
return (NumCopies (length have), numcopies, S.fromList untrusted) return (NumCopies (length have), numcopies, S.fromList untrusted)
{- Check that we have enough copies still to drop the content. {- Check that we have enough copies still to drop the content.
@ -85,13 +87,23 @@ handleDropsFrom locs rs reason fromhere key (Just afile) knownpresentremote runn
dropr fs r n >>= go fs rest dropr fs r n >>= go fs rest
| otherwise = noop | otherwise = noop
checkdrop fs n@(have, numcopies, _untrusted) u a = checkdrop fs n u a
ifM (allM (wantDrop True u . Just) fs) | null fs = check $ -- no associated files; unused content
( ifM (safely $ runner $ a numcopies) wantDrop True u (Just key) Nothing
| otherwise = check $
allM (wantDrop True u (Just key) . Just) fs
where
check c = ifM c
( dodrop n u a
, return n
)
dodrop n@(have, numcopies, _untrusted) u a =
ifM (safely $ runner $ a numcopies)
( do ( do
liftIO $ debugM "drop" $ unwords liftIO $ debugM "drop" $ unwords
[ "dropped" [ "dropped"
, afile , fromMaybe (key2file key) afile
, "(from " ++ maybe "here" show u ++ ")" , "(from " ++ maybe "here" show u ++ ")"
, "(copies now " ++ show (fromNumCopies have - 1) ++ ")" , "(copies now " ++ show (fromNumCopies have - 1) ++ ")"
, ": " ++ reason , ": " ++ reason
@ -99,14 +111,12 @@ handleDropsFrom locs rs reason fromhere key (Just afile) knownpresentremote runn
return $ decrcopies n u return $ decrcopies n u
, return n , return n
) )
, return n
)
dropl fs n = checkdrop fs n Nothing $ \numcopies -> dropl fs n = checkdrop fs n Nothing $ \numcopies ->
Command.Drop.startLocal (Just afile) numcopies key knownpresentremote Command.Drop.startLocal afile numcopies key knownpresentremote
dropr fs r n = checkdrop fs n (Just $ Remote.uuid r) $ \numcopies -> dropr fs r n = checkdrop fs n (Just $ Remote.uuid r) $ \numcopies ->
Command.Drop.startRemote (Just afile) numcopies key r Command.Drop.startRemote afile numcopies key r
slocs = S.fromList locs slocs = S.fromList locs

View file

@ -1,6 +1,6 @@
{- git-annex file matching {- git-annex file matching
- -
- Copyright 2012, 2013 Joey Hess <joey@kitenet.net> - Copyright 2012-2014 Joey Hess <joey@kitenet.net>
- -
- Licensed under the GNU GPL version 3 or higher. - Licensed under the GNU GPL version 3 or higher.
-} -}
@ -28,18 +28,25 @@ import qualified Data.Set as S
type FileMatcher = Matcher MatchFiles type FileMatcher = Matcher MatchFiles
checkFileMatcher :: FileMatcher -> FilePath -> Annex Bool checkFileMatcher :: FileMatcher -> FilePath -> Annex Bool
checkFileMatcher matcher file = checkFileMatcher' matcher file S.empty True checkFileMatcher matcher file = checkMatcher matcher Nothing (Just file) S.empty True
checkFileMatcher' :: FileMatcher -> FilePath -> AssumeNotPresent -> Bool -> Annex Bool checkMatcher :: FileMatcher -> Maybe Key -> AssociatedFile -> AssumeNotPresent -> Bool -> Annex Bool
checkFileMatcher' matcher file notpresent def checkMatcher matcher mkey afile notpresent def
| isEmpty matcher = return def | isEmpty matcher = return def
| otherwise = do | otherwise = case (mkey, afile) of
(_, Just file) -> go =<< fileMatchInfo file
(Just key, _) -> go (MatchingKey key)
_ -> return def
where
go mi = matchMrun matcher $ \a -> a notpresent mi
fileMatchInfo :: FilePath -> Annex MatchInfo
fileMatchInfo file = do
matchfile <- getTopFilePath <$> inRepo (toTopFilePath file) matchfile <- getTopFilePath <$> inRepo (toTopFilePath file)
let mi = MatchingFile $ FileInfo return $ MatchingFile $ FileInfo
{ matchFile = matchfile { matchFile = matchfile
, relFile = file , relFile = file
} }
matchMrun matcher $ \a -> a notpresent mi
matchAll :: FileMatcher matchAll :: FileMatcher
matchAll = generate [] matchAll = generate []

View file

@ -14,19 +14,16 @@ import Annex.UUID
import qualified Data.Set as S import qualified Data.Set as S
{- Check if a file is preferred content for the local repository. -} {- Check if a file is preferred content for the local repository. -}
wantGet :: Bool -> AssociatedFile -> Annex Bool wantGet :: Bool -> Maybe Key -> AssociatedFile -> Annex Bool
wantGet def Nothing = return def wantGet def key file = isPreferredContent Nothing S.empty key file def
wantGet def (Just file) = isPreferredContent Nothing S.empty file def
{- Check if a file is preferred content for a remote. -} {- Check if a file is preferred content for a remote. -}
wantSend :: Bool -> AssociatedFile -> UUID -> Annex Bool wantSend :: Bool -> Maybe Key -> AssociatedFile -> UUID -> Annex Bool
wantSend def Nothing _ = return def wantSend def key file to = isPreferredContent (Just to) S.empty key file def
wantSend def (Just file) to = isPreferredContent (Just to) S.empty file def
{- Check if a file can be dropped, maybe from a remote. {- Check if a file can be dropped, maybe from a remote.
- Don't drop files that are preferred content. -} - Don't drop files that are preferred content. -}
wantDrop :: Bool -> Maybe UUID -> AssociatedFile -> Annex Bool wantDrop :: Bool -> Maybe UUID -> Maybe Key -> AssociatedFile -> Annex Bool
wantDrop def _ Nothing = return $ not def wantDrop def from key file = do
wantDrop def from (Just file) = do
u <- maybe getUUID (return . id) from u <- maybe getUUID (return . id) from
not <$> isPreferredContent (Just u) (S.singleton u) file def not <$> isPreferredContent (Just u) (S.singleton u) key file def

View file

@ -19,7 +19,6 @@ import RunCommand
{- Drop from local and/or remote when allowed by the preferred content and {- Drop from local and/or remote when allowed by the preferred content and
- numcopies settings. -} - numcopies settings. -}
handleDrops :: Reason -> Bool -> Key -> AssociatedFile -> Maybe Remote -> Assistant () handleDrops :: Reason -> Bool -> Key -> AssociatedFile -> Maybe Remote -> Assistant ()
handleDrops _ _ _ Nothing _ = noop
handleDrops reason fromhere key f knownpresentremote = do handleDrops reason fromhere key f knownpresentremote = do
syncrs <- syncDataRemotes <$> getDaemonStatus syncrs <- syncDataRemotes <$> getDaemonStatus
locs <- liftAnnex $ loggedLocations key locs <- liftAnnex $ loggedLocations key

View file

@ -164,9 +164,9 @@ expensiveScan urlrenderer rs = unless onlyweb $ batch <~> do
let slocs = S.fromList locs let slocs = S.fromList locs
let use a = return $ mapMaybe (a key slocs) syncrs let use a = return $ mapMaybe (a key slocs) syncrs
ts <- if present ts <- if present
then filterM (wantSend True (Just f) . Remote.uuid . fst) then filterM (wantSend True (Just key) (Just f) . Remote.uuid . fst)
=<< use (genTransfer Upload False) =<< use (genTransfer Upload False)
else ifM (wantGet True $ Just f) else ifM (wantGet True (Just key) (Just f))
( use (genTransfer Download True) , return [] ) ( use (genTransfer Download True) , return [] )
let unwanted' = S.difference unwanted slocs let unwanted' = S.difference unwanted slocs
return (unwanted', ts) return (unwanted', ts)

View file

@ -58,7 +58,7 @@ queueTransfers = queueTransfersMatching (const True)
- condition. Honors preferred content settings. -} - condition. Honors preferred content settings. -}
queueTransfersMatching :: (UUID -> Bool) -> Reason -> Schedule -> Key -> AssociatedFile -> Direction -> Assistant () queueTransfersMatching :: (UUID -> Bool) -> Reason -> Schedule -> Key -> AssociatedFile -> Direction -> Assistant ()
queueTransfersMatching matching reason schedule k f direction queueTransfersMatching matching reason schedule k f direction
| direction == Download = whenM (liftAnnex $ wantGet True f) go | direction == Download = whenM (liftAnnex $ wantGet True (Just k) f) go
| otherwise = go | otherwise = go
where where
go = do go = do
@ -82,7 +82,7 @@ queueTransfersMatching matching reason schedule k f direction
- already have it. -} - already have it. -}
| otherwise = do | otherwise = do
s <- locs s <- locs
filterM (wantSend True 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)) rs
where where
locs = S.fromList <$> Remote.keyLocations k locs = S.fromList <$> Remote.keyLocations k

View file

@ -103,8 +103,8 @@ runTransferThread' program batchmaker d run = go
{- By the time this is called, the daemonstatus's currentTransfers map should {- By the time this is called, the daemonstatus's currentTransfers map should
- already have been updated to include the transfer. -} - already have been updated to include the transfer. -}
genTransfer :: Transfer -> TransferInfo -> TransferGenerator genTransfer :: Transfer -> TransferInfo -> TransferGenerator
genTransfer t info = case (transferRemote info, associatedFile info) of genTransfer t info = case transferRemote info of
(Just remote, Just file) Just remote
| Git.repoIsLocalUnknown (Remote.repo remote) -> do | Git.repoIsLocalUnknown (Remote.repo remote) -> do
-- optimisation for removable drives not plugged in -- optimisation for removable drives not plugged in
liftAnnex $ recordFailedTransfer t info liftAnnex $ recordFailedTransfer t info
@ -114,7 +114,7 @@ genTransfer t info = case (transferRemote info, associatedFile info) of
( do ( do
debug [ "Transferring:" , describeTransfer t info ] debug [ "Transferring:" , describeTransfer t info ]
notifyTransfer notifyTransfer
return $ Just (t, info, go remote file) return $ Just (t, info, go remote)
, do , do
debug [ "Skipping unnecessary transfer:", debug [ "Skipping unnecessary transfer:",
describeTransfer t info ] describeTransfer t info ]
@ -149,10 +149,12 @@ genTransfer t info = case (transferRemote info, associatedFile info) of
- usual cleanup. However, first check if something else is - usual cleanup. However, first check if something else is
- running the transfer, to avoid removing active transfers. - running the transfer, to avoid removing active transfers.
-} -}
go remote file transferrer = ifM (liftIO $ performTransfer transferrer t $ associatedFile info) go remote transferrer = ifM (liftIO $ performTransfer transferrer t $ associatedFile info)
( do ( do
void $ addAlert $ makeAlertFiller True $ maybe noop
transferFileAlert direction True file (void . addAlert . makeAlertFiller True
. transferFileAlert direction True)
(associatedFile info)
unless isdownload $ unless isdownload $
handleDrops handleDrops
("object uploaded to " ++ show remote) ("object uploaded to " ++ show remote)
@ -188,11 +190,11 @@ genTransfer t info = case (transferRemote info, associatedFile info) of
shouldTransfer :: Transfer -> TransferInfo -> Annex Bool shouldTransfer :: Transfer -> TransferInfo -> Annex Bool
shouldTransfer t info shouldTransfer t info
| transferDirection t == Download = | transferDirection t == Download =
(not <$> inAnnex key) <&&> wantGet True file (not <$> inAnnex key) <&&> wantGet True (Just key) file
| transferDirection t == Upload = case transferRemote info of | transferDirection t == Upload = case transferRemote info of
Nothing -> return False Nothing -> return False
Just r -> notinremote r Just r -> notinremote r
<&&> wantSend True file (Remote.uuid r) <&&> wantSend True (Just key) file (Remote.uuid r)
| otherwise = return False | otherwise = return False
where where
key = transferKey t key = transferKey t

View file

@ -37,5 +37,5 @@ start to from file (key, backend) = stopUnless shouldCopy $
where where
shouldCopy = checkAuto (check <||> numCopiesCheck file key (<)) shouldCopy = checkAuto (check <||> numCopiesCheck file key (<))
check = case to of check = case to of
Nothing -> wantGet False (Just file) Nothing -> wantGet False (Just key) (Just file)
Just r -> wantSend False (Just file) (Remote.uuid r) Just r -> wantSend False (Just key) (Just file) (Remote.uuid r)

View file

@ -34,7 +34,7 @@ seek ps = do
start :: Maybe Remote -> FilePath -> (Key, Backend) -> CommandStart start :: Maybe Remote -> FilePath -> (Key, Backend) -> CommandStart
start from file (key, _) = checkDropAuto from file key $ \numcopies -> start from file (key, _) = checkDropAuto from file key $ \numcopies ->
stopUnless (checkAuto $ wantDrop False (Remote.uuid <$> from) (Just file)) $ stopUnless (checkAuto $ wantDrop False (Remote.uuid <$> from) (Just key) (Just file)) $
case from of case from of
Nothing -> startLocal (Just file) numcopies key Nothing Nothing -> startLocal (Just file) numcopies key Nothing
Just remote -> do Just remote -> do

View file

@ -36,7 +36,7 @@ seek ps = do
start :: Maybe Remote -> FilePath -> (Key, Backend) -> CommandStart start :: Maybe Remote -> FilePath -> (Key, Backend) -> CommandStart
start from file (key, _) = start' expensivecheck from key (Just file) start from file (key, _) = start' expensivecheck from key (Just file)
where where
expensivecheck = checkAuto (numCopiesCheck file key (<) <||> wantGet False (Just file)) expensivecheck = checkAuto (numCopiesCheck file key (<) <||> wantGet False (Just key) (Just file))
startKeys :: Maybe Remote -> Key -> CommandStart startKeys :: Maybe Remote -> Key -> CommandStart
startKeys from key = start' (return True) from key Nothing startKeys from key = start' (return True) from key Nothing

View file

@ -519,7 +519,7 @@ syncFile rs f (k, _) = do
wantget have = allM id wantget have = allM id
[ pure (not $ null have) [ pure (not $ null have)
, not <$> inAnnex k , not <$> inAnnex k
, wantGet True (Just f) , wantGet True (Just k) (Just f)
] ]
handleget have = ifM (wantget have) handleget have = ifM (wantget have)
( return [ get have ] ( return [ get have ]
@ -531,7 +531,7 @@ syncFile rs f (k, _) = do
wantput r wantput r
| Remote.readonly r || remoteAnnexReadOnly (Types.Remote.gitconfig r) = return False | Remote.readonly r || remoteAnnexReadOnly (Types.Remote.gitconfig r) = return False
| otherwise = wantSend True (Just f) (Remote.uuid r) | otherwise = wantSend True (Just k) (Just f) (Remote.uuid r)
handleput lack = ifM (inAnnex k) handleput lack = ifM (inAnnex k)
( map put <$> (filterM wantput lack) ( map put <$> (filterM wantput lack)
, return [] , return []

View file

@ -13,10 +13,10 @@ import Limit
import Types.FileMatcher import Types.FileMatcher
addWantGet :: Annex () addWantGet :: Annex ()
addWantGet = addLimit $ Right $ const $ checkWant $ wantGet False addWantGet = addLimit $ Right $ const $ checkWant $ wantGet False Nothing
addWantDrop :: Annex () addWantDrop :: Annex ()
addWantDrop = addLimit $ Right $ const $ checkWant $ wantDrop False Nothing addWantDrop = addLimit $ Right $ const $ checkWant $ wantDrop False Nothing Nothing
checkWant :: (Maybe FilePath -> Annex Bool) -> MatchInfo -> Annex Bool checkWant :: (Maybe FilePath -> Annex Bool) -> MatchInfo -> Annex Bool
checkWant a (MatchingFile fi) = a (Just $ matchFile fi) checkWant a (MatchingFile fi) = a (Just $ matchFile fi)

View file

@ -38,13 +38,13 @@ import Types.StandardGroups
{- Checks if a file is preferred content for the specified repository {- Checks if a file is preferred content for the specified repository
- (or the current repository if none is specified). -} - (or the current repository if none is specified). -}
isPreferredContent :: Maybe UUID -> AssumeNotPresent -> FilePath -> Bool -> Annex Bool isPreferredContent :: Maybe UUID -> AssumeNotPresent -> Maybe Key -> AssociatedFile -> Bool -> Annex Bool
isPreferredContent mu notpresent file def = do isPreferredContent mu notpresent mkey afile def = do
u <- maybe getUUID return mu u <- maybe getUUID return mu
m <- preferredContentMap m <- preferredContentMap
case M.lookup u m of case M.lookup u m of
Nothing -> return def Nothing -> return def
Just matcher -> checkFileMatcher' matcher file notpresent def Just matcher -> checkMatcher matcher mkey afile notpresent def
{- The map is cached for speed. -} {- The map is cached for speed. -}
preferredContentMap :: Annex Annex.PreferredContentMap preferredContentMap :: Annex Annex.PreferredContentMap