From 0c5373c111138401608330d9fac1044637158827 Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Thu, 5 Sep 2019 18:37:30 +0200 Subject: [PATCH 1/7] Adapt behavior to linux FileShare limitations --- .../FollowingFileStreamTest.cs | 18 ++++++++----- FollowingFileStream/FollowingFileStream.cs | 27 +++++++++++++++++-- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/FollowingFileStream.Tests/FollowingFileStreamTest.cs b/FollowingFileStream.Tests/FollowingFileStreamTest.cs index 19186e6..eea7d2b 100644 --- a/FollowingFileStream.Tests/FollowingFileStreamTest.cs +++ b/FollowingFileStream.Tests/FollowingFileStreamTest.cs @@ -15,7 +15,7 @@ public FollowingFileStreamTest() { using (var sw = File.CreateText(inputFilePath)) { - sw.WriteLine("coucou"); + sw.Write("coucou"); } } @@ -66,6 +66,7 @@ public void FFS_Caps() Assert.IsTrue(ffs.CanRead); Assert.IsFalse(ffs.CanWrite); Assert.IsTrue(ffs.CanSeek); + Assert.IsTrue(ffs.CanTimeout); } } @@ -104,11 +105,11 @@ public void FFS_Read(bool async) { using (var ffs = new FollowingFileStream(inputFilePath, 4*1096, async)) { + var expected = "coucou"; Assert.AreEqual(0, ffs.Position); - Assert.AreEqual(8, ffs.Length); + Assert.AreEqual(expected.Length, ffs.Length); - var expected = "coucou" + Environment.NewLine; - var bytes = new byte[8]; + var bytes = new byte[expected.Length]; Assert.AreEqual(expected.Length, ffs.Read(bytes, 0, bytes.Length)); Assert.AreEqual(expected, System.Text.Encoding.Default.GetString(bytes)); @@ -134,6 +135,7 @@ public void FFS_CopyTo(bool async) using (var ffs = new FollowingFileStream(inputFilePath, 4*1096, async)) using (var destination = File.CreateText(outputFilePath)) { + ffs.ReadTimeout = 0; ffs.CopyTo(destination.BaseStream); } Assert.IsTrue(FileCompare(inputFilePath, outputFilePath)); @@ -148,16 +150,18 @@ public void FFS_FollowingRead(bool async) using (var ffs = new FollowingFileStream(inputFilePath, 4*1024, async)) using (var destination = File.CreateText(outputFilePath)) { + ffs.ReadTimeout = 400; destination.AutoFlush = true; var os = destination.BaseStream; var copy = ffs.CopyToAsync(os); Assert.AreEqual(0, os.Length); - Thread.Sleep(200); + Thread.Sleep(ffs.ReadTimeout/2); Assert.IsFalse(copy.IsCompleted); input.WriteLine("coucou2"); input.Close(); - Thread.Sleep(200); - Assert.IsTrue(copy.IsCompletedSuccessfully); + //Thread.Sleep(200); + //Assert.IsTrue(copy.IsCompletedSuccessfully); + Assert.IsTrue(copy.Wait(2*ffs.ReadTimeout)); } Assert.IsTrue(FileCompare(inputFilePath, outputFilePath)); } diff --git a/FollowingFileStream/FollowingFileStream.cs b/FollowingFileStream/FollowingFileStream.cs index 027435f..c1d6153 100644 --- a/FollowingFileStream/FollowingFileStream.cs +++ b/FollowingFileStream/FollowingFileStream.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; @@ -243,6 +244,8 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, read = await fileStream.ReadAsync(buffer, offset, count, cancellationToken); } + TotalTime = 0; + return read; } @@ -257,12 +260,20 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, /// private async Task RetryNeededAsync() { - bool retry = IsFileLockedForWriting(); + bool retry = true; + // File locking for read/write operations is only supported on Windows + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + retry = IsFileLockedForWriting(); + } if (retry) { try { - await Task.Delay(MillisecondsRetryTimeout, cts.Token).ConfigureAwait(false); + var duration = MillisecondsRetryTimeout; + await Task.Delay(duration, cts.Token).ConfigureAwait(false); + TotalTime += duration; + retry = ReadTimeout == Timeout.Infinite || TotalTime < ReadTimeout; } catch (TaskCanceledException) { @@ -272,6 +283,18 @@ private async Task RetryNeededAsync() return retry; } + private long TotalTime; + + /// + /// + /// + public override bool CanTimeout => true; + + /// + /// + /// + public override int ReadTimeout { get; set; } = Timeout.Infinite; + /// /// Synchronously checks whether the file is locked for writing /// From 9cf53104c33b5ebe1bc5819dad73169a9e849bac Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Thu, 5 Sep 2019 18:48:47 +0200 Subject: [PATCH 2/7] Update azure-pipelines.yml for linux support --- azure-pipelines.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 28d7674..0fa40c6 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -6,8 +6,17 @@ trigger: - master +strategy: + matrix: + linux: + imageName: 'ubuntu-latest' + mac: + imageName: 'macos-latest' + windows: + imageName: 'windows-latest' + pool: - vmImage: 'windows-latest' + vmImage: $(imageName) variables: buildConfiguration: 'Release' From 31151bbce0f72fa2c00726f9b11ea608af4e3d0f Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Thu, 5 Sep 2019 19:36:28 +0200 Subject: [PATCH 3/7] Fix check timeout --- FollowingFileStream.Tests/FollowingFileStreamTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FollowingFileStream.Tests/FollowingFileStreamTest.cs b/FollowingFileStream.Tests/FollowingFileStreamTest.cs index eea7d2b..7fe0d48 100644 --- a/FollowingFileStream.Tests/FollowingFileStreamTest.cs +++ b/FollowingFileStream.Tests/FollowingFileStreamTest.cs @@ -161,7 +161,7 @@ public void FFS_FollowingRead(bool async) input.Close(); //Thread.Sleep(200); //Assert.IsTrue(copy.IsCompletedSuccessfully); - Assert.IsTrue(copy.Wait(2*ffs.ReadTimeout)); + Assert.IsTrue(copy.Wait(3*ffs.ReadTimeout)); } Assert.IsTrue(FileCompare(inputFilePath, outputFilePath)); } From 6650b6b6e6e1ca05881ecebc498a65066e992b72 Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Thu, 5 Sep 2019 19:39:13 +0200 Subject: [PATCH 4/7] Update azure-pipelines.yml for publishSymbols on WIndows only --- azure-pipelines.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0fa40c6..eab6a82 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -98,6 +98,7 @@ steps: versionEnvVar: 'GitVersion.NuGetVersion' - task: PublishSymbols@2 + condition: eq( variables['Agent.OS'], 'Windows_NT' ) inputs: SearchPattern: | **/bin/**/FollowingFileStream.pdb From d1059900ee0887911f679bd6b5d53d2fa4260170 Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Thu, 5 Sep 2019 19:55:32 +0200 Subject: [PATCH 5/7] Update azure-pipelines.yml for ReportGenerator on MacOS --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index eab6a82..36ee115 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -68,7 +68,7 @@ steps: - script: | dotnet tool install dotnet-reportgenerator-globaltool --tool-path . ./reportgenerator "-reports:$(Build.SourcesDirectory)/coverage/coverage.opencover.xml" "-targetdir:coverage/Cobertura" "-reporttypes:Cobertura;HTMLInline;HTMLChart" - condition: eq( variables['Agent.OS'], 'Linux' ) + condition: ne( variables['Agent.OS'], 'Windows_NT' ) displayName: Run Reportgenerator on Linux - script: | From dc9ab6ad48e9b4b645214124ab1f8adfaf9fcac1 Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Thu, 5 Sep 2019 20:14:45 +0200 Subject: [PATCH 6/7] Rollback latest update of azure-pipelines.yml --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index eab6a82..36ee115 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -68,7 +68,7 @@ steps: - script: | dotnet tool install dotnet-reportgenerator-globaltool --tool-path . ./reportgenerator "-reports:$(Build.SourcesDirectory)/coverage/coverage.opencover.xml" "-targetdir:coverage/Cobertura" "-reporttypes:Cobertura;HTMLInline;HTMLChart" - condition: eq( variables['Agent.OS'], 'Linux' ) + condition: ne( variables['Agent.OS'], 'Windows_NT' ) displayName: Run Reportgenerator on Linux - script: | From 10e44c3b29ae665a18f7365d470ec935778341ff Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Thu, 5 Sep 2019 20:29:40 +0200 Subject: [PATCH 7/7] Rollback manually --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 36ee115..eab6a82 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -68,7 +68,7 @@ steps: - script: | dotnet tool install dotnet-reportgenerator-globaltool --tool-path . ./reportgenerator "-reports:$(Build.SourcesDirectory)/coverage/coverage.opencover.xml" "-targetdir:coverage/Cobertura" "-reporttypes:Cobertura;HTMLInline;HTMLChart" - condition: ne( variables['Agent.OS'], 'Windows_NT' ) + condition: eq( variables['Agent.OS'], 'Linux' ) displayName: Run Reportgenerator on Linux - script: |