added StoreContentTo

This is needed in addition to StoreContent, because retrieveKeyFile can
be used to retrieve to different destination files, not only the tmp
file for a key.

This commit was sponsored by Ole-Morten Duesund on Patreon.
This commit is contained in:
Joey Hess 2016-12-06 15:05:44 -04:00
parent b29088b8dc
commit 2bd2e0880c
No known key found for this signature in database
GPG key ID: C910D9222512E3C7
2 changed files with 49 additions and 27 deletions

View file

@ -16,7 +16,6 @@ module P2P.Annex
import Annex.Common import Annex.Common
import Annex.Content import Annex.Content
import Annex.Transfer import Annex.Transfer
import Annex.Notification
import P2P.Protocol import P2P.Protocol
import P2P.IO import P2P.IO
import Logs.Location import Logs.Location
@ -46,6 +45,9 @@ runLocal runmode runner a = case a of
tmp <- fromRepo $ gitAnnexTmpObjectLocation k tmp <- fromRepo $ gitAnnexTmpObjectLocation k
size <- liftIO $ catchDefaultIO 0 $ getFileSize tmp size <- liftIO $ catchDefaultIO 0 $ getFileSize tmp
runner (next (Len size)) runner (next (Len size))
FileSize f next -> do
size <- liftIO $ catchDefaultIO 0 $ getFileSize f
runner (next (Len size))
ContentSize k next -> do ContentSize k next -> do
let getsize = liftIO . catchMaybeIO . getFileSize let getsize = liftIO . catchMaybeIO . getFileSize
size <- inAnnex' isJust Nothing getsize k size <- inAnnex' isJust Nothing getsize k
@ -69,16 +71,15 @@ runLocal runmode runner a = case a of
Left _ -> return Nothing Left _ -> return Nothing
Right b -> runner (next b) Right b -> runner (next b)
_ -> return Nothing _ -> return Nothing
WriteContent k af (Offset o) (Len l) b next -> do StoreContent k af o l b next -> do
ok <- flip catchNonAsync (const $ return False) $ ok <- flip catchNonAsync (const $ return False) $
transfer download k af $ transfer download k af $
getViaTmp AlwaysVerify k $ \tmp -> liftIO $ do getViaTmp AlwaysVerify k $ \tmp ->
withBinaryFile tmp WriteMode $ \h -> do unVerified $ storefile tmp o l b
when (o /= 0) $ runner (next ok)
hSeek h AbsoluteSeek o StoreContentTo dest o l b next -> do
L.hPut h b ok <- flip catchNonAsync (const $ return False) $
sz <- getFileSize tmp storefile dest o l b
return (toInteger sz == l, UnVerified)
runner (next ok) runner (next ok)
SetPresent k u next -> do SetPresent k u next -> do
v <- tryNonAsync $ logChange k u InfoPresent v <- tryNonAsync $ logChange k u InfoPresent
@ -111,10 +112,17 @@ runLocal runmode runner a = case a of
next next
Right _ -> runner next Right _ -> runner next
where where
transfer mk k af a = case runmode of transfer mk k af ta = case runmode of
-- Update transfer logs when serving. -- Update transfer logs when serving.
Serving theiruuid -> Serving theiruuid ->
mk theiruuid k af noRetry (const a) noNotification mk theiruuid k af noRetry (const ta) noNotification
-- Transfer logs are updated higher in the stack when -- Transfer logs are updated higher in the stack when
-- a client. -- a client.
Client -> a Client -> ta
storefile dest (Offset o) (Len l) b = liftIO $ do
withBinaryFile dest WriteMode $ \h -> do
when (o /= 0) $
hSeek h AbsoluteSeek o
L.hPut h b
sz <- getFileSize dest
return (toInteger sz == l)

View file

@ -189,16 +189,25 @@ data LocalF c
= TmpContentSize Key (Len -> c) = TmpContentSize Key (Len -> c)
-- ^ Gets size of the temp file where received content may have -- ^ Gets size of the temp file where received content may have
-- been stored. If not present, returns 0. -- been stored. If not present, returns 0.
| FileSize FilePath (Len -> c)
-- ^ Gets size of the content of a file. If not present, returns 0.
| ContentSize Key (Maybe Len -> c) | ContentSize Key (Maybe Len -> c)
-- ^ Gets size of the content of a key, when the full content is -- ^ Gets size of the content of a key, when the full content is
-- present. -- present.
| ReadContent Key AssociatedFile Offset (L.ByteString -> c) | ReadContent Key AssociatedFile Offset (L.ByteString -> c)
-- ^ Lazily reads the content of a key. Note that the content -- ^ Lazily reads the content of a key. Note that the content
-- may change while it's being sent. -- may change while it's being sent.
| WriteContent Key AssociatedFile Offset Len L.ByteString (Bool -> c) | StoreContent Key AssociatedFile Offset Len L.ByteString (Bool -> c)
-- ^ Writes content to temp file starting at an offset. -- ^ Stores content to the key's temp file starting at an offset.
-- Once the whole content of the key has been stored, moves the -- Once the whole content of the key has been stored, moves the
-- temp file into place and returns True. -- temp file into place as the content of the key, and returns True.
--
-- Note: The ByteString may not contain the entire remaining content
-- of the key. Only once the temp file size == Len has the whole
-- content been transferred.
| StoreContentTo FilePath Offset Len L.ByteString (Bool -> c)
-- ^ Stores the content to a temp file starting at an offset.
-- Once the whole content of the key has been stored, returns True.
-- --
-- Note: The ByteString may not contain the entire remaining content -- Note: The ByteString may not contain the entire remaining content
-- of the key. Only once the temp file size == Len has the whole -- of the key. Only once the temp file size == Len has the whole
@ -246,16 +255,16 @@ checkPresent key = do
-} -}
lockContentWhile lockContentWhile
:: MonadMask m :: MonadMask m
=> (forall r. Proto r -> m r) => (forall r. r -> Proto r -> m r)
-> Key -> Key
-> (Bool -> m ()) -> (Bool -> m a)
-> m () -> m a
lockContentWhile runproto key a = bracket setup cleanup a lockContentWhile runproto key a = bracket setup cleanup a
where where
setup = runproto $ do setup = runproto False $ do
net $ sendMessage (LOCKCONTENT key) net $ sendMessage (LOCKCONTENT key)
checkSuccess checkSuccess
cleanup True = runproto $ net $ sendMessage UNLOCKCONTENT cleanup True = runproto () $ net $ sendMessage UNLOCKCONTENT
cleanup False = return () cleanup False = return ()
remove :: Key -> Proto Bool remove :: Key -> Proto Bool
@ -263,8 +272,11 @@ remove key = do
net $ sendMessage (REMOVE key) net $ sendMessage (REMOVE key)
checkSuccess checkSuccess
get :: Key -> AssociatedFile -> Proto Bool get :: FilePath -> Key -> AssociatedFile -> Proto Bool
get key af = receiveContent key af (\offset -> GET offset af key) get dest key af = receiveContent sizer storer (\offset -> GET offset af key)
where
sizer = fileSize dest
storer = storeContentTo dest
put :: Key -> AssociatedFile -> Proto Bool put :: Key -> AssociatedFile -> Proto Bool
put key af = do put key af = do
@ -349,7 +361,9 @@ serveAuthed myuuid = void $ serverLoop handler
if have if have
then net $ sendMessage ALREADY_HAVE then net $ sendMessage ALREADY_HAVE
else do else do
ok <- receiveContent key af PUT_FROM let sizer = tmpContentSize key
let storer = storeContent key af
ok <- receiveContent sizer storer PUT_FROM
when ok $ when ok $
local $ setPresent key myuuid local $ setPresent key myuuid
return ServerContinue return ServerContinue
@ -370,15 +384,15 @@ sendContent key af offset = do
net $ sendBytes len content net $ sendBytes len content
checkSuccess checkSuccess
receiveContent :: Key -> AssociatedFile -> (Offset -> Message) -> Proto Bool receiveContent :: Local Len -> (Offset -> Len -> L.ByteString -> Local Bool) -> (Offset -> Message) -> Proto Bool
receiveContent key af mkmsg = do receiveContent sizer storer mkmsg = do
Len n <- local $ tmpContentSize key Len n <- local sizer
let offset = Offset n let offset = Offset n
net $ sendMessage (mkmsg offset) net $ sendMessage (mkmsg offset)
r <- net receiveMessage r <- net receiveMessage
case r of case r of
DATA len -> do DATA len -> do
ok <- local . writeContent key af offset len ok <- local . storer offset len
=<< net (receiveBytes len) =<< net (receiveBytes len)
sendSuccess ok sendSuccess ok
return ok return ok