/** * Retrieves the {@link CachedLayer} for the layer with digest {@code layerDigest}. * * @param layerDigest the layer digest * @return the {@link CachedLayer} referenced by the layer digest, if found * @throws CacheCorruptedException if the cache was found to be corrupted * @throws IOException if an I/O exception occurs */ public Maybe <CachedLayer> Retrieve(DescriptorDigest layerDigest) { layerDigest = layerDigest ?? throw new ArgumentNullException(nameof(layerDigest)); SystemPath layerDirectory = cacheStorageFiles.GetLayerDirectory(layerDigest); if (!Files.Exists(layerDirectory)) { return(Maybe.Empty <CachedLayer>()); } CachedLayer.Builder cachedLayerBuilder = CachedLayer.CreateBuilder().SetLayerDigest(layerDigest); foreach (SystemPath fileInLayerDirectory in Files.List(layerDirectory)) { if (CacheStorageFiles.IsLayerFile(fileInLayerDirectory)) { if (cachedLayerBuilder.HasLayerBlob()) { throw new CacheCorruptedException( cacheStorageFiles.GetCacheDirectory(), "Multiple layer files found for layer with digest " + layerDigest.GetHash() + " in directory: " + layerDirectory); } cachedLayerBuilder .SetLayerBlob(Blobs.From(fileInLayerDirectory)) .SetLayerDiffId(cacheStorageFiles.GetDiffId(fileInLayerDirectory)) .SetLayerSize(Files.Size(fileInLayerDirectory)); } } return(Maybe.Of(cachedLayerBuilder.Build())); }
/** * Writes an uncompressed {@code layerBlob} to the {@code layerDirectory}. * * @param uncompressedLayerBlob the uncompressed layer {@link Blob} * @param layerDirectory the directory for the layer * @return a {@link WrittenLayer} with the written layer information * @throws IOException if an I/O exception occurs */ private async Task <WrittenLayer> WriteUncompressedLayerBlobToDirectoryAsync( IBlob uncompressedLayerBlob, SystemPath layerDirectory) { using (TemporaryFile temporaryLayerFile = CacheStorageFiles.GetTemporaryLayerFile(layerDirectory)) { DescriptorDigest layerDiffId; BlobDescriptor blobDescriptor; // Writes the layer with GZIP compression. The original bytes are captured as the layer's // diff ID and the bytes outputted from the GZIP compression are captured as the layer's // content descriptor. using (CountingDigestOutputStream compressedDigestOutputStream = new CountingDigestOutputStream( Files.NewOutputStream(temporaryLayerFile.Path))) { using (GZipStream compressorStream = new GZipStream(compressedDigestOutputStream, CompressionMode.Compress, true)) { BlobDescriptor descriptor = await uncompressedLayerBlob.WriteToAsync(compressorStream).ConfigureAwait(false); layerDiffId = descriptor.GetDigest(); } // The GZIPOutputStream must be closed in order to write out the remaining compressed data. blobDescriptor = compressedDigestOutputStream.ComputeDigest(); } DescriptorDigest layerDigest = blobDescriptor.GetDigest(); long layerSize = blobDescriptor.GetSize(); // Renames the temporary layer file to the correct filename. SystemPath layerFile = layerDirectory.Resolve(cacheStorageFiles.GetLayerFilename(layerDiffId)); temporaryLayerFile.MoveIfDoesNotExist(layerFile); return(new WrittenLayer(layerDigest, layerDiffId, layerSize)); } }
/** * Writes a compressed {@code layerBlob} to the {@code layerDirectory}. * * @param compressedLayerBlob the compressed layer {@link Blob} * @param layerDirectory the directory for the layer * @return a {@link WrittenLayer} with the written layer information * @throws IOException if an I/O exception occurs */ private async Task <WrittenLayer> WriteCompressedLayerBlobToDirectoryAsync( IBlob compressedLayerBlob, SystemPath layerDirectory) { // Writes the layer file to the temporary directory. using (TemporaryFile temporaryLayerFile = CacheStorageFiles.GetTemporaryLayerFile(layerDirectory)) { BlobDescriptor layerBlobDescriptor; using (Stream fileOutputStream = Files.NewOutputStream(temporaryLayerFile.Path)) { layerBlobDescriptor = await compressedLayerBlob.WriteToAsync(fileOutputStream).ConfigureAwait(false); } // Gets the diff ID. DescriptorDigest layerDiffId = await GetDiffIdByDecompressingFileAsync(temporaryLayerFile.Path).ConfigureAwait(false); // Renames the temporary layer file to the correct filename. SystemPath layerFile = layerDirectory.Resolve(cacheStorageFiles.GetLayerFilename(layerDiffId)); temporaryLayerFile.MoveIfDoesNotExist(layerFile); return(new WrittenLayer( layerBlobDescriptor.GetDigest(), layerDiffId, layerBlobDescriptor.GetSize())); } }
public CacheStorageReader(CacheStorageFiles cacheStorageFiles) { this.cacheStorageFiles = cacheStorageFiles; }
public CacheStorageWriter(CacheStorageFiles cacheStorageFiles) { this.cacheStorageFiles = cacheStorageFiles; }
private LayersCache(CacheStorageFiles cacheStorageFiles) { cacheStorageWriter = new CacheStorageWriter(cacheStorageFiles); cacheStorageReader = new CacheStorageReader(cacheStorageFiles); }