diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index f2867b595..9c68df771 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -104,13 +104,16 @@ namespace MediaBrowser.Api.Library
///
private readonly IApplicationHost _appHost;
private readonly ILibraryManager _libraryManager;
+ private readonly IUserManager _userManager;
///
/// Initializes a new instance of the class.
///
/// The app host.
+ /// The library manager.
+ /// The user manager.
/// appHost
- public LibraryService(IApplicationHost appHost, ILibraryManager libraryManager)
+ public LibraryService(IApplicationHost appHost, ILibraryManager libraryManager, IUserManager userManager)
{
if (appHost == null)
{
@@ -119,6 +122,7 @@ namespace MediaBrowser.Api.Library
_appHost = appHost;
_libraryManager = libraryManager;
+ _userManager = userManager;
}
///
@@ -133,7 +137,7 @@ namespace MediaBrowser.Api.Library
// Get everything
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
- var result = new DtoBuilder(Logger, _libraryManager).GetBaseItemDto(item, fields.ToList()).Result;
+ var result = new DtoBuilder(Logger, _libraryManager, _userManager).GetBaseItemDto(item, fields.ToList()).Result;
return ToOptimizedResult(result);
}
@@ -150,7 +154,7 @@ namespace MediaBrowser.Api.Library
// Get everything
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
- var result = new DtoBuilder(Logger, _libraryManager).GetBaseItemDto(item, fields.ToList()).Result;
+ var result = new DtoBuilder(Logger, _libraryManager, _userManager).GetBaseItemDto(item, fields.ToList()).Result;
return ToOptimizedResult(result);
}
@@ -167,7 +171,7 @@ namespace MediaBrowser.Api.Library
// Get everything
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
- var result = new DtoBuilder(Logger, _libraryManager).GetBaseItemDto(item, fields.ToList()).Result;
+ var result = new DtoBuilder(Logger, _libraryManager, _userManager).GetBaseItemDto(item, fields.ToList()).Result;
return ToOptimizedResult(result);
}
@@ -184,7 +188,7 @@ namespace MediaBrowser.Api.Library
// Get everything
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
- var result = new DtoBuilder(Logger, _libraryManager).GetBaseItemDto(item, fields.ToList()).Result;
+ var result = new DtoBuilder(Logger, _libraryManager, _userManager).GetBaseItemDto(item, fields.ToList()).Result;
return ToOptimizedResult(result);
}
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
index 8dc9cfd62..a0ad1fb2a 100644
--- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
+++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
@@ -149,7 +149,7 @@ namespace MediaBrowser.Api.UserLibrary
return null;
}
- var dto = await new DtoBuilder(Logger, LibraryManager).GetBaseItemDto(item, user, fields).ConfigureAwait(false);
+ var dto = await new DtoBuilder(Logger, LibraryManager, UserManager).GetBaseItemDto(item, user, fields).ConfigureAwait(false);
dto.ChildCount = stub.Item2();
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index 77b991a54..a74516fa2 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -179,7 +179,7 @@ namespace MediaBrowser.Api.UserLibrary
var fields = GetItemFields(request).ToList();
- var dtoBuilder = new DtoBuilder(Logger, _libraryManager);
+ var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userManager);
var returnItems = await Task.WhenAll(pagedItems.Select(i => dtoBuilder.GetBaseItemDto(i, user, fields))).ConfigureAwait(false);
@@ -241,12 +241,15 @@ namespace MediaBrowser.Api.UserLibrary
/// IEnumerable{BaseItem}.
private IEnumerable ApplyFilter(IEnumerable items, ItemFilter filter, User user)
{
+ // Avoids implicitly captured closure
+ var currentUser = user;
+
switch (filter)
{
case ItemFilter.Likes:
return items.Where(item =>
{
- var userdata = item.GetUserData(user, false);
+ var userdata = _userManager.GetUserData(user.Id, item.UserDataId).Result;
return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value;
});
@@ -254,7 +257,7 @@ namespace MediaBrowser.Api.UserLibrary
case ItemFilter.Dislikes:
return items.Where(item =>
{
- var userdata = item.GetUserData(user, false);
+ var userdata = _userManager.GetUserData(user.Id, item.UserDataId).Result;
return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value;
});
@@ -262,18 +265,18 @@ namespace MediaBrowser.Api.UserLibrary
case ItemFilter.IsFavorite:
return items.Where(item =>
{
- var userdata = item.GetUserData(user, false);
+ var userdata = _userManager.GetUserData(user.Id, item.UserDataId).Result;
return userdata != null && userdata.IsFavorite;
});
case ItemFilter.IsRecentlyAdded:
- return items.Where(item => item.IsRecentlyAdded(user));
+ return items.Where(item => item.IsRecentlyAdded(currentUser));
case ItemFilter.IsResumable:
return items.Where(item =>
{
- var userdata = item.GetUserData(user, false);
+ var userdata = _userManager.GetUserData(user.Id, item.UserDataId).Result;
return userdata != null && userdata.PlaybackPositionTicks > 0;
});
@@ -281,7 +284,7 @@ namespace MediaBrowser.Api.UserLibrary
case ItemFilter.IsPlayed:
return items.Where(item =>
{
- var userdata = item.GetUserData(user, false);
+ var userdata = _userManager.GetUserData(user.Id, item.UserDataId).Result;
return userdata != null && userdata.PlayCount > 0;
});
@@ -289,7 +292,7 @@ namespace MediaBrowser.Api.UserLibrary
case ItemFilter.IsUnplayed:
return items.Where(item =>
{
- var userdata = item.GetUserData(user, false);
+ var userdata = _userManager.GetUserData(user.Id, item.UserDataId).Result;
return userdata == null || userdata.PlayCount == 0;
});
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
index 5c9c8e1f3..d1f963a9e 100644
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using System.Threading;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Connectivity;
@@ -385,7 +386,7 @@ namespace MediaBrowser.Api.UserLibrary
var movie = (Movie)item;
- var dtoBuilder = new DtoBuilder(Logger, _libraryManager);
+ var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userManager);
var items = movie.SpecialFeatures.Select(i => dtoBuilder.GetBaseItemDto(i, user, fields)).AsParallel().Select(t => t.Result).ToList();
@@ -406,7 +407,7 @@ namespace MediaBrowser.Api.UserLibrary
// Get everything
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
- var dtoBuilder = new DtoBuilder(Logger, _libraryManager);
+ var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userManager);
var items = item.LocalTrailers.Select(i => dtoBuilder.GetBaseItemDto(i, user, fields)).AsParallel().Select(t => t.Result).ToList();
@@ -427,7 +428,7 @@ namespace MediaBrowser.Api.UserLibrary
// Get everything
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
- var dtoBuilder = new DtoBuilder(Logger, _libraryManager);
+ var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userManager);
var result = dtoBuilder.GetBaseItemDto(item, user, fields).Result;
@@ -443,7 +444,7 @@ namespace MediaBrowser.Api.UserLibrary
// Get everything
var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
- var dtoBuilder = new DtoBuilder(Logger, _libraryManager);
+ var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userManager);
var result = dtoBuilder.GetBaseItemDto(item, user, fields).Result;
@@ -486,7 +487,7 @@ namespace MediaBrowser.Api.UserLibrary
// Serialize to json and then back so that the core doesn't see the request dto type
var displayPreferences = _jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(request));
- var task = _libraryManager.SaveDisplayPreferencesForFolder(user, folder, displayPreferences);
+ var task = _userManager.SaveDisplayPreferences(user.Id, folder.DisplayPreferencesId, displayPreferences, CancellationToken.None);
Task.WaitAll(task);
}
@@ -502,12 +503,12 @@ namespace MediaBrowser.Api.UserLibrary
var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
// Get the user data for this item
- var data = item.GetUserData(user, true);
+ var data = _userManager.GetUserData(user.Id, item.UserDataId).Result;
// Set favorite status
data.IsFavorite = true;
- var task = _userManager.SaveUserDataForItem(user, item, data);
+ var task = _userManager.SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None);
Task.WaitAll(task);
}
@@ -523,12 +524,12 @@ namespace MediaBrowser.Api.UserLibrary
var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
// Get the user data for this item
- var data = item.GetUserData(user, true);
+ var data = _userManager.GetUserData(user.Id, item.UserDataId).Result;
// Set favorite status
data.IsFavorite = false;
- var task = _userManager.SaveUserDataForItem(user, item, data);
+ var task = _userManager.SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None);
Task.WaitAll(task);
}
@@ -544,11 +545,11 @@ namespace MediaBrowser.Api.UserLibrary
var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
// Get the user data for this item
- var data = item.GetUserData(user, true);
+ var data = _userManager.GetUserData(user.Id, item.UserDataId).Result;
data.Rating = null;
- var task = _userManager.SaveUserDataForItem(user, item, data);
+ var task = _userManager.SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None);
Task.WaitAll(task);
}
@@ -564,11 +565,11 @@ namespace MediaBrowser.Api.UserLibrary
var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
// Get the user data for this item
- var data = item.GetUserData(user, true);
+ var data = _userManager.GetUserData(user.Id, item.UserDataId).Result;
data.Likes = request.Likes;
- var task = _userManager.SaveUserDataForItem(user, item, data);
+ var task = _userManager.SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None);
Task.WaitAll(task);
}
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
index b495d07f9..f2a9ca24b 100644
--- a/MediaBrowser.Api/UserService.cs
+++ b/MediaBrowser.Api/UserService.cs
@@ -142,6 +142,8 @@ namespace MediaBrowser.Api
/// Initializes a new instance of the class.
///
/// The XML serializer.
+ /// The user manager.
+ /// The library manager.
/// xmlSerializer
public UserService(IXmlSerializer xmlSerializer, IUserManager userManager, ILibraryManager libraryManager)
: base()
@@ -163,7 +165,7 @@ namespace MediaBrowser.Api
/// System.Object.
public object Get(GetUsers request)
{
- var dtoBuilder = new DtoBuilder(Logger, _libraryManager);
+ var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userManager);
var tasks = _userManager.Users.OrderBy(u => u.Name).Select(dtoBuilder.GetUserDto).ToArray();
@@ -186,7 +188,7 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException("User not found");
}
- var result = new DtoBuilder(Logger, _libraryManager).GetUserDto(user).Result;
+ var result = new DtoBuilder(Logger, _libraryManager, _userManager).GetUserDto(user).Result;
return ToOptimizedResult(result);
}
@@ -300,7 +302,7 @@ namespace MediaBrowser.Api
newUser.UpdateConfiguration(dtoUser.Configuration, _xmlSerializer);
- var result = new DtoBuilder(Logger, _libraryManager).GetUserDto(newUser).Result;
+ var result = new DtoBuilder(Logger, _libraryManager, _userManager).GetUserDto(newUser).Result;
return ToOptimizedResult(result);
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index d30f11f7d..411190d77 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -796,109 +796,6 @@ namespace MediaBrowser.Controller.Entities
get { return null; }
}
- ///
- /// The _user data
- ///
- private IEnumerable _userData;
- ///
- /// The _user data initialized
- ///
- private bool _userDataInitialized;
- ///
- /// The _user data sync lock
- ///
- private object _userDataSyncLock = new object();
- ///
- /// Gets the user data.
- ///
- /// The user data.
- [IgnoreDataMember]
- public IEnumerable UserData
- {
- get
- {
- // Call ToList to exhaust the stream because we'll be iterating over this multiple times
- LazyInitializer.EnsureInitialized(ref _userData, ref _userDataInitialized, ref _userDataSyncLock, () => Kernel.Instance.UserDataRepository.RetrieveUserData(this).ToList());
- return _userData;
- }
- private set
- {
- _userData = value;
-
- if (value == null)
- {
- _userDataInitialized = false;
- }
- }
- }
-
- ///
- /// Gets the user data.
- ///
- /// The user.
- /// if set to true [create if null].
- /// UserItemData.
- ///
- public UserItemData GetUserData(User user, bool createIfNull)
- {
- if (user == null)
- {
- throw new ArgumentNullException();
- }
-
- if (UserData == null)
- {
- if (!createIfNull)
- {
- return null;
- }
-
- AddOrUpdateUserData(user, new UserItemData { UserId = user.Id });
- }
-
- var data = UserData.FirstOrDefault(u => u.UserId == user.Id);
-
- if (data == null && createIfNull)
- {
- data = new UserItemData { UserId = user.Id };
- AddOrUpdateUserData(user, data);
- }
-
- return data;
- }
-
- ///
- /// Adds the or update user data.
- ///
- /// The user.
- /// The data.
- ///
- public void AddOrUpdateUserData(User user, UserItemData data)
- {
- if (user == null)
- {
- throw new ArgumentNullException();
- }
-
- if (data == null)
- {
- throw new ArgumentNullException();
- }
-
- data.UserId = user.Id;
-
- if (UserData == null)
- {
- UserData = new[] { data };
- }
- else
- {
- var list = UserData.Where(u => u.UserId != user.Id).ToList();
- list.Add(data);
- UserData = list;
- }
- }
-
///
/// The _user data id
///
@@ -1205,16 +1102,17 @@ namespace MediaBrowser.Controller.Entities
///
/// The user.
/// if set to true [was played].
+ /// The user manager.
/// Task.
///
- public virtual Task SetPlayedStatus(User user, bool wasPlayed, IUserManager userManager)
+ public virtual async Task SetPlayedStatus(User user, bool wasPlayed, IUserManager userManager)
{
if (user == null)
{
throw new ArgumentNullException();
}
- var data = GetUserData(user, true);
+ var data = await userManager.GetUserData(user.Id, UserDataId).ConfigureAwait(false);
if (wasPlayed)
{
@@ -1237,7 +1135,7 @@ namespace MediaBrowser.Controller.Entities
data.Played = wasPlayed;
- return userManager.SaveUserDataForItem(user, this, data);
+ await userManager.SaveUserData(user.Id, UserDataId, data, CancellationToken.None).ConfigureAwait(false);
}
///
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 5a61844c2..05ee87def 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -74,109 +74,6 @@ namespace MediaBrowser.Controller.Entities
}
}
- ///
- /// The _display prefs
- ///
- private IEnumerable _displayPreferences;
- ///
- /// The _display prefs initialized
- ///
- private bool _displayPreferencesInitialized;
- ///
- /// The _display prefs sync lock
- ///
- private object _displayPreferencesSyncLock = new object();
- ///
- /// Gets the display prefs.
- ///
- /// The display prefs.
- [IgnoreDataMember]
- public IEnumerable DisplayPreferences
- {
- get
- {
- // Call ToList to exhaust the stream because we'll be iterating over this multiple times
- LazyInitializer.EnsureInitialized(ref _displayPreferences, ref _displayPreferencesInitialized, ref _displayPreferencesSyncLock, () => Kernel.Instance.DisplayPreferencesRepository.RetrieveDisplayPreferences(this).ToList());
- return _displayPreferences;
- }
- private set
- {
- _displayPreferences = value;
-
- if (value == null)
- {
- _displayPreferencesInitialized = false;
- }
- }
- }
-
- ///
- /// Gets the display prefs.
- ///
- /// The user.
- /// if set to true [create if null].
- /// DisplayPreferences.
- ///
- public DisplayPreferences GetDisplayPreferences(User user, bool createIfNull)
- {
- if (user == null)
- {
- throw new ArgumentNullException();
- }
-
- if (DisplayPreferences == null)
- {
- if (!createIfNull)
- {
- return null;
- }
-
- AddOrUpdateDisplayPreferences(user, new DisplayPreferences { UserId = user.Id });
- }
-
- var data = DisplayPreferences.FirstOrDefault(u => u.UserId == user.Id);
-
- if (data == null && createIfNull)
- {
- data = new DisplayPreferences { UserId = user.Id };
- AddOrUpdateDisplayPreferences(user, data);
- }
-
- return data;
- }
-
- ///
- /// Adds the or update display prefs.
- ///
- /// The user.
- /// The data.
- ///
- public void AddOrUpdateDisplayPreferences(User user, DisplayPreferences data)
- {
- if (user == null)
- {
- throw new ArgumentNullException();
- }
-
- if (data == null)
- {
- throw new ArgumentNullException();
- }
-
- data.UserId = user.Id;
-
- if (DisplayPreferences == null)
- {
- DisplayPreferences = new[] { data };
- }
- else
- {
- var list = DisplayPreferences.Where(u => u.UserId != user.Id).ToList();
- list.Add(data);
- DisplayPreferences = list;
- }
- }
-
#region Indexing
///
@@ -902,6 +799,7 @@ namespace MediaBrowser.Controller.Entities
///
/// The user.
/// if set to true [was played].
+ /// The user manager.
/// Task.
public override async Task SetPlayedStatus(User user, bool wasPlayed, IUserManager userManager)
{
diff --git a/MediaBrowser.Controller/Library/DtoBuilder.cs b/MediaBrowser.Controller/Library/DtoBuilder.cs
index 36c7eba1f..d9244c64c 100644
--- a/MediaBrowser.Controller/Library/DtoBuilder.cs
+++ b/MediaBrowser.Controller/Library/DtoBuilder.cs
@@ -28,11 +28,13 @@ namespace MediaBrowser.Controller.Library
private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager;
+ private readonly IUserManager _userManager;
- public DtoBuilder(ILogger logger, ILibraryManager libraryManager)
+ public DtoBuilder(ILogger logger, ILibraryManager libraryManager, IUserManager userManager)
{
_logger = logger;
_libraryManager = libraryManager;
+ _userManager = userManager;
}
///
@@ -141,9 +143,9 @@ namespace MediaBrowser.Controller.Library
tasks.Add(AttachPeople(dto, item));
}
- AttachBasicFields(dto, item, fields);
+ tasks.Add(AttachUserSpecificInfo(dto, item, user, fields));
- AttachUserSpecificInfo(dto, item, user, fields);
+ AttachBasicFields(dto, item, fields);
// Make sure all the tasks we kicked off have completed.
if (tasks.Count > 0)
@@ -161,21 +163,20 @@ namespace MediaBrowser.Controller.Library
/// The item.
/// The user.
/// The fields.
- private void AttachUserSpecificInfo(BaseItemDto dto, BaseItem item, User user, List fields)
+ private async Task AttachUserSpecificInfo(BaseItemDto dto, BaseItem item, User user, List fields)
{
if (fields.Contains(ItemFields.UserData))
{
- var userData = item.GetUserData(user, false);
+ var userData = await _userManager.GetUserData(user.Id, item.UserDataId).ConfigureAwait(false);
- if (userData != null)
- {
- dto.UserData = GetUserItemDataDto(userData);
- }
+ dto.UserData = GetUserItemDataDto(userData);
}
if (item.IsFolder && fields.Contains(ItemFields.DisplayPreferences))
{
- dto.DisplayPreferences = ((Folder)item).GetDisplayPreferences(user, false) ?? new DisplayPreferences { UserId = user.Id };
+ var displayPreferencesId = ((Folder) item).DisplayPreferencesId;
+
+ dto.DisplayPreferences = await _userManager.GetDisplayPreferences(user.Id, displayPreferencesId).ConfigureAwait(false);
}
if (item.IsFolder)
@@ -187,11 +188,11 @@ namespace MediaBrowser.Controller.Library
// Skip sorting since all we want is a count
dto.ChildCount = folder.GetChildren(user).Count();
- SetSpecialCounts(folder, user, dto);
+ await SetSpecialCounts(folder, user, dto, _userManager).ConfigureAwait(false);
}
}
}
-
+
///
/// Attaches the primary image aspect ratio.
///
@@ -484,7 +485,9 @@ namespace MediaBrowser.Controller.Library
/// The folder.
/// The user.
/// The dto.
- private static void SetSpecialCounts(Folder folder, User user, BaseItemDto dto)
+ /// The user manager.
+ /// Task.
+ private static async Task SetSpecialCounts(Folder folder, User user, BaseItemDto dto, IUserManager userManager)
{
var rcentlyAddedItemCount = 0;
var recursiveItemCount = 0;
@@ -494,7 +497,7 @@ namespace MediaBrowser.Controller.Library
// Loop through each recursive child
foreach (var child in folder.GetRecursiveChildren(user).Where(i => !i.IsFolder))
{
- var userdata = child.GetUserData(user, false);
+ var userdata = await userManager.GetUserData(user.Id, child.UserDataId).ConfigureAwait(false);
recursiveItemCount++;
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index 1b9d2f4b2..da2f46abb 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -107,15 +107,6 @@ namespace MediaBrowser.Controller.Library
/// Task.
Task ValidateMediaLibrary(IProgress progress, CancellationToken cancellationToken);
- ///
- /// Saves display preferences for a Folder
- ///
- /// The user.
- /// The folder.
- /// The data.
- /// Task.
- Task SaveDisplayPreferencesForFolder(User user, Folder folder, DisplayPreferences data);
-
///
/// Gets the default view.
///
diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs
index 229e4cb76..8374c6880 100644
--- a/MediaBrowser.Controller/Library/IUserManager.cs
+++ b/MediaBrowser.Controller/Library/IUserManager.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Events;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Connectivity;
+using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.Threading;
@@ -156,14 +157,6 @@ namespace MediaBrowser.Controller.Library
///
Task OnPlaybackStopped(User user, BaseItem item, long? positionTicks, string clientType, string deviceId, string deviceName);
- ///
- /// Saves user data for an item
- ///
- /// The user.
- /// The item.
- /// The data.
- Task SaveUserDataForItem(User user, BaseItem item, UserItemData data);
-
///
/// Resets the password.
///
@@ -178,5 +171,43 @@ namespace MediaBrowser.Controller.Library
/// The new password.
/// Task.
Task ChangePassword(User user, string newPassword);
+
+ ///
+ /// Saves display preferences for an item
+ ///
+ /// The user id.
+ /// The user data id.
+ /// The user data.
+ /// The cancellation token.
+ /// Task.
+ Task SaveUserData(Guid userId, Guid userDataId, UserItemData userData,
+ CancellationToken cancellationToken);
+
+ ///
+ /// Gets the display preferences.
+ ///
+ /// The user id.
+ /// The user data id.
+ /// Task{DisplayPreferences}.
+ Task GetUserData(Guid userId, Guid userDataId);
+
+ ///
+ /// Gets the display preferences.
+ ///
+ /// The user id.
+ /// The display preferences id.
+ /// DisplayPreferences.
+ Task GetDisplayPreferences(Guid userId, Guid displayPreferencesId);
+
+ ///
+ /// Saves display preferences for an item
+ ///
+ /// The user id.
+ /// The display preferences id.
+ /// The display preferences.
+ /// The cancellation token.
+ /// Task.
+ Task SaveDisplayPreferences(Guid userId, Guid displayPreferencesId, DisplayPreferences displayPreferences,
+ CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs b/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs
index 6f03810c2..eb43c8ca5 100644
--- a/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs
@@ -1,6 +1,5 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
+using MediaBrowser.Model.Entities;
+using System;
using System.Threading;
using System.Threading.Tasks;
@@ -14,16 +13,20 @@ namespace MediaBrowser.Controller.Persistence
///
/// Saves display preferences for an item
///
- /// The item.
+ /// The user id.
+ /// The display preferences id.
+ /// The display preferences.
/// The cancellation token.
/// Task.
- Task SaveDisplayPreferences(Folder item, CancellationToken cancellationToken);
+ Task SaveDisplayPreferences(Guid userId, Guid displayPreferencesId, DisplayPreferences displayPreferences,
+ CancellationToken cancellationToken);
///
- /// Gets display preferences for an item
+ /// Gets the display preferences.
///
- /// The item.
- /// IEnumerable{DisplayPreferences}.
- IEnumerable RetrieveDisplayPreferences(Folder item);
+ /// The user id.
+ /// The display preferences id.
+ /// Task{DisplayPreferences}.
+ Task GetDisplayPreferences(Guid userId, Guid displayPreferencesId);
}
}
diff --git a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs
index 115bd411a..592206faf 100644
--- a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs
@@ -1,5 +1,5 @@
using MediaBrowser.Controller.Entities;
-using System.Collections.Generic;
+using System;
using System.Threading;
using System.Threading.Tasks;
@@ -11,18 +11,22 @@ namespace MediaBrowser.Controller.Persistence
public interface IUserDataRepository : IRepository
{
///
- /// Saves user data for an item
+ /// Saves the user data.
///
- /// The item.
+ /// The user id.
+ /// The user data id.
+ /// The user data.
/// The cancellation token.
/// Task.
- Task SaveUserData(BaseItem item, CancellationToken cancellationToken);
+ Task SaveUserData(Guid userId, Guid userDataId, UserItemData userData,
+ CancellationToken cancellationToken);
///
- /// Gets user data for an item
+ /// Gets the user data.
///
- /// The item.
- /// IEnumerable{UserItemData}.
- IEnumerable RetrieveUserData(BaseItem item);
+ /// The user id.
+ /// The user data id.
+ /// Task{UserItemData}.
+ Task GetUserData(Guid userId, Guid userDataId);
}
}
diff --git a/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs b/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs
index b9da1f6a6..76d84a653 100644
--- a/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs
+++ b/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
namespace MediaBrowser.Controller.Sorting
{
@@ -12,5 +13,11 @@ namespace MediaBrowser.Controller.Sorting
///
/// The user.
User User { get; set; }
+
+ ///
+ /// Gets or sets the user manager.
+ ///
+ /// The user manager.
+ IUserManager UserManager { get; set; }
}
}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs
index edb227c79..669603958 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs
@@ -160,7 +160,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
if (exception != null)
{
- _logger.ErrorException("Error processing request", exception);
+ _logger.ErrorException("Error processing request for {0}", exception, req.RawUrl);
if (!string.IsNullOrEmpty(exception.Message))
{
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index 84055cea7..a57eb8eaa 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -124,15 +124,6 @@ namespace MediaBrowser.Server.Implementations.Library
LazyInitializer.EnsureInitialized(ref _libraryItemsCache, ref _libraryItemsCacheInitialized, ref _libraryItemsCacheSyncLock, CreateLibraryItemsCache);
return _libraryItemsCache;
}
- set
- {
- _libraryItemsCache = value;
-
- if (value == null)
- {
- _libraryItemsCacheInitialized = false;
- }
- }
}
///
@@ -267,10 +258,22 @@ namespace MediaBrowser.Server.Implementations.Library
items.AddRange(specialFeatures);
items.AddRange(localTrailers);
- // Can't add these right now because there could be separate instances with the same id.
- //items.AddRange(_userManager.Users.Select(i => i.RootFolder).Distinct().ToList());
+ // Need to use DistinctBy Id because there could be multiple instances with the same id
+ // due to sharing the default library
+ var userRootFolders = _userManager.Users.Select(i => i.RootFolder)
+ .DistinctBy(i => i.Id)
+ .ToList();
- items.AddRange(_userManager.Users.SelectMany(i => i.RootFolder.Children).Where(i => !(i is BasePluginFolder)).Distinct().ToList());
+ items.AddRange(userRootFolders);
+
+ // Get all user collection folders
+ var userFolders =
+ _userManager.Users.SelectMany(i => i.RootFolder.Children)
+ .Where(i => !(i is BasePluginFolder))
+ .DistinctBy(i => i.Id)
+ .ToList();
+
+ items.AddRange(userFolders);
return new ConcurrentDictionary(items.ToDictionary(i => i.Id));
}
@@ -744,26 +747,6 @@ namespace MediaBrowser.Server.Implementations.Library
await RootFolder.ValidateChildren(progress, cancellationToken, recursive: true).ConfigureAwait(false);
}
- ///
- /// Saves display preferences for a Folder
- ///
- /// The user.
- /// The folder.
- /// The data.
- /// Task.
- public Task SaveDisplayPreferencesForFolder(User user, Folder folder, DisplayPreferences data)
- {
- // Need to update all items with the same DisplayPreferencesId
- foreach (var child in RootFolder.GetRecursiveChildren(user)
- .OfType()
- .Where(i => i.DisplayPreferencesId == folder.DisplayPreferencesId))
- {
- child.AddOrUpdateDisplayPreferences(user, data);
- }
-
- return Kernel.DisplayPreferencesRepository.SaveDisplayPreferences(folder, CancellationToken.None);
- }
-
///
/// Gets the default view.
///
@@ -878,6 +861,7 @@ namespace MediaBrowser.Server.Implementations.Library
var userComparer = (IUserBaseItemComparer)Activator.CreateInstance(comparer.GetType());
userComparer.User = user;
+ userComparer.UserManager = _userManager;
return userComparer;
}
diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs
index 49b2a3f18..ca3c1fe7c 100644
--- a/MediaBrowser.Server.Implementations/Library/UserManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs
@@ -5,8 +5,10 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Connectivity;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
@@ -97,6 +99,13 @@ namespace MediaBrowser.Server.Implementations.Library
/// The configuration manager.
private IServerConfigurationManager ConfigurationManager { get; set; }
+ ///
+ /// The _user data
+ ///
+ private readonly ConcurrentDictionary> _displayPreferences = new ConcurrentDictionary>();
+
+ private readonly ConcurrentDictionary> _userData = new ConcurrentDictionary>();
+
///
/// Initializes a new instance of the class.
///
@@ -156,6 +165,63 @@ namespace MediaBrowser.Server.Implementations.Library
}
#endregion
+ ///
+ /// Gets the display preferences.
+ ///
+ /// The user id.
+ /// The display preferences id.
+ /// DisplayPreferences.
+ public Task GetDisplayPreferences(Guid userId, Guid displayPreferencesId)
+ {
+ var key = userId + displayPreferencesId.ToString();
+
+ return _displayPreferences.GetOrAdd(key, keyName => RetrieveDisplayPreferences(userId, displayPreferencesId));
+ }
+
+ ///
+ /// Retrieves the display preferences.
+ ///
+ /// The user id.
+ /// The display preferences id.
+ /// DisplayPreferences.
+ private async Task RetrieveDisplayPreferences(Guid userId, Guid displayPreferencesId)
+ {
+ var displayPreferences = await Kernel.Instance.DisplayPreferencesRepository.GetDisplayPreferences(userId, displayPreferencesId).ConfigureAwait(false);
+
+ return displayPreferences ?? new DisplayPreferences();
+ }
+
+ ///
+ /// Saves display preferences for an item
+ ///
+ /// The user id.
+ /// The display preferences id.
+ /// The display preferences.
+ /// The cancellation token.
+ /// Task.
+ public async Task SaveDisplayPreferences(Guid userId, Guid displayPreferencesId, DisplayPreferences displayPreferences, CancellationToken cancellationToken)
+ {
+ var key = userId + displayPreferencesId.ToString();
+
+ try
+ {
+ await Kernel.Instance.DisplayPreferencesRepository.SaveDisplayPreferences(userId, displayPreferencesId,
+ displayPreferences,
+ cancellationToken).ConfigureAwait(false);
+
+ var newValue = Task.FromResult(displayPreferences);
+
+ // Once it succeeds, put it into the dictionary to make it available to everyone else
+ _displayPreferences.AddOrUpdate(key, newValue, delegate { return newValue; });
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error saving display preferences", ex);
+
+ throw;
+ }
+ }
+
///
/// Gets a User by Id
///
@@ -588,10 +654,10 @@ namespace MediaBrowser.Server.Implementations.Library
if (positionTicks.HasValue)
{
- var data = item.GetUserData(user, true);
+ var data = await GetUserData(user.Id, item.UserDataId).ConfigureAwait(false);
UpdatePlayState(item, data, positionTicks.Value, false);
- await SaveUserDataForItem(user, item, data).ConfigureAwait(false);
+ await SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None).ConfigureAwait(false);
}
EventHelper.QueueEventIfNotNull(PlaybackProgress, this, new PlaybackProgressEventArgs
@@ -626,7 +692,7 @@ namespace MediaBrowser.Server.Implementations.Library
RemoveNowPlayingItemId(user, clientType, deviceId, deviceName, item);
- var data = item.GetUserData(user, true);
+ var data = await GetUserData(user.Id, item.UserDataId).ConfigureAwait(false);
if (positionTicks.HasValue)
{
@@ -639,7 +705,7 @@ namespace MediaBrowser.Server.Implementations.Library
data.Played = true;
}
- await SaveUserDataForItem(user, item, data).ConfigureAwait(false);
+ await SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None).ConfigureAwait(false);
EventHelper.QueueEventIfNotNull(PlaybackStopped, this, new PlaybackProgressEventArgs
{
@@ -700,17 +766,57 @@ namespace MediaBrowser.Server.Implementations.Library
}
///
- /// Saves user data for an item
+ /// Saves display preferences for an item
///
- /// The user.
- /// The item.
- /// The data.
- public Task SaveUserDataForItem(User user, BaseItem item, UserItemData data)
+ /// The user id.
+ /// The user data id.
+ /// The user data.
+ /// The cancellation token.
+ /// Task.
+ public async Task SaveUserData(Guid userId, Guid userDataId, UserItemData userData, CancellationToken cancellationToken)
{
- item.AddOrUpdateUserData(user, data);
+ var key = userId + userDataId.ToString();
+ try
+ {
+ await Kernel.Instance.UserDataRepository.SaveUserData(userId, userDataId, userData, cancellationToken).ConfigureAwait(false);
- return Kernel.UserDataRepository.SaveUserData(item, CancellationToken.None);
+ var newValue = Task.FromResult(userData);
+
+ // Once it succeeds, put it into the dictionary to make it available to everyone else
+ _userData.AddOrUpdate(key, newValue, delegate { return newValue; });
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error saving user data", ex);
+
+ throw;
+ }
}
+ ///
+ /// Gets the display preferences.
+ ///
+ /// The user id.
+ /// The user data id.
+ /// Task{DisplayPreferences}.
+ public Task GetUserData(Guid userId, Guid userDataId)
+ {
+ var key = userId + userDataId.ToString();
+
+ return _userData.GetOrAdd(key, keyName => RetrieveUserData(userId, userDataId));
+ }
+
+ ///
+ /// Retrieves the display preferences.
+ ///
+ /// The user id.
+ /// The user data id.
+ /// DisplayPreferences.
+ private async Task RetrieveUserData(Guid userId, Guid userDataId)
+ {
+ var userdata = await Kernel.Instance.UserDataRepository.GetUserData(userId, userDataId).ConfigureAwait(false);
+
+ return userdata ?? new UserItemData();
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs
index c37b6b4a4..905d5413a 100644
--- a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs
+++ b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Querying;
using System;
@@ -16,6 +17,12 @@ namespace MediaBrowser.Server.Implementations.Sorting
/// The user.
public User User { get; set; }
+ ///
+ /// Gets or sets the user manager.
+ ///
+ /// The user manager.
+ public IUserManager UserManager { get; set; }
+
///
/// Compares the specified x.
///
@@ -34,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
/// DateTime.
private DateTime GetDate(BaseItem x)
{
- var userdata = x.GetUserData(User, false);
+ var userdata = UserManager.GetUserData(User.Id, x.UserDataId).Result;
if (userdata != null && userdata.LastPlayedDate.HasValue)
{
diff --git a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs
index 9cd5281c3..82e76e78d 100644
--- a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs
+++ b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Querying;
@@ -33,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
/// DateTime.
private int GetValue(BaseItem x)
{
- var userdata = x.GetUserData(User, false);
+ var userdata = UserManager.GetUserData(User.Id, x.UserDataId).Result;
return userdata == null ? 0 : userdata.PlayCount;
}
@@ -46,5 +47,11 @@ namespace MediaBrowser.Server.Implementations.Sorting
{
get { return ItemSortBy.PlayCount; }
}
+
+ ///
+ /// Gets or sets the user manager.
+ ///
+ /// The user manager.
+ public IUserManager UserManager { get; set; }
}
}
diff --git a/MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs b/MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs
index baa38cde0..44674e125 100644
--- a/MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs
+++ b/MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs
@@ -1,11 +1,9 @@
using MediaBrowser.Common.Configuration;
-using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System;
-using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Threading;
@@ -80,8 +78,8 @@ namespace MediaBrowser.Server.Implementations.Sqlite
string[] queries = {
- "create table if not exists display_prefs (item_id GUID, user_id GUID, data BLOB)",
- "create unique index if not exists idx_display_prefs on display_prefs (item_id, user_id)",
+ "create table if not exists displaypreferences (id GUID, userId GUID, data BLOB)",
+ "create unique index if not exists displaypreferencesindex on displaypreferences (id, userId)",
"create table if not exists schema_version (table_name primary key, version)",
//pragmas
"pragma temp_store = memory"
@@ -93,82 +91,87 @@ namespace MediaBrowser.Server.Implementations.Sqlite
///
/// Save the display preferences associated with an item in the repo
///
- /// The item.
+ /// The user id.
+ /// The display preferences id.
+ /// The display preferences.
/// The cancellation token.
/// Task.
/// item
- public Task SaveDisplayPreferences(Folder item, CancellationToken cancellationToken)
+ public Task SaveDisplayPreferences(Guid userId, Guid displayPreferencesId, DisplayPreferences displayPreferences, CancellationToken cancellationToken)
{
- if (item == null)
+ if (displayPreferences == null)
{
- throw new ArgumentNullException("item");
+ throw new ArgumentNullException("displayPreferences");
}
-
if (cancellationToken == null)
{
throw new ArgumentNullException("cancellationToken");
}
+ if (userId == Guid.Empty)
+ {
+ throw new ArgumentNullException("userId");
+ }
+ if (displayPreferencesId == Guid.Empty)
+ {
+ throw new ArgumentNullException("displayPreferencesId");
+ }
cancellationToken.ThrowIfCancellationRequested();
-
+
return Task.Run(() =>
{
+ var serialized = _protobufSerializer.SerializeToBytes(displayPreferences);
+
+ cancellationToken.ThrowIfCancellationRequested();
+
var cmd = connection.CreateCommand();
-
- cmd.CommandText = "delete from display_prefs where item_id = @guid";
- cmd.AddParam("@guid", item.DisplayPreferencesId);
-
+ cmd.CommandText = "replace into displaypreferences (id, userId, data) values (@1, @2, @3)";
+ cmd.AddParam("@1", displayPreferencesId);
+ cmd.AddParam("@2", userId);
+ cmd.AddParam("@3", serialized);
QueueCommand(cmd);
-
- if (item.DisplayPreferences != null)
- {
- foreach (var data in item.DisplayPreferences)
- {
- cmd = connection.CreateCommand();
- cmd.CommandText = "insert into display_prefs (item_id, user_id, data) values (@1, @2, @3)";
- cmd.AddParam("@1", item.DisplayPreferencesId);
- cmd.AddParam("@2", data.UserId);
-
- cmd.AddParam("@3", _protobufSerializer.SerializeToBytes(data));
-
- QueueCommand(cmd);
- }
- }
});
}
///
- /// Gets display preferences for an item
+ /// Gets the display preferences.
///
- /// The item.
- /// IEnumerable{DisplayPreferences}.
- ///
- public IEnumerable RetrieveDisplayPreferences(Folder item)
+ /// The user id.
+ /// The display preferences id.
+ /// Task{DisplayPreferences}.
+ /// item
+ public async Task GetDisplayPreferences(Guid userId, Guid displayPreferencesId)
{
- if (item == null)
+ if (userId == Guid.Empty)
{
- throw new ArgumentNullException("item");
+ throw new ArgumentNullException("userId");
+ }
+ if (displayPreferencesId == Guid.Empty)
+ {
+ throw new ArgumentNullException("displayPreferencesId");
}
var cmd = connection.CreateCommand();
- cmd.CommandText = "select data from display_prefs where item_id = @guid";
- var guidParam = cmd.Parameters.Add("@guid", DbType.Guid);
- guidParam.Value = item.DisplayPreferencesId;
+ cmd.CommandText = "select data from displaypreferences where id = @id and userId=@userId";
+
+ var idParam = cmd.Parameters.Add("@id", DbType.Guid);
+ idParam.Value = displayPreferencesId;
- using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
+ var userIdParam = cmd.Parameters.Add("@userId", DbType.Guid);
+ userIdParam.Value = userId;
+
+ using (var reader = await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow).ConfigureAwait(false))
{
- while (reader.Read())
+ if (reader.Read())
{
using (var stream = GetStream(reader, 0))
{
- var data = _protobufSerializer.DeserializeFromStream(stream);
- if (data != null)
- {
- yield return data;
- }
+ return _protobufSerializer.DeserializeFromStream(stream);
}
}
}
+
+ return null;
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs
index dafdce798..f3dede889 100644
--- a/MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs
+++ b/MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs
@@ -79,8 +79,8 @@ namespace MediaBrowser.Server.Implementations.Sqlite
string[] queries = {
- "create table if not exists user_data (item_id GUID, user_id GUID, data BLOB)",
- "create unique index if not exists idx_user_data on user_data (item_id, user_id)",
+ "create table if not exists userdata (id GUID, userId GUID, data BLOB)",
+ "create unique index if not exists userdataindex on userdata (id, userId)",
"create table if not exists schema_version (table_name primary key, version)",
//pragmas
"pragma temp_store = memory"
@@ -90,84 +90,101 @@ namespace MediaBrowser.Server.Implementations.Sqlite
}
///
- /// Save the user specific data associated with an item in the repo
+ /// Saves the user data.
///
- /// The item.
+ /// The user id.
+ /// The user data id.
+ /// The user data.
/// The cancellation token.
/// Task.
- /// item
- public Task SaveUserData(BaseItem item, CancellationToken cancellationToken)
+ ///
+ /// userData
+ /// or
+ /// cancellationToken
+ /// or
+ /// userId
+ /// or
+ /// userDataId
+ ///
+ public Task SaveUserData(Guid userId, Guid userDataId, UserItemData userData, CancellationToken cancellationToken)
{
- if (item == null)
+ if (userData == null)
{
- throw new ArgumentNullException("item");
+ throw new ArgumentNullException("userData");
}
-
if (cancellationToken == null)
{
throw new ArgumentNullException("cancellationToken");
}
-
+ if (userId == Guid.Empty)
+ {
+ throw new ArgumentNullException("userId");
+ }
+ if (userDataId == Guid.Empty)
+ {
+ throw new ArgumentNullException("userDataId");
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
return Task.Run(() =>
{
+ var serialized = _protobufSerializer.SerializeToBytes(userData);
+
cancellationToken.ThrowIfCancellationRequested();
var cmd = connection.CreateCommand();
-
- cmd.CommandText = "delete from user_data where item_id = @guid";
- cmd.AddParam("@guid", item.UserDataId);
-
+ cmd.CommandText = "replace into userdata (id, userId, data) values (@1, @2, @3)";
+ cmd.AddParam("@1", userDataId);
+ cmd.AddParam("@2", userId);
+ cmd.AddParam("@3", serialized);
QueueCommand(cmd);
-
- if (item.UserData != null)
- {
- foreach (var data in item.UserData)
- {
- cmd = connection.CreateCommand();
- cmd.CommandText = "insert into user_data (item_id, user_id, data) values (@1, @2, @3)";
- cmd.AddParam("@1", item.UserDataId);
- cmd.AddParam("@2", data.UserId);
-
- cmd.AddParam("@3", _protobufSerializer.SerializeToBytes(data));
-
- QueueCommand(cmd);
- }
- }
});
}
///
- /// Gets user data for an item
+ /// Gets the user data.
///
- /// The item.
- /// IEnumerable{UserItemData}.
- /// item
- public IEnumerable RetrieveUserData(BaseItem item)
+ /// The user id.
+ /// The user data id.
+ /// Task{UserItemData}.
+ ///
+ /// userId
+ /// or
+ /// userDataId
+ ///
+ public async Task GetUserData(Guid userId, Guid userDataId)
{
- if (item == null)
+ if (userId == Guid.Empty)
{
- throw new ArgumentNullException("item");
+ throw new ArgumentNullException("userId");
+ }
+ if (userDataId == Guid.Empty)
+ {
+ throw new ArgumentNullException("userDataId");
}
var cmd = connection.CreateCommand();
- cmd.CommandText = "select data from user_data where item_id = @guid";
- var guidParam = cmd.Parameters.Add("@guid", DbType.Guid);
- guidParam.Value = item.UserDataId;
+ cmd.CommandText = "select data from userdata where id = @id and userId=@userId";
- using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
+ var idParam = cmd.Parameters.Add("@id", DbType.Guid);
+ idParam.Value = userDataId;
+
+ var userIdParam = cmd.Parameters.Add("@userId", DbType.Guid);
+ userIdParam.Value = userId;
+
+ using (var reader = await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow).ConfigureAwait(false))
{
- while (reader.Read())
+ if (reader.Read())
{
using (var stream = GetStream(reader, 0))
{
- var data = _protobufSerializer.DeserializeFromStream(stream);
- if (data != null)
- {
- yield return data;
- }
+ return _protobufSerializer.DeserializeFromStream(stream);
}
}
}
+
+ return null;
}
}
}
diff --git a/MediaBrowser.ServerApplication/EntryPoints/WebSocketEvents.cs b/MediaBrowser.ServerApplication/EntryPoints/WebSocketEvents.cs
index 50d625739..9ddd14491 100644
--- a/MediaBrowser.ServerApplication/EntryPoints/WebSocketEvents.cs
+++ b/MediaBrowser.ServerApplication/EntryPoints/WebSocketEvents.cs
@@ -174,7 +174,7 @@ namespace MediaBrowser.ServerApplication.EntryPoints
/// The e.
async void userManager_UserUpdated(object sender, GenericEventArgs e)
{
- var dto = await new DtoBuilder(_logger, _libraryManager).GetUserDto(e.Argument).ConfigureAwait(false);
+ var dto = await new DtoBuilder(_logger, _libraryManager, _userManager).GetUserDto(e.Argument).ConfigureAwait(false);
_serverManager.SendWebSocketMessage("UserUpdated", dto);
}
diff --git a/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs b/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs
index ca69459be..8811de9db 100644
--- a/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs
+++ b/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs
@@ -33,7 +33,8 @@ namespace MediaBrowser.ServerApplication
private readonly IJsonSerializer _jsonSerializer;
private readonly ILibraryManager _libraryManager;
-
+ private readonly IUserManager _userManager;
+
///
/// The current user
///
@@ -46,6 +47,7 @@ namespace MediaBrowser.ServerApplication
_logger = logger;
_jsonSerializer = jsonSerializer;
_libraryManager = libraryManager;
+ _userManager = userManager;
InitializeComponent();
lblVersion.Content = "Version: " + appHost.ApplicationVersion;
@@ -89,7 +91,7 @@ namespace MediaBrowser.ServerApplication
var currentFolder = folder;
Task.Factory.StartNew(() =>
{
- var prefs = ddlProfile.SelectedItem != null ? currentFolder.GetDisplayPreferences(ddlProfile.SelectedItem as User, false) ?? new DisplayPreferences {SortBy = ItemSortBy.SortName} : new DisplayPreferences {SortBy = ItemSortBy.SortName};
+ var prefs = ddlProfile.SelectedItem != null ? _userManager.GetDisplayPreferences((ddlProfile.SelectedItem as User).Id, currentFolder.DisplayPreferencesId).Result ?? new DisplayPreferences { SortBy = ItemSortBy.SortName } : new DisplayPreferences { SortBy = ItemSortBy.SortName };
var node = new TreeViewItem { Tag = currentFolder };
var subChildren = currentFolder.GetChildren(CurrentUser, prefs.IndexBy);
@@ -142,7 +144,8 @@ namespace MediaBrowser.ServerApplication
var subFolder = item as Folder;
if (subFolder != null)
{
- var prefs = subFolder.GetDisplayPreferences(user, false) ?? new DisplayPreferences {SortBy = LocalizedStrings.Instance.GetString("NameDispPref")};
+ var prefs = _userManager.GetDisplayPreferences(user.Id, subFolder.DisplayPreferencesId).Result;
+
AddChildren(node, OrderBy(subFolder.GetChildren(user), user, prefs.SortBy), user);
node.Header = item.Name + " (" + node.Items.Count + ")";
}
@@ -196,7 +199,10 @@ namespace MediaBrowser.ServerApplication
ItemSortBy.Runtime
};
- var prefs = folder.GetDisplayPreferences(ddlProfile.SelectedItem as User, false);
+ var prefs =
+ await
+ _userManager.GetDisplayPreferences((ddlProfile.SelectedItem as User).Id,
+ folder.DisplayPreferencesId);
ddlIndexBy.SelectedItem = prefs != null
? prefs.IndexBy ?? LocalizedStrings.Instance.GetString("NoneDispPref")
: LocalizedStrings.Instance.GetString("NoneDispPref");
@@ -354,7 +360,7 @@ namespace MediaBrowser.ServerApplication
var folder = treeItem != null
? treeItem.Tag as Folder
: null;
- var prefs = folder != null ? folder.GetDisplayPreferences(CurrentUser, true) : new DisplayPreferences {SortBy = ItemSortBy.SortName};
+ var prefs = folder != null ? _userManager.GetDisplayPreferences(CurrentUser.Id, folder.DisplayPreferencesId).Result : new DisplayPreferences {SortBy = ItemSortBy.SortName};
if (folder != null && prefs.IndexBy != ddlIndexBy.SelectedItem as string)
{
//grab UI context so we can update within the below task
@@ -395,7 +401,7 @@ namespace MediaBrowser.ServerApplication
var folder = treeItem != null
? treeItem.Tag as Folder
: null;
- var prefs = folder != null ? folder.GetDisplayPreferences(CurrentUser, true) : new DisplayPreferences();
+ var prefs = folder != null ? _userManager.GetDisplayPreferences(CurrentUser.Id, folder.DisplayPreferencesId).Result : new DisplayPreferences();
if (folder != null && prefs.SortBy != ddlSortBy.SelectedItem as string)
{
//grab UI context so we can update within the below task
diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs
index b80b1bffd..f6c64b49e 100644
--- a/MediaBrowser.WebDashboard/Api/DashboardService.cs
+++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs
@@ -163,7 +163,7 @@ namespace MediaBrowser.WebDashboard.Api
{
var connections = userManager.RecentConnections.ToArray();
- var dtoBuilder = new DtoBuilder(logger, libraryManager);
+ var dtoBuilder = new DtoBuilder(logger, libraryManager, userManager);
var tasks = userManager.Users.Where(u => connections.Any(c => c.UserId == u.Id)).Select(dtoBuilder.GetUserDto);
var users = await Task.WhenAll(tasks).ConfigureAwait(false);