From dcd2ae26b662c19b1c2961fc6ef529a206bc1d86 Mon Sep 17 00:00:00 2001 From: bezzad Date: Wed, 18 Sep 2024 17:47:19 +0330 Subject: [PATCH] fixed name conventions to camelcase protected members --- src/Downloader.DummyHttpServer/DummyData.cs | 4 +- src/Downloader.DummyHttpServer/HttpServer.cs | 4 +- .../HelperTests/AssertHelperTest.cs | 4 +- .../HelperTests/DummyDataTest.cs | 8 +- .../HelperTests/DummyFileControllerTest.cs | 80 +++---- .../HelperTests/DummyLazyStreamTest.cs | 8 +- .../DownloadIntegrationTest.cs | 60 +++--- .../UnitTests/ChunkDownloaderTest.cs | 4 +- .../UnitTests/DownloadBuilderTest.cs | 88 ++++---- .../UnitTests/PauseTokenTest.cs | 12 +- .../UnitTests/StorageTestOnFile.cs | 16 +- src/Downloader/AbstractDownloadService.cs | 202 ++++++++++++++---- src/Downloader/ConcurrentPacketBuffer.cs | 54 ++--- src/Downloader/Download.cs | 48 ++--- src/Downloader/DownloadBuilder.cs | 30 +-- src/Downloader/DownloadService.cs | 26 +-- src/Downloader/PauseToken.cs | 8 +- src/Downloader/PauseTokenSource.cs | 12 +- 18 files changed, 391 insertions(+), 277 deletions(-) diff --git a/src/Downloader.DummyHttpServer/DummyData.cs b/src/Downloader.DummyHttpServer/DummyData.cs index 998cf50..66a0ba8 100644 --- a/src/Downloader.DummyHttpServer/DummyData.cs +++ b/src/Downloader.DummyHttpServer/DummyData.cs @@ -9,7 +9,7 @@ namespace Downloader.DummyHttpServer; [ExcludeFromCodeCoverage] public static class DummyData { - private static Random _rand = new Random(DateTime.Now.GetHashCode()); + private static Random Rand = new Random(DateTime.Now.GetHashCode()); /// /// Generates random bytes @@ -21,7 +21,7 @@ public static byte[] GenerateRandomBytes(int length) throw new ArgumentException("length has to be > 0"); byte[] buffer = new byte[length]; - _rand.NextBytes(buffer); + Rand.NextBytes(buffer); return buffer; } diff --git a/src/Downloader.DummyHttpServer/HttpServer.cs b/src/Downloader.DummyHttpServer/HttpServer.cs index 7482a4a..f6cb7e4 100644 --- a/src/Downloader.DummyHttpServer/HttpServer.cs +++ b/src/Downloader.DummyHttpServer/HttpServer.cs @@ -13,7 +13,7 @@ namespace Downloader.DummyHttpServer; [ExcludeFromCodeCoverage] public class HttpServer { - private static IMemoryCache _cache = new MemoryCache(new MemoryCacheOptions()); + private static IMemoryCache Cache = new MemoryCache(new MemoryCacheOptions()); private static IWebHost Server; public static int Port { get; set; } = 3333; public static CancellationTokenSource CancellationToken { get; set; } @@ -31,7 +31,7 @@ public static void Run(int port) if (CancellationToken.IsCancellationRequested) return; - Server ??= _cache.GetOrCreate("DownloaderWebHost", e => { + Server ??= Cache.GetOrCreate("DownloaderWebHost", e => { var host = CreateHostBuilder(port); host.RunAsync(CancellationToken.Token).ConfigureAwait(false); return host; diff --git a/src/Downloader.Test/HelperTests/AssertHelperTest.cs b/src/Downloader.Test/HelperTests/AssertHelperTest.cs index ace572d..dc658c3 100644 --- a/src/Downloader.Test/HelperTests/AssertHelperTest.cs +++ b/src/Downloader.Test/HelperTests/AssertHelperTest.cs @@ -66,10 +66,10 @@ public void TestChunksAreNotEquals() }; // act - void testAssertHelper() => AssertHelper.AreEquals(chunk1, chunk2); + void TestAssertHelper() => AssertHelper.AreEquals(chunk1, chunk2); // assert - Assert.ThrowsAny(testAssertHelper); + Assert.ThrowsAny(TestAssertHelper); Assert.NotEqual(chunk1, chunk2); } diff --git a/src/Downloader.Test/HelperTests/DummyDataTest.cs b/src/Downloader.Test/HelperTests/DummyDataTest.cs index 57fbcc8..3a1d902 100644 --- a/src/Downloader.Test/HelperTests/DummyDataTest.cs +++ b/src/Downloader.Test/HelperTests/DummyDataTest.cs @@ -29,10 +29,10 @@ public void GenerateOrderedBytesLessThan1Test() int size = 0; // act - void act() => DummyData.GenerateOrderedBytes(size); + void Act() => DummyData.GenerateOrderedBytes(size); // assert - Assert.ThrowsAny(act); + Assert.ThrowsAny(Act); } [Fact] @@ -56,10 +56,10 @@ public void GenerateRandomBytesLessThan1Test() int size = 0; // act - void act() => DummyData.GenerateRandomBytes(size); + void Act() => DummyData.GenerateRandomBytes(size); // assert - Assert.ThrowsAny(act); + Assert.ThrowsAny(Act); } [Fact] diff --git a/src/Downloader.Test/HelperTests/DummyFileControllerTest.cs b/src/Downloader.Test/HelperTests/DummyFileControllerTest.cs index 8773bf4..6a2b666 100644 --- a/src/Downloader.Test/HelperTests/DummyFileControllerTest.cs +++ b/src/Downloader.Test/HelperTests/DummyFileControllerTest.cs @@ -10,8 +10,8 @@ namespace Downloader.Test.HelperTests; public class DummyFileControllerTest { - private readonly string contentType = "application/octet-stream"; - private WebHeaderCollection headers; + private readonly string _contentType = "application/octet-stream"; + private WebHeaderCollection _headers; [Fact] public void GetFileTest() @@ -27,8 +27,8 @@ public void GetFileTest() // assert Assert.True(dummyData.SequenceEqual(bytes)); - Assert.Equal(size.ToString(), headers["Content-Length"]); - Assert.Equal(contentType, headers["Content-Type"]); + Assert.Equal(size.ToString(), _headers["Content-Length"]); + Assert.Equal(_contentType, _headers["Content-Type"]); } [Fact] @@ -46,8 +46,8 @@ public void GetFileWithNameTest() // assert Assert.True(dummyData.SequenceEqual(bytes)); - Assert.Equal(size.ToString(), headers["Content-Length"]); - Assert.Equal(contentType, headers["Content-Type"]); + Assert.Equal(size.ToString(), _headers["Content-Length"]); + Assert.Equal(_contentType, _headers["Content-Type"]); } [Fact] @@ -67,8 +67,8 @@ public void GetSingleByteFileWithNameTest() // assert Assert.True(bytes.All(i => i == fillByte)); Assert.True(dummyData.SequenceEqual(bytes)); - Assert.Equal(size.ToString(), headers["Content-Length"]); - Assert.Equal(contentType, headers["Content-Type"]); + Assert.Equal(size.ToString(), _headers["Content-Length"]); + Assert.Equal(_contentType, _headers["Content-Type"]); } [Fact] @@ -86,8 +86,8 @@ public void GetFileWithoutHeaderTest() // assert Assert.True(dummyData.SequenceEqual(bytes)); - Assert.Null(headers["Content-Length"]); - Assert.Null(headers["Content-Type"]); + Assert.Null(_headers["Content-Length"]); + Assert.Null(_headers["Content-Type"]); } [Fact] @@ -107,8 +107,8 @@ public void GetSingleByteFileWithoutHeaderTest() // assert Assert.True(bytes.All(i => i == fillByte)); Assert.True(dummyData.SequenceEqual(bytes)); - Assert.Null(headers["Content-Length"]); - Assert.Null(headers["Content-Type"]); + Assert.Null(_headers["Content-Length"]); + Assert.Null(_headers["Content-Type"]); } [Fact] @@ -126,9 +126,9 @@ public void GetFileWithContentDispositionTest() // assert Assert.True(dummyData.SequenceEqual(bytes)); - Assert.Equal(size.ToString(), headers["Content-Length"]); - Assert.Equal(contentType, headers["Content-Type"]); - Assert.Contains($"filename={filename};", headers["Content-Disposition"]); + Assert.Equal(size.ToString(), _headers["Content-Length"]); + Assert.Equal(_contentType, _headers["Content-Type"]); + Assert.Contains($"filename={filename};", _headers["Content-Disposition"]); } [Fact] @@ -148,9 +148,9 @@ public void GetSingleByteFileWithContentDispositionTest() // assert Assert.True(bytes.All(i => i == fillByte)); Assert.True(dummyData.SequenceEqual(bytes)); - Assert.Equal(size.ToString(), headers["Content-Length"]); - Assert.Equal(contentType, headers["Content-Type"]); - Assert.Contains($"filename={filename};", headers["Content-Disposition"]); + Assert.Equal(size.ToString(), _headers["Content-Length"]); + Assert.Equal(_contentType, _headers["Content-Type"]); + Assert.Contains($"filename={filename};", _headers["Content-Disposition"]); } [Fact] @@ -167,10 +167,10 @@ public void GetFileWithRangeTest() // assert Assert.True(dummyData.Take(512).SequenceEqual(bytes.Take(512))); - Assert.Equal(contentType, headers["Content-Type"]); - Assert.Equal("512", headers["Content-Length"]); - Assert.Equal("bytes 0-511/1024", headers["Content-Range"]); - Assert.Equal("bytes", headers["Accept-Ranges"]); + Assert.Equal(_contentType, _headers["Content-Type"]); + Assert.Equal("512", _headers["Content-Length"]); + Assert.Equal("bytes 0-511/1024", _headers["Content-Range"]); + Assert.Equal("bytes", _headers["Accept-Ranges"]); } [Fact] @@ -188,9 +188,9 @@ public void GetFileWithNoAcceptRangeTest() // assert Assert.True(dummyData.SequenceEqual(bytes)); - Assert.Equal(size.ToString(), headers["Content-Length"]); - Assert.Equal(contentType, headers["Content-Type"]); - Assert.Null(headers["Accept-Ranges"]); + Assert.Equal(size.ToString(), _headers["Content-Length"]); + Assert.Equal(_contentType, _headers["Content-Type"]); + Assert.Null(_headers["Accept-Ranges"]); } [Fact] @@ -210,9 +210,9 @@ public void GetSingleByteFileWithNoAcceptRangeTest() // assert Assert.True(bytes.All(i => i == fillByte)); Assert.True(dummyData.SequenceEqual(bytes)); - Assert.Equal(size.ToString(), headers["Content-Length"]); - Assert.Equal(contentType, headers["Content-Type"]); - Assert.Null(headers["Accept-Ranges"]); + Assert.Equal(size.ToString(), _headers["Content-Length"]); + Assert.Equal(_contentType, _headers["Content-Type"]); + Assert.Null(_headers["Accept-Ranges"]); } [Fact] @@ -230,9 +230,9 @@ public void GetFileWithNameOnRedirectTest() // assert Assert.True(dummyData.SequenceEqual(bytes)); - Assert.Equal(size.ToString(), headers["Content-Length"]); - Assert.Equal(contentType, headers["Content-Type"]); - Assert.NotEqual(url, headers[nameof(WebResponse.ResponseUri)]); + Assert.Equal(size.ToString(), _headers["Content-Length"]); + Assert.Equal(_contentType, _headers["Content-Type"]); + Assert.NotEqual(url, _headers[nameof(WebResponse.ResponseUri)]); } [Fact] @@ -245,12 +245,12 @@ public void GetFileWithFailureAfterOffsetTest() string url = DummyFileHelper.GetFileWithFailureAfterOffset(size, failureOffset); // act - void getHeaders() => ReadAndGetHeaders(url, bytes, false); + void GetHeaders() => ReadAndGetHeaders(url, bytes, false); // assert - Assert.ThrowsAny(getHeaders); - Assert.Equal(size.ToString(), headers["Content-Length"]); - Assert.Equal(contentType, headers["Content-Type"]); + Assert.ThrowsAny(GetHeaders); + Assert.Equal(size.ToString(), _headers["Content-Length"]); + Assert.Equal(_contentType, _headers["Content-Type"]); Assert.Equal(0, bytes[size - 1]); } @@ -264,12 +264,12 @@ public void GetFileWithTimeoutAfterOffsetTest() string url = DummyFileHelper.GetFileWithTimeoutAfterOffset(size, timeoutOffset); // act - void getHeaders() => ReadAndGetHeaders(url, bytes, false); + void GetHeaders() => ReadAndGetHeaders(url, bytes, false); // assert - Assert.ThrowsAny(getHeaders); - Assert.Equal(size.ToString(), headers["Content-Length"]); - Assert.Equal(contentType, headers["Content-Type"]); + Assert.ThrowsAny(GetHeaders); + Assert.Equal(size.ToString(), _headers["Content-Length"]); + Assert.Equal(_contentType, _headers["Content-Type"]); Assert.Equal(0, bytes[size - 1]); } @@ -287,7 +287,7 @@ private void ReadAndGetHeaders(string url, byte[] bytes, bool justFirst512Bytes // keep response headers downloadResponse.Headers.Add(nameof(WebResponse.ResponseUri), downloadResponse.ResponseUri.ToString()); - headers = downloadResponse.Headers; + _headers = downloadResponse.Headers; // read stream data var readCount = 1; diff --git a/src/Downloader.Test/HelperTests/DummyLazyStreamTest.cs b/src/Downloader.Test/HelperTests/DummyLazyStreamTest.cs index bf447fd..1f576c8 100644 --- a/src/Downloader.Test/HelperTests/DummyLazyStreamTest.cs +++ b/src/Downloader.Test/HelperTests/DummyLazyStreamTest.cs @@ -31,10 +31,10 @@ public void GenerateOrderedBytesStreamLessThan1Test() int size = 0; // act - void act() => new DummyLazyStream(DummyDataType.Order, size); + void Act() => new DummyLazyStream(DummyDataType.Order, size); // assert - Assert.ThrowsAny(act); + Assert.ThrowsAny(Act); } [Fact] @@ -58,10 +58,10 @@ public void GenerateRandomBytesLessThan1Test() int size = 0; // act - void act() => new DummyLazyStream(DummyDataType.Random, size); + void Act() => new DummyLazyStream(DummyDataType.Random, size); // assert - Assert.ThrowsAny(act); + Assert.ThrowsAny(Act); } [Fact] diff --git a/src/Downloader.Test/IntegrationTests/DownloadIntegrationTest.cs b/src/Downloader.Test/IntegrationTests/DownloadIntegrationTest.cs index 26f282b..65d26da 100644 --- a/src/Downloader.Test/IntegrationTests/DownloadIntegrationTest.cs +++ b/src/Downloader.Test/IntegrationTests/DownloadIntegrationTest.cs @@ -15,7 +15,7 @@ public abstract class DownloadIntegrationTest : IDisposable { protected static byte[] FileData { get; set; } protected readonly ITestOutputHelper Output; - protected string URL { get; set; } + protected string Url { get; set; } protected int FileSize { get; set; } protected string Filename { get; set; } protected string FilePath { get; set; } @@ -29,7 +29,7 @@ public DownloadIntegrationTest(ITestOutputHelper output) FilePath = Path.Combine(Path.GetTempPath(), Filename); FileSize = DummyFileHelper.FileSize16Kb; FileData ??= DummyFileHelper.File16Kb; - URL = DummyFileHelper.GetFileWithNameUrl(Filename, FileSize); + Url = DummyFileHelper.GetFileWithNameUrl(Filename, FileSize); } public void Dispose() @@ -64,7 +64,7 @@ public async Task DownloadUrlWithFilenameOnMemoryTest() }; // act - await using var memoryStream = await Downloader.DownloadFileTaskAsync(URL); + await using var memoryStream = await Downloader.DownloadFileTaskAsync(Url); // assert Assert.True(downloadCompletedSuccessfully, resultMessage); @@ -98,7 +98,7 @@ public async Task DownloadAndReadFileOnDownloadFileCompletedEventTest() }; // act - await Downloader.DownloadFileTaskAsync(URL, destFilename); + await Downloader.DownloadFileTaskAsync(Url, destFilename); // assert Assert.True(downloadCompletedSuccessfully); @@ -118,7 +118,7 @@ public async Task Download16KbWithoutFilenameOnDirectoryTest() var dir = new DirectoryInfo(Path.GetTempPath()); // act - await Downloader.DownloadFileTaskAsync(URL, dir); + await Downloader.DownloadFileTaskAsync(Url, dir); // assert Assert.True(Downloader.Package.IsSaveComplete); @@ -136,7 +136,7 @@ public async Task Download16KbWithoutFilenameOnDirectoryTest() public async Task Download16KbWithFilenameTest() { // act - await Downloader.DownloadFileTaskAsync(URL, Path.GetTempFileName()); + await Downloader.DownloadFileTaskAsync(Url, Path.GetTempFileName()); // assert Assert.True(File.Exists(Downloader.Package.FileName)); @@ -178,7 +178,7 @@ public async Task Download1KbWhenAnotherBiggerFileExistTest() public async Task Download16KbOnMemoryTest() { // act - var fileBytes = await Downloader.DownloadFileTaskAsync(URL); + var fileBytes = await Downloader.DownloadFileTaskAsync(Url); // assert Assert.Equal(expected: FileSize, actual: Downloader.Package.TotalFileSize); @@ -195,7 +195,7 @@ public async Task DownloadProgressChangedTest() Downloader.DownloadProgressChanged += (_, _) => Interlocked.Increment(ref progressCounter); // act - await Downloader.DownloadFileTaskAsync(URL); + await Downloader.DownloadFileTaskAsync(Url); // assert // Note: some times received bytes on read stream method was less than block size! @@ -234,7 +234,7 @@ public async Task StopResumeDownloadTest() }; // act - await Downloader.DownloadFileTaskAsync(URL, Path.GetTempFileName()); + await Downloader.DownloadFileTaskAsync(Url, Path.GetTempFileName()); while (expectedStopCount > downloadFileExecutionCounter++) { // resume download from stopped point. @@ -275,7 +275,7 @@ public async Task PauseResumeDownloadTest() }; // act - await Downloader.DownloadFileTaskAsync(URL, Path.GetTempFileName()); + await Downloader.DownloadFileTaskAsync(Url, Path.GetTempFileName()); var stream = File.ReadAllBytes(Downloader.Package.FileName); // assert @@ -313,7 +313,7 @@ public async Task StopResumeDownloadFromLastPositionTest() }; // act - await Downloader.DownloadFileTaskAsync(URL); + await Downloader.DownloadFileTaskAsync(Url); while (expectedStopCount > downloadFileExecutionCounter++) { // resume download from stopped point. @@ -345,7 +345,7 @@ public async Task StopResumeDownloadOverFirstPackagePositionTest() }; // act - var result = await Downloader.DownloadFileTaskAsync(URL); + var result = await Downloader.DownloadFileTaskAsync(Url); // check point of package for once time var firstCheckPointPackage = JsonConvert.SerializeObject(Downloader.Package); @@ -389,7 +389,7 @@ public async Task TestTotalReceivedBytesWhenResumeDownload() }; // act - await Downloader.DownloadFileTaskAsync(URL); + await Downloader.DownloadFileTaskAsync(Url); await Downloader.DownloadFileTaskAsync(Downloader.Package); // resume download from stopped point. // assert @@ -421,7 +421,7 @@ public async Task TestTotalReceivedBytesOnResumeDownloadWhenLostDownloadedData() }; // act - await Downloader.DownloadFileTaskAsync(URL); + await Downloader.DownloadFileTaskAsync(Url); Downloader.Package.Storage.Dispose(); // set position to zero await Downloader.DownloadFileTaskAsync(Downloader.Package); // resume download from stopped point. @@ -448,7 +448,7 @@ public async Task SpeedLimitTest() }; // act - await Downloader.DownloadFileTaskAsync(URL); + await Downloader.DownloadFileTaskAsync(Url); // assert Assert.Equal(FileSize, Downloader.Package.TotalFileSize); @@ -478,7 +478,7 @@ public async Task DynamicSpeedLimitTest() }; // act - await Downloader.DownloadFileTaskAsync(URL); + await Downloader.DownloadFileTaskAsync(Url); averageSpeed /= progressCounter; // assert @@ -495,7 +495,7 @@ public async Task TestSizeWhenDownloadOnMemoryStream() // act - await using var stream = await Downloader.DownloadFileTaskAsync(URL); + await using var stream = await Downloader.DownloadFileTaskAsync(Url); // assert Assert.Equal(FileSize, Downloader.Package.TotalFileSize); @@ -509,7 +509,7 @@ public async Task TestTypeWhenDownloadOnMemoryStream() // act - await using var stream = await Downloader.DownloadFileTaskAsync(URL); + await using var stream = await Downloader.DownloadFileTaskAsync(Url); // assert Assert.True(stream is MemoryStream); @@ -519,7 +519,7 @@ public async Task TestTypeWhenDownloadOnMemoryStream() public async Task TestContentWhenDownloadOnMemoryStream() { // act - await using var stream = await Downloader.DownloadFileTaskAsync(URL); + await using var stream = await Downloader.DownloadFileTaskAsync(Url); var data = (stream as MemoryStream)?.ToArray(); // assert @@ -537,7 +537,7 @@ public async Task Download256BytesRangeOfFileTest() // act - await using var stream = await Downloader.DownloadFileTaskAsync(URL); + await using var stream = await Downloader.DownloadFileTaskAsync(Url); // assert Assert.NotNull(stream); @@ -562,7 +562,7 @@ public async Task DownloadNegetiveRangeOfFileTest() // act - await using var stream = await Downloader.DownloadFileTaskAsync(URL); + await using var stream = await Downloader.DownloadFileTaskAsync(Url); var bytes = ((MemoryStream)stream).ToArray(); // assert @@ -587,7 +587,7 @@ public async Task TestDownloadParallelVsHalfOfChunks() }; // act - await using var stream = await Downloader.DownloadFileTaskAsync(URL); + await using var stream = await Downloader.DownloadFileTaskAsync(Url); var bytes = ((MemoryStream)stream).ToArray(); // assert @@ -622,7 +622,7 @@ public async Task TestResumeImmediatelyAfterCanceling() }; // act - await Downloader.DownloadFileTaskAsync(URL); + await Downloader.DownloadFileTaskAsync(Url); await using var stream = await Downloader.DownloadFileTaskAsync(Downloader.Package); // resume // assert @@ -732,7 +732,7 @@ public async Task TestStopDownloadWithCancellationToken() }; // act - await Downloader.DownloadFileTaskAsync(URL, cts.Token); + await Downloader.DownloadFileTaskAsync(Url, cts.Token); // assert Assert.True(downloadCancelled); @@ -813,12 +813,12 @@ public async Task DownloadBigFileOnDisk() Config.ChunkCount = 8; Config.ParallelCount = 8; Config.MaximumBytesPerSecond = 0; - URL = DummyFileHelper.GetFileWithNameUrl(Filename, totalSize); + Url = DummyFileHelper.GetFileWithNameUrl(Filename, totalSize); //Downloader.AddLogger(FileLogger.Factory("D:\\TestDownload")); var actualFile = DummyData.GenerateOrderedBytes(totalSize); // act - await Downloader.DownloadFileTaskAsync(URL, FilePath); + await Downloader.DownloadFileTaskAsync(Url, FilePath); var file = await File.ReadAllBytesAsync(FilePath); // assert @@ -838,11 +838,11 @@ public async Task DownloadBigFileOnMemory() Config.ChunkCount = 8; Config.ParallelCount = 8; Config.MaximumBytesPerSecond = 0; - URL = DummyFileHelper.GetFileWithNameUrl(Filename, totalSize); + Url = DummyFileHelper.GetFileWithNameUrl(Filename, totalSize); var actualFile = DummyData.GenerateOrderedBytes(totalSize); // act - await using var stream = await Downloader.DownloadFileTaskAsync(URL); + await using var stream = await Downloader.DownloadFileTaskAsync(Url); // assert Assert.Equal(totalSize, Downloader.Package.TotalFileSize); @@ -861,11 +861,11 @@ public async Task DownloadBigFileWithMemoryLimitationOnDisk() Config.ParallelCount = 16; Config.MaximumBytesPerSecond = 0; Config.MaximumMemoryBufferBytes = 1024 * 1024 * 50; // 50MB - URL = DummyFileHelper.GetFileWithNameUrl(Filename, totalSize, fillByte); + Url = DummyFileHelper.GetFileWithNameUrl(Filename, totalSize, fillByte); //Downloader.AddLogger(FileLogger.Factory("D:\\TestDownload")); // act - await Downloader.DownloadFileTaskAsync(URL, FilePath); + await Downloader.DownloadFileTaskAsync(Url, FilePath); await using var fileStream = File.Open(FilePath, FileMode.Open, FileAccess.Read); // assert diff --git a/src/Downloader.Test/UnitTests/ChunkDownloaderTest.cs b/src/Downloader.Test/UnitTests/ChunkDownloaderTest.cs index 7e7512b..5f68323 100644 --- a/src/Downloader.Test/UnitTests/ChunkDownloaderTest.cs +++ b/src/Downloader.Test/UnitTests/ChunkDownloaderTest.cs @@ -157,7 +157,7 @@ public async Task CancelReadStreamTest() } }; - async Task act() + async Task Act() { try { @@ -171,7 +171,7 @@ async Task act() } // act - await Assert.ThrowsAnyAsync(act); + await Assert.ThrowsAnyAsync(Act); await using var chunkStream = Storage.OpenRead(); // assert diff --git a/src/Downloader.Test/UnitTests/DownloadBuilderTest.cs b/src/Downloader.Test/UnitTests/DownloadBuilderTest.cs index 47a7747..6a72937 100644 --- a/src/Downloader.Test/UnitTests/DownloadBuilderTest.cs +++ b/src/Downloader.Test/UnitTests/DownloadBuilderTest.cs @@ -9,18 +9,18 @@ namespace Downloader.Test.UnitTests; public class DownloadBuilderTest { // arrange - private string url; - private string filename; - private string folder; - private string path; + private string _url; + private string _filename; + private string _folder; + private string _path; public DownloadBuilderTest() { // arrange - url = DummyFileHelper.GetFileUrl(DummyFileHelper.FileSize16Kb); - filename = Path.GetRandomFileName(); - folder = Path.GetTempPath().TrimEnd('\\', '/'); - path = Path.Combine(folder, filename); + _url = DummyFileHelper.GetFileUrl(DummyFileHelper.FileSize16Kb); + _filename = Path.GetRandomFileName(); + _folder = Path.GetTempPath().TrimEnd('\\', '/'); + _path = Path.Combine(_folder, _filename); } [Fact] @@ -28,16 +28,16 @@ public void TestCorrect() { // act IDownload download = DownloadBuilder.New() - .WithUrl(url) - .WithFileLocation(path) + .WithUrl(_url) + .WithFileLocation(_path) .Configure(config => { config.ParallelDownload = true; }) .Build(); // assert - Assert.Equal(folder, download.Folder); - Assert.Equal(filename, download.Filename); + Assert.Equal(_folder, download.Folder); + Assert.Equal(_filename, download.Filename); } [Fact] @@ -45,14 +45,14 @@ public void TestSetFolderAndName() { // act IDownload download = DownloadBuilder.New() - .WithUrl(url) - .WithDirectory(folder) - .WithFileName(filename) + .WithUrl(_url) + .WithDirectory(_folder) + .WithFileName(_filename) .Build(); // assert - Assert.Equal(folder, download.Folder); - Assert.Equal(filename, download.Filename); + Assert.Equal(_folder, download.Folder); + Assert.Equal(_filename, download.Filename); } [Fact] @@ -63,7 +63,7 @@ public void TestSetFolder() // act IDownload download = DownloadBuilder.New() - .WithUrl(url) + .WithUrl(_url) .WithDirectory(dir) .Build(); @@ -77,21 +77,21 @@ public void TestSetName() { // act IDownload download = DownloadBuilder.New() - .WithUrl(url) - .WithFileLocation(path) - .WithFileName(filename) + .WithUrl(_url) + .WithFileLocation(_path) + .WithFileName(_filename) .Build(); // assert - Assert.Equal(folder, download.Folder); - Assert.Equal(filename, download.Filename); + Assert.Equal(_folder, download.Folder); + Assert.Equal(_filename, download.Filename); } [Fact] public void TestUrlless() { // act - Action act = () => DownloadBuilder.New().WithFileLocation(path).Build(); + Action act = () => DownloadBuilder.New().WithFileLocation(_path).Build(); // assert Assert.ThrowsAny(act); @@ -102,7 +102,7 @@ public void TestPathless() { // act IDownload result = DownloadBuilder.New() - .WithUrl(url) + .WithUrl(_url) .Build(); // assert @@ -115,7 +115,7 @@ public async Task TestPackageWhenNewUrl() // arrange DownloadPackage beforePackage = null; IDownload download = DownloadBuilder.New() - .WithUrl(url) + .WithUrl(_url) .Build(); // act @@ -134,7 +134,7 @@ public async Task TestPackageWhenResume() { // arrange DownloadPackage package = new DownloadPackage() { - Urls = new[] { url }, + Urls = new[] { _url }, IsSupportDownloadInRange = true }; IDownload download = DownloadBuilder.New().Build(package); @@ -157,8 +157,8 @@ public async Task TestPauseAndResume() // arrange var pauseCount = 0; var downloader = DownloadBuilder.New() - .WithUrl(url) - .WithFileLocation(path) + .WithUrl(_url) + .WithFileLocation(_path) .Build(); downloader.DownloadProgressChanged += (s, e) => { @@ -176,10 +176,10 @@ public async Task TestPauseAndResume() // assert Assert.True(downloader.Package?.IsSaveComplete); Assert.Equal(10, pauseCount); - Assert.True(File.Exists(path)); + Assert.True(File.Exists(_path)); // clean up - File.Delete(path); + File.Delete(_path); } [Fact] @@ -188,23 +188,23 @@ public async Task TestOverwriteFileWithDownloadSameLocation() // arrange var content = "THIS IS TEST CONTENT WHICH MUST BE OVERWRITE WITH THE DOWNLOADER"; var downloader = DownloadBuilder.New() - .WithUrl(url) - .WithFileLocation(path) + .WithUrl(_url) + .WithFileLocation(_path) .Build(); // act - await File.WriteAllTextAsync(path, content); // create file + await File.WriteAllTextAsync(_path, content); // create file await downloader.StartAsync(); // overwrite file - var file = await File.ReadAllTextAsync(path); + var file = await File.ReadAllTextAsync(_path); // assert Assert.True(downloader.Package?.IsSaveComplete); - Assert.True(File.Exists(path)); + Assert.True(File.Exists(_path)); Assert.False(file.StartsWith(content)); Assert.Equal(DummyFileHelper.FileSize16Kb, Encoding.ASCII.GetByteCount(file)); // clean up - File.Delete(path); + File.Delete(_path); } [Fact] @@ -213,23 +213,23 @@ public async Task TestOverwriteFileWithDownloadSameFileName() // arrange var content = "THIS IS TEST CONTENT WHICH MUST BE OVERWRITE WITH THE DOWNLOADER"; var downloader = DownloadBuilder.New() - .WithUrl(url) - .WithDirectory(folder) - .WithFileName(filename) + .WithUrl(_url) + .WithDirectory(_folder) + .WithFileName(_filename) .Build(); // act - await File.WriteAllTextAsync(path, content); // create file + await File.WriteAllTextAsync(_path, content); // create file await downloader.StartAsync(); // overwrite file - var file = await File.ReadAllTextAsync(path); + var file = await File.ReadAllTextAsync(_path); // assert Assert.True(downloader.Package?.IsSaveComplete); - Assert.True(File.Exists(path)); + Assert.True(File.Exists(_path)); Assert.False(file.StartsWith(content)); Assert.Equal(DummyFileHelper.FileSize16Kb, Encoding.ASCII.GetByteCount(file)); // clean up - File.Delete(path); + File.Delete(_path); } } diff --git a/src/Downloader.Test/UnitTests/PauseTokenTest.cs b/src/Downloader.Test/UnitTests/PauseTokenTest.cs index 3901506..7c616c0 100644 --- a/src/Downloader.Test/UnitTests/PauseTokenTest.cs +++ b/src/Downloader.Test/UnitTests/PauseTokenTest.cs @@ -7,7 +7,7 @@ namespace Downloader.Test.UnitTests; public class PauseTokenTest { private PauseTokenSource _pauseTokenSource; - private volatile int actualPauseCount = 0; + private volatile int _actualPauseCount = 0; public PauseTokenTest() { @@ -40,20 +40,20 @@ public async Task TestPauseTaskWithPauseToken() for (var i = 0; i < 10; i++) { await Task.Delay(1); - tasksAlreadyPaused &= (actualPauseCount == expectedCount); + tasksAlreadyPaused &= (_actualPauseCount == expectedCount); pts.Resume(); checkTokenStateIsNotPaused |= pts.IsPaused; await Task.Delay(1); pts.Pause(); checkTokenStateIsPaused &= pts.IsPaused; await Task.Delay(1); - hasRunningTask &= (actualPauseCount > expectedCount); - expectedCount = actualPauseCount; + hasRunningTask &= (_actualPauseCount > expectedCount); + expectedCount = _actualPauseCount; } cts.Cancel(); // assert - Assert.True(expectedCount >= actualPauseCount, $"Expected: {expectedCount}, Actual: {actualPauseCount}"); + Assert.True(expectedCount >= _actualPauseCount, $"Expected: {expectedCount}, Actual: {_actualPauseCount}"); Assert.True(pts.IsPaused); Assert.True(checkTokenStateIsPaused); Assert.False(checkTokenStateIsNotPaused); @@ -66,7 +66,7 @@ private async Task IncreaseAsync(PauseToken pause, CancellationToken cancel) while (cancel.IsCancellationRequested == false) { await pause.WaitWhilePausedAsync(); - actualPauseCount++; + _actualPauseCount++; await Task.Yield(); } } diff --git a/src/Downloader.Test/UnitTests/StorageTestOnFile.cs b/src/Downloader.Test/UnitTests/StorageTestOnFile.cs index 9346650..2d5193b 100644 --- a/src/Downloader.Test/UnitTests/StorageTestOnFile.cs +++ b/src/Downloader.Test/UnitTests/StorageTestOnFile.cs @@ -6,18 +6,18 @@ namespace Downloader.Test.UnitTests; public class StorageTestOnFile : StorageTest { - private string path; + private string _path; protected override void CreateStorage(int initialSize) { - path = Path.GetTempFileName(); - Storage = new ConcurrentStream(path, initialSize); + _path = Path.GetTempFileName(); + Storage = new ConcurrentStream(_path, initialSize); } public override void Dispose() { base.Dispose(); - File.Delete(path); + File.Delete(_path); } [Fact] @@ -27,7 +27,7 @@ public void TestInitialSizeOnFileStream() CreateStorage(DataLength); // assert - Assert.Equal(DataLength, new FileInfo(path).Length); + Assert.Equal(DataLength, new FileInfo(_path).Length); Assert.Equal(DataLength, Storage.Length); } @@ -41,7 +41,7 @@ public async Task TestInitialSizeWithNegativeNumberOnFileStream() await Storage.FlushAsync(); // create lazy stream // assert - Assert.Equal(0, new FileInfo(path).Length); + Assert.Equal(0, new FileInfo(_path).Length); Assert.Equal(0, Storage.Length); } @@ -62,7 +62,7 @@ public async Task TestWriteSizeOverflowOnFileStream() var readerStream = Storage.OpenRead(); // assert - Assert.Equal(actualSize, new FileInfo(path).Length); + Assert.Equal(actualSize, new FileInfo(_path).Length); Assert.Equal(actualSize, Storage.Length); for (int i = 0; i < actualSize; i++) Assert.Equal(1, readerStream.ReadByte()); @@ -85,7 +85,7 @@ public async Task TestAccessMoreThanSizeOnFileStream() var readerStream = Storage.OpenRead(); // assert - Assert.Equal(actualSize, new FileInfo(path).Length); + Assert.Equal(actualSize, new FileInfo(_path).Length); Assert.Equal(actualSize, Storage.Length); for (int i = 0; i < size + jumpStepCount; i++) Assert.Equal(0, readerStream.ReadByte()); // empty spaces diff --git a/src/Downloader/AbstractDownloadService.cs b/src/Downloader/AbstractDownloadService.cs index 8f338bf..05fc688 100644 --- a/src/Downloader/AbstractDownloadService.cs +++ b/src/Downloader/AbstractDownloadService.cs @@ -15,37 +15,115 @@ namespace Downloader; /// /// Abstract base class for download services implementing and . /// -public abstract class AbstractDownloadService : IDownloadService, IDisposable +public abstract class AbstractDownloadService : IDownloadService, IDisposable, IAsyncDisposable { - protected ILogger _logger; - protected SemaphoreSlim _parallelSemaphore; - protected readonly SemaphoreSlim _singleInstanceSemaphore = new SemaphoreSlim(1, 1); - protected CancellationTokenSource _globalCancellationTokenSource; - protected TaskCompletionSource _taskCompletion; - protected readonly PauseTokenSource _pauseTokenSource; - protected ChunkHub _chunkHub; - protected List _requestInstances; - protected readonly Bandwidth _bandwidth; + /// + /// Logger instance for logging messages. + /// + protected ILogger Logger; + + /// + /// Semaphore to control parallel downloads. + /// + protected SemaphoreSlim ParallelSemaphore; + + /// + /// Semaphore to ensure single instance operations. + /// + protected readonly SemaphoreSlim SingleInstanceSemaphore = new SemaphoreSlim(1, 1); + + /// + /// Global cancellation token source for managing download cancellation. + /// + protected CancellationTokenSource GlobalCancellationTokenSource; + + /// + /// Task completion source for managing asynchronous operations. + /// + protected TaskCompletionSource TaskCompletion; + + /// + /// Pause token source for managing download pausing. + /// + protected readonly PauseTokenSource PauseTokenSource; + + /// + /// Chunk hub for managing download chunks. + /// + protected ChunkHub ChunkHub; + + /// + /// List of request instances for download operations. + /// + protected List RequestInstances; + + /// + /// Bandwidth tracker for download speed calculations. + /// + protected readonly Bandwidth Bandwidth; + + /// + /// Configuration options for the download service. + /// protected DownloadConfiguration Options { get; set; } + /// + /// Indicates whether the download service is currently busy. + /// public bool IsBusy => Status == DownloadStatus.Running; - public bool IsCancelled => _globalCancellationTokenSource?.IsCancellationRequested == true; - public bool IsPaused => _pauseTokenSource.IsPaused; + + /// + /// Indicates whether the download operation has been cancelled. + /// + public bool IsCancelled => GlobalCancellationTokenSource?.IsCancellationRequested == true; + + /// + /// Indicates whether the download operation is paused. + /// + public bool IsPaused => PauseTokenSource.IsPaused; + + /// + /// The download package containing the necessary information for the download. + /// public DownloadPackage Package { get; set; } + + /// + /// The current status of the download operation. + /// public DownloadStatus Status { get => Package?.Status ?? DownloadStatus.None; set => Package.Status = value; } + + /// + /// Event triggered when the download file operation is completed. + /// public event EventHandler DownloadFileCompleted; + + /// + /// Event triggered when the download progress changes. + /// public event EventHandler DownloadProgressChanged; + + /// + /// Event triggered when the progress of a chunk download changes. + /// public event EventHandler ChunkDownloadProgressChanged; + + /// + /// Event triggered when the download operation starts. + /// public event EventHandler DownloadStarted; - public AbstractDownloadService(DownloadConfiguration options) + /// + /// Initializes a new instance of the class with the specified options. + /// + /// The configuration options for the download service. + protected AbstractDownloadService(DownloadConfiguration options) { - _pauseTokenSource = new PauseTokenSource(); - _bandwidth = new Bandwidth(); + PauseTokenSource = new PauseTokenSource(); + Bandwidth = new Bandwidth(); Options = options ?? new DownloadConfiguration(); Package = new DownloadPackage(); @@ -176,7 +254,7 @@ public Task DownloadFileTaskAsync(string address, DirectoryInfo folder, Cancella public virtual async Task DownloadFileTaskAsync(string[] urls, DirectoryInfo folder, CancellationToken cancellationToken = default) { await InitialDownloader(cancellationToken, urls).ConfigureAwait(false); - var name = await _requestInstances.First().GetFileName().ConfigureAwait(false); + var name = await RequestInstances.First().GetFileName().ConfigureAwait(false); var filename = Path.Combine(folder.FullName, name); await StartDownload(filename).ConfigureAwait(false); } @@ -186,7 +264,7 @@ public virtual async Task DownloadFileTaskAsync(string[] urls, DirectoryInfo fol /// public virtual void CancelAsync() { - _globalCancellationTokenSource?.Cancel(true); + GlobalCancellationTokenSource?.Cancel(true); Resume(); Status = DownloadStatus.Stopped; } @@ -198,8 +276,8 @@ public virtual void CancelAsync() public virtual async Task CancelTaskAsync() { CancelAsync(); - if (_taskCompletion != null) - await _taskCompletion.Task.ConfigureAwait(false); + if (TaskCompletion != null) + await TaskCompletion.Task.ConfigureAwait(false); } /// @@ -208,7 +286,7 @@ public virtual async Task CancelTaskAsync() public virtual void Resume() { Status = DownloadStatus.Running; - _pauseTokenSource.Resume(); + PauseTokenSource.Resume(); } /// @@ -216,7 +294,7 @@ public virtual void Resume() /// public virtual void Pause() { - _pauseTokenSource.Pause(); + PauseTokenSource.Pause(); Status = DownloadStatus.Paused; } @@ -231,41 +309,52 @@ public virtual async Task Clear() if (IsBusy || IsPaused) await CancelTaskAsync().ConfigureAwait(false); - await _singleInstanceSemaphore.WaitAsync().ConfigureAwait(false); + await SingleInstanceSemaphore.WaitAsync().ConfigureAwait(false); - _parallelSemaphore?.Dispose(); - _globalCancellationTokenSource?.Dispose(); - _bandwidth.Reset(); - _requestInstances = null; + ParallelSemaphore?.Dispose(); + GlobalCancellationTokenSource?.Dispose(); + Bandwidth.Reset(); + RequestInstances = null; - if (_taskCompletion != null) + if (TaskCompletion != null) { - if (_taskCompletion.Task.IsCompleted == false) - _taskCompletion.TrySetCanceled(); + if (TaskCompletion.Task.IsCompleted == false) + TaskCompletion.TrySetCanceled(); - _taskCompletion = null; + TaskCompletion = null; } // Note: don't clear package from `DownloadService.Dispose()`. // Because maybe it will be used at another time. } finally { - _singleInstanceSemaphore?.Release(); + SingleInstanceSemaphore?.Release(); } } + /// + /// Initializes the downloader with the specified and . + /// + /// A cancellation token that can be used to cancel the download. + /// The array of URL addresses of the file to download. + /// A task that represents the asynchronous initialization operation. protected async Task InitialDownloader(CancellationToken cancellationToken, params string[] addresses) { await Clear().ConfigureAwait(false); Status = DownloadStatus.Created; - _globalCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - _taskCompletion = new TaskCompletionSource(); - _requestInstances = addresses.Select(url => new Request(url, Options.RequestConfiguration)).ToList(); - Package.Urls = _requestInstances.Select(req => req.Address.OriginalString).ToArray(); - _chunkHub = new ChunkHub(Options); - _parallelSemaphore = new SemaphoreSlim(Options.ParallelCount, Options.ParallelCount); + GlobalCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + TaskCompletion = new TaskCompletionSource(); + RequestInstances = addresses.Select(url => new Request(url, Options.RequestConfiguration)).ToList(); + Package.Urls = RequestInstances.Select(req => req.Address.OriginalString).ToArray(); + ChunkHub = new ChunkHub(Options); + ParallelSemaphore = new SemaphoreSlim(Options.ParallelCount, Options.ParallelCount); } + /// + /// Starts the download operation and saves it to the specified . + /// + /// The name of the file to save the download as. + /// A task that represents the asynchronous download operation. protected async Task StartDownload(string fileName) { Package.FileName = fileName; @@ -279,8 +368,16 @@ protected async Task StartDownload(string fileName) await StartDownload().ConfigureAwait(false); } + /// + /// Starts the download operation. + /// + /// A task that represents the asynchronous download operation. The task result contains the downloaded stream. protected abstract Task StartDownload(); + /// + /// Raises the event. + /// + /// The event arguments for the download started event. protected void OnDownloadStarted(DownloadStartedEventArgs e) { Status = DownloadStatus.Running; @@ -288,6 +385,10 @@ protected void OnDownloadStarted(DownloadStartedEventArgs e) DownloadStarted?.Invoke(this, e); } + /// + /// Raises the event. + /// + /// The event arguments for the download file completed event. protected void OnDownloadFileCompleted(AsyncCompletedEventArgs e) { Package.IsSaving = false; @@ -318,38 +419,43 @@ protected void OnDownloadFileCompleted(AsyncCompletedEventArgs e) Package.Storage = null; } - _taskCompletion.TrySetResult(e); + TaskCompletion.TrySetResult(e); DownloadFileCompleted?.Invoke(this, e); } + /// + /// Raises the and events. + /// + /// The sender of the event. + /// The event arguments for the download progress changed event. protected void OnChunkDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { if (e.ReceivedBytesSize > Package.TotalFileSize) Package.TotalFileSize = e.ReceivedBytesSize; - _bandwidth.CalculateSpeed(e.ProgressedByteSize); + Bandwidth.CalculateSpeed(e.ProgressedByteSize); var totalProgressArg = new DownloadProgressChangedEventArgs(nameof(DownloadService)) { TotalBytesToReceive = Package.TotalFileSize, ReceivedBytesSize = Package.ReceivedBytesSize, - BytesPerSecondSpeed = _bandwidth.Speed, - AverageBytesPerSecondSpeed = _bandwidth.AverageSpeed, + BytesPerSecondSpeed = Bandwidth.Speed, + AverageBytesPerSecondSpeed = Bandwidth.AverageSpeed, ProgressedByteSize = e.ProgressedByteSize, ReceivedBytes = e.ReceivedBytes, - ActiveChunks = Options.ParallelCount - _parallelSemaphore.CurrentCount, + ActiveChunks = Options.ParallelCount - ParallelSemaphore.CurrentCount, }; Package.SaveProgress = totalProgressArg.ProgressPercentage; e.ActiveChunks = totalProgressArg.ActiveChunks; ChunkDownloadProgressChanged?.Invoke(this, e); DownloadProgressChanged?.Invoke(this, totalProgressArg); } - + /// /// Adds a logger to the download service. /// /// The logger instance to add. public void AddLogger(ILogger logger) { - _logger = logger; + Logger = logger; } /// @@ -359,4 +465,12 @@ public virtual void Dispose() { Clear().Wait(); } + + /// + /// Disposes asynchronously of the download service, including clearing the current download operation. + /// + public async ValueTask DisposeAsync() + { + await Clear().ConfigureAwait(false); + } } \ No newline at end of file diff --git a/src/Downloader/ConcurrentPacketBuffer.cs b/src/Downloader/ConcurrentPacketBuffer.cs index a1426ac..0d5c6af 100644 --- a/src/Downloader/ConcurrentPacketBuffer.cs +++ b/src/Downloader/ConcurrentPacketBuffer.cs @@ -21,11 +21,11 @@ internal class ConcurrentPacketBuffer : IReadOnlyCollection, IDisposable w { private volatile bool _disposed = false; private long _bufferSize = long.MaxValue; - protected readonly ILogger _logger; - protected readonly SemaphoreSlim _queueConsumeLocker = new SemaphoreSlim(0); - protected readonly PauseTokenSource _addingBlocker = new PauseTokenSource(); - protected readonly PauseTokenSource _flushBlocker = new PauseTokenSource(); - protected readonly ConcurrentQueue _queue; + protected readonly ILogger Logger; + protected readonly SemaphoreSlim QueueConsumeLocker = new SemaphoreSlim(0); + protected readonly PauseTokenSource AddingBlocker = new PauseTokenSource(); + protected readonly PauseTokenSource FlushBlocker = new PauseTokenSource(); + protected readonly ConcurrentQueue Queue; public long BufferSize { @@ -43,13 +43,13 @@ public ConcurrentPacketBuffer(long size, ILogger logger = null) : this(logger) public ConcurrentPacketBuffer(ILogger logger = null) { - _queue = new ConcurrentQueue(); - _logger = logger; + Queue = new ConcurrentQueue(); + Logger = logger; } public IEnumerator GetEnumerator() { - return _queue.GetEnumerator(); + return Queue.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() @@ -57,23 +57,23 @@ IEnumerator IEnumerable.GetEnumerator() return GetEnumerator(); } - public int Count => _queue.Count; - public bool IsAddingCompleted => _addingBlocker.IsPaused; - public bool IsEmpty => _queue.Count == 0; + public int Count => Queue.Count; + public bool IsAddingCompleted => AddingBlocker.IsPaused; + public bool IsEmpty => Queue.Count == 0; public T[] ToArray() { - return _queue.ToArray(); + return Queue.ToArray(); } public async Task TryAdd(T item) { try { - await _addingBlocker.WaitWhilePausedAsync().ConfigureAwait(false); - _flushBlocker.Pause(); - _queue.Enqueue(item); - _queueConsumeLocker.Release(); + await AddingBlocker.WaitWhilePausedAsync().ConfigureAwait(false); + FlushBlocker.Pause(); + Queue.Enqueue(item); + QueueConsumeLocker.Release(); StopAddingIfLimitationExceeded(item.Length); return true; } @@ -87,8 +87,8 @@ public async Task WaitTryTakeAsync(CancellationToken cancellation, Func { try { - await _queueConsumeLocker.WaitAsync(cancellation).ConfigureAwait(false); - if (_queue.TryDequeue(out var item) && item != null) + await QueueConsumeLocker.WaitAsync(cancellation).ConfigureAwait(false); + if (Queue.TryDequeue(out var item) && item != null) { await callbackTask(item).ConfigureAwait(false); } @@ -103,7 +103,7 @@ private void StopAddingIfLimitationExceeded(long packetSize) { if (BufferSize < packetSize * Count) { - _logger?.LogDebug($"ConcurrentPacketBuffer: Stop writing packets to the queue on size {packetSize * Count}bytes until the memory is free"); + Logger?.LogDebug($"ConcurrentPacketBuffer: Stop writing packets to the queue on size {packetSize * Count}bytes until the memory is free"); StopAdding(); } } @@ -112,26 +112,26 @@ private void ResumeAddingIfEmpty() { if (IsEmpty) { - _flushBlocker.Resume(); + FlushBlocker.Resume(); ResumeAdding(); } } public async Task WaitToComplete() { - await _flushBlocker.WaitWhilePausedAsync().ConfigureAwait(false); + await FlushBlocker.WaitWhilePausedAsync().ConfigureAwait(false); } public void StopAdding() { - _logger?.LogDebug("ConcurrentPacketBuffer: stop writing new items to the list by blocking writer threads"); - _addingBlocker.Pause(); + Logger?.LogDebug("ConcurrentPacketBuffer: stop writing new items to the list by blocking writer threads"); + AddingBlocker.Pause(); } public void ResumeAdding() { - _logger?.LogDebug("ConcurrentPacketBuffer: resume writing new item to the list"); - _addingBlocker.Resume(); + Logger?.LogDebug("ConcurrentPacketBuffer: resume writing new item to the list"); + AddingBlocker.Resume(); } public void Dispose() @@ -141,7 +141,7 @@ public void Dispose() _disposed = true; StopAdding(); - _queueConsumeLocker.Dispose(); - _addingBlocker.Resume(); + QueueConsumeLocker.Dispose(); + AddingBlocker.Resume(); } } diff --git a/src/Downloader/Download.cs b/src/Downloader/Download.cs index 26af573..e9a1f1e 100644 --- a/src/Downloader/Download.cs +++ b/src/Downloader/Download.cs @@ -9,57 +9,57 @@ namespace Downloader; internal class Download : IDownload { - private readonly IDownloadService downloadService; + private readonly IDownloadService _downloadService; public string Url { get; } public string Folder { get; } public string Filename { get; } - public long DownloadedFileSize => downloadService?.Package?.ReceivedBytesSize ?? 0; - public long TotalFileSize => downloadService?.Package?.TotalFileSize ?? DownloadedFileSize; + public long DownloadedFileSize => _downloadService?.Package?.ReceivedBytesSize ?? 0; + public long TotalFileSize => _downloadService?.Package?.TotalFileSize ?? DownloadedFileSize; public DownloadPackage Package { get; private set; } public DownloadStatus Status => Package?.Status ?? DownloadStatus.None; public event EventHandler ChunkDownloadProgressChanged { - add { downloadService.ChunkDownloadProgressChanged += value; } - remove { downloadService.ChunkDownloadProgressChanged -= value; } + add { _downloadService.ChunkDownloadProgressChanged += value; } + remove { _downloadService.ChunkDownloadProgressChanged -= value; } } public event EventHandler DownloadFileCompleted { - add { downloadService.DownloadFileCompleted += value; } - remove { downloadService.DownloadFileCompleted -= value; } + add { _downloadService.DownloadFileCompleted += value; } + remove { _downloadService.DownloadFileCompleted -= value; } } public event EventHandler DownloadProgressChanged { - add { downloadService.DownloadProgressChanged += value; } - remove { downloadService.DownloadProgressChanged -= value; } + add { _downloadService.DownloadProgressChanged += value; } + remove { _downloadService.DownloadProgressChanged -= value; } } public event EventHandler DownloadStarted { - add { downloadService.DownloadStarted += value; } - remove { downloadService.DownloadStarted -= value; } + add { _downloadService.DownloadStarted += value; } + remove { _downloadService.DownloadStarted -= value; } } public Download(string url, string path, string filename, DownloadConfiguration configuration) { - downloadService = new DownloadService(configuration); + _downloadService = new DownloadService(configuration); Url = url; Folder = path; Filename = filename; - Package = downloadService.Package; + Package = _downloadService.Package; } public Download(DownloadPackage package, DownloadConfiguration configuration) { - downloadService = new DownloadService(configuration); + _downloadService = new DownloadService(configuration); Package = package; } public Download(DownloadPackage package, string address, DownloadConfiguration configuration) { - downloadService = new DownloadService(configuration); + _downloadService = new DownloadService(configuration); Package = package; Url = address; } @@ -70,43 +70,43 @@ public async Task StartAsync(CancellationToken cancellationToken = defau { if (string.IsNullOrWhiteSpace(Folder) && string.IsNullOrWhiteSpace(Filename)) { - return await downloadService.DownloadFileTaskAsync(Url, cancellationToken).ConfigureAwait(false); + return await _downloadService.DownloadFileTaskAsync(Url, cancellationToken).ConfigureAwait(false); } else if (string.IsNullOrWhiteSpace(Filename)) { - await downloadService.DownloadFileTaskAsync(Url, new DirectoryInfo(Folder), cancellationToken).ConfigureAwait(false); + await _downloadService.DownloadFileTaskAsync(Url, new DirectoryInfo(Folder), cancellationToken).ConfigureAwait(false); return null; } else { // with Folder and Filename - await downloadService.DownloadFileTaskAsync(Url, Path.Combine(Folder, Filename), cancellationToken).ConfigureAwait(false); + await _downloadService.DownloadFileTaskAsync(Url, Path.Combine(Folder, Filename), cancellationToken).ConfigureAwait(false); return null; } } else if(string.IsNullOrWhiteSpace(Url)) { - return await downloadService.DownloadFileTaskAsync(Package, cancellationToken).ConfigureAwait(false); + return await _downloadService.DownloadFileTaskAsync(Package, cancellationToken).ConfigureAwait(false); } else { - return await downloadService.DownloadFileTaskAsync(Package, Url, cancellationToken).ConfigureAwait(false); + return await _downloadService.DownloadFileTaskAsync(Package, Url, cancellationToken).ConfigureAwait(false); } } public void Stop() { - downloadService.CancelTaskAsync().Wait(); + _downloadService.CancelTaskAsync().Wait(); } public void Pause() { - downloadService.Pause(); + _downloadService.Pause(); } public void Resume() { - downloadService.Resume(); + _downloadService.Resume(); } public override bool Equals(object obj) @@ -125,7 +125,7 @@ public override int GetHashCode() public async void Dispose() { - await downloadService.Clear().ConfigureAwait(false); + await _downloadService.Clear().ConfigureAwait(false); Package = null; } } diff --git a/src/Downloader/DownloadBuilder.cs b/src/Downloader/DownloadBuilder.cs index 363c3c1..0b86c7b 100644 --- a/src/Downloader/DownloadBuilder.cs +++ b/src/Downloader/DownloadBuilder.cs @@ -5,10 +5,10 @@ namespace Downloader; public class DownloadBuilder { - private string url; - private string directoryPath; - private string filename; - private DownloadConfiguration downloadConfiguration; + private string _url; + private string _directoryPath; + private string _filename; + private DownloadConfiguration _downloadConfiguration; public static DownloadBuilder New() { @@ -17,7 +17,7 @@ public static DownloadBuilder New() public DownloadBuilder WithUrl(string url) { - this.url = url; + this._url = url; return this; } @@ -29,8 +29,8 @@ public DownloadBuilder WithUrl(Uri url) public DownloadBuilder WithFileLocation(string fullPath) { fullPath = Path.GetFullPath(fullPath); - filename = Path.GetFileName(fullPath); - directoryPath = Path.GetDirectoryName(fullPath); + _filename = Path.GetFileName(fullPath); + _directoryPath = Path.GetDirectoryName(fullPath); return this; } @@ -46,7 +46,7 @@ public DownloadBuilder WithFileLocation(FileInfo fileInfo) public DownloadBuilder WithDirectory(string directoryPath) { - this.directoryPath = directoryPath; + this._directoryPath = directoryPath; return this; } @@ -62,13 +62,13 @@ public DownloadBuilder WithFolder(DirectoryInfo folder) public DownloadBuilder WithFileName(string name) { - this.filename = name; + this._filename = name; return this; } public DownloadBuilder WithConfiguration(DownloadConfiguration configuration) { - downloadConfiguration = configuration; + _downloadConfiguration = configuration; return this; } @@ -81,21 +81,21 @@ public DownloadBuilder Configure(Action configure) public IDownload Build() { - if (string.IsNullOrWhiteSpace(url)) + if (string.IsNullOrWhiteSpace(_url)) { - throw new ArgumentNullException($"{nameof(url)} has not been declared."); + throw new ArgumentNullException($"{nameof(_url)} has not been declared."); } - return new Download(url, directoryPath, filename, downloadConfiguration); + return new Download(_url, _directoryPath, _filename, _downloadConfiguration); } public IDownload Build(DownloadPackage package) { - return new Download(package, url, downloadConfiguration); + return new Download(package, _url, _downloadConfiguration); } public IDownload Build(DownloadPackage package, DownloadConfiguration downloadConfiguration) { - return new Download(package, url, downloadConfiguration); + return new Download(package, _url, downloadConfiguration); } } diff --git a/src/Downloader/DownloadService.cs b/src/Downloader/DownloadService.cs index 0f963e6..275a00a 100644 --- a/src/Downloader/DownloadService.cs +++ b/src/Downloader/DownloadService.cs @@ -18,23 +18,23 @@ protected override async Task StartDownload() { try { - await _singleInstanceSemaphore.WaitAsync().ConfigureAwait(false); - Package.TotalFileSize = await _requestInstances.First().GetFileSize().ConfigureAwait(false); - Package.IsSupportDownloadInRange = await _requestInstances.First().IsSupportDownloadInRange().ConfigureAwait(false); + await SingleInstanceSemaphore.WaitAsync().ConfigureAwait(false); + Package.TotalFileSize = await RequestInstances.First().GetFileSize().ConfigureAwait(false); + Package.IsSupportDownloadInRange = await RequestInstances.First().IsSupportDownloadInRange().ConfigureAwait(false); Package.BuildStorage(Options.ReserveStorageSpaceBeforeStartingDownload, Options.MaximumMemoryBufferBytes); ValidateBeforeChunking(); - _chunkHub.SetFileChunks(Package); + ChunkHub.SetFileChunks(Package); // firing the start event after creating chunks OnDownloadStarted(new DownloadStartedEventArgs(Package.FileName, Package.TotalFileSize)); if (Options.ParallelDownload) { - await ParallelDownload(_pauseTokenSource.Token).ConfigureAwait(false); + await ParallelDownload(PauseTokenSource.Token).ConfigureAwait(false); } else { - await SerialDownload(_pauseTokenSource.Token).ConfigureAwait(false); + await SerialDownload(PauseTokenSource.Token).ConfigureAwait(false); } await SendDownloadCompletionSignal(DownloadStatus.Completed).ConfigureAwait(false); @@ -49,7 +49,7 @@ protected override async Task StartDownload() } finally { - _singleInstanceSemaphore.Release(); + SingleInstanceSemaphore.Release(); await Task.Yield(); } @@ -137,7 +137,7 @@ private void SetSingleChunkDownload() { Options.ChunkCount = 1; Options.ParallelCount = 1; - _parallelSemaphore = new SemaphoreSlim(1, 1); + ParallelSemaphore = new SemaphoreSlim(1, 1); } private async Task ParallelDownload(PauseToken pauseToken) @@ -163,16 +163,16 @@ private IEnumerable GetChunksTasks(PauseToken pauseToken) { for (int i = 0; i < Package.Chunks.Length; i++) { - var request = _requestInstances[i % _requestInstances.Count]; - yield return DownloadChunk(Package.Chunks[i], request, pauseToken, _globalCancellationTokenSource); + var request = RequestInstances[i % RequestInstances.Count]; + yield return DownloadChunk(Package.Chunks[i], request, pauseToken, GlobalCancellationTokenSource); } } private async Task DownloadChunk(Chunk chunk, Request request, PauseToken pause, CancellationTokenSource cancellationTokenSource) { - ChunkDownloader chunkDownloader = new ChunkDownloader(chunk, Options, Package.Storage, _logger); + ChunkDownloader chunkDownloader = new ChunkDownloader(chunk, Options, Package.Storage, Logger); chunkDownloader.DownloadProgressChanged += OnChunkDownloadProgressChanged; - await _parallelSemaphore.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); + await ParallelSemaphore.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); try { cancellationTokenSource.Token.ThrowIfCancellationRequested(); @@ -190,7 +190,7 @@ private async Task DownloadChunk(Chunk chunk, Request request, PauseToken } finally { - _parallelSemaphore.Release(); + ParallelSemaphore.Release(); } } } \ No newline at end of file diff --git a/src/Downloader/PauseToken.cs b/src/Downloader/PauseToken.cs index 02863cf..331cd3b 100644 --- a/src/Downloader/PauseToken.cs +++ b/src/Downloader/PauseToken.cs @@ -4,18 +4,18 @@ namespace Downloader; public struct PauseToken { - private readonly PauseTokenSource tokenSource; - public bool IsPaused => tokenSource?.IsPaused == true; + private readonly PauseTokenSource _tokenSource; + public bool IsPaused => _tokenSource?.IsPaused == true; internal PauseToken(PauseTokenSource source) { - tokenSource = source; + _tokenSource = source; } public Task WaitWhilePausedAsync() { return IsPaused - ? tokenSource.WaitWhilePausedAsync() + ? _tokenSource.WaitWhilePausedAsync() : Task.FromResult(true); } } diff --git a/src/Downloader/PauseTokenSource.cs b/src/Downloader/PauseTokenSource.cs index b06f14a..202d715 100644 --- a/src/Downloader/PauseTokenSource.cs +++ b/src/Downloader/PauseTokenSource.cs @@ -5,15 +5,15 @@ namespace Downloader; public class PauseTokenSource { - private volatile TaskCompletionSource tcsPaused; + private volatile TaskCompletionSource _tcsPaused; public PauseToken Token => new PauseToken(this); - public bool IsPaused => tcsPaused != null; + public bool IsPaused => _tcsPaused != null; public void Pause() { // if (tcsPause == null) tcsPause = new TaskCompletionSource(); - Interlocked.CompareExchange(ref tcsPaused, new TaskCompletionSource(), null); + Interlocked.CompareExchange(ref _tcsPaused, new TaskCompletionSource(), null); } public void Resume() @@ -24,13 +24,13 @@ public void Resume() // and the time we did the compare-exchange, repeat. while (true) { - var tcs = tcsPaused; + var tcs = _tcsPaused; if (tcs == null) return; // if(tcsPaused == tcs) tcsPaused = null; - if (Interlocked.CompareExchange(ref tcsPaused, null, tcs) == tcs) + if (Interlocked.CompareExchange(ref _tcsPaused, null, tcs) == tcs) { tcs.SetResult(true); return; @@ -40,6 +40,6 @@ public void Resume() internal Task WaitWhilePausedAsync() { - return tcsPaused?.Task ?? Task.FromResult(true); + return _tcsPaused?.Task ?? Task.FromResult(true); } }