mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-15 09:59:06 -07:00
Merge pull request #621 from Bond-009/perf
Minor improvements to library scan code
This commit is contained in:
commit
803bf563d7
@ -22,17 +22,17 @@ namespace Emby.Naming.TV
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
var isStub = false;
|
||||
bool isStub = false;
|
||||
string container = null;
|
||||
string stubType = null;
|
||||
|
||||
if (!IsDirectory)
|
||||
{
|
||||
var extension = Path.GetExtension(path) ?? string.Empty;
|
||||
var extension = Path.GetExtension(path);
|
||||
// Check supported extensions
|
||||
if (!_options.VideoFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
var stubResult = new StubResolver(_options).ResolveFile(path);
|
||||
var stubResult = StubResolver.ResolveFile(path, _options);
|
||||
|
||||
isStub = stubResult.IsStub;
|
||||
|
||||
|
@ -5,21 +5,14 @@ using Emby.Naming.Common;
|
||||
|
||||
namespace Emby.Naming.Video
|
||||
{
|
||||
public class StubResolver
|
||||
public static class StubResolver
|
||||
{
|
||||
private readonly NamingOptions _options;
|
||||
|
||||
public StubResolver(NamingOptions options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public StubResult ResolveFile(string path)
|
||||
public static StubResult ResolveFile(string path, NamingOptions options)
|
||||
{
|
||||
var result = new StubResult();
|
||||
var extension = Path.GetExtension(path) ?? string.Empty;
|
||||
|
||||
if (_options.StubFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
|
||||
if (options.StubFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
result.IsStub = true;
|
||||
|
||||
@ -27,12 +20,11 @@ namespace Emby.Naming.Video
|
||||
|
||||
var token = (Path.GetExtension(path) ?? string.Empty).TrimStart('.');
|
||||
|
||||
foreach (var rule in _options.StubTypes)
|
||||
foreach (var rule in options.StubTypes)
|
||||
{
|
||||
if (string.Equals(rule.Token, token, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result.StubType = rule.StubType;
|
||||
result.Tokens.Add(token);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Emby.Naming.Video
|
||||
{
|
||||
public class StubResult
|
||||
public struct StubResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is stub.
|
||||
@ -14,15 +12,5 @@ namespace Emby.Naming.Video
|
||||
/// </summary>
|
||||
/// <value>The type of the stub.</value>
|
||||
public string StubType { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the tokens.
|
||||
/// </summary>
|
||||
/// <value>The tokens.</value>
|
||||
public List<string> Tokens { get; set; }
|
||||
|
||||
public StubResult()
|
||||
{
|
||||
Tokens = new List<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,17 +48,17 @@ namespace Emby.Naming.Video
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
var isStub = false;
|
||||
bool isStub = false;
|
||||
string container = null;
|
||||
string stubType = null;
|
||||
|
||||
if (!IsDirectory)
|
||||
{
|
||||
var extension = Path.GetExtension(path) ?? string.Empty;
|
||||
var extension = Path.GetExtension(path);
|
||||
// Check supported extensions
|
||||
if (!_options.VideoFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
var stubResult = new StubResolver(_options).ResolveFile(path);
|
||||
var stubResult = StubResolver.ResolveFile(path, _options);
|
||||
|
||||
isStub = stubResult.IsStub;
|
||||
|
||||
@ -79,9 +79,9 @@ namespace Emby.Naming.Video
|
||||
|
||||
var extraResult = new ExtraResolver(_options).GetExtraInfo(path);
|
||||
|
||||
var name = !IsDirectory
|
||||
? Path.GetFileNameWithoutExtension(path)
|
||||
: Path.GetFileName(path);
|
||||
var name = IsDirectory
|
||||
? Path.GetFileName(path)
|
||||
: Path.GetFileNameWithoutExtension(path);
|
||||
|
||||
int? year = null;
|
||||
|
||||
@ -91,8 +91,7 @@ namespace Emby.Naming.Video
|
||||
|
||||
if (string.IsNullOrEmpty(extraResult.ExtraType))
|
||||
{
|
||||
name = cleanDateTimeResult.Name;
|
||||
name = CleanString(name).Name;
|
||||
name = CleanString(cleanDateTimeResult.Name).Name;
|
||||
}
|
||||
|
||||
year = cleanDateTimeResult.Year;
|
||||
|
@ -268,7 +268,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
||||
|
||||
var responseCachePath = Path.Combine(_appPaths.CachePath, "httpclient", urlHash);
|
||||
|
||||
var response = await GetCachedResponse(responseCachePath, options.CacheLength, url).ConfigureAwait(false);
|
||||
var response = GetCachedResponse(responseCachePath, options.CacheLength, url);
|
||||
if (response != null)
|
||||
{
|
||||
return response;
|
||||
@ -284,30 +284,24 @@ namespace Emby.Server.Implementations.HttpClientManager
|
||||
return response;
|
||||
}
|
||||
|
||||
private async Task<HttpResponseInfo> GetCachedResponse(string responseCachePath, TimeSpan cacheLength, string url)
|
||||
private HttpResponseInfo GetCachedResponse(string responseCachePath, TimeSpan cacheLength, string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_fileSystem.GetLastWriteTimeUtc(responseCachePath).Add(cacheLength) > DateTime.UtcNow)
|
||||
{
|
||||
using (var stream = _fileSystem.GetFileStream(responseCachePath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true))
|
||||
var stream = _fileSystem.GetFileStream(responseCachePath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true);
|
||||
|
||||
return new HttpResponseInfo
|
||||
{
|
||||
var memoryStream = new MemoryStream();
|
||||
|
||||
await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||
memoryStream.Position = 0;
|
||||
|
||||
return new HttpResponseInfo
|
||||
{
|
||||
ResponseUrl = url,
|
||||
Content = memoryStream,
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
ContentLength = memoryStream.Length
|
||||
};
|
||||
}
|
||||
ResponseUrl = url,
|
||||
Content = stream,
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
ContentLength = stream.Length
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
catch (FileNotFoundException) // REVIEW: @bond Is this really faster?
|
||||
{
|
||||
|
||||
}
|
||||
@ -323,19 +317,11 @@ namespace Emby.Server.Implementations.HttpClientManager
|
||||
{
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(responseCachePath));
|
||||
|
||||
using (var responseStream = response.Content)
|
||||
using (var fileStream = _fileSystem.GetFileStream(responseCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None, true))
|
||||
{
|
||||
var memoryStream = new MemoryStream();
|
||||
await responseStream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||
memoryStream.Position = 0;
|
||||
await response.Content.CopyToAsync(fileStream).ConfigureAwait(false);
|
||||
|
||||
using (var fileStream = _fileSystem.GetFileStream(responseCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None, true))
|
||||
{
|
||||
await memoryStream.CopyToAsync(fileStream).ConfigureAwait(false);
|
||||
|
||||
memoryStream.Position = 0;
|
||||
response.Content = memoryStream;
|
||||
}
|
||||
response.Content.Position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,10 +450,7 @@ namespace Emby.Server.Implementations.IO
|
||||
}
|
||||
|
||||
public Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, FileOpenOptions fileOpenOptions)
|
||||
{
|
||||
var defaultBufferSize = 4096;
|
||||
return new FileStream(path, GetFileMode(mode), GetFileAccess(access), GetFileShare(share), defaultBufferSize, GetFileOptions(fileOpenOptions));
|
||||
}
|
||||
=> new FileStream(path, GetFileMode(mode), GetFileAccess(access), GetFileShare(share), 4096, GetFileOptions(fileOpenOptions));
|
||||
|
||||
private static FileOptions GetFileOptions(FileOpenOptions mode)
|
||||
{
|
||||
@ -764,18 +761,13 @@ namespace Emby.Server.Implementations.IO
|
||||
// Only include drives in the ready state or this method could end up being very slow, waiting for drives to timeout
|
||||
return DriveInfo.GetDrives().Where(d => d.IsReady).Select(d => new FileSystemMetadata
|
||||
{
|
||||
Name = GetName(d),
|
||||
Name = d.Name,
|
||||
FullName = d.RootDirectory.FullName,
|
||||
IsDirectory = true
|
||||
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
private static string GetName(DriveInfo drive)
|
||||
{
|
||||
return drive.Name;
|
||||
}
|
||||
|
||||
public IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false)
|
||||
{
|
||||
var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||||
@ -851,17 +843,6 @@ namespace Emby.Server.Implementations.IO
|
||||
return File.OpenRead(path);
|
||||
}
|
||||
|
||||
private void CopyFileUsingStreams(string source, string target, bool overwrite)
|
||||
{
|
||||
using (var sourceStream = OpenRead(source))
|
||||
{
|
||||
using (var targetStream = GetFileStream(target, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
|
||||
{
|
||||
sourceStream.CopyTo(targetStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyFile(string source, string target, bool overwrite)
|
||||
{
|
||||
File.Copy(source, target, overwrite);
|
||||
|
@ -107,7 +107,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool IsSeriesFolder(string path,
|
||||
public static bool IsSeriesFolder(
|
||||
string path,
|
||||
IEnumerable<FileSystemMetadata> fileSystemChildren,
|
||||
IDirectoryService directoryService,
|
||||
IFileSystem fileSystem,
|
||||
@ -135,7 +136,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
{
|
||||
if (IsSeasonFolder(child.FullName, isTvContentType, libraryManager))
|
||||
{
|
||||
//logger.LogDebug("{0} is a series because of season folder {1}.", path, child.FullName);
|
||||
logger.LogDebug("{Path} is a series because of season folder {Dir}.", path, child.FullName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -161,7 +162,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
isOptimistic = false;
|
||||
}
|
||||
|
||||
var episodeInfo = episodeResolver.Resolve(fullName, false, isNamed, isOptimistic, null, false);
|
||||
var episodeInfo = episodeResolver.Resolve(fullName, false, isNamed, isOptimistic, fillExtendedInfo: false);
|
||||
if (episodeInfo != null && episodeInfo.EpisodeNumber.HasValue)
|
||||
{
|
||||
return true;
|
||||
@ -170,7 +171,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
}
|
||||
}
|
||||
|
||||
//logger.LogDebug("{0} is not a series folder.", path);
|
||||
logger.LogDebug("{Path} is not a series folder.", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1403,9 +1403,9 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
private async Task<bool> RefreshLocalTrailers(IHasTrailers item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
||||
{
|
||||
var newItems = LibraryManager.FindTrailers(this, fileSystemChildren, options.DirectoryService).ToList();
|
||||
var newItems = LibraryManager.FindTrailers(this, fileSystemChildren, options.DirectoryService);
|
||||
|
||||
var newItemIds = newItems.Select(i => i.Id).ToArray();
|
||||
var newItemIds = newItems.Select(i => i.Id);
|
||||
|
||||
var itemsChanged = !item.LocalTrailerIds.SequenceEqual(newItemIds);
|
||||
var ownerId = item.Id;
|
||||
@ -1414,8 +1414,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var subOptions = new MetadataRefreshOptions(options);
|
||||
|
||||
if (!i.ExtraType.HasValue ||
|
||||
i.ExtraType.Value != Model.Entities.ExtraType.Trailer ||
|
||||
if (i.ExtraType != Model.Entities.ExtraType.Trailer ||
|
||||
i.OwnerId != ownerId ||
|
||||
!i.ParentId.Equals(Guid.Empty))
|
||||
{
|
||||
@ -1430,7 +1429,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
|
||||
item.LocalTrailerIds = newItemIds;
|
||||
item.LocalTrailerIds = newItemIds.ToArray();
|
||||
|
||||
return itemsChanged;
|
||||
}
|
||||
|
@ -177,13 +177,7 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
private async Task<MetadataResult<Series>> FetchMovieData(string tmdbId, string language, string preferredCountryCode, CancellationToken cancellationToken)
|
||||
{
|
||||
string dataFilePath = null;
|
||||
RootObject seriesInfo = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(tmdbId))
|
||||
{
|
||||
seriesInfo = await FetchMainResult(tmdbId, language, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
RootObject seriesInfo = await FetchMainResult(tmdbId, language, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (seriesInfo == null)
|
||||
{
|
||||
@ -192,7 +186,7 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
tmdbId = seriesInfo.id.ToString(_usCulture);
|
||||
|
||||
dataFilePath = GetDataFilePath(tmdbId, language);
|
||||
string dataFilePath = GetDataFilePath(tmdbId, language);
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath));
|
||||
_jsonSerializer.SerializeToFile(seriesInfo, dataFilePath);
|
||||
|
||||
@ -220,7 +214,7 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
string voteAvg = seriesInfo.vote_average.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (float.TryParse(voteAvg, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var rating))
|
||||
if (float.TryParse(voteAvg, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out float rating))
|
||||
{
|
||||
series.CommunityRating = rating;
|
||||
}
|
||||
@ -293,14 +287,11 @@ namespace MediaBrowser.Providers.TV
|
||||
{
|
||||
foreach (var video in seriesInfo.videos.results)
|
||||
{
|
||||
if (video.type.Equals("trailer", System.StringComparison.OrdinalIgnoreCase)
|
||||
|| video.type.Equals("clip", System.StringComparison.OrdinalIgnoreCase))
|
||||
if ((video.type.Equals("trailer", StringComparison.OrdinalIgnoreCase)
|
||||
|| video.type.Equals("clip", StringComparison.OrdinalIgnoreCase))
|
||||
&& video.site.Equals("youtube", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (video.site.Equals("youtube", System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var videoUrl = string.Format("http://www.youtube.com/watch?v={0}", video.key);
|
||||
series.AddTrailerUrl(videoUrl);
|
||||
}
|
||||
series.AddTrailerUrl($"http://www.youtube.com/watch?v={video.key}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -351,9 +342,12 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
internal async Task DownloadSeriesInfo(string id, string preferredMetadataLanguage, CancellationToken cancellationToken)
|
||||
{
|
||||
var mainResult = await FetchMainResult(id, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
|
||||
RootObject mainResult = await FetchMainResult(id, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (mainResult == null) return;
|
||||
if (mainResult == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var dataFilePath = GetDataFilePath(id, preferredMetadataLanguage);
|
||||
|
||||
@ -368,10 +362,8 @@ namespace MediaBrowser.Providers.TV
|
||||
|
||||
if (!string.IsNullOrEmpty(language))
|
||||
{
|
||||
url += string.Format("&language={0}", MovieDbProvider.NormalizeLanguage(language));
|
||||
|
||||
// Get images in english and with no language
|
||||
url += "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language);
|
||||
url += "&language=" + MovieDbProvider.NormalizeLanguage(language)
|
||||
+ "&include_image_language=" + MovieDbProvider.GetImageLanguagesParam(language); // Get images in english and with no language
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@ -405,7 +397,7 @@ namespace MediaBrowser.Providers.TV
|
||||
!string.IsNullOrEmpty(language) &&
|
||||
!string.Equals(language, "en", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_logger.LogInformation("MovieDbSeriesProvider couldn't find meta for language " + language + ". Trying English...");
|
||||
_logger.LogInformation("MovieDbSeriesProvider couldn't find meta for language {Language}. Trying English...", language);
|
||||
|
||||
url = string.Format(GetTvInfo3, id, MovieDbProvider.ApiKey) + "&language=en";
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user