update tuner pooling

This commit is contained in:
Luke Pulverenti
2015-10-30 12:40:12 -04:00
parent a050f20ac5
commit 9bfb2f0813
3 changed files with 81 additions and 27 deletions

View File

@@ -117,8 +117,23 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
foreach (var host in hostsWithChannel)
{
var resourcePool = GetLock(host.Url);
Logger.Debug("GetChannelStreamMediaSources - Waiting on tuner resource pool");
await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
Logger.Debug("GetChannelStreamMediaSources - Unlocked resource pool");
try
{
// Check to make sure the tuner is available
// If there's only one tuner, don't bother with the check and just let the tuner be the one to throw an error
if (hostsWithChannel.Count > 1 &&
!await IsAvailable(host, channelId, cancellationToken).ConfigureAwait(false))
{
Logger.Error("Tuner is not currently available");
continue;
}
var mediaSources = await GetChannelStreamMediaSources(host, channelId, cancellationToken).ConfigureAwait(false);
// Prefix the id with the host Id so that we can easily find it
@@ -133,6 +148,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
{
Logger.Error("Error opening tuner", ex);
}
finally
{
resourcePool.Release();
}
}
}
@@ -170,17 +189,35 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
foreach (var host in hostsWithChannel)
{
var resourcePool = GetLock(host.Url);
Logger.Debug("GetChannelStream - Waiting on tuner resource pool");
await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
Logger.Debug("GetChannelStream - Unlocked resource pool");
try
{
var stream = await GetChannelStream(host, channelId, streamId, cancellationToken).ConfigureAwait(false);
var resourcePool = GetLock(host.Url);
// Check to make sure the tuner is available
// If there's only one tuner, don't bother with the check and just let the tuner be the one to throw an error
// If a streamId is specified then availibility has already been checked in GetChannelStreamMediaSources
if (string.IsNullOrWhiteSpace(streamId) && hostsWithChannel.Count > 1)
{
if (!await IsAvailable(host, channelId, cancellationToken).ConfigureAwait(false))
{
Logger.Error("Tuner is not currently available");
resourcePool.Release();
continue;
}
}
await AddMediaInfo(stream, false, resourcePool, cancellationToken).ConfigureAwait(false);
var stream = await GetChannelStream(host, channelId, streamId, cancellationToken).ConfigureAwait(false);
//await AddMediaInfo(stream, false, resourcePool, cancellationToken).ConfigureAwait(false);
return new Tuple<MediaSourceInfo, SemaphoreSlim>(stream, resourcePool);
}
catch (Exception ex)
{
Logger.Error("Error opening tuner", ex);
resourcePool.Release();
}
}
}
@@ -188,6 +225,21 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
throw new LiveTvConflictException();
}
protected async Task<bool> IsAvailable(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
{
try
{
return await IsAvailableInternal(tuner, channelId, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
Logger.ErrorException("Error checking tuner availability", ex);
return false;
}
}
protected abstract Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken);
/// <summary>
/// The _semaphoreLocks
/// </summary>
@@ -202,25 +254,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
return _semaphoreLocks.GetOrAdd(url, key => new SemaphoreSlim(1, 1));
}
private async Task AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
{
await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
await AddMediaInfoInternal(mediaSource, isAudio, cancellationToken).ConfigureAwait(false);
// Leave the resource locked. it will be released upstream
}
catch (Exception)
{
// Release the resource if there's some kind of failure.
resourcePool.Release();
throw;
}
}
private async Task AddMediaInfoInternal(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
{
var originalRuntime = mediaSource.RunTimeTicks;