distinguish between incremental verification failing and not being done

Sponsored-by: Dartmouth College's DANDI project
This commit is contained in:
Joey Hess 2021-08-18 13:54:40 -04:00
parent 325bfda12d
commit 88b63a43fa
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
7 changed files with 41 additions and 37 deletions

View file

@ -633,8 +633,8 @@ saveState nocommit = doSideAction $ do
{- Downloads content from any of a list of urls, displaying a progress {- Downloads content from any of a list of urls, displaying a progress
- meter. -} - meter. -}
downloadUrl :: Key -> MeterUpdate -> [Url.URLString] -> FilePath -> Url.UrlOptions -> Annex Bool downloadUrl :: Key -> MeterUpdate -> Maybe IncrementalVerifier -> [Url.URLString] -> FilePath -> Url.UrlOptions -> Annex Bool
downloadUrl k p urls file uo = downloadUrl k p iv urls file uo =
-- Poll the file to handle configurations where an external -- Poll the file to handle configurations where an external
-- download command is used. -- download command is used.
meteredFile file (Just p) k (go urls Nothing) meteredFile file (Just p) k (go urls Nothing)
@ -643,7 +643,7 @@ downloadUrl k p urls file uo =
-- download. -- download.
go [] (Just err) = warning err >> return False go [] (Just err) = warning err >> return False
go [] Nothing = return False go [] Nothing = return False
go (u:us) _ = Url.download' p u file uo >>= \case go (u:us) _ = Url.download' p iv u file uo >>= \case
Right () -> return True Right () -> return True
Left err -> go us (Just err) Left err -> go us (Just err)

View file

@ -72,9 +72,7 @@ fileCopier _ src dest meterupdate iv = docopy
fileCopier copycowtried src dest meterupdate iv = fileCopier copycowtried src dest meterupdate iv =
ifM (liftIO $ tryCopyCoW copycowtried src dest meterupdate) ifM (liftIO $ tryCopyCoW copycowtried src dest meterupdate)
( do ( do
-- Make sure the incremental verifier fails, liftIO $ maybe noop unableIncremental iv
-- since we did not feed it.
liftIO $ maybe noop failIncremental iv
return CopiedCoW return CopiedCoW
, docopy , docopy
) )

View file

@ -110,17 +110,19 @@ resumeVerifyKeyContent k f iv = liftIO (positionIncremental iv) >>= \case
then fallback then fallback
else case fromKey keySize k of else case fromKey keySize k of
Just size | fsz /= size -> return False Just size | fsz /= size -> return False
_ -> go fsz endpos _ -> go fsz endpos >>= \case
Just v -> return v
Nothing -> fallback
where where
fallback = verifyKeyContent k f fallback = verifyKeyContent k f
go fsz endpos go fsz endpos
| fsz == endpos = | fsz == endpos =
liftIO $ catchDefaultIO False $ liftIO $ catchDefaultIO (Just False) $
finalizeIncremental iv finalizeIncremental iv
| otherwise = do | otherwise = do
showAction (descVerify iv) showAction (descVerify iv)
liftIO $ catchDefaultIO False $ liftIO $ catchDefaultIO (Just False) $
withBinaryFile (fromRawFilePath f) ReadMode $ \h -> do withBinaryFile (fromRawFilePath f) ReadMode $ \h -> do
hSeek h AbsoluteSeek endpos hSeek h AbsoluteSeek endpos
feedincremental h feedincremental h
@ -172,12 +174,13 @@ finishVerifyKeyContentIncrementally :: Maybe IncrementalVerifier -> Annex (Bool,
finishVerifyKeyContentIncrementally Nothing = finishVerifyKeyContentIncrementally Nothing =
return (True, UnVerified) return (True, UnVerified)
finishVerifyKeyContentIncrementally (Just iv) = finishVerifyKeyContentIncrementally (Just iv) =
ifM (liftIO $ finalizeIncremental iv) liftIO (finalizeIncremental iv) >>= \case
( return (True, Verified) Just True -> return (True, Verified)
, do Just False -> do
warning "verification of content failed" warning "verification of content failed"
return (False, UnVerified) return (False, UnVerified)
) -- Incremental verification was not able to be done.
Nothing -> return (True, UnVerified)
-- | Reads the file as it grows, and feeds it to the incremental verifier. -- | Reads the file as it grows, and feeds it to the incremental verifier.
-- --
@ -190,11 +193,11 @@ finishVerifyKeyContentIncrementally (Just iv) =
-- for the file to appear before opening it and starting verification. -- for the file to appear before opening it and starting verification.
-- --
-- This is not supported for all OSs, and on OS's where it is not -- This is not supported for all OSs, and on OS's where it is not
-- supported, verification will fail. -- supported, verification will not happen.
-- --
-- The writer probably needs to be another process. If the file is being -- The writer probably needs to be another process. If the file is being
-- written directly by git-annex, the haskell RTS will prevent opening it -- written directly by git-annex, the haskell RTS will prevent opening it
-- for read at the same time, and verification will fail. -- for read at the same time, and verification will not happen.
-- --
-- Note that there are situations where the file may fail to verify despite -- Note that there are situations where the file may fail to verify despite
-- having the correct content. For example, when the file is written out -- having the correct content. For example, when the file is written out
@ -221,7 +224,7 @@ tailVerify :: IncrementalVerifier -> RawFilePath -> TMVar () -> IO ()
tailVerify iv f finished = tailVerify iv f finished =
tryNonAsync go >>= \case tryNonAsync go >>= \case
Right r -> return r Right r -> return r
Left _ -> failIncremental iv Left _ -> unableIncremental iv
where where
-- Watch the directory containing the file, and wait for -- Watch the directory containing the file, and wait for
-- the file to be modified. It's possible that the file already -- the file to be modified. It's possible that the file already
@ -246,7 +249,7 @@ tailVerify iv f finished =
let cleanup = void . tryNonAsync . INotify.removeWatch let cleanup = void . tryNonAsync . INotify.removeWatch
let stop w = do let stop w = do
cleanup w cleanup w
failIncremental iv unableIncremental iv
waitopen modified >>= \case waitopen modified >>= \case
Nothing -> stop wd Nothing -> stop wd
Just h -> do Just h -> do
@ -305,5 +308,5 @@ tailVerify iv f finished =
chunk = 65536 chunk = 65536
#else #else
tailVerify iv _ _ = failIncremental iv tailVerify iv _ _ = unableIncremental iv
#endif #endif

View file

@ -202,10 +202,12 @@ runLocal runst runner a = case a of
runner validitycheck >>= \case runner validitycheck >>= \case
Right (Just Valid) -> case incrementalverifier of Right (Just Valid) -> case incrementalverifier of
Just iv -> ifM (liftIO (finalizeIncremental iv) <&&> pure rightsize) Just iv
( return (True, Verified) | rightsize -> liftIO (finalizeIncremental iv) >>= \case
, return (False, UnVerified) Nothing -> return (True, UnVerified)
) Just True -> return (True, Verified)
Just False -> return (False, UnVerified)
| otherwise -> return (False, UnVerified)
Nothing -> return (rightsize, UnVerified) Nothing -> return (rightsize, UnVerified)
Right (Just Invalid) | l == 0 -> Right (Just Invalid) | l == 0 ->
-- Special case, for when -- Special case, for when

View file

@ -367,10 +367,9 @@ retrieveChunks retriever u vc chunkconfig encryptor basek dest basep enc encc
finalize (Right Nothing) = return UnVerified finalize (Right Nothing) = return UnVerified
finalize (Right (Just iv)) = finalize (Right (Just iv)) =
ifM (liftIO $ finalizeIncremental iv) liftIO (finalizeIncremental iv) >>= \case
( return Verified Just True -> return Verified
, return UnVerified _ -> return UnVerified
)
finalize (Left v) = return v finalize (Left v) = return v
{- Writes retrieved file content to the provided Handle, decrypting it {- Writes retrieved file content to the provided Handle, decrypting it

View file

@ -173,7 +173,7 @@ retrieve hv cc = fileRetriever' $ \d k p iv ->
withDavHandle hv $ \dav -> case cc of withDavHandle hv $ \dav -> case cc of
LegacyChunks _ -> do LegacyChunks _ -> do
-- Not doing incremental verification for chunks. -- Not doing incremental verification for chunks.
liftIO $ maybe noop failIncremental iv liftIO $ maybe noop unableIncremental iv
retrieveLegacyChunked (fromRawFilePath d) k p dav retrieveLegacyChunked (fromRawFilePath d) k p dav
_ -> liftIO $ goDAV dav $ _ -> liftIO $ goDAV dav $
retrieveHelper (keyLocation k) (fromRawFilePath d) p iv retrieveHelper (keyLocation k) (fromRawFilePath d) p iv

View file

@ -283,14 +283,15 @@ props_macs_stable = map (\(desc, mac, result) -> (desc ++ " stable", calcMac mac
data IncrementalVerifier = IncrementalVerifier data IncrementalVerifier = IncrementalVerifier
{ updateIncremental :: S.ByteString -> IO () { updateIncremental :: S.ByteString -> IO ()
-- ^ Called repeatedly on each peice of the content. -- ^ Called repeatedly on each peice of the content.
, finalizeIncremental :: IO Bool , finalizeIncremental :: IO (Maybe Bool)
-- ^ Called once the full content has been sent, returns true -- ^ Called once the full content has been sent, returns True
-- if the hash verified. -- if the hash verified, False if it did not, and Nothing if
, failIncremental :: IO () -- incremental verification was unable to be done.
-- ^ Call if the incremental verification needs to fail. , unableIncremental :: IO ()
-- ^ Call if the incremental verification is unable to be done.
, positionIncremental :: IO (Maybe Integer) , positionIncremental :: IO (Maybe Integer)
-- ^ Returns the number of bytes that have been fed to this -- ^ Returns the number of bytes that have been fed to this
-- incremental verifier so far. (Nothing if failIncremental was -- incremental verifier so far. (Nothing if unableIncremental was
-- called.) -- called.)
, descVerify :: String , descVerify :: String
-- ^ A description of what is done to verify the content. -- ^ A description of what is done to verify the content.
@ -311,9 +312,10 @@ mkIncrementalVerifier ctx descverify samechecksum = do
readIORef v >>= \case readIORef v >>= \case
(Just (ctx', _)) -> do (Just (ctx', _)) -> do
let digest = hashFinalize ctx' let digest = hashFinalize ctx'
return $ samechecksum (show digest) return $ Just $
Nothing -> return False samechecksum (show digest)
, failIncremental = writeIORef v Nothing Nothing -> return Nothing
, unableIncremental = writeIORef v Nothing
, positionIncremental = readIORef v >>= \case , positionIncremental = readIORef v >>= \case
Just (_, n) -> return (Just n) Just (_, n) -> return (Just n)
Nothing -> return Nothing Nothing -> return Nothing