aboutsummaryrefslogtreecommitdiff
path: root/Annex/NumCopies.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joeyh@joeyh.name>2015-10-08 18:11:39 -0400
committerGravatar Joey Hess <joeyh@joeyh.name>2015-10-08 18:11:39 -0400
commit69903541bcb21b71c6aeecfb1a617a2a243f70b5 (patch)
treeec01f713b2507ee08b2a17c1cde27d68f2608f0b /Annex/NumCopies.hs
parenta56d3c92b9672c6d84ac007a404b07d3eeb51025 (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/NumCopies.hs')
-rw-r--r--Annex/NumCopies.hs26
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"