summaryrefslogtreecommitdiff
path: root/Remote/Helper
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2012-11-19 13:18:23 -0400
committerGravatar Joey Hess <joey@kitenet.net>2012-11-19 13:18:23 -0400
commit798c3d45c11cfe3d7604b27f3271f50d0f810db7 (patch)
tree946bf6b717e069623d8c48a93402e08db564dcd5 /Remote/Helper
parent8ed7d090ab319bcc45e1593cd2613d38a3615120 (diff)
directory special remote: Made more efficient and robust.
Files are now written to a tmp directory in the remote, and once all chunks are written, etc, it's moved into the final place atomically. For now, checkpresent still checks every single chunk of a file, because the old method could leave partially transferred files with some chunks present and others not.
Diffstat (limited to 'Remote/Helper')
-rw-r--r--Remote/Helper/Chunked.hs27
1 files changed, 11 insertions, 16 deletions
diff --git a/Remote/Helper/Chunked.hs b/Remote/Helper/Chunked.hs
index e609e6354..4f04a1c38 100644
--- a/Remote/Helper/Chunked.hs
+++ b/Remote/Helper/Chunked.hs
@@ -58,33 +58,28 @@ chunkStream = map (\n -> ".chunk" ++ show n) [1 :: Integer ..]
{- Given the base destination to use to store a value,
- generates a stream of temporary destinations (just one when not chunking)
- and passes it to an action, which should chunk and store the data,
- - and return the destinations it stored to, or [] on error.
- -
- - Then calles the finalizer to rename the temporary destinations into
- - their final places (and do any other cleanup), and writes the chunk count
- - (if chunking)
+ - and return the destinations it stored to, or [] on error. Then
+ - calls the storer to write the chunk count (if chunking). Finally, the
+ - fianlizer is called to rename the tmp into the dest
+ - (and do any other cleanup).
-}
-storeChunks :: FilePath -> ChunkSize -> ([FilePath] -> IO [FilePath]) -> (FilePath -> String -> IO ()) -> (FilePath -> FilePath -> IO ()) -> IO Bool
-storeChunks basedest chunksize storer recorder finalizer =
+storeChunks :: Key -> FilePath -> FilePath -> ChunkSize -> ([FilePath] -> IO [FilePath]) -> (FilePath -> String -> IO ()) -> (FilePath -> FilePath -> IO ()) -> IO Bool
+storeChunks key tmp dest chunksize storer recorder finalizer =
either (const $ return False) return
=<< (E.try go :: IO (Either E.SomeException Bool))
where
go = do
stored <- storer tmpdests
- forM_ stored $ \d -> do
- let dest = detmpprefix d
- finalizer d dest
when (chunksize /= Nothing) $ do
- let chunkcount = basedest ++ chunkCount
+ let chunkcount = basef ++ chunkCount
recorder chunkcount (show $ length stored)
+ finalizer tmp dest
return (not $ null stored)
- tmpprefix = ".tmp"
- detmpprefix f = take (length f - tmpprefixlen) f
- tmpprefixlen = length tmpprefix
+ basef = tmp ++ keyFile key
tmpdests
- | chunksize == Nothing = [basedest ++ tmpprefix]
- | otherwise = map (++ tmpprefix) $ map (basedest ++) chunkStream
+ | chunksize == Nothing = [basef]
+ | otherwise = map (basef ++ ) chunkStream
{- Given a list of destinations to use, chunks the data according to the
- ChunkSize, and runs the storer action to store each chunk. Returns