diff options
author | Joey Hess <joeyh@joeyh.name> | 2015-10-08 18:11:39 -0400 |
---|---|---|
committer | Joey Hess <joeyh@joeyh.name> | 2015-10-08 18:11:39 -0400 |
commit | 69903541bcb21b71c6aeecfb1a617a2a243f70b5 (patch) | |
tree | ec01f713b2507ee08b2a17c1cde27d68f2608f0b /Annex | |
parent | a56d3c92b9672c6d84ac007a404b07d3eeb51025 (diff) |
require 1 locked copy while dropping from local or a remote
See doc/bugs/concurrent_drop--from_presence_checking_failures.mdwn for
discussion about why 1 locked copy is all we can require, and how this
fixes concurrent dropping bugs.
Note that, since nothing yet generates a VerifiedCopyLock yet, this commit
breaks dropping temporarily.
Diffstat (limited to 'Annex')
-rw-r--r-- | Annex/NumCopies.hs | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/Annex/NumCopies.hs b/Annex/NumCopies.hs index 6b534591e..636855401 100644 --- a/Annex/NumCopies.hs +++ b/Annex/NumCopies.hs @@ -108,7 +108,11 @@ verifyEnoughCopies nolocmsg key need skip preverified tocheck = notEnoughCopies key need have (skip++missing) bad nolocmsg return False helper bad missing have (r:rs) - | NumCopies (length have) >= need = return True + | verifiedEnoughCopies need have = do + stillhave <- liftIO $ filterM checkVerifiedCopy have + if verifiedEnoughCopies need stillhave + then return True + else helper bad missing stillhave (r:rs) | any (== u) (map toUUID have) = helper bad missing have rs | otherwise = do haskey <- Remote.hasKey r key @@ -119,6 +123,26 @@ verifyEnoughCopies nolocmsg key need skip preverified tocheck = where u = Remote.uuid r +{- Check whether enough verification has been done of copies to allow + - dropping content safely. + - + - Unless numcopies is 0, at least one VerifiedCopyLock is required. + - This prevents races between concurrent drops from dropping the last + - copy, no matter what. + - + - The other N-1 copies can be less strong verifications. While those + - are subject to concurrent drop races, and so could be dropped + - all at once, causing numcopies to be violated, this is the best that can + - be done without requiring all special remotes to support locking. + -} +verifiedEnoughCopies :: NumCopies -> [VerifiedCopy] -> Bool +verifiedEnoughCopies (NumCopies n) l + | n == 0 = True + | otherwise = length l >= n && any islock l + where + islock (VerifiedCopyLock _) = True + islock _ = False + notEnoughCopies :: Key -> NumCopies -> [VerifiedCopy] -> [UUID] -> [Remote] -> String -> Annex () notEnoughCopies key need have skip bad nolocmsg = do showNote "unsafe" |