This commit is contained in:
Bond_009 2021-10-03 19:52:38 +02:00
parent 9718c0b2ee
commit 9af16fcb6c
18 changed files with 77 additions and 74 deletions

View File

@ -359,14 +359,17 @@ namespace Emby.Dlna
// The stream should exist as we just got its name from GetManifestResourceNames // The stream should exist as we just got its name from GetManifestResourceNames
using (var stream = _assembly.GetManifestResourceStream(name)!) using (var stream = _assembly.GetManifestResourceStream(name)!)
{ {
var length = stream.Length;
var fileInfo = _fileSystem.GetFileInfo(path); var fileInfo = _fileSystem.GetFileInfo(path);
if (!fileInfo.Exists || fileInfo.Length != stream.Length) if (!fileInfo.Exists || fileInfo.Length != length)
{ {
Directory.CreateDirectory(systemProfilesPath); Directory.CreateDirectory(systemProfilesPath);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . var fileOptions = AsyncFile.WriteOptions;
using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) fileOptions.Mode = FileMode.CreateNew;
fileOptions.PreallocationSize = length;
using (var fileStream = new FileStream(path, fileOptions))
{ {
await stream.CopyToAsync(fileStream).ConfigureAwait(false); await stream.CopyToAsync(fileStream).ConfigureAwait(false);
} }

View File

@ -102,7 +102,7 @@ namespace Emby.Drawing
{ {
var file = await ProcessImage(options).ConfigureAwait(false); var file = await ProcessImage(options).ConfigureAwait(false);
using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) using (var fileStream = AsyncFile.OpenRead(file.Item1))
{ {
await fileStream.CopyToAsync(toStream).ConfigureAwait(false); await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
} }

View File

@ -41,20 +41,19 @@ namespace Emby.Server.Implementations.AppBase
xmlSerializer.SerializeToStream(configuration, stream); xmlSerializer.SerializeToStream(configuration, stream);
// Take the object we just got and serialize it back to bytes // Take the object we just got and serialize it back to bytes
byte[] newBytes = stream.GetBuffer(); Span<byte> newBytes = stream.GetBuffer().AsSpan(0, (int)stream.Length);
int newBytesLen = (int)stream.Length;
// If the file didn't exist before, or if something has changed, re-save // If the file didn't exist before, or if something has changed, re-save
if (buffer == null || !newBytes.AsSpan(0, newBytesLen).SequenceEqual(buffer)) if (buffer == null || !newBytes.SequenceEqual(buffer))
{ {
var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path)); var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path));
Directory.CreateDirectory(directory); Directory.CreateDirectory(directory);
// Save it after load in case we got new items // Save it after load in case we got new items
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
{ {
fs.Write(newBytes, 0, newBytesLen); fs.Write(newBytes);
} }
} }

View File

@ -46,8 +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))); 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.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
{ {
onStarted(); onStarted();
@ -79,8 +78,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile))); 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.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.CopyToBufferSize, FileOptions.Asynchronous);
await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous);
onStarted(); onStarted();

View File

@ -1848,14 +1848,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return; return;
} }
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None))
{ {
var settings = new XmlWriterSettings var settings = new XmlWriterSettings
{ {
Indent = true, Indent = true,
Encoding = Encoding.UTF8, Encoding = Encoding.UTF8
CloseOutput = false
}; };
using (var writer = XmlWriter.Create(stream, settings)) using (var writer = XmlWriter.Create(stream, settings))
@ -1913,14 +1911,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return; return;
} }
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None))
{ {
var settings = new XmlWriterSettings var settings = new XmlWriterSettings
{ {
Indent = true, Indent = true,
Encoding = Encoding.UTF8, Encoding = Encoding.UTF8
CloseOutput = false
}; };
var options = _config.GetNfoConfiguration(); var options = _config.GetNfoConfiguration();

View File

@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); 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. // 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, FileOptions.Asynchronous); _logFileStream = new FileStream(logFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false); 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); await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false);

View File

@ -183,36 +183,5 @@ namespace Jellyfin.Api.Controllers
{ {
return Path.Combine(_applicationPaths.CachePath, "remote-images", filename.Substring(0, 1), filename); return Path.Combine(_applicationPaths.CachePath, "remote-images", filename.Substring(0, 1), filename);
} }
/// <summary>
/// Downloads the image.
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="urlHash">The URL hash.</param>
/// <param name="pointerCachePath">The pointer cache path.</param>
/// <returns>Task.</returns>
private async Task DownloadImage(Uri url, Guid urlHash, string pointerCachePath)
{
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
using var response = await httpClient.GetAsync(url).ConfigureAwait(false);
if (response.Content.Headers.ContentType?.MediaType == null)
{
throw new ResourceNotFoundException(nameof(response.Content.Headers.ContentType));
}
var ext = response.Content.Headers.ContentType.MediaType.AsSpan().RightPart('/').ToString();
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid.");
Directory.CreateDirectory(fullCacheDirectory);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
await response.Content.CopyToAsync(fileStream).ConfigureAwait(false);
var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ArgumentException($"Provided path ({pointerCachePath}) is not valid.", nameof(pointerCachePath));
Directory.CreateDirectory(pointerCacheDirectory);
await System.IO.File.WriteAllTextAsync(pointerCachePath, fullCachePath, CancellationToken.None)
.ConfigureAwait(false);
}
} }
} }

View File

@ -113,11 +113,19 @@ namespace MediaBrowser.LocalMetadata.Savers
{ {
var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path)); var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path));
Directory.CreateDirectory(directory); Directory.CreateDirectory(directory);
// On Windows, savint the file will fail if the file is hidden or readonly // On Windows, savint the file will fail if the file is hidden or readonly
FileSystem.SetAttributes(path, false, false); FileSystem.SetAttributes(path, false, false);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . var fileStreamOptions = new FileStreamOptions()
using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) {
Mode = FileMode.Create,
Access = FileAccess.Write,
Share = FileShare.None,
PreallocationSize = stream.Length
};
using (var filestream = new FileStream(path, fileStreamOptions))
{ {
stream.CopyTo(filestream); stream.CopyTo(filestream);
} }

View File

@ -679,7 +679,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles
if (!string.Equals(text, newText, StringComparison.Ordinal)) if (!string.Equals(text, newText, StringComparison.Ordinal))
{ {
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
using (var writer = new StreamWriter(fileStream, encoding)) using (var writer = new StreamWriter(fileStream, encoding))
{ {

View File

@ -7,6 +7,25 @@ namespace MediaBrowser.Model.IO
/// </summary> /// </summary>
public static class AsyncFile public static class AsyncFile
{ {
/// <summary>
/// Gets the default <see cref="FileStreamOptions"/> for reading files async.
/// </summary>
public static FileStreamOptions ReadOptions => new FileStreamOptions()
{
Options = FileOptions.Asynchronous
};
/// <summary>
/// Gets the default <see cref="FileStreamOptions"/> for writing files async.
/// </summary>
public static FileStreamOptions WriteOptions => new FileStreamOptions()
{
Mode = FileMode.OpenOrCreate,
Access = FileAccess.Write,
Share = FileShare.None,
Options = FileOptions.Asynchronous
};
/// <summary> /// <summary>
/// Opens an existing file for reading. /// Opens an existing file for reading.
/// </summary> /// </summary>

View File

@ -261,8 +261,10 @@ namespace MediaBrowser.Providers.Manager
_fileSystem.SetAttributes(path, false, false); _fileSystem.SetAttributes(path, false, false);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . var fileStreamOptions = AsyncFile.WriteOptions;
await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) fileStreamOptions.Mode = FileMode.Create;
fileStreamOptions.PreallocationSize = source.Length;
await using (var fs = new FileStream(path, fileStreamOptions))
{ {
await source.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); await source.CopyToAsync(fs, cancellationToken).ConfigureAwait(false);
} }

View File

@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.Manager
{ {
var mimeType = MimeTypes.GetMimeType(response.Path); var mimeType = MimeTypes.GetMimeType(response.Path);
var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); var stream = AsyncFile.OpenRead(response.Path);
await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false);
} }

View File

@ -210,8 +210,7 @@ namespace MediaBrowser.Providers.Manager
throw new ArgumentNullException(nameof(source)); throw new ArgumentNullException(nameof(source));
} }
var fileStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); var fileStream = AsyncFile.OpenRead(source);
return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken); return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken);
} }

View File

@ -172,8 +172,11 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); var fileStreamOptions = AsyncFile.WriteOptions;
fileStreamOptions.Mode = FileMode.Create;
fileStreamOptions.PreallocationSize = stream.Length;
await using var xmlFileStream = new FileStream(path, fileStreamOptions);
await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
} }

View File

@ -154,8 +154,10 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
Directory.CreateDirectory(Path.GetDirectoryName(path)); Directory.CreateDirectory(Path.GetDirectoryName(path));
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . var fileStreamOptions = AsyncFile.WriteOptions;
await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); fileStreamOptions.Mode = FileMode.Create;
fileStreamOptions.PreallocationSize = stream.Length;
await using var xmlFileStream = new FileStream(path, fileStreamOptions);
await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
} }

View File

@ -172,19 +172,16 @@ namespace MediaBrowser.Providers.Studios
public IEnumerable<string> GetAvailableImages(string file) public IEnumerable<string> GetAvailableImages(string file)
{ {
using var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read); using var fileStream = File.OpenRead(file);
using var reader = new StreamReader(fileStream); using var reader = new StreamReader(fileStream);
var lines = new List<string>();
foreach (var line in reader.ReadAllLines()) foreach (var line in reader.ReadAllLines())
{ {
if (!string.IsNullOrWhiteSpace(line)) if (!string.IsNullOrWhiteSpace(line))
{ {
lines.Add(line); yield return line;
} }
} }
return lines;
} }
} }
} }

View File

@ -244,8 +244,10 @@ namespace MediaBrowser.Providers.Subtitles
{ {
Directory.CreateDirectory(Path.GetDirectoryName(savePath)); Directory.CreateDirectory(Path.GetDirectoryName(savePath));
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . var fileOptions = AsyncFile.WriteOptions;
using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, FileOptions.Asynchronous); fileOptions.Mode = FileMode.CreateNew;
fileOptions.PreallocationSize = stream.Length;
using var fs = new FileStream(savePath, fileOptions);
await stream.CopyToAsync(fs).ConfigureAwait(false); await stream.CopyToAsync(fs).ConfigureAwait(false);
return; return;

View File

@ -203,8 +203,15 @@ namespace MediaBrowser.XbmcMetadata.Savers
// On Windows, saving the file will fail if the file is hidden or readonly // On Windows, saving the file will fail if the file is hidden or readonly
FileSystem.SetAttributes(path, false, false); FileSystem.SetAttributes(path, false, false);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . var fileStreamOptions = new FileStreamOptions()
using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) {
Mode = FileMode.Create,
Access = FileAccess.Write,
Share = FileShare.None,
PreallocationSize = stream.Length
};
using (var filestream = new FileStream(path, fileStreamOptions))
{ {
stream.CopyTo(filestream); stream.CopyTo(filestream);
} }