summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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"