github.com/Synthesix/Sia@v1.3.3-0.20180413141344-f863baeed3ca/modules/renter/downloadcache.go (about)

     1  package renter
     2  
     3  // TODO expose the downloadCacheSize as a variable and allow users to set it
     4  // via the API.
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/NebulousLabs/errors"
    10  )
    11  
    12  // addChunkToCache adds the chunk to the cache if the download is a streaming
    13  // endpoint download.
    14  // TODO this won't be necessary anymore once we have partial downloads.
    15  func (udc *unfinishedDownloadChunk) addChunkToCache(data []byte) {
    16  	if udc.download.staticDestinationType == destinationTypeSeekStream {
    17  		// We only cache streaming chunks since browsers and media players tend to only request a few kib at once when streaming data. That way we can prevent scheduling the same chunk for download over and over.
    18  		return
    19  	}
    20  	udc.cacheMu.Lock()
    21  	// Prune cache if necessary.
    22  	// TODO insteado of deleting a 'random' key, delete the
    23  	// least-recently-accessed element of the cache.
    24  	for key := range udc.chunkCache {
    25  		if len(udc.chunkCache) < downloadCacheSize {
    26  			break
    27  		}
    28  		delete(udc.chunkCache, key)
    29  	}
    30  	udc.chunkCache[udc.staticCacheID] = data
    31  	udc.cacheMu.Unlock()
    32  }
    33  
    34  // managedTryCache tries to retrieve the chunk from the renter's cache. If
    35  // successful it will write the data to the destination and stop the download
    36  // if it was the last missing chunk. The function returns true if the chunk was
    37  // in the cache.
    38  // TODO in the future we might need cache invalidation. At the
    39  // moment this doesn't worry us since our files are static.
    40  func (r *Renter) managedTryCache(udc *unfinishedDownloadChunk) bool {
    41  	udc.mu.Lock()
    42  	defer udc.mu.Unlock()
    43  	r.cmu.Lock()
    44  	data, cached := r.chunkCache[udc.staticCacheID]
    45  	r.cmu.Unlock()
    46  	if !cached {
    47  		return false
    48  	}
    49  	start := udc.staticFetchOffset
    50  	end := start + udc.staticFetchLength
    51  	_, err := udc.destination.WriteAt(data[start:end], udc.staticWriteOffset)
    52  	if err != nil {
    53  		r.log.Println("WARN: failed to write cached chunk to destination:", err)
    54  		udc.fail(errors.AddContext(err, "failed to write cached chunk to destination"))
    55  		return true
    56  	}
    57  
    58  	// Check if the download is complete now.
    59  	udc.download.mu.Lock()
    60  	udc.download.chunksRemaining--
    61  	if udc.download.chunksRemaining == 0 {
    62  		udc.download.endTime = time.Now()
    63  		close(udc.download.completeChan)
    64  	}
    65  	udc.download.mu.Unlock()
    66  	return true
    67  }