summaryrefslogtreecommitdiff
path: root/Remote
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2011-04-21 10:31:54 -0400
committerGravatar Joey Hess <joey@kitenet.net>2011-04-21 10:33:17 -0400
commit6fcd3e1ef77d3dc99da30cdf2b82489d4bd3d7df (patch)
tree5508b32f00b72af6eaee42ba132758af5d076651 /Remote
parentd8329731c617b278967304389c300f2c832db28d (diff)
fix S3 upload buffering problem
Provide file size to new version of hS3.
Diffstat (limited to 'Remote')
-rw-r--r--Remote/S3real.hs45
1 files changed, 31 insertions, 14 deletions
diff --git a/Remote/S3real.hs b/Remote/S3real.hs
index 5095b4039..2b0234dc2 100644
--- a/Remote/S3real.hs
+++ b/Remote/S3real.hs
@@ -10,7 +10,7 @@ module Remote.S3 (remote) where
import Control.Exception.Extensible (IOException)
import Network.AWS.AWSConnection
import Network.AWS.S3Object
-import Network.AWS.S3Bucket
+import Network.AWS.S3Bucket hiding (size)
import Network.AWS.AWSResult
import qualified Data.ByteString.Lazy.Char8 as L
import qualified Data.Map as M
@@ -18,6 +18,8 @@ import Data.Maybe
import Control.Monad (when)
import Control.Monad.State (liftIO)
import System.Environment
+import System.Posix.Files
+import System.Directory
import RemoteClass
import Types
@@ -30,6 +32,7 @@ import Config
import Remote.Special
import Remote.Encryptable
import Crypto
+import Key
remote :: RemoteType Annex
remote = RemoteType {
@@ -100,21 +103,35 @@ s3Setup u c = do
store :: Remote Annex -> Key -> Annex Bool
store r k = s3Action r False $ \(conn, bucket) -> do
g <- Annex.gitRepo
- content <- liftIO $ L.readFile $ gitAnnexLocation g k
- res <- liftIO $ storeHelper (conn, bucket) r k content
+ res <- liftIO $ storeHelper (conn, bucket) r k $ gitAnnexLocation g k
s3Bool res
storeEncrypted :: Remote Annex -> (Cipher, Key) -> Key -> Annex Bool
storeEncrypted r (cipher, enck) k = s3Action r False $ \(conn, bucket) -> do
g <- Annex.gitRepo
let f = gitAnnexLocation g k
- res <- liftIO $ withEncryptedContent cipher (L.readFile f) $ \s -> do
- storeHelper (conn, bucket) r enck s
+ -- To get file size of the encrypted content, have to use a temp file.
+ -- (An alternative would be chunking to to a constant size.)
+ let tmp = gitAnnexTmpLocation g enck
+ liftIO $ withEncryptedContent cipher (L.readFile f) $ \s -> L.writeFile tmp s
+ res <- liftIO $ storeHelper (conn, bucket) r enck tmp
+ tmp_exists <- liftIO $ doesFileExist tmp
+ when tmp_exists $ liftIO $ removeFile tmp
s3Bool res
-storeHelper :: (AWSConnection, String) -> Remote Annex -> Key -> L.ByteString -> IO (AWSResult ())
-storeHelper (conn, bucket) r k content = do
- let object = setStorageClass storageclass $ bucketKey bucket k content
+storeHelper :: (AWSConnection, String) -> Remote Annex -> Key -> FilePath -> IO (AWSResult ())
+storeHelper (conn, bucket) r k file = do
+ content <- liftIO $ L.readFile file
+ -- size is provided to S3 so the whole content does not need to be
+ -- buffered to calculate it
+ size <- case keySize k of
+ Just s -> return $ fromIntegral s
+ Nothing -> do
+ s <- liftIO $ getFileStatus file
+ return $ fileSize s
+ let object = setStorageClass storageclass $
+ S3Object bucket (show k) ""
+ [("Content-Length",(show size))] content
sendObject conn object
where
storageclass =
@@ -124,7 +141,7 @@ storeHelper (conn, bucket) r k content = do
retrieve :: Remote Annex -> Key -> FilePath -> Annex Bool
retrieve r k f = s3Action r False $ \(conn, bucket) -> do
- res <- liftIO $ getObject conn $ bucketKey bucket k L.empty
+ res <- liftIO $ getObject conn $ bucketKey bucket k
case res of
Right o -> do
liftIO $ L.writeFile f $ obj_data o
@@ -133,7 +150,7 @@ retrieve r k f = s3Action r False $ \(conn, bucket) -> do
retrieveEncrypted :: Remote Annex -> (Cipher, Key) -> FilePath -> Annex Bool
retrieveEncrypted r (cipher, enck) f = s3Action r False $ \(conn, bucket) -> do
- res <- liftIO $ getObject conn $ bucketKey bucket enck L.empty
+ res <- liftIO $ getObject conn $ bucketKey bucket enck
case res of
Right o -> liftIO $
withDecryptedContent cipher (return $ obj_data o) $ \content -> do
@@ -143,13 +160,13 @@ retrieveEncrypted r (cipher, enck) f = s3Action r False $ \(conn, bucket) -> do
remove :: Remote Annex -> Key -> Annex Bool
remove r k = s3Action r False $ \(conn, bucket) -> do
- res <- liftIO $ deleteObject conn $ bucketKey bucket k L.empty
+ res <- liftIO $ deleteObject conn $ bucketKey bucket k
s3Bool res
checkPresent :: Remote Annex -> Key -> Annex (Either IOException Bool)
checkPresent r k = s3Action r noconn $ \(conn, bucket) -> do
showNote ("checking " ++ name r ++ "...")
- res <- liftIO $ getObjectInfo conn $ bucketKey bucket k L.empty
+ res <- liftIO $ getObjectInfo conn $ bucketKey bucket k
case res of
Right _ -> return $ Right True
Left (AWSError _ _) -> return $ Right False
@@ -205,5 +222,5 @@ s3Action r noconn action = do
(Just b, Just c) -> action (c, b)
_ -> return noconn
-bucketKey :: String -> Key -> L.ByteString -> S3Object
-bucketKey bucket k content = S3Object bucket (show k) "" [] content
+bucketKey :: String -> Key -> S3Object
+bucketKey bucket k = S3Object bucket (show k) "" [] L.empty