mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-05-02 14:56:31 +01:00
Use async FileStreams where it makes sense
This commit is contained in:
@@ -46,7 +46,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile)));
|
||||
|
||||
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
|
||||
using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO))
|
||||
{
|
||||
onStarted();
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile)));
|
||||
|
||||
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
|
||||
await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, AsyncFile.UseAsyncIO);
|
||||
|
||||
onStarted();
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
|
||||
|
||||
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
|
||||
_logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true);
|
||||
_logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
|
||||
await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false);
|
||||
await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||
|
||||
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(path, cancellationToken).ConfigureAwait(false);
|
||||
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
|
||||
await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew))
|
||||
await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, AsyncFile.UseAsyncIO))
|
||||
{
|
||||
await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(channelCacheFile));
|
||||
await using var writeStream = File.OpenWrite(channelCacheFile);
|
||||
await using var writeStream = AsyncFile.OpenWrite(channelCacheFile);
|
||||
await JsonSerializer.SerializeAsync(writeStream, channels, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (IOException)
|
||||
@@ -108,7 +108,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
{
|
||||
try
|
||||
{
|
||||
await using var readStream = File.OpenRead(channelCacheFile);
|
||||
await using var readStream = AsyncFile.OpenRead(channelCacheFile);
|
||||
var channels = await JsonSerializer.DeserializeAsync<List<ChannelInfo>>(readStream, cancellationToken: cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
list.AddRange(channels);
|
||||
|
||||
@@ -155,15 +155,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
using var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, LiveStreamCancellationTokenSource.Token);
|
||||
cancellationToken = linkedCancellationTokenSource.Token;
|
||||
|
||||
// use non-async filestream on windows along with read due to https://github.com/dotnet/corefx/issues/6039
|
||||
var allowAsync = Environment.OSVersion.Platform != PlatformID.Win32NT;
|
||||
|
||||
bool seekFile = (DateTime.UtcNow - DateOpened).TotalSeconds > 10;
|
||||
|
||||
var nextFileInfo = GetNextFile(null);
|
||||
var nextFile = nextFileInfo.file;
|
||||
var isLastFile = nextFileInfo.isLastFile;
|
||||
|
||||
var allowAsync = AsyncFile.UseAsyncIO;
|
||||
while (!string.IsNullOrEmpty(nextFile))
|
||||
{
|
||||
var emptyReadLimit = isLastFile ? EmptyReadLimit : 1;
|
||||
|
||||
@@ -14,6 +14,7 @@ using Jellyfin.Extensions;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -50,7 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
if (!info.Url.StartsWith("http", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return File.OpenRead(info.Url);
|
||||
return AsyncFile.OpenRead(info.Url);
|
||||
}
|
||||
|
||||
using var requestMessage = new HttpRequestMessage(HttpMethod.Get, info.Url);
|
||||
|
||||
@@ -129,37 +129,39 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
private Task StartStreaming(HttpResponseMessage response, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
return Task.Run(
|
||||
async () =>
|
||||
{
|
||||
Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath);
|
||||
using var message = response;
|
||||
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
|
||||
await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||
await StreamHelper.CopyToAsync(
|
||||
stream,
|
||||
fileStream,
|
||||
IODefaults.CopyToBufferSize,
|
||||
() => Resolve(openTaskCompletionSource),
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
Logger.LogInformation("Copying of {0} to {1} was canceled", GetType().Name, TempFilePath);
|
||||
openTaskCompletionSource.TrySetException(ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error copying live stream {0} to {1}.", GetType().Name, TempFilePath);
|
||||
openTaskCompletionSource.TrySetException(ex);
|
||||
}
|
||||
try
|
||||
{
|
||||
Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath);
|
||||
using var message = response;
|
||||
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
|
||||
await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
await StreamHelper.CopyToAsync(
|
||||
stream,
|
||||
fileStream,
|
||||
IODefaults.CopyToBufferSize,
|
||||
() => Resolve(openTaskCompletionSource),
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
Logger.LogInformation("Copying of {0} to {1} was canceled", GetType().Name, TempFilePath);
|
||||
openTaskCompletionSource.TrySetException(ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error copying live stream {0} to {1}.", GetType().Name, TempFilePath);
|
||||
openTaskCompletionSource.TrySetException(ex);
|
||||
}
|
||||
|
||||
openTaskCompletionSource.TrySetResult(false);
|
||||
openTaskCompletionSource.TrySetResult(false);
|
||||
|
||||
EnableStreamSharing = false;
|
||||
await DeleteTempFiles(new List<string> { TempFilePath }).ConfigureAwait(false);
|
||||
}, CancellationToken.None);
|
||||
EnableStreamSharing = false;
|
||||
await DeleteTempFiles(new List<string> { TempFilePath }).ConfigureAwait(false);
|
||||
},
|
||||
CancellationToken.None);
|
||||
}
|
||||
|
||||
private void Resolve(TaskCompletionSource<bool> openTaskCompletionSource)
|
||||
|
||||
Reference in New Issue
Block a user