Merge pull request #5938 from cvium/allocationz

This commit is contained in:
Bond-009
2021-05-05 09:35:30 +02:00
committed by GitHub
12 changed files with 253 additions and 100 deletions

View File

@@ -1002,15 +1002,12 @@ namespace Emby.Server.Implementations.Data
return;
}
var parts = value.Split('|', StringSplitOptions.RemoveEmptyEntries);
foreach (var part in parts)
foreach (var part in value.SpanSplit('|'))
{
var idParts = part.Split('=');
if (idParts.Length == 2)
var providerDelimiterIndex = part.IndexOf('=');
if (providerDelimiterIndex != -1 && providerDelimiterIndex == part.LastIndexOf('='))
{
item.SetProviderId(idParts[0], idParts[1]);
item.SetProviderId(part.Slice(0, providerDelimiterIndex).ToString(), part.Slice(providerDelimiterIndex + 1).ToString());
}
}
}
@@ -1045,9 +1042,8 @@ namespace Emby.Server.Implementations.Data
return Array.Empty<ItemImageInfo>();
}
var parts = value.Split('|' , StringSplitOptions.RemoveEmptyEntries);
var list = new List<ItemImageInfo>();
foreach (var part in parts)
foreach (var part in value.SpanSplit('|'))
{
var image = ItemImageInfoFromValueString(part);
@@ -1086,41 +1082,93 @@ namespace Emby.Server.Implementations.Data
}
}
public ItemImageInfo ItemImageInfoFromValueString(string value)
internal ItemImageInfo ItemImageInfoFromValueString(ReadOnlySpan<char> value)
{
var parts = value.Split('*', StringSplitOptions.None);
if (parts.Length < 3)
var nextSegment = value.IndexOf('*');
if (nextSegment == -1)
{
return null;
}
var image = new ItemImageInfo();
ReadOnlySpan<char> path = value[..nextSegment];
value = value[(nextSegment + 1)..];
nextSegment = value.IndexOf('*');
if (nextSegment == -1)
{
return null;
}
image.Path = RestorePath(parts[0]);
ReadOnlySpan<char> dateModified = value[..nextSegment];
value = value[(nextSegment + 1)..];
nextSegment = value.IndexOf('*');
if (nextSegment == -1)
{
nextSegment = value.Length;
}
if (long.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var ticks))
ReadOnlySpan<char> imageType = value[..nextSegment];
var image = new ItemImageInfo
{
Path = RestorePath(path.ToString())
};
if (long.TryParse(dateModified, NumberStyles.Any, CultureInfo.InvariantCulture, out var ticks))
{
image.DateModified = new DateTime(ticks, DateTimeKind.Utc);
}
if (Enum.TryParse(parts[2], true, out ImageType type))
if (Enum.TryParse(imageType.ToString(), true, out ImageType type))
{
image.Type = type;
}
if (parts.Length >= 5)
// Optional parameters: width*height*blurhash
if (nextSegment + 1 < value.Length - 1)
{
if (int.TryParse(parts[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out var width)
&& int.TryParse(parts[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out var height))
value = value[(nextSegment + 1)..];
nextSegment = value.IndexOf('*');
if (nextSegment == -1 || nextSegment == value.Length)
{
return image;
}
ReadOnlySpan<char> widthSpan = value[..nextSegment];
value = value[(nextSegment + 1)..];
nextSegment = value.IndexOf('*');
if (nextSegment == -1)
{
nextSegment = value.Length;
}
ReadOnlySpan<char> heightSpan = value[..nextSegment];
if (int.TryParse(widthSpan, NumberStyles.Integer, CultureInfo.InvariantCulture, out var width)
&& int.TryParse(heightSpan, NumberStyles.Integer, CultureInfo.InvariantCulture, out var height))
{
image.Width = width;
image.Height = height;
}
if (parts.Length >= 6)
if (nextSegment < value.Length - 1)
{
image.BlurHash = parts[5].Replace('/', '*').Replace('\\', '|');
value = value[(nextSegment + 1)..];
var length = value.Length;
Span<char> blurHashSpan = stackalloc char[length];
for (int i = 0; i < length; i++)
{
var c = value[i];
blurHashSpan[i] = c switch
{
'/' => '*',
'\\' => '|',
_ => c
};
}
image.BlurHash = new string(blurHashSpan);
}
}
@@ -2110,27 +2158,6 @@ namespace Emby.Server.Implementations.Data
private readonly ItemFields[] _allFields = Enum.GetValues<ItemFields>();
private string[] GetColumnNamesFromField(ItemFields field)
{
switch (field)
{
case ItemFields.Settings:
return new[] { "IsLocked", "PreferredMetadataCountryCode", "PreferredMetadataLanguage", "LockedFields" };
case ItemFields.ServiceName:
return new[] { "ExternalServiceId" };
case ItemFields.SortName:
return new[] { "ForcedSortName" };
case ItemFields.Taglines:
return new[] { "Tagline" };
case ItemFields.Tags:
return new[] { "Tags" };
case ItemFields.IsHD:
return Array.Empty<string>();
default:
return new[] { field.ToString() };
}
}
private bool HasField(InternalItemsQuery query, ItemFields name)
{
switch (name)
@@ -2319,9 +2346,32 @@ namespace Emby.Server.Implementations.Data
{
if (!HasField(query, field))
{
foreach (var fieldToRemove in GetColumnNamesFromField(field))
switch (field)
{
list.Remove(fieldToRemove);
case ItemFields.Settings:
list.Remove("IsLocked");
list.Remove("PreferredMetadataCountryCode");
list.Remove("PreferredMetadataLanguage");
list.Remove("LockedFields");
break;
case ItemFields.ServiceName:
list.Remove("ExternalServiceId");
break;
case ItemFields.SortName:
list.Remove("ForcedSortName");
break;
case ItemFields.Taglines:
list.Remove("Tagline");
break;
case ItemFields.Tags:
list.Remove("Tags");
break;
case ItemFields.IsHD:
// do nothing
break;
default:
list.Remove(field.ToString());
break;
}
}
}
@@ -2568,9 +2618,9 @@ namespace Emby.Server.Implementations.Data
}
var commandText = "select "
+ string.Join(',', GetFinalColumnsToSelect(query, new[] { "count(distinct PresentationUniqueKey)" }))
+ GetFromText()
+ GetJoinUserDataText(query);
+ string.Join(',', GetFinalColumnsToSelect(query, new[] { "count(distinct PresentationUniqueKey)" }))
+ GetFromText()
+ GetJoinUserDataText(query);
var whereClauses = GetWhereClauses(query, null);
if (whereClauses.Count != 0)

View File

@@ -590,18 +590,9 @@ namespace Emby.Server.Implementations.Library
public Task<IDirectStreamProvider> GetDirectStreamProviderByUniqueId(string uniqueId, CancellationToken cancellationToken)
{
var info = _openStreams.Values.FirstOrDefault(i =>
{
var liveStream = i as ILiveStream;
if (liveStream != null)
{
return string.Equals(liveStream.UniqueId, uniqueId, StringComparison.OrdinalIgnoreCase);
}
var info = _openStreams.FirstOrDefault(i => i.Value != null && string.Equals(i.Value.UniqueId, uniqueId, StringComparison.OrdinalIgnoreCase));
return false;
});
return Task.FromResult(info as IDirectStreamProvider);
return Task.FromResult(info.Value as IDirectStreamProvider);
}
public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken)

View File

@@ -801,22 +801,22 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
public ActiveRecordingInfo GetActiveRecordingInfo(string path)
{
if (string.IsNullOrWhiteSpace(path))
if (string.IsNullOrWhiteSpace(path) || _activeRecordings.IsEmpty)
{
return null;
}
foreach (var recording in _activeRecordings.Values)
foreach (var (_, recordingInfo) in _activeRecordings)
{
if (string.Equals(recording.Path, path, StringComparison.Ordinal) && !recording.CancellationTokenSource.IsCancellationRequested)
if (string.Equals(recordingInfo.Path, path, StringComparison.Ordinal) && !recordingInfo.CancellationTokenSource.IsCancellationRequested)
{
var timer = recording.Timer;
var timer = recordingInfo.Timer;
if (timer.Status != RecordingStatus.InProgress)
{
return null;
}
return recording;
return recordingInfo;
}
}
@@ -1621,9 +1621,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
return _activeRecordings
.Values
.ToList()
.Any(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Timer.Id, timerId, StringComparison.OrdinalIgnoreCase));
.Any(i => string.Equals(i.Value.Path, path, StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Value.Timer.Id, timerId, StringComparison.OrdinalIgnoreCase));
}
private IRecorder GetRecorder(MediaSourceInfo mediaSource)

View File

@@ -661,7 +661,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
_modelCache.Clear();
}
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(new CancellationTokenSource(discoveryDurationMs).Token, cancellationToken).Token;
using var timedCancellationToken = new CancellationTokenSource(discoveryDurationMs);
using var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(timedCancellationToken.Token, cancellationToken);
cancellationToken = linkedCancellationTokenSource.Token;
var list = new List<TunerHostInfo>();
// Create udp broadcast discovery message

View File

@@ -150,7 +150,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
public async Task CopyToAsync(Stream stream, CancellationToken cancellationToken)
{
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, LiveStreamCancellationTokenSource.Token).Token;
using var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, LiveStreamCancellationTokenSource.Token);
cancellationToken = linkedCancellationTokenSource.Token;
// use non-async filestream on windows along with read due to https://github.com/dotnet/corefx/issues/6039
var allowAsync = Environment.OSVersion.Platform != PlatformID.Win32NT;

View File

@@ -315,10 +315,9 @@ namespace Emby.Server.Implementations.Localization
}
const string Prefix = "Core";
var key = Prefix + culture;
return _dictionaries.GetOrAdd(
key,
culture,
f => GetDictionary(Prefix, culture, DefaultCulture + ".json").GetAwaiter().GetResult());
}

View File

@@ -257,20 +257,17 @@ namespace Emby.Server.Implementations.QuickConnect
}
// Expire stale connection requests
var code = string.Empty;
var values = _currentRequests.Values.ToList();
for (int i = 0; i < values.Count; i++)
foreach (var (_, currentRequest) in _currentRequests)
{
var added = values[i].DateAdded ?? DateTime.UnixEpoch;
if (DateTime.UtcNow > added.AddMinutes(Timeout) || expireAll)
var added = currentRequest.DateAdded ?? DateTime.UnixEpoch;
if (expireAll || DateTime.UtcNow > added.AddMinutes(Timeout))
{
code = values[i].Code;
_logger.LogDebug("Removing expired request {code}", code);
var code = currentRequest.Code;
_logger.LogDebug("Removing expired request {Code}", code);
if (!_currentRequests.TryRemove(code, out _))
{
_logger.LogWarning("Request {code} already expired", code);
_logger.LogWarning("Request {Code} already expired", code);
}
}
}

View File

@@ -269,14 +269,17 @@ namespace Emby.Server.Implementations.SyncPlay
var user = _userManager.GetUserById(session.UserId);
List<GroupInfoDto> list = new List<GroupInfoDto>();
foreach (var group in _groups.Values)
lock (_groupsLock)
{
// Locking required as group is not thread-safe.
lock (group)
foreach (var (_, group) in _groups)
{
if (group.HasAccessToPlayQueue(user))
// Locking required as group is not thread-safe.
lock (group)
{
list.Add(group.GetInfo());
if (group.HasAccessToPlayQueue(user))
{
list.Add(group.GetInfo());
}
}
}
}