|
@@ -54,11 +54,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
new ConcurrentDictionary<string, LiveStreamData>();
|
|
|
|
|
|
private List<Guid> _channelIdList = new List<Guid>();
|
|
|
- private Dictionary<Guid, LiveTvProgram> _programs = new Dictionary<Guid, LiveTvProgram>();
|
|
|
+ private Dictionary<Guid, LiveTvProgram> _programs;
|
|
|
private readonly ConcurrentDictionary<Guid, bool> _refreshedPrograms = new ConcurrentDictionary<Guid, bool>();
|
|
|
|
|
|
- private readonly SemaphoreSlim _refreshSemaphore = new SemaphoreSlim(1, 1);
|
|
|
-
|
|
|
public LiveTvManager(IApplicationHost appHost, IServerConfigurationManager config, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, IProviderManager providerManager)
|
|
|
{
|
|
|
_config = config;
|
|
@@ -109,6 +107,37 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
_taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>();
|
|
|
}
|
|
|
|
|
|
+ private readonly object _programsDataLock = new object();
|
|
|
+ private Dictionary<Guid, LiveTvProgram> GetProgramsDictionary()
|
|
|
+ {
|
|
|
+ if (_programs == null)
|
|
|
+ {
|
|
|
+ lock (_programsDataLock)
|
|
|
+ {
|
|
|
+ if (_programs == null)
|
|
|
+ {
|
|
|
+ var dict = new Dictionary<Guid, LiveTvProgram>();
|
|
|
+
|
|
|
+ foreach (var item in _itemRepo.GetItemsOfType(typeof (LiveTvProgram))
|
|
|
+ .Cast<LiveTvProgram>()
|
|
|
+ .ToList())
|
|
|
+ {
|
|
|
+ dict[item.Id] = item;
|
|
|
+ }
|
|
|
+
|
|
|
+ _programs = dict;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return _programs;
|
|
|
+ }
|
|
|
+
|
|
|
+ private IEnumerable<LiveTvProgram> GetPrograms()
|
|
|
+ {
|
|
|
+ return GetProgramsDictionary().Values;
|
|
|
+ }
|
|
|
+
|
|
|
public async Task<QueryResult<LiveTvChannel>> GetInternalChannels(LiveTvChannelQuery query, CancellationToken cancellationToken)
|
|
|
{
|
|
|
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
|
|
@@ -260,7 +289,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
|
|
LiveTvProgram obj = null;
|
|
|
|
|
|
- _programs.TryGetValue(guid, out obj);
|
|
|
+ GetProgramsDictionary().TryGetValue(guid, out obj);
|
|
|
|
|
|
if (obj != null)
|
|
|
{
|
|
@@ -597,7 +626,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
|
|
item.ProductionYear = info.ProductionYear;
|
|
|
item.PremiereDate = item.PremiereDate ?? info.OriginalAirDate;
|
|
|
-
|
|
|
+
|
|
|
await item.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
return item;
|
|
@@ -691,7 +720,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
|
|
public async Task<QueryResult<ProgramInfoDto>> GetPrograms(ProgramQuery query, CancellationToken cancellationToken)
|
|
|
{
|
|
|
- IEnumerable<LiveTvProgram> programs = _programs.Values;
|
|
|
+ IEnumerable<LiveTvProgram> programs = GetPrograms();
|
|
|
|
|
|
if (query.MinEndDate.HasValue)
|
|
|
{
|
|
@@ -806,7 +835,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
|
|
public async Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, CancellationToken cancellationToken)
|
|
|
{
|
|
|
- IEnumerable<LiveTvProgram> programs = _programs.Values;
|
|
|
+ IEnumerable<LiveTvProgram> programs = GetPrograms();
|
|
|
|
|
|
var user = _userManager.GetUserById(query.UserId);
|
|
|
|
|
@@ -995,24 +1024,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
|
|
internal async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
|
|
|
{
|
|
|
- await _refreshSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
|
-
|
|
|
- try
|
|
|
- {
|
|
|
- var innerProgress = new ActionableProgress<double>();
|
|
|
- innerProgress.RegisterAction(p => progress.Report(p * .9));
|
|
|
- await RefreshChannelsInternal(innerProgress, cancellationToken).ConfigureAwait(false);
|
|
|
+ var innerProgress = new ActionableProgress<double>();
|
|
|
+ innerProgress.RegisterAction(p => progress.Report(p * .9));
|
|
|
+ await RefreshChannelsInternal(innerProgress, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
- innerProgress = new ActionableProgress<double>();
|
|
|
- innerProgress.RegisterAction(p => progress.Report(90 + (p * .1)));
|
|
|
- await CleanDatabaseInternal(progress, cancellationToken).ConfigureAwait(false);
|
|
|
+ innerProgress = new ActionableProgress<double>();
|
|
|
+ innerProgress.RegisterAction(p => progress.Report(90 + (p * .1)));
|
|
|
+ await CleanDatabaseInternal(progress, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
- RefreshIfNeeded(_programs.Values.Where(i => (i.StartDate - DateTime.UtcNow).TotalDays <= 1).ToList());
|
|
|
- }
|
|
|
- finally
|
|
|
- {
|
|
|
- _refreshSemaphore.Release();
|
|
|
- }
|
|
|
+ RefreshIfNeeded(GetPrograms().Where(i => (i.StartDate - DateTime.UtcNow).TotalDays <= 1).ToList());
|
|
|
}
|
|
|
|
|
|
private async Task RefreshChannelsInternal(IProgress<double> progress, CancellationToken cancellationToken)
|
|
@@ -1136,7 +1156,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
progress.Report(80 * percent + 10);
|
|
|
}
|
|
|
|
|
|
- _programs = programs.ToDictionary(i => i.Id);
|
|
|
+ lock (_programsDataLock)
|
|
|
+ {
|
|
|
+ _programs = programs.ToDictionary(i => i.Id);
|
|
|
+ }
|
|
|
+
|
|
|
_refreshedPrograms.Clear();
|
|
|
progress.Report(90);
|
|
|
|
|
@@ -1147,28 +1171,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
progress.Report(100);
|
|
|
}
|
|
|
|
|
|
- public async Task CleanDatabase(IProgress<double> progress, CancellationToken cancellationToken)
|
|
|
- {
|
|
|
- await _refreshSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
|
-
|
|
|
- try
|
|
|
- {
|
|
|
- await DeleteOldPrograms(_programs.Keys.ToList(), progress, cancellationToken).ConfigureAwait(false);
|
|
|
- }
|
|
|
- finally
|
|
|
- {
|
|
|
- _refreshSemaphore.Release();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
private Task CleanDatabaseInternal(IProgress<double> progress, CancellationToken cancellationToken)
|
|
|
{
|
|
|
- return DeleteOldPrograms(_programs.Keys.ToList(), progress, cancellationToken);
|
|
|
+ return DeleteOldPrograms(GetProgramsDictionary().Keys.ToList(), progress, cancellationToken);
|
|
|
}
|
|
|
|
|
|
private async Task DeleteOldPrograms(List<Guid> currentIdList, IProgress<double> progress, CancellationToken cancellationToken)
|
|
|
{
|
|
|
- var list = _itemRepo.GetItemsOfType(typeof(LiveTvProgram)).ToList();
|
|
|
+ var list = _itemRepo.GetItemIdsOfType(typeof(LiveTvProgram)).ToList();
|
|
|
|
|
|
var numComplete = 0;
|
|
|
|
|
@@ -1549,7 +1559,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
{
|
|
|
var now = DateTime.UtcNow;
|
|
|
|
|
|
- var program = _programs.Values
|
|
|
+ var program = GetPrograms()
|
|
|
.Where(i => string.Equals(externalChannelId, i.ExternalChannelId, StringComparison.OrdinalIgnoreCase))
|
|
|
.OrderBy(i => i.StartDate)
|
|
|
.SkipWhile(i => now >= (i.EndDate ?? DateTime.MinValue))
|
|
@@ -1742,7 +1752,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
{
|
|
|
var dtoOptions = new DtoOptions();
|
|
|
dtoOptions.Fields.Remove(ItemFields.SyncInfo);
|
|
|
-
|
|
|
+
|
|
|
var recordingResult = await GetRecordings(new RecordingQuery
|
|
|
{
|
|
|
UserId = query.UserId
|
|
@@ -1855,13 +1865,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
|
|
public GuideInfo GetGuideInfo()
|
|
|
{
|
|
|
- var programs = _programs.ToList();
|
|
|
+ var programs = GetPrograms().OrderBy(i => i.StartDate).ToList();
|
|
|
|
|
|
- var startDate = _programs.Count == 0 ? DateTime.MinValue :
|
|
|
- programs.Select(i => i.Value.StartDate).Min();
|
|
|
+ var startDate = programs.Count == 0 ?
|
|
|
+ DateTime.MinValue :
|
|
|
+ programs[0].StartDate;
|
|
|
|
|
|
- var endDate = programs.Count == 0 ? DateTime.MinValue :
|
|
|
- programs.Select(i => i.Value.StartDate).Max();
|
|
|
+ var endDate = programs.Count == 0 ?
|
|
|
+ DateTime.MinValue :
|
|
|
+ programs[programs.Count - 1].StartDate;
|
|
|
|
|
|
return new GuideInfo
|
|
|
{
|