From 771323510d8718ce58705a1d244b90e86db06ec8 Mon Sep 17 00:00:00 2001 From: Gilbert Chen Date: Mon, 8 Jan 2018 23:58:49 -0500 Subject: [PATCH] Don't download a fossil directly; resurrect it and download the chunk instead --- src/duplicacy_chunkdownloader.go | 51 +++++++++++++++++++------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/duplicacy_chunkdownloader.go b/src/duplicacy_chunkdownloader.go index ded4dee..71a1c03 100644 --- a/src/duplicacy_chunkdownloader.go +++ b/src/duplicacy_chunkdownloader.go @@ -298,35 +298,46 @@ func (downloader *ChunkDownloader) Download(threadIndex int, task ChunkDownloadT // will be set up before the encryption chunk.Reset(false) - // Find the chunk by ID first. - chunkPath, exist, _, err := downloader.storage.FindChunk(threadIndex, chunkID, false) - if err != nil { - LOG_ERROR("DOWNLOAD_CHUNK", "Failed to find the chunk %s: %v", chunkID, err) - return false - } + const MaxDownloadAttempts = 3 + for downloadAttempt := 0; ; downloadAttempt++ { - if !exist { - // No chunk is found. Have to find it in the fossil pool again. - chunkPath, exist, _, err = downloader.storage.FindChunk(threadIndex, chunkID, true) + // Find the chunk by ID first. + chunkPath, exist, _, err := downloader.storage.FindChunk(threadIndex, chunkID, false) if err != nil { LOG_ERROR("DOWNLOAD_CHUNK", "Failed to find the chunk %s: %v", chunkID, err) return false } if !exist { - // A chunk is not found. This is a serious error and hopefully it will never happen. + // No chunk is found. Have to find it in the fossil pool again. + fossilPath, exist, _, err := downloader.storage.FindChunk(threadIndex, chunkID, true) if err != nil { - LOG_FATAL("DOWNLOAD_CHUNK", "Chunk %s can't be found: %v", chunkID, err) - } else { - LOG_FATAL("DOWNLOAD_CHUNK", "Chunk %s can't be found", chunkID) + LOG_ERROR("DOWNLOAD_CHUNK", "Failed to find the chunk %s: %v", chunkID, err) + return false } - return false - } - LOG_DEBUG("CHUNK_FOSSIL", "Chunk %s has been marked as a fossil", chunkID) - } - const MaxDownloadAttempts = 3 - for downloadAttempt := 0; ; downloadAttempt++ { + if !exist { + // A chunk is not found. This is a serious error and hopefully it will never happen. + if err != nil { + LOG_FATAL("DOWNLOAD_CHUNK", "Chunk %s can't be found: %v", chunkID, err) + } else { + LOG_FATAL("DOWNLOAD_CHUNK", "Chunk %s can't be found", chunkID) + } + return false + } + + // We can't download the fossil directly. We have to turn it back into a regular chunk and try + // downloading again. + err = downloader.storage.MoveFile(threadIndex, fossilPath, chunkPath) + if err != nil { + LOG_FATAL("DOWNLOAD_CHUNK", "Failed to resurrect chunk %s: %v", chunkID, err) + return false + } + + LOG_WARN("DOWNLOAD_RESURRECT", "Fossil %s has been resurrected", chunkID) + continue + } + err = downloader.storage.DownloadFile(threadIndex, chunkPath, chunk) if err != nil { if err == io.ErrUnexpectedEOF && downloadAttempt < MaxDownloadAttempts { @@ -368,7 +379,7 @@ func (downloader *ChunkDownloader) Download(threadIndex int, task ChunkDownloadT if len(cachedPath) > 0 { // Save a copy to the local snapshot cache - err = downloader.snapshotCache.UploadFile(threadIndex, cachedPath, chunk.GetBytes()) + err := downloader.snapshotCache.UploadFile(threadIndex, cachedPath, chunk.GetBytes()) if err != nil { LOG_WARN("DOWNLOAD_CACHE", "Failed to add the chunk %s to the snapshot cache: %v", chunkID, err) }