mirror of https://github.com/apache/jclouds.git
Added retry to download-blob if MD5 checksums don't match.
This commit is contained in:
parent
d670ecfa6d
commit
c0d8e90e72
|
@ -25,6 +25,7 @@ See http://code.google.com/p/jclouds for details."
|
||||||
AsyncBlobStore BlobStore BlobStoreContext BlobStoreContextFactory
|
AsyncBlobStore BlobStore BlobStoreContext BlobStoreContextFactory
|
||||||
domain.BlobMetadata domain.StorageMetadata domain.Blob
|
domain.BlobMetadata domain.StorageMetadata domain.Blob
|
||||||
options.ListContainerOptions]
|
options.ListContainerOptions]
|
||||||
|
[java.security DigestOutputStream MessageDigest]
|
||||||
[com.google.common.collect ImmutableSet]))
|
[com.google.common.collect ImmutableSet]))
|
||||||
|
|
||||||
(defn blobstore
|
(defn blobstore
|
||||||
|
@ -67,6 +68,8 @@ Options can also be specified for extension modules
|
||||||
|
|
||||||
(def *blobstore*)
|
(def *blobstore*)
|
||||||
|
|
||||||
|
(def *max-retries* 3)
|
||||||
|
|
||||||
(defmacro with-blobstore [[& blobstore-or-args] & body]
|
(defmacro with-blobstore [[& blobstore-or-args] & body]
|
||||||
`(binding [*blobstore* (as-blobstore ~@blobstore-or-args)]
|
`(binding [*blobstore* (as-blobstore ~@blobstore-or-args)]
|
||||||
~@body))
|
~@body))
|
||||||
|
@ -256,9 +259,19 @@ container, name, string -> etag
|
||||||
[container-name name target]
|
[container-name name target]
|
||||||
(download-blob *blobstore* container-name name target))
|
(download-blob *blobstore* container-name name target))
|
||||||
|
|
||||||
(defmethod download-blob OutputStream [blobstore container-name name target]
|
(defmethod download-blob OutputStream [blobstore container-name name target
|
||||||
(let [blob (get-blob blobstore container-name name)]
|
& [retries]]
|
||||||
(copy (.getContent blob) target)))
|
(let [blob (get-blob blobstore container-name name)
|
||||||
|
digest-stream (DigestOutputStream. ;; TODO: not all clouds use MD5
|
||||||
|
target (MessageDigest/getInstance "MD5"))]
|
||||||
|
(copy (.getContent blob) digest-stream)
|
||||||
|
(let [digest (.digest (.getMessageDigest digest-stream))
|
||||||
|
metadata-digest (.getContentMD5 (.getMetadata blob))]
|
||||||
|
(when-not (MessageDigest/isEqual digest metadata-digest)
|
||||||
|
(if (<= (or retries 0) *max-retries*)
|
||||||
|
(recur blobstore container-name name target [(inc (or retries 1))])
|
||||||
|
(throw (Exception. (format "Download failed for %s/%s"
|
||||||
|
container-name name))))))))
|
||||||
|
|
||||||
(defmethod download-blob File [blobstore container-name name target]
|
(defmethod download-blob File [blobstore container-name name target]
|
||||||
(download-blob blobstore container-name name (FileOutputStream. target)))
|
(download-blob blobstore container-name name (FileOutputStream. target)))
|
||||||
|
|
|
@ -72,5 +72,22 @@
|
||||||
(is (= data (slurp (.getAbsolutePath data-file))))
|
(is (= data (slurp (.getAbsolutePath data-file))))
|
||||||
(finally (.delete data-file)))))
|
(finally (.delete data-file)))))
|
||||||
|
|
||||||
|
(deftest download-checksum-test
|
||||||
|
(binding [get-blob (fn [blobstore c-name name]
|
||||||
|
(let [blob (.newBlob blobstore name)
|
||||||
|
md (.getMetadata blob)]
|
||||||
|
(.setPayload blob "bogus payload")
|
||||||
|
(.setContentMD5 md (.getBytes "bogus MD5"))
|
||||||
|
blob))]
|
||||||
|
(let [name "test"
|
||||||
|
container-name "test-container"
|
||||||
|
data "test content"
|
||||||
|
data-file (java.io.File/createTempFile "jclouds" "data")]
|
||||||
|
(try (create-container container-name)
|
||||||
|
(create-blob container-name name data)
|
||||||
|
(is (thrown? Exception
|
||||||
|
(download-blob container-name name data-file)))
|
||||||
|
(finally (.delete data-file))))))
|
||||||
|
|
||||||
;; TODO: more tests involving blob-specific functions
|
;; TODO: more tests involving blob-specific functions
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue