aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2016-06-03 20:15:14 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2016-06-03 20:15:14 -0400
commitddb6ea6f0576a6ba9c6050cc0799ac6b0e3c2fa8 (patch)
tree3a89421939b5c69ebe122396f4f2af92da49c893 /MediaBrowser.Server.Implementations
parent7cf424303b95d589a7ad318767139106db5f5363 (diff)
rework user data
Diffstat (limited to 'MediaBrowser.Server.Implementations')
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserDataManager.cs98
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs48
-rw-r--r--MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs40
3 files changed, 90 insertions, 96 deletions
diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
index afbce87a9..c2606dc4b 100644
--- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
@@ -23,7 +23,8 @@ namespace MediaBrowser.Server.Implementations.Library
{
public event EventHandler<UserDataSaveEventArgs> UserDataSaved;
- private readonly Dictionary<string, UserItemData> _userData = new Dictionary<string, UserItemData>(StringComparer.OrdinalIgnoreCase);
+ private readonly ConcurrentDictionary<string, UserItemData> _userData =
+ new ConcurrentDictionary<string, UserItemData>(StringComparer.OrdinalIgnoreCase);
private readonly ILogger _logger;
private readonly IServerConfigurationManager _config;
@@ -64,13 +65,6 @@ namespace MediaBrowser.Server.Implementations.Library
try
{
await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false);
-
- var newValue = userData;
-
- lock (_userData)
- {
- _userData[GetCacheKey(userId, key)] = newValue;
- }
}
catch (Exception ex)
{
@@ -80,6 +74,9 @@ namespace MediaBrowser.Server.Implementations.Library
}
}
+ var cacheKey = GetCacheKey(userId, item.Id);
+ _userData.AddOrUpdate(cacheKey, userData, (k, v) => userData);
+
EventHelper.FireEventIfNotNull(UserDataSaved, this, new UserDataSaveEventArgs
{
Keys = keys,
@@ -122,7 +119,7 @@ namespace MediaBrowser.Server.Implementations.Library
throw;
}
-
+
}
/// <summary>
@@ -140,7 +137,7 @@ namespace MediaBrowser.Server.Implementations.Library
return Repository.GetAllUserData(userId);
}
- public UserItemData GetUserData(Guid userId, List<string> keys)
+ public UserItemData GetUserData(Guid userId, Guid itemId, List<string> keys)
{
if (userId == Guid.Empty)
{
@@ -150,26 +147,23 @@ namespace MediaBrowser.Server.Implementations.Library
{
throw new ArgumentNullException("keys");
}
-
- lock (_userData)
+ if (keys.Count == 0)
{
- foreach (var key in keys)
- {
- var cacheKey = GetCacheKey(userId, key);
- UserItemData value;
- if (_userData.TryGetValue(cacheKey, out value))
- {
- return value;
- }
+ throw new ArgumentException("UserData keys cannot be empty.");
+ }
- value = Repository.GetUserData(userId, key);
+ var cacheKey = GetCacheKey(userId, itemId);
- if (value != null)
- {
- _userData[cacheKey] = value;
- return value;
- }
- }
+ return _userData.GetOrAdd(cacheKey, k => GetUserDataInternal(userId, keys));
+ }
+
+ private UserItemData GetUserDataInternal(Guid userId, List<string> keys)
+ {
+ var userData = Repository.GetUserData(userId, keys);
+
+ if (userData != null)
+ {
+ return userData;
}
if (keys.Count > 0)
@@ -185,56 +179,12 @@ namespace MediaBrowser.Server.Implementations.Library
}
/// <summary>
- /// Gets the user data.
- /// </summary>
- /// <param name="userId">The user id.</param>
- /// <param name="key">The key.</param>
- /// <returns>Task{UserItemData}.</returns>
- public UserItemData GetUserData(Guid userId, string key)
- {
- if (userId == Guid.Empty)
- {
- throw new ArgumentNullException("userId");
- }
- if (string.IsNullOrEmpty(key))
- {
- throw new ArgumentNullException("key");
- }
-
- lock (_userData)
- {
- var cacheKey = GetCacheKey(userId, key);
- UserItemData value;
- if (_userData.TryGetValue(cacheKey, out value))
- {
- return value;
- }
-
- value = Repository.GetUserData(userId, key);
-
- if (value == null)
- {
- value = new UserItemData
- {
- UserId = userId,
- Key = key
- };
- }
-
- _userData[cacheKey] = value;
- return value;
- }
- }
-
- /// <summary>
/// Gets the internal key.
/// </summary>
- /// <param name="userId">The user id.</param>
- /// <param name="key">The key.</param>
/// <returns>System.String.</returns>
- private string GetCacheKey(Guid userId, string key)
+ private string GetCacheKey(Guid userId, Guid itemId)
{
- return userId + key;
+ return userId.ToString("N") + itemId.ToString("N");
}
public UserItemData GetUserData(IHasUserData user, IHasUserData item)
@@ -249,7 +199,7 @@ namespace MediaBrowser.Server.Implementations.Library
public UserItemData GetUserData(Guid userId, IHasUserData item)
{
- return GetUserData(userId, item.GetUserDataKeys());
+ return GetUserData(userId, item.Id, item.GetUserDataKeys());
}
public UserItemDataDto GetUserDataDto(IHasUserData item, User user)
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs
index 7f3b32e06..bfdb9e0c7 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs
@@ -5,7 +5,9 @@ using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Data;
+using System.Globalization;
using System.IO;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -300,6 +302,52 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
+ public UserItemData GetUserData(Guid userId, List<string> keys)
+ {
+ if (userId == Guid.Empty)
+ {
+ throw new ArgumentNullException("userId");
+ }
+ if (keys == null)
+ {
+ throw new ArgumentNullException("keys");
+ }
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ var index = 0;
+ var excludeIds = new List<string>();
+ var builder = new StringBuilder();
+ foreach (var key in keys)
+ {
+ var paramName = "@Key" + index;
+ excludeIds.Add("Key =" + paramName);
+ cmd.Parameters.Add(cmd, paramName, DbType.String).Value = key;
+ builder.Append(" WHEN Key=" + paramName + " THEN " + index);
+ index++;
+ }
+
+ var keyText = string.Join(" OR ", excludeIds.ToArray());
+
+ cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId AND (" + keyText + ") ";
+
+ cmd.CommandText += " ORDER BY (Case " + builder + " Else " + keys.Count.ToString(CultureInfo.InvariantCulture) + " End )";
+ cmd.CommandText += " LIMIT 1";
+
+ cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
+ {
+ if (reader.Read())
+ {
+ return ReadRow(reader);
+ }
+ }
+
+ return null;
+ }
+ }
+
/// <summary>
/// Return all user-data associated with the given user
/// </summary>
diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
index ec91dc1b7..6019d64b4 100644
--- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
+++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
@@ -111,24 +111,6 @@ namespace MediaBrowser.Server.Implementations.TV
.Select(i => GetNextUp(i, currentUser))
// Include if an episode was found, and either the series is not unwatched or the specific series was requested
.Where(i => i.Item1 != null && (!i.Item3 || !string.IsNullOrWhiteSpace(request.SeriesId)))
- //.OrderByDescending(i =>
- //{
- // var episode = i.Item1;
-
- // var seriesUserData = _userDataManager.GetUserData(user, episode.Series);
-
- // if (seriesUserData.IsFavorite)
- // {
- // return 2;
- // }
-
- // if (seriesUserData.Likes.HasValue)
- // {
- // return seriesUserData.Likes.Value ? 1 : -1;
- // }
-
- // return 0;
- //})
.OrderByDescending(i => i.Item2)
.ThenByDescending(i => i.Item1.PremiereDate ?? DateTime.MinValue)
.Select(i => i.Item1);
@@ -143,9 +125,8 @@ namespace MediaBrowser.Server.Implementations.TV
private Tuple<Episode, DateTime, bool> GetNextUp(Series series, User user)
{
// Get them in display order, then reverse
- var allEpisodes = series.GetSeasons(user, true, true)
- .Where(i => !i.IndexNumber.HasValue || i.IndexNumber.Value != 0)
- .SelectMany(i => i.GetEpisodes(user))
+ var allEpisodes = series.GetEpisodes(user, true, true)
+ .Where(i => !i.ParentIndexNumber.HasValue || i.ParentIndexNumber.Value != 0)
.Reverse()
.ToList();
@@ -155,6 +136,8 @@ namespace MediaBrowser.Server.Implementations.TV
var includeMissing = user.Configuration.DisplayMissingEpisodes;
+ var unplayedEpisodes = new List<Episode>();
+
// Go back starting with the most recent episodes
foreach (var episode in allEpisodes)
{
@@ -172,6 +155,8 @@ namespace MediaBrowser.Server.Implementations.TV
}
else
{
+ unplayedEpisodes.Add(episode);
+
if (!episode.IsVirtualUnaired && (includeMissing || !episode.IsMissingEpisode))
{
nextUp = episode;
@@ -184,7 +169,18 @@ namespace MediaBrowser.Server.Implementations.TV
return new Tuple<Episode, DateTime, bool>(nextUp, lastWatchedDate, false);
}
- var firstEpisode = allEpisodes.LastOrDefault(i => !i.IsVirtualUnaired && (includeMissing || !i.IsMissingEpisode) && !i.IsPlayed(user));
+ Episode firstEpisode = null;
+ // Find the first unplayed episode. Start from the back of the list since they're in reverse order
+ for (var i = unplayedEpisodes.Count - 1; i >= 0; i--)
+ {
+ var unplayedEpisode = unplayedEpisodes[i];
+
+ if (!unplayedEpisode.IsVirtualUnaired && (includeMissing || !unplayedEpisode.IsMissingEpisode))
+ {
+ firstEpisode = unplayedEpisode;
+ break;
+ }
+ }
// Return the first episode
return new Tuple<Episode, DateTime, bool>(firstEpisode, DateTime.MinValue, true);