/// <see cref="StoreWriter.DoOptCommitAsync"/> protected override async Task DoOptCommitAsync(Hash hash, Func <Task> optionalWrite, CancellationToken cancel) { var path = DiskStorePaths.PathOfHash(_path, hash); if (!File.Exists(path)) { if (optionalWrite != null) { await optionalWrite().ConfigureAwait(false); } // Close the file before the move, but only after the optional // writes are finished. _temp.Close(); // ReSharper disable AssignNullToNotNullAttribute // ... we know there's a dirname in the path (it's, at the very least, _path itself) Directory.CreateDirectory(Path.GetDirectoryName(path)); // ReSharper restore AssignNullToNotNullAttribute try { File.Move(_tempPath, path); } catch (IOException) when(File.Exists(path)) { // Another writer raced us to create the destination file. // So, there's nothing left for us to do. } } }
/// <summary> Delete the blob for the specified hash. </summary> /// <remarks> Disks do not have infinite storage space, so deleting values is necessary. </remarks> public void Delete(Hash hash) { var path = DiskStorePaths.PathOfHash(Path, hash); if (!File.Exists(path)) { return; } try { File.Delete(path); } catch (IOException) when(!File.Exists(path)) { // Another writer raced us to delete the destination file. // So, there's nothing left for us to do. } var directory = P.GetDirectoryName(path); if (directory == null) { return; } try { Directory.Delete(path); } catch (IOException) { // There is no thread-safe way to check whether a directory is // empty, and then delete it (there's always the possibility for // another thread to create a file in that directory between the // empty-check and the deletion), so all we can do is try to delete // it (in non-recursive mode, so that it can only be dropped if it // is empty) and ignore the exception thrown if it contains a file. } }
/// <summary> Determine whether the blob exists. </summary> public bool BlobExists(Hash hash) { var blobPath = DiskStorePaths.PathOfHash(Path, hash); return(File.Exists(blobPath)); }
/// <see cref="IReadOnlyStore{TBlobRef}.this"/> public IReadBlobRef this[Hash hash] => new DiskBlobRef(hash, DiskStorePaths.PathOfHash(Path, hash));