commit
a9eb446288
|
@ -290,8 +290,6 @@
|
|||
<Compile Include="Providers\IImageFileSaver.cs" />
|
||||
<Compile Include="Providers\IImageProvider.cs" />
|
||||
<Compile Include="Providers\IImageSaver.cs" />
|
||||
<Compile Include="Providers\IItemIdentityConverter.cs" />
|
||||
<Compile Include="Providers\IItemIdentityProvider.cs" />
|
||||
<Compile Include="Providers\ILocalImageFileProvider.cs" />
|
||||
<Compile Include="Providers\ILocalMetadataProvider.cs" />
|
||||
<Compile Include="Providers\ImageRefreshMode.cs" />
|
||||
|
@ -329,8 +327,6 @@
|
|||
<Compile Include="Sorting\SortHelper.cs" />
|
||||
<Compile Include="Subtitles\ISubtitleManager.cs" />
|
||||
<Compile Include="Subtitles\ISubtitleProvider.cs" />
|
||||
<Compile Include="Providers\ItemIdentifier.cs" />
|
||||
<Compile Include="Providers\ItemIdentities.cs" />
|
||||
<Compile Include="Providers\ItemLookupInfo.cs" />
|
||||
<Compile Include="Providers\MetadataRefreshOptions.cs" />
|
||||
<Compile Include="Providers\ISeriesOrderManager.cs" />
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
public interface IItemIdentityConverter { }
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
public interface IItemIdentityProvider { }
|
||||
}
|
|
@ -97,13 +97,11 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// </summary>
|
||||
/// <param name="imageProviders">The image providers.</param>
|
||||
/// <param name="metadataServices">The metadata services.</param>
|
||||
/// <param name="identityProviders">The identity providers.</param>
|
||||
/// <param name="identityConverters">The identity converters.</param>
|
||||
/// <param name="metadataProviders">The metadata providers.</param>
|
||||
/// <param name="savers">The savers.</param>
|
||||
/// <param name="imageSavers">The image savers.</param>
|
||||
/// <param name="externalIds">The external ids.</param>
|
||||
void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IItemIdentityProvider> identityProviders, IEnumerable<IItemIdentityConverter> identityConverters, IEnumerable<IMetadataProvider> metadataProviders,
|
||||
void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders,
|
||||
IEnumerable<IMetadataSaver> savers,
|
||||
IEnumerable<IImageSaver> imageSavers,
|
||||
IEnumerable<IExternalId> externalIds);
|
||||
|
@ -190,21 +188,5 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
||||
Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item identity providers.
|
||||
/// </summary>
|
||||
/// <typeparam name="TLookupInfo">The type of the t lookup information.</typeparam>
|
||||
/// <returns>IEnumerable<IItemIdentityProvider<TLookupInfo, TIdentity>>.</returns>
|
||||
IEnumerable<IItemIdentityProvider<TLookupInfo>> GetItemIdentityProviders<TLookupInfo>()
|
||||
where TLookupInfo : ItemLookupInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item identity converters.
|
||||
/// </summary>
|
||||
/// <typeparam name="TLookupInfo">The type of the t lookup information.</typeparam>
|
||||
/// <returns>IEnumerable<IItemIdentityConverter<TIdentity>>.</returns>
|
||||
IEnumerable<IItemIdentityConverter<TLookupInfo>> GetItemIdentityConverters<TLookupInfo>()
|
||||
where TLookupInfo : ItemLookupInfo;
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
public static class ItemIdentifier<TLookupInfo>
|
||||
where TLookupInfo : ItemLookupInfo
|
||||
{
|
||||
public static async Task FindIdentities(TLookupInfo item, IProviderManager providerManager, CancellationToken cancellationToken)
|
||||
{
|
||||
var providers = providerManager.GetItemIdentityProviders<TLookupInfo>();
|
||||
var converters = providerManager.GetItemIdentityConverters<TLookupInfo>().ToList();
|
||||
|
||||
foreach (var provider in providers)
|
||||
{
|
||||
await provider.Identify(item);
|
||||
}
|
||||
|
||||
bool changesMade = true;
|
||||
|
||||
while (changesMade)
|
||||
{
|
||||
changesMade = false;
|
||||
|
||||
foreach (var converter in converters)
|
||||
{
|
||||
if (await converter.Convert(item))
|
||||
{
|
||||
changesMade = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
public interface IItemIdentityProvider<in TLookupInfo> : IItemIdentityProvider
|
||||
where TLookupInfo : ItemLookupInfo
|
||||
{
|
||||
Task Identify(TLookupInfo info);
|
||||
}
|
||||
|
||||
public interface IItemIdentityConverter<in TLookupInfo> : IItemIdentityConverter
|
||||
where TLookupInfo : ItemLookupInfo
|
||||
{
|
||||
Task<bool> Convert(TLookupInfo info);
|
||||
}
|
||||
}
|
|
@ -179,18 +179,6 @@ namespace MediaBrowser.Providers.Manager
|
|||
lookupInfo.Year = result.ProductionYear;
|
||||
}
|
||||
|
||||
private async Task FindIdentities(TIdType id, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ItemIdentifier<TIdType>.FindIdentities(id, ProviderManager, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error in FindIdentities", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime GetLastRefreshDate(IHasMetadata item)
|
||||
{
|
||||
return item.DateLastRefreshed;
|
||||
|
|
|
@ -55,8 +55,6 @@ namespace MediaBrowser.Providers.Manager
|
|||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
private IMetadataService[] _metadataServices = { };
|
||||
private IItemIdentityProvider[] _identityProviders = { };
|
||||
private IItemIdentityConverter[] _identityConverters = { };
|
||||
private IMetadataProvider[] _metadataProviders = { };
|
||||
private IEnumerable<IMetadataSaver> _savers;
|
||||
private IImageSaver[] _imageSavers;
|
||||
|
@ -92,22 +90,17 @@ namespace MediaBrowser.Providers.Manager
|
|||
/// </summary>
|
||||
/// <param name="imageProviders">The image providers.</param>
|
||||
/// <param name="metadataServices">The metadata services.</param>
|
||||
/// <param name="identityProviders">The identity providers.</param>
|
||||
/// <param name="identityConverters">The identity converters.</param>
|
||||
/// <param name="metadataProviders">The metadata providers.</param>
|
||||
/// <param name="metadataSavers">The metadata savers.</param>
|
||||
/// <param name="imageSavers">The image savers.</param>
|
||||
/// <param name="externalIds">The external ids.</param>
|
||||
public void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices,
|
||||
IEnumerable<IItemIdentityProvider> identityProviders, IEnumerable<IItemIdentityConverter> identityConverters,
|
||||
IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> metadataSavers,
|
||||
IEnumerable<IImageSaver> imageSavers, IEnumerable<IExternalId> externalIds)
|
||||
{
|
||||
ImageProviders = imageProviders.ToArray();
|
||||
|
||||
_metadataServices = metadataServices.OrderBy(i => i.Order).ToArray();
|
||||
_identityProviders = identityProviders.ToArray();
|
||||
_identityConverters = identityConverters.ToArray();
|
||||
_metadataProviders = metadataProviders.ToArray();
|
||||
_imageSavers = imageSavers.ToArray();
|
||||
_externalIds = externalIds.OrderBy(i => i.Name).ToArray();
|
||||
|
@ -301,18 +294,6 @@ namespace MediaBrowser.Providers.Manager
|
|||
.ThenBy(GetDefaultOrder);
|
||||
}
|
||||
|
||||
public IEnumerable<IItemIdentityProvider<TLookupInfo>> GetItemIdentityProviders<TLookupInfo>()
|
||||
where TLookupInfo : ItemLookupInfo
|
||||
{
|
||||
return _identityProviders.OfType<IItemIdentityProvider<TLookupInfo>>();
|
||||
}
|
||||
|
||||
public IEnumerable<IItemIdentityConverter<TLookupInfo>> GetItemIdentityConverters<TLookupInfo>()
|
||||
where TLookupInfo : ItemLookupInfo
|
||||
{
|
||||
return _identityConverters.OfType<IItemIdentityConverter<TLookupInfo>>();
|
||||
}
|
||||
|
||||
private IEnumerable<IRemoteImageProvider> GetRemoteImageProviders(IHasImages item, bool includeDisabled)
|
||||
{
|
||||
var options = GetMetadataOptions(item);
|
||||
|
|
|
@ -177,7 +177,6 @@
|
|||
<Compile Include="TV\SeriesMetadataService.cs" />
|
||||
<Compile Include="TV\TheTVDB\TvdbEpisodeImageProvider.cs" />
|
||||
<Compile Include="People\TvdbPersonImageProvider.cs" />
|
||||
<Compile Include="TV\TheTVDB\TvdbSeasonIdentityProvider.cs" />
|
||||
<Compile Include="TV\TheTVDB\TvdbSeasonImageProvider.cs" />
|
||||
<Compile Include="TV\TheTVDB\TvdbSeriesImageProvider.cs" />
|
||||
<Compile Include="TV\SeasonMetadataService.cs" />
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace MediaBrowser.Providers.TV
|
|||
/// <summary>
|
||||
/// Class RemoteEpisodeProvider
|
||||
/// </summary>
|
||||
class TvdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IItemIdentityProvider<EpisodeInfo>
|
||||
class TvdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>
|
||||
{
|
||||
private static readonly string FullIdKey = MetadataProviders.Tvdb + "-Full";
|
||||
|
||||
|
@ -871,86 +871,6 @@ namespace MediaBrowser.Providers.TV
|
|||
});
|
||||
}
|
||||
|
||||
public Task Identify(EpisodeInfo info)
|
||||
{
|
||||
if (info.ProviderIds.ContainsKey(FullIdKey))
|
||||
{
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
|
||||
string seriesTvdbId;
|
||||
info.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId);
|
||||
|
||||
if (string.IsNullOrEmpty(seriesTvdbId) || info.IndexNumber == null)
|
||||
{
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
|
||||
var id = new Identity(seriesTvdbId, info.ParentIndexNumber, info.IndexNumber.Value, info.IndexNumberEnd);
|
||||
info.SetProviderId(FullIdKey, id.ToString());
|
||||
|
||||
return Task.FromResult(id);
|
||||
}
|
||||
|
||||
public int Order { get { return 0; } }
|
||||
|
||||
public struct Identity
|
||||
{
|
||||
public string SeriesId { get; private set; }
|
||||
public int? SeasonIndex { get; private set; }
|
||||
public int EpisodeNumber { get; private set; }
|
||||
public int? EpisodeNumberEnd { get; private set; }
|
||||
|
||||
public Identity(string id)
|
||||
: this()
|
||||
{
|
||||
this = ParseIdentity(id).Value;
|
||||
}
|
||||
|
||||
public Identity(string seriesId, int? seasonIndex, int episodeNumber, int? episodeNumberEnd)
|
||||
: this()
|
||||
{
|
||||
SeriesId = seriesId;
|
||||
SeasonIndex = seasonIndex;
|
||||
EpisodeNumber = episodeNumber;
|
||||
EpisodeNumberEnd = episodeNumberEnd;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0}:{1}:{2}",
|
||||
SeriesId,
|
||||
SeasonIndex != null ? SeasonIndex.Value.ToString() : "A",
|
||||
EpisodeNumber + (EpisodeNumberEnd != null ? "-" + EpisodeNumberEnd.Value.ToString() : ""));
|
||||
}
|
||||
|
||||
public static Identity? ParseIdentity(string id)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id))
|
||||
return null;
|
||||
|
||||
try {
|
||||
var parts = id.Split(':');
|
||||
var series = parts[0];
|
||||
var season = parts[1] != "A" ? (int?)int.Parse(parts[1]) : null;
|
||||
|
||||
int index;
|
||||
int? indexEnd;
|
||||
|
||||
if (parts[2].Contains("-")) {
|
||||
var split = parts[2].IndexOf("-", StringComparison.OrdinalIgnoreCase);
|
||||
index = int.Parse(parts[2].Substring(0, split));
|
||||
indexEnd = int.Parse(parts[2].Substring(split + 1));
|
||||
} else {
|
||||
index = int.Parse(parts[2]);
|
||||
indexEnd = null;
|
||||
}
|
||||
|
||||
return new Identity(series, season, index, indexEnd);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Providers.TV
|
||||
{
|
||||
public class TvdbSeasonIdentityProvider : IItemIdentityProvider<SeasonInfo>
|
||||
{
|
||||
public static readonly string FullIdKey = MetadataProviders.Tvdb + "-Full";
|
||||
|
||||
public Task Identify(SeasonInfo info)
|
||||
{
|
||||
string tvdbSeriesId;
|
||||
if (!info.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out tvdbSeriesId) || string.IsNullOrEmpty(tvdbSeriesId) || info.IndexNumber == null)
|
||||
{
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(info.GetProviderId(FullIdKey)))
|
||||
{
|
||||
var id = string.Format("{0}:{1}", tvdbSeriesId, info.IndexNumber.Value);
|
||||
info.SetProviderId(FullIdKey, id);
|
||||
}
|
||||
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
|
||||
public static TvdbSeasonIdentity? ParseIdentity(string id)
|
||||
{
|
||||
if (id == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var parts = id.Split(':');
|
||||
return new TvdbSeasonIdentity(parts[0], int.Parse(parts[1]));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct TvdbSeasonIdentity
|
||||
{
|
||||
public string SeriesId { get; private set; }
|
||||
public int Index { get; private set; }
|
||||
|
||||
public TvdbSeasonIdentity(string id)
|
||||
: this()
|
||||
{
|
||||
this = TvdbSeasonIdentityProvider.ParseIdentity(id).Value;
|
||||
}
|
||||
|
||||
public TvdbSeasonIdentity(string seriesId, int index)
|
||||
: this()
|
||||
{
|
||||
SeriesId = seriesId;
|
||||
Index = index;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,21 +70,6 @@ namespace MediaBrowser.Providers.TV
|
|||
var seriesProviderIds = series.ProviderIds;
|
||||
var seasonNumber = season.IndexNumber.Value;
|
||||
|
||||
var identity = TvdbSeasonIdentityProvider.ParseIdentity(season.GetProviderId(TvdbSeasonIdentityProvider.FullIdKey));
|
||||
if (identity == null)
|
||||
{
|
||||
identity = new TvdbSeasonIdentity(series.GetProviderId(MetadataProviders.Tvdb), seasonNumber);
|
||||
}
|
||||
|
||||
if (identity != null)
|
||||
{
|
||||
var id = identity.Value;
|
||||
seasonNumber = AdjustForSeriesOffset(series, id.Index);
|
||||
|
||||
seriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
seriesProviderIds[MetadataProviders.Tvdb.ToString()] = id.SeriesId;
|
||||
}
|
||||
|
||||
var seriesDataPath = await TvdbSeriesProvider.Current.EnsureSeriesInfo(seriesProviderIds, series.GetPreferredMetadataLanguage(), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(seriesDataPath))
|
||||
|
|
|
@ -25,7 +25,7 @@ using CommonIO;
|
|||
|
||||
namespace MediaBrowser.Providers.TV
|
||||
{
|
||||
public class TvdbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IItemIdentityProvider<SeriesInfo>, IHasOrder
|
||||
public class TvdbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder
|
||||
{
|
||||
private const string TvdbSeriesOffset = "TvdbSeriesOffset";
|
||||
private const string TvdbSeriesOffsetFormat = "{0}-{1}";
|
||||
|
|
241
MediaBrowser.Server.Implementations/IO/FileRefresher.cs
Normal file
241
MediaBrowser.Server.Implementations/IO/FileRefresher.cs
Normal file
|
@ -0,0 +1,241 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CommonIO;
|
||||
using MediaBrowser.Common.ScheduledTasks;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Server.Implementations.ScheduledTasks;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.IO
|
||||
{
|
||||
public class FileRefresher : IDisposable
|
||||
{
|
||||
private ILogger Logger { get; set; }
|
||||
private ITaskManager TaskManager { get; set; }
|
||||
private ILibraryManager LibraryManager { get; set; }
|
||||
private IServerConfigurationManager ConfigurationManager { get; set; }
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly List<string> _affectedPaths = new List<string>();
|
||||
private Timer _timer;
|
||||
private readonly object _timerLock = new object();
|
||||
|
||||
public FileRefresher(string path, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ITaskManager taskManager, ILogger logger)
|
||||
{
|
||||
_affectedPaths.Add(path);
|
||||
|
||||
_fileSystem = fileSystem;
|
||||
ConfigurationManager = configurationManager;
|
||||
LibraryManager = libraryManager;
|
||||
TaskManager = taskManager;
|
||||
Logger = logger;
|
||||
}
|
||||
|
||||
private void RestartTimer()
|
||||
{
|
||||
lock (_timerLock)
|
||||
{
|
||||
if (_timer == null)
|
||||
{
|
||||
_timer = new Timer(OnTimerCallback, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
|
||||
}
|
||||
else
|
||||
{
|
||||
_timer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnTimerCallback(object state)
|
||||
{
|
||||
// Extend the timer as long as any of the paths are still being written to.
|
||||
if (_affectedPaths.Any(IsFileLocked))
|
||||
{
|
||||
Logger.Info("Timer extended.");
|
||||
RestartTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.Debug("Timer stopped.");
|
||||
|
||||
DisposeTimer();
|
||||
|
||||
try
|
||||
{
|
||||
await ProcessPathChanges(_affectedPaths).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error processing directory changes", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessPathChanges(List<string> paths)
|
||||
{
|
||||
var itemsToRefresh = paths
|
||||
.Select(GetAffectedBaseItem)
|
||||
.Where(item => item != null)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
foreach (var p in paths)
|
||||
{
|
||||
Logger.Info(p + " reports change.");
|
||||
}
|
||||
|
||||
// If the root folder changed, run the library task so the user can see it
|
||||
if (itemsToRefresh.Any(i => i is AggregateFolder))
|
||||
{
|
||||
TaskManager.CancelIfRunningAndQueue<RefreshMediaLibraryTask>();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var item in itemsToRefresh)
|
||||
{
|
||||
Logger.Info(item.Name + " (" + item.Path + ") will be refreshed.");
|
||||
|
||||
try
|
||||
{
|
||||
await item.ChangedExternally().ConfigureAwait(false);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// For now swallow and log.
|
||||
// Research item: If an IOException occurs, the item may be in a disconnected state (media unavailable)
|
||||
// Should we remove it from it's parent?
|
||||
Logger.ErrorException("Error refreshing {0}", ex, item.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error refreshing {0}", ex, item.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the affected base item.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>BaseItem.</returns>
|
||||
private BaseItem GetAffectedBaseItem(string path)
|
||||
{
|
||||
BaseItem item = null;
|
||||
|
||||
while (item == null && !string.IsNullOrEmpty(path))
|
||||
{
|
||||
item = LibraryManager.FindByPath(path, null);
|
||||
|
||||
path = Path.GetDirectoryName(path);
|
||||
}
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
// If the item has been deleted find the first valid parent that still exists
|
||||
while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path))
|
||||
{
|
||||
item = item.GetParent();
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
private bool IsFileLocked(string path)
|
||||
{
|
||||
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
|
||||
{
|
||||
// Causing lockups on linux
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var data = _fileSystem.GetFileSystemInfo(path);
|
||||
|
||||
if (!data.Exists
|
||||
|| data.IsDirectory
|
||||
|
||||
// Opening a writable stream will fail with readonly files
|
||||
|| data.Attributes.HasFlag(FileAttributes.ReadOnly))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error getting file system info for: {0}", ex, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
// In order to determine if the file is being written to, we have to request write access
|
||||
// But if the server only has readonly access, this is going to cause this entire algorithm to fail
|
||||
// So we'll take a best guess about our access level
|
||||
var requestedFileAccess = ConfigurationManager.Configuration.SaveLocalMeta
|
||||
? FileAccess.ReadWrite
|
||||
: FileAccess.Read;
|
||||
|
||||
try
|
||||
{
|
||||
using (_fileSystem.GetFileStream(path, FileMode.Open, requestedFileAccess, FileShare.ReadWrite))
|
||||
{
|
||||
//file is not locked
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
// File may have been deleted
|
||||
return false;
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
// File may have been deleted
|
||||
return false;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
//the file is unavailable because it is:
|
||||
//still being written to
|
||||
//or being processed by another thread
|
||||
//or does not exist (has already been processed)
|
||||
Logger.Debug("{0} is locked.", path);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error determining if file is locked: {0}", ex, path);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void DisposeTimer()
|
||||
{
|
||||
lock (_timerLock)
|
||||
{
|
||||
if (_timer != null)
|
||||
{
|
||||
_timer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeTimer();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -929,10 +929,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
|
||||
recordPath = recorder.GetOutputPath(mediaStreamInfo, recordPath);
|
||||
recordPath = EnsureFileUnique(recordPath, timer.Id);
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(recordPath));
|
||||
activeRecordingInfo.Path = recordPath;
|
||||
|
||||
_libraryMonitor.ReportFileSystemChangeBeginning(recordPath);
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(recordPath));
|
||||
activeRecordingInfo.Path = recordPath;
|
||||
|
||||
var duration = recordingEndDate - DateTime.UtcNow;
|
||||
|
||||
|
|
|
@ -180,6 +180,7 @@
|
|||
<Compile Include="HttpServer\SocketSharp\WebSocketSharpRequest.cs" />
|
||||
<Compile Include="HttpServer\SocketSharp\WebSocketSharpResponse.cs" />
|
||||
<Compile Include="Intros\DefaultIntroProvider.cs" />
|
||||
<Compile Include="IO\FileRefresher.cs" />
|
||||
<Compile Include="IO\LibraryMonitor.cs" />
|
||||
<Compile Include="Library\CoreResolutionIgnoreRule.cs" />
|
||||
<Compile Include="Library\LibraryManager.cs" />
|
||||
|
|
|
@ -247,7 +247,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
{
|
||||
"create index if not exists idx_PresentationUniqueKey on TypedBaseItems(PresentationUniqueKey)",
|
||||
"create index if not exists idx_Type on TypedBaseItems(Type)",
|
||||
"create index if not exists idx_TopParentId on TypedBaseItems(TopParentId)"
|
||||
"create index if not exists idx_TopParentId on TypedBaseItems(TopParentId)",
|
||||
//"create index if not exists idx_TypeTopParentId on TypedBaseItems(Type,TopParentId)"
|
||||
};
|
||||
|
||||
_connection.RunQueries(postQueries, Logger);
|
||||
|
@ -1673,7 +1674,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
var slowThreshold = 1000;
|
||||
|
||||
#if DEBUG
|
||||
slowThreshold = 200;
|
||||
slowThreshold = 100;
|
||||
#endif
|
||||
|
||||
if (elapsed >= slowThreshold)
|
||||
|
|
|
@ -804,8 +804,6 @@ namespace MediaBrowser.Server.Startup.Common
|
|||
|
||||
ProviderManager.AddParts(GetExports<IImageProvider>(),
|
||||
GetExports<IMetadataService>(),
|
||||
GetExports<IItemIdentityProvider>(),
|
||||
GetExports<IItemIdentityConverter>(),
|
||||
GetExports<IMetadataProvider>(),
|
||||
GetExports<IMetadataSaver>(),
|
||||
GetExports<IImageSaver>(),
|
||||
|
|
Loading…
Reference in New Issue
Block a user