aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Implementations')
-rw-r--r--MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelManager.cs12
-rw-r--r--MediaBrowser.Server.Implementations/Dto/DtoService.cs9
-rw-r--r--MediaBrowser.Server.Implementations/Library/LibraryManager.cs24
-rw-r--r--MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserDataManager.cs42
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs12
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj6
-rw-r--r--MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs6
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs (renamed from MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs)46
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs10
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs204
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs6
-rw-r--r--MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionManager.cs25
-rw-r--r--MediaBrowser.Server.Implementations/Social/SharingRepository.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs10
-rw-r--r--MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncRepository.cs4
-rw-r--r--MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs84
27 files changed, 330 insertions, 210 deletions
diff --git a/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs
index 85ab76182..b0e05a5bc 100644
--- a/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs
+++ b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs
@@ -27,11 +27,11 @@ namespace MediaBrowser.Server.Implementations.Activity
_appPaths = appPaths;
}
- public async Task Initialize()
+ public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "activitylog.db");
- _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
+ _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index c9956c68a..6a9842cb2 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -133,7 +133,7 @@ namespace MediaBrowser.Server.Implementations.Channels
if (query.IsFavorite.HasValue)
{
var val = query.IsFavorite.Value;
- channels = channels.Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite == val)
+ channels = channels.Where(i => _userDataManager.GetUserData(user, i).IsFavorite == val)
.ToList();
}
@@ -1437,7 +1437,7 @@ namespace MediaBrowser.Server.Implementations.Channels
case ItemFilter.IsFavoriteOrLikes:
return items.Where(item =>
{
- var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
+ var userdata = _userDataManager.GetUserData(user, item);
if (userdata == null)
{
@@ -1453,7 +1453,7 @@ namespace MediaBrowser.Server.Implementations.Channels
case ItemFilter.Likes:
return items.Where(item =>
{
- var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
+ var userdata = _userDataManager.GetUserData(user, item);
return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value;
});
@@ -1461,7 +1461,7 @@ namespace MediaBrowser.Server.Implementations.Channels
case ItemFilter.Dislikes:
return items.Where(item =>
{
- var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
+ var userdata = _userDataManager.GetUserData(user, item);
return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value;
});
@@ -1469,7 +1469,7 @@ namespace MediaBrowser.Server.Implementations.Channels
case ItemFilter.IsFavorite:
return items.Where(item =>
{
- var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
+ var userdata = _userDataManager.GetUserData(user, item);
return userdata != null && userdata.IsFavorite;
});
@@ -1477,7 +1477,7 @@ namespace MediaBrowser.Server.Implementations.Channels
case ItemFilter.IsResumable:
return items.Where(item =>
{
- var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
+ var userdata = _userDataManager.GetUserData(user, item);
return userdata != null && userdata.PlaybackPositionTicks > 0;
});
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index 7adde5c27..e8af0c3cb 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -487,7 +487,7 @@ namespace MediaBrowser.Server.Implementations.Dto
{
if (item.IsFolder)
{
- var userData = _userDataRepository.GetUserData(user.Id, item.GetUserDataKey());
+ var userData = _userDataRepository.GetUserData(user, item);
// Skip the user data manager because we've already looped through the recursive tree and don't want to do it twice
// TODO: Improve in future
@@ -1363,9 +1363,10 @@ namespace MediaBrowser.Server.Implementations.Dto
if (fields.Contains(ItemFields.MediaSourceCount))
{
- if (video.MediaSourceCount != 1)
+ var mediaSourceCount = video.MediaSourceCount;
+ if (mediaSourceCount != 1)
{
- dto.MediaSourceCount = video.MediaSourceCount;
+ dto.MediaSourceCount = mediaSourceCount;
}
}
@@ -1686,7 +1687,7 @@ namespace MediaBrowser.Server.Implementations.Dto
dateLastMediaAdded = new[] { dateLastMediaAdded.Value, child.DateCreated }.Max();
}
- var userdata = _userDataRepository.GetUserData(user.Id, child.GetUserDataKey());
+ var userdata = _userDataRepository.GetUserData(user, child);
recursiveItemCount++;
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index e1bcfa861..87fdc56b3 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -522,29 +522,7 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentNullException("items");
}
- var dict = new Dictionary<Guid, BaseItem>();
-
- foreach (var item in items)
- {
- var video = item as Video;
-
- if (video != null)
- {
- if (video.PrimaryVersionId.HasValue)
- {
- var primary = GetItemById(video.PrimaryVersionId.Value) as Video;
-
- if (primary != null)
- {
- dict[primary.Id] = primary;
- continue;
- }
- }
- }
- dict[item.Id] = item;
- }
-
- return dict.Values;
+ return items.DistinctBy(i => i.PresentationUniqueKey, StringComparer.OrdinalIgnoreCase);
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
index 092b797ce..a47fcdf4f 100644
--- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
@@ -267,7 +267,7 @@ namespace MediaBrowser.Server.Implementations.Library
private void SetUserProperties(IHasUserData item, MediaSourceInfo source, User user)
{
- var userData = item == null ? new UserItemData() : _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
+ var userData = item == null ? new UserItemData() : _userDataManager.GetUserData(user, item);
var allowRememberingSelection = item == null || item.EnableRememberingTrackSelections;
diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
index ae737d244..98f8abd40 100644
--- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
@@ -56,27 +56,30 @@ namespace MediaBrowser.Server.Implementations.Library
cancellationToken.ThrowIfCancellationRequested();
- var key = item.GetUserDataKey();
+ var keys = item.GetUserDataKeys();
- try
+ foreach (var key in keys)
{
- await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false);
+ try
+ {
+ await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false);
- var newValue = userData;
+ var newValue = userData;
- // Once it succeeds, put it into the dictionary to make it available to everyone else
- _userData.AddOrUpdate(GetCacheKey(userId, key), newValue, delegate { return newValue; });
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error saving user data", ex);
+ // Once it succeeds, put it into the dictionary to make it available to everyone else
+ _userData.AddOrUpdate(GetCacheKey(userId, key), newValue, delegate { return newValue; });
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error saving user data", ex);
- throw;
+ throw;
+ }
}
EventHelper.FireEventIfNotNull(UserDataSaved, this, new UserDataSaveEventArgs
{
- Key = key,
+ Keys = keys,
UserData = userData,
SaveReason = reason,
UserId = userId,
@@ -172,6 +175,21 @@ namespace MediaBrowser.Server.Implementations.Library
return userId + key;
}
+ public UserItemData GetUserData(IHasUserData user, IHasUserData item)
+ {
+ return GetUserData(user.Id, item.GetUserDataKey());
+ }
+
+ public UserItemData GetUserData(string userId, IHasUserData item)
+ {
+ return GetUserData(userId, item.GetUserDataKey());
+ }
+
+ public UserItemData GetUserData(Guid userId, IHasUserData item)
+ {
+ return GetUserData(userId, item.GetUserDataKey());
+ }
+
public UserItemDataDto GetUserDataDto(IHasUserData item, User user)
{
var userData = GetUserData(user.Id, item.GetUserDataKey());
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index ab2b59d48..eec8328f8 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -164,7 +164,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var val = query.IsFavorite.Value;
channels = channels
- .Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite == val);
+ .Where(i => _userDataManager.GetUserData(user, i).IsFavorite == val);
}
if (query.IsLiked.HasValue)
@@ -174,7 +174,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
channels = channels
.Where(i =>
{
- var likes = _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).Likes;
+ var likes = _userDataManager.GetUserData(user, i).Likes;
return likes.HasValue && likes.Value == val;
});
@@ -187,7 +187,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
channels = channels
.Where(i =>
{
- var likes = _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).Likes;
+ var likes = _userDataManager.GetUserData(user, i).Likes;
return likes.HasValue && likes.Value != val;
});
@@ -200,7 +200,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
if (enableFavoriteSorting)
{
- var userData = _userDataManager.GetUserData(user.Id, i.GetUserDataKey());
+ var userData = _userDataManager.GetUserData(user, i);
if (userData.IsFavorite)
{
@@ -1005,7 +1005,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var channel = GetInternalChannel(program.ChannelId);
- var channelUserdata = _userDataManager.GetUserData(userId, channel.GetUserDataKey());
+ var channelUserdata = _userDataManager.GetUserData(userId, channel);
if (channelUserdata.Likes ?? false)
{
@@ -1036,7 +1036,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (genres.TryGetValue(i, out genre))
{
- var genreUserdata = _userDataManager.GetUserData(userId, genre.GetUserDataKey());
+ var genreUserdata = _userDataManager.GetUserData(userId, genre);
if (genreUserdata.Likes ?? false)
{
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 43f5d741b..aff3a5e16 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -78,9 +78,6 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
- <Reference Include="System.Data.SQLite">
- <HintPath>..\ThirdParty\System.Data.SQLite.ManagedOnly\1.0.94.0\System.Data.SQLite.dll</HintPath>
- </Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net" />
@@ -261,6 +258,8 @@
<Compile Include="Notifications\IConfigurableNotificationService.cs" />
<Compile Include="Persistence\BaseSqliteRepository.cs" />
<Compile Include="Persistence\CleanDatabaseScheduledTask.cs" />
+ <Compile Include="Persistence\DataExtensions.cs" />
+ <Compile Include="Persistence\IDbConnector.cs" />
<Compile Include="Persistence\MediaStreamColumns.cs" />
<Compile Include="Social\SharingManager.cs" />
<Compile Include="Social\SharingRepository.cs" />
@@ -275,7 +274,6 @@
<Compile Include="Notifications\InternalNotificationService.cs" />
<Compile Include="Notifications\NotificationConfigurationFactory.cs" />
<Compile Include="Notifications\NotificationManager.cs" />
- <Compile Include="Persistence\SqliteExtensions.cs" />
<Compile Include="Persistence\SqliteFileOrganizationRepository.cs" />
<Compile Include="Notifications\SqliteNotificationsRepository.cs" />
<Compile Include="Persistence\SqliteProviderInfoRepository.cs" />
diff --git a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs
index 7302431e1..cecf03ddf 100644
--- a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs
+++ b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs
@@ -32,11 +32,11 @@ namespace MediaBrowser.Server.Implementations.Notifications
_appPaths = appPaths;
}
- public async Task Initialize()
+ public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "notifications.db");
- _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
+ _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs
index 031333f2c..2a2f9a09d 100644
--- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs
@@ -110,6 +110,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
_config.SaveConfiguration();
}
+ if (_config.Configuration.SchemaVersion < SqliteItemRepository.LatestSchemaVersion)
+ {
+ _config.Configuration.SchemaVersion = SqliteItemRepository.LatestSchemaVersion;
+ _config.SaveConfiguration();
+ }
+
if (EnableUnavailableMessage)
{
EnableUnavailableMessage = false;
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs
index 4fb1e07dd..103b75f84 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs
@@ -3,16 +3,12 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System;
using System.Data;
-using System.Data.SQLite;
using System.IO;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Persistence
{
- /// <summary>
- /// Class SQLiteExtensions
- /// </summary>
- static class SqliteExtensions
+ static class DataExtensions
{
/// <summary>
/// Determines whether the specified conn is open.
@@ -28,11 +24,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
return (IDataParameter)cmd.Parameters[index];
}
-
+
public static IDataParameter Add(this IDataParameterCollection paramCollection, IDbCommand cmd, string name, DbType type)
{
var param = cmd.CreateParameter();
-
+
param.ParameterName = name;
param.DbType = type;
@@ -48,11 +44,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
param.ParameterName = name;
paramCollection.Add(param);
-
+
return param;
}
-
+
/// <summary>
/// Gets a stream from a DataReader at a given ordinal
/// </summary>
@@ -122,38 +118,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
- /// <summary>
- /// Connects to db.
- /// </summary>
- /// <param name="dbPath">The db path.</param>
- /// <param name="logger">The logger.</param>
- /// <returns>Task{IDbConnection}.</returns>
- /// <exception cref="System.ArgumentNullException">dbPath</exception>
- public static async Task<IDbConnection> ConnectToDb(string dbPath, ILogger logger)
- {
- if (string.IsNullOrEmpty(dbPath))
- {
- throw new ArgumentNullException("dbPath");
- }
-
- logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath);
-
- var connectionstr = new SQLiteConnectionStringBuilder
- {
- PageSize = 4096,
- CacheSize = 2000,
- SyncMode = SynchronizationModes.Full,
- DataSource = dbPath,
- JournalMode = SQLiteJournalModeEnum.Wal
- };
-
- var connection = new SQLiteConnection(connectionstr.ConnectionString);
-
- await connection.OpenAsync().ConfigureAwait(false);
-
- return connection;
- }
-
public static void Attach(IDbConnection db, string path, string alias)
{
using (var cmd = db.CreateCommand())
diff --git a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs
new file mode 100644
index 000000000..cac9fe983
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs
@@ -0,0 +1,10 @@
+using System.Data;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Persistence
+{
+ public interface IDbConnector
+ {
+ Task<IDbConnection> Connect(string dbPath);
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs
index 45e0304c1..6077cfdba 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs
@@ -52,11 +52,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
- public async Task Initialize()
+ public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "displaypreferences.db");
- _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
+ _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs
index 2d5aad04d..037776997 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs
@@ -35,11 +35,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
- public async Task Initialize()
+ public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "fileorganization.db");
- _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
+ _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
index a44d66c73..6959de8e6 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
@@ -20,6 +20,7 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.LiveTv;
@@ -55,7 +56,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <summary>
/// The _app paths
/// </summary>
- private readonly IApplicationPaths _appPaths;
+ private readonly IServerConfigurationManager _config;
/// <summary>
/// The _save item command
@@ -81,35 +82,31 @@ namespace MediaBrowser.Server.Implementations.Persistence
private IDbCommand _updateInheritedRatingCommand;
private IDbCommand _updateInheritedTagsCommand;
- private const int LatestSchemaVersion = 65;
+ public const int LatestSchemaVersion = 68;
/// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
/// </summary>
- /// <param name="appPaths">The app paths.</param>
- /// <param name="jsonSerializer">The json serializer.</param>
- /// <param name="logManager">The log manager.</param>
- /// <exception cref="System.ArgumentNullException">
/// appPaths
/// or
/// jsonSerializer
/// </exception>
- public SqliteItemRepository(IApplicationPaths appPaths, IJsonSerializer jsonSerializer, ILogManager logManager)
+ public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager)
: base(logManager)
{
- if (appPaths == null)
+ if (config == null)
{
- throw new ArgumentNullException("appPaths");
+ throw new ArgumentNullException("config");
}
if (jsonSerializer == null)
{
throw new ArgumentNullException("jsonSerializer");
}
- _appPaths = appPaths;
+ _config = config;
_jsonSerializer = jsonSerializer;
- _criticReviewsPath = Path.Combine(_appPaths.DataPath, "critic-reviews");
+ _criticReviewsPath = Path.Combine(_config.ApplicationPaths.DataPath, "critic-reviews");
}
private const string ChaptersTableName = "Chapters2";
@@ -118,11 +115,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
- public async Task Initialize()
+ public async Task Initialize(IDbConnector dbConnector)
{
- var dbFile = Path.Combine(_appPaths.DataPath, "library.db");
+ var dbFile = Path.Combine(_config.ApplicationPaths.DataPath, "library.db");
- _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
+ _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
var createMediaStreamsTableCommand
= "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, PRIMARY KEY (ItemId, StreamIndex))";
@@ -228,18 +225,27 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection.AddColumn(Logger, "TypedBaseItems", "DateModifiedDuringLastRefresh", "DATETIME");
_connection.AddColumn(Logger, "TypedBaseItems", "InheritedTags", "Text");
_connection.AddColumn(Logger, "TypedBaseItems", "CleanName", "Text");
+ _connection.AddColumn(Logger, "TypedBaseItems", "PresentationUniqueKey", "Text");
+
+ string[] postQueries =
+ {
+ "create index if not exists idx_PresentationUniqueKey on TypedBaseItems(PresentationUniqueKey)",
+ "create index if not exists idx_Type on TypedBaseItems(Type)"
+ };
+
+ _connection.RunQueries(postQueries, Logger);
PrepareStatements();
new MediaStreamColumns(_connection, Logger).AddColumns();
- var chapterDbFile = Path.Combine(_appPaths.DataPath, "chapters.db");
+ var chapterDbFile = Path.Combine(_config.ApplicationPaths.DataPath, "chapters.db");
if (File.Exists(chapterDbFile))
{
MigrateChapters(chapterDbFile);
}
- var mediaStreamsDbFile = Path.Combine(_appPaths.DataPath, "mediainfo.db");
+ var mediaStreamsDbFile = Path.Combine(_config.ApplicationPaths.DataPath, "mediainfo.db");
if (File.Exists(mediaStreamsDbFile))
{
MigrateMediaStreams(mediaStreamsDbFile);
@@ -252,7 +258,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
var backupFile = file + ".bak";
File.Copy(file, backupFile, true);
- SqliteExtensions.Attach(_connection, backupFile, "MediaInfoOld");
+ DataExtensions.Attach(_connection, backupFile, "MediaInfoOld");
var columns = string.Join(",", _mediaStreamSaveColumns);
@@ -278,7 +284,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
var backupFile = file + ".bak";
File.Copy(file, backupFile, true);
- SqliteExtensions.Attach(_connection, backupFile, "ChaptersOld");
+ DataExtensions.Attach(_connection, backupFile, "ChaptersOld");
string[] queries = {
"REPLACE INTO "+ChaptersTableName+"(ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath) SELECT ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath FROM ChaptersOld.Chapters;"
@@ -469,7 +475,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"CriticRatingSummary",
"DateModifiedDuringLastRefresh",
"InheritedTags",
- "CleanName"
+ "CleanName",
+ "PresentationUniqueKey"
};
_saveItemCommand = _connection.CreateCommand();
_saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
@@ -803,6 +810,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
_saveItemCommand.GetParameter(index++).Value = item.Name.RemoveDiacritics();
}
+ _saveItemCommand.GetParameter(index++).Value = item.PresentationUniqueKey;
_saveItemCommand.Transaction = transaction;
@@ -1463,6 +1471,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
CheckDisposed();
+ var now = DateTime.UtcNow;
+
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems";
@@ -1475,6 +1485,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += whereText;
+ if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
+ {
+ cmd.CommandText += " Group by PresentationUniqueKey";
+ }
+
cmd.CommandText += GetOrderByText(query);
if (query.Limit.HasValue)
@@ -1482,10 +1497,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
}
- //Logger.Debug(cmd.CommandText);
-
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
+ Logger.Debug("GetItemList query time: {0}ms. Query: {1}",
+ Convert.ToInt32((DateTime.UtcNow - now).TotalMilliseconds),
+ cmd.CommandText);
+
while (reader.Read())
{
var item = GetItem(reader);
@@ -1507,6 +1524,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
CheckDisposed();
+ var now = DateTime.UtcNow;
+
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems";
@@ -1525,6 +1544,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += whereText;
+ if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
+ {
+ cmd.CommandText += " Group by PresentationUniqueKey";
+ }
+
cmd.CommandText += GetOrderByText(query);
if (query.Limit.HasValue)
@@ -1532,15 +1556,24 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
}
- cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
-
- //Logger.Debug(cmd.CommandText);
+ if (_config.Configuration.SchemaVersion >= 66)
+ {
+ cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems" + whereTextWithoutPaging;
+ }
+ else
+ {
+ cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
+ }
var list = new List<BaseItem>();
var count = 0;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
+ Logger.Debug("GetItems query time: {0}ms. Query: {1}",
+ Convert.ToInt32((DateTime.UtcNow - now).TotalMilliseconds),
+ cmd.CommandText);
+
while (reader.Read())
{
var item = GetItem(reader);
@@ -1608,6 +1641,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
CheckDisposed();
+ var now = DateTime.UtcNow;
+
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select guid from TypedBaseItems";
@@ -1620,6 +1655,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += whereText;
+ if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
+ {
+ cmd.CommandText += " Group by PresentationUniqueKey";
+ }
+
cmd.CommandText += GetOrderByText(query);
if (query.Limit.HasValue)
@@ -1629,10 +1669,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
var list = new List<Guid>();
- //Logger.Debug(cmd.CommandText);
-
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
+ Logger.Debug("GetItemIdsList query time: {0}ms. Query: {1}",
+ Convert.ToInt32((DateTime.UtcNow - now).TotalMilliseconds),
+ cmd.CommandText);
+
while (reader.Read())
{
list.Add(reader.GetGuid(0));
@@ -1662,7 +1704,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
- whereClauses = GetWhereClauses(query, cmd, true);
+ whereClauses = GetWhereClauses(query, cmd, true, false);
var whereText = whereClauses.Count == 0 ?
string.Empty :
@@ -1670,6 +1712,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += whereText;
+ if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
+ {
+ cmd.CommandText += " Group by PresentationUniqueKey";
+ }
+
cmd.CommandText += GetOrderByText(query);
if (query.Limit.HasValue)
@@ -1721,6 +1768,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
CheckDisposed();
+ var now = DateTime.UtcNow;
+
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select guid from TypedBaseItems";
@@ -1739,6 +1788,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += whereText;
+ if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
+ {
+ cmd.CommandText += " Group by PresentationUniqueKey";
+ }
+
cmd.CommandText += GetOrderByText(query);
if (query.Limit.HasValue)
@@ -1746,15 +1800,24 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
}
- cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
+ if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
+ {
+ cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems" + whereTextWithoutPaging;
+ }
+ else
+ {
+ cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
+ }
var list = new List<Guid>();
var count = 0;
- //Logger.Debug(cmd.CommandText);
-
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
+ Logger.Debug("GetItemIds query time: {0}ms. Query: {1}",
+ Convert.ToInt32((DateTime.UtcNow - now).TotalMilliseconds),
+ cmd.CommandText);
+
while (reader.Read())
{
list.Add(reader.GetGuid(0));
@@ -1774,7 +1837,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
- private List<string> GetWhereClauses(InternalItemsQuery query, IDbCommand cmd, bool addPaging)
+ private List<string> GetWhereClauses(InternalItemsQuery query, IDbCommand cmd, bool addPaging, bool enablePresentationUniqueKey = true)
{
var whereClauses = new List<string>();
@@ -1873,6 +1936,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.Parameters.Add(cmd, "@Path", DbType.String).Value = query.Path;
}
+ if (!string.IsNullOrWhiteSpace(query.PresentationUniqueKey))
+ {
+ whereClauses.Add("PresentationUniqueKey=@PresentationUniqueKey");
+ cmd.Parameters.Add(cmd, "@PresentationUniqueKey", DbType.String).Value = query.PresentationUniqueKey;
+ }
+
if (query.MinCommunityRating.HasValue)
{
whereClauses.Add("CommunityRating>=@MinCommunityRating");
@@ -1998,9 +2067,40 @@ namespace MediaBrowser.Server.Implementations.Persistence
if (!string.IsNullOrWhiteSpace(query.NameContains))
{
- whereClauses.Add("CleanName like @NameContains");
+ if (_config.Configuration.SchemaVersion >= 66)
+ {
+ whereClauses.Add("CleanName like @NameContains");
+ }
+ else
+ {
+ whereClauses.Add("Name like @NameContains");
+ }
cmd.Parameters.Add(cmd, "@NameContains", DbType.String).Value = "%" + query.NameContains + "%";
}
+ if (!string.IsNullOrWhiteSpace(query.NameStartsWith))
+ {
+ if (_config.Configuration.SchemaVersion >= 66)
+ {
+ whereClauses.Add("CleanName like @NameStartsWith");
+ }
+ else
+ {
+ whereClauses.Add("Name like @NameStartsWith");
+ }
+ cmd.Parameters.Add(cmd, "@NameStartsWith", DbType.String).Value = query.NameStartsWith + "%";
+ }
+ if (!string.IsNullOrWhiteSpace(query.NameStartsWithOrGreater))
+ {
+ whereClauses.Add("SortName >= @NameStartsWithOrGreater");
+ // lowercase this because SortName is stored as lowercase
+ cmd.Parameters.Add(cmd, "@NameStartsWithOrGreater", DbType.String).Value = query.NameStartsWithOrGreater.ToLower();
+ }
+ if (!string.IsNullOrWhiteSpace(query.NameLessThan))
+ {
+ whereClauses.Add("SortName < @NameLessThan");
+ // lowercase this because SortName is stored as lowercase
+ cmd.Parameters.Add(cmd, "@NameLessThan", DbType.String).Value = query.NameLessThan.ToLower();
+ }
if (query.Genres.Length > 0)
{
@@ -2134,7 +2234,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
whereClauses.Add("MediaType in (" + val + ")");
}
- var enableItemsByName = query.IncludeItemsByName ?? query.IncludeItemTypes.Length > 0;
+ //var enableItemsByName = query.IncludeItemsByName ?? query.IncludeItemTypes.Length > 0;
+ var enableItemsByName = query.IncludeItemsByName ?? false;
if (query.TopParentIds.Length == 1)
{
@@ -2197,7 +2298,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
excludeTagIndex = 0;
foreach (var excludeTag in query.ExcludeInheritedTags)
{
- whereClauses.Add("(InheritedTags is null OR InheritedTags not like @excludeInheritedTag" + excludeTagIndex +")");
+ whereClauses.Add("(InheritedTags is null OR InheritedTags not like @excludeInheritedTag" + excludeTagIndex + ")");
cmd.Parameters.Add(cmd, "@excludeInheritedTag" + excludeTagIndex, DbType.String).Value = "%" + excludeTag + "%";
excludeTagIndex++;
}
@@ -2210,6 +2311,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
+ if (enablePresentationUniqueKey && EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
+ {
+ pagingWhereText += " Group by PresentationUniqueKey";
+ }
+
var orderBy = GetOrderByText(query);
whereClauses.Add(string.Format("guid NOT IN (SELECT guid FROM TypedBaseItems {0}" + orderBy + " LIMIT {1})",
@@ -2221,6 +2327,34 @@ namespace MediaBrowser.Server.Implementations.Persistence
return whereClauses;
}
+ private bool EnableGroupByPresentationUniqueKey(InternalItemsQuery query)
+ {
+ if (!string.IsNullOrWhiteSpace(query.PresentationUniqueKey))
+ {
+ return false;
+ }
+
+ if (query.IncludeItemTypes.Length == 0)
+ {
+ return true;
+ }
+
+ var types = new[] {
+ typeof(Episode).Name,
+ typeof(Video).Name ,
+ typeof(Movie).Name ,
+ typeof(MusicVideo).Name ,
+ typeof(Series).Name ,
+ typeof(Season).Name };
+
+ if (types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
private static readonly Type[] KnownTypes =
{
typeof(LiveTvProgram),
@@ -2299,7 +2433,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
try
{
transaction = _connection.BeginTransaction();
-
+
foreach (var item in newValues)
{
_updateInheritedTagsCommand.GetParameter(0).Value = item.Item1;
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs
index dbceda727..40d5c9586 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs
@@ -39,11 +39,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
- public async Task Initialize()
+ public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "refreshinfo.db");
- _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
+ _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs
index 63c41c71f..33a2b1187 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs
@@ -37,11 +37,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
- public async Task Initialize()
+ public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "userdata_v2.db");
- _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
+ _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs
index 9bd7e47f3..f7ca39a54 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs
@@ -43,12 +43,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
- public async Task Initialize()
+ public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "users.db");
- _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
-
+ _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
+
string[] queries = {
"create table if not exists users (guid GUID primary key, data BLOB)",
diff --git a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs
index b932f0cac..e8d9814ec 100644
--- a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs
+++ b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs
@@ -27,11 +27,11 @@ namespace MediaBrowser.Server.Implementations.Security
_appPaths = appPaths;
}
- public async Task Initialize()
+ public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "authentication.db");
- _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
+ _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index 88f11c368..014e8babf 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -601,11 +601,9 @@ namespace MediaBrowser.Server.Implementations.Session
if (libraryItem != null)
{
- var key = libraryItem.GetUserDataKey();
-
foreach (var user in users)
{
- await OnPlaybackStart(user.Id, key, libraryItem).ConfigureAwait(false);
+ await OnPlaybackStart(user.Id, libraryItem).ConfigureAwait(false);
}
}
@@ -632,12 +630,11 @@ namespace MediaBrowser.Server.Implementations.Session
/// Called when [playback start].
/// </summary>
/// <param name="userId">The user identifier.</param>
- /// <param name="userDataKey">The user data key.</param>
/// <param name="item">The item.</param>
/// <returns>Task.</returns>
- private async Task OnPlaybackStart(Guid userId, string userDataKey, IHasUserData item)
+ private async Task OnPlaybackStart(Guid userId, IHasUserData item)
{
- var data = _userDataRepository.GetUserData(userId, userDataKey);
+ var data = _userDataRepository.GetUserData(userId, item);
data.PlayCount++;
data.LastPlayedDate = DateTime.UtcNow;
@@ -676,11 +673,9 @@ namespace MediaBrowser.Server.Implementations.Session
if (libraryItem != null)
{
- var key = libraryItem.GetUserDataKey();
-
foreach (var user in users)
{
- await OnPlaybackProgress(user, key, libraryItem, info).ConfigureAwait(false);
+ await OnPlaybackProgress(user, libraryItem, info).ConfigureAwait(false);
}
}
@@ -714,9 +709,9 @@ namespace MediaBrowser.Server.Implementations.Session
StartIdleCheckTimer();
}
- private async Task OnPlaybackProgress(User user, string userDataKey, BaseItem item, PlaybackProgressInfo info)
+ private async Task OnPlaybackProgress(User user, BaseItem item, PlaybackProgressInfo info)
{
- var data = _userDataRepository.GetUserData(user.Id, userDataKey);
+ var data = _userDataRepository.GetUserData(user.Id, item);
var positionTicks = info.PositionTicks;
@@ -811,11 +806,9 @@ namespace MediaBrowser.Server.Implementations.Session
if (libraryItem != null)
{
- var key = libraryItem.GetUserDataKey();
-
foreach (var user in users)
{
- playedToCompletion = await OnPlaybackStopped(user.Id, key, libraryItem, info.PositionTicks, info.Failed).ConfigureAwait(false);
+ playedToCompletion = await OnPlaybackStopped(user.Id, libraryItem, info.PositionTicks, info.Failed).ConfigureAwait(false);
}
}
@@ -848,13 +841,13 @@ namespace MediaBrowser.Server.Implementations.Session
await SendPlaybackStoppedNotification(session, CancellationToken.None).ConfigureAwait(false);
}
- private async Task<bool> OnPlaybackStopped(Guid userId, string userDataKey, BaseItem item, long? positionTicks, bool playbackFailed)
+ private async Task<bool> OnPlaybackStopped(Guid userId, BaseItem item, long? positionTicks, bool playbackFailed)
{
bool playedToCompletion = false;
if (!playbackFailed)
{
- var data = _userDataRepository.GetUserData(userId, userDataKey);
+ var data = _userDataRepository.GetUserData(userId, item);
if (positionTicks.HasValue)
{
diff --git a/MediaBrowser.Server.Implementations/Social/SharingRepository.cs b/MediaBrowser.Server.Implementations/Social/SharingRepository.cs
index d6d7f021a..317743eb1 100644
--- a/MediaBrowser.Server.Implementations/Social/SharingRepository.cs
+++ b/MediaBrowser.Server.Implementations/Social/SharingRepository.cs
@@ -26,11 +26,11 @@ namespace MediaBrowser.Server.Implementations.Social
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
- public async Task Initialize()
+ public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "shares.db");
- _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
+ _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
diff --git a/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs
index 70cf805cf..91abbe34c 100644
--- a/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs
+++ b/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs
@@ -49,8 +49,8 @@ namespace MediaBrowser.Server.Implementations.Sorting
private int Compare(Episode x, Episode y)
{
- var isXSpecial = (x.PhysicalSeasonNumber ?? -1) == 0;
- var isYSpecial = (y.PhysicalSeasonNumber ?? -1) == 0;
+ var isXSpecial = (x.ParentIndexNumber ?? -1) == 0;
+ var isYSpecial = (y.ParentIndexNumber ?? -1) == 0;
if (isXSpecial && isYSpecial)
{
@@ -74,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
{
// http://thetvdb.com/wiki/index.php?title=Special_Episodes
- var xSeason = x.PhysicalSeasonNumber ?? -1;
+ var xSeason = x.ParentIndexNumber ?? -1;
var ySeason = y.AirsAfterSeasonNumber ?? y.AirsBeforeSeasonNumber ?? -1;
if (xSeason != ySeason)
@@ -142,8 +142,8 @@ namespace MediaBrowser.Server.Implementations.Sorting
private int CompareEpisodes(Episode x, Episode y)
{
- var xValue = (x.PhysicalSeasonNumber ?? -1) * 1000 + (x.IndexNumber ?? -1);
- var yValue = (y.PhysicalSeasonNumber ?? -1) * 1000 + (y.IndexNumber ?? -1);
+ var xValue = (x.ParentIndexNumber ?? -1) * 1000 + (x.IndexNumber ?? -1);
+ var yValue = (y.ParentIndexNumber ?? -1) * 1000 + (y.IndexNumber ?? -1);
return xValue.CompareTo(yValue);
}
diff --git a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs
index c881591be..3edf23020 100644
--- a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs
+++ b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs
@@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
/// <returns>DateTime.</returns>
private DateTime GetDate(BaseItem x)
{
- var userdata = UserDataRepository.GetUserData(User.Id, x.GetUserDataKey());
+ var userdata = UserDataRepository.GetUserData(User, x);
if (userdata != null && userdata.LastPlayedDate.HasValue)
{
diff --git a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs
index 1bc5261b4..8b14efffc 100644
--- a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs
+++ b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs
@@ -34,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
/// <returns>DateTime.</returns>
private int GetValue(BaseItem x)
{
- var userdata = UserDataRepository.GetUserData(User.Id, x.GetUserDataKey());
+ var userdata = UserDataRepository.GetUserData(User, x);
return userdata == null ? 0 : userdata.PlayCount;
}
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
index fe1a7fb28..38edc3024 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
@@ -687,7 +687,7 @@ namespace MediaBrowser.Server.Implementations.Sync
private Task ReportOfflinePlayedItem(UserAction action)
{
var item = _libraryManager.GetItemById(action.ItemId);
- var userData = _userDataManager.GetUserData(new Guid(action.UserId), item.GetUserDataKey());
+ var userData = _userDataManager.GetUserData(action.UserId, item);
userData.LastPlayedDate = action.Date;
_userDataManager.UpdatePlayState(item, userData, action.PositionTicks);
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
index 965c081eb..6d31663b9 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
@@ -39,11 +39,11 @@ namespace MediaBrowser.Server.Implementations.Sync
_appPaths = appPaths;
}
- public async Task Initialize()
+ public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "sync14.db");
- _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
+ _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
index 3e43ebe9b..ec91dc1b7 100644
--- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
+++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
@@ -36,10 +36,25 @@ namespace MediaBrowser.Server.Implementations.TV
? new string[] { }
: new[] { request.ParentId };
+ string presentationUniqueKey = null;
+ int? limit = null;
+ if (!string.IsNullOrWhiteSpace(request.SeriesId))
+ {
+ var series = _libraryManager.GetItemById(request.SeriesId);
+
+ if (series != null)
+ {
+ presentationUniqueKey = series.PresentationUniqueKey;
+ limit = 1;
+ }
+ }
+
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Series).Name },
- SortOrder = SortOrder.Ascending
+ SortOrder = SortOrder.Ascending,
+ PresentationUniqueKey = presentationUniqueKey,
+ Limit = limit
}, parentIds).Cast<Series>();
@@ -58,10 +73,25 @@ namespace MediaBrowser.Server.Implementations.TV
throw new ArgumentException("User not found");
}
+ string presentationUniqueKey = null;
+ int? limit = null;
+ if (!string.IsNullOrWhiteSpace(request.SeriesId))
+ {
+ var series = _libraryManager.GetItemById(request.SeriesId);
+
+ if (series != null)
+ {
+ presentationUniqueKey = series.PresentationUniqueKey;
+ limit = 1;
+ }
+ }
+
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Series).Name },
- SortOrder = SortOrder.Ascending
+ SortOrder = SortOrder.Ascending,
+ PresentationUniqueKey = presentationUniqueKey,
+ Limit = limit
}, parentsFolders.Select(i => i.Id.ToString("N"))).Cast<Series>();
@@ -76,30 +106,30 @@ namespace MediaBrowser.Server.Implementations.TV
// Avoid implicitly captured closure
var currentUser = user;
- return FilterSeries(request, series)
+ return series
.AsParallel()
.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;
+ //.OrderByDescending(i =>
+ //{
+ // var episode = i.Item1;
- var seriesUserData = _userDataManager.GetUserData(user.Id, episode.Series.GetUserDataKey());
+ // var seriesUserData = _userDataManager.GetUserData(user, episode.Series);
- if (seriesUserData.IsFavorite)
- {
- return 2;
- }
+ // if (seriesUserData.IsFavorite)
+ // {
+ // return 2;
+ // }
- if (seriesUserData.Likes.HasValue)
- {
- return seriesUserData.Likes.Value ? 1 : -1;
- }
+ // if (seriesUserData.Likes.HasValue)
+ // {
+ // return seriesUserData.Likes.Value ? 1 : -1;
+ // }
- return 0;
- })
- .ThenByDescending(i => i.Item2)
+ // return 0;
+ //})
+ .OrderByDescending(i => i.Item2)
.ThenByDescending(i => i.Item1.PremiereDate ?? DateTime.MinValue)
.Select(i => i.Item1);
}
@@ -128,7 +158,7 @@ namespace MediaBrowser.Server.Implementations.TV
// Go back starting with the most recent episodes
foreach (var episode in allEpisodes)
{
- var userData = _userDataManager.GetUserData(user.Id, episode.GetUserDataKey());
+ var userData = _userDataManager.GetUserData(user, episode);
if (userData.Played)
{
@@ -142,7 +172,7 @@ namespace MediaBrowser.Server.Implementations.TV
}
else
{
- if (!episode.IsVirtualUnaired && (!episode.IsMissingEpisode || includeMissing))
+ if (!episode.IsVirtualUnaired && (includeMissing || !episode.IsMissingEpisode))
{
nextUp = episode;
}
@@ -154,24 +184,12 @@ namespace MediaBrowser.Server.Implementations.TV
return new Tuple<Episode, DateTime, bool>(nextUp, lastWatchedDate, false);
}
- var firstEpisode = allEpisodes.LastOrDefault(i => !i.IsVirtualUnaired && (!i.IsMissingEpisode || includeMissing) && !i.IsPlayed(user));
+ var firstEpisode = allEpisodes.LastOrDefault(i => !i.IsVirtualUnaired && (includeMissing || !i.IsMissingEpisode) && !i.IsPlayed(user));
// Return the first episode
return new Tuple<Episode, DateTime, bool>(firstEpisode, DateTime.MinValue, true);
}
- private IEnumerable<Series> FilterSeries(NextUpQuery request, IEnumerable<Series> items)
- {
- if (!string.IsNullOrWhiteSpace(request.SeriesId))
- {
- var id = new Guid(request.SeriesId);
-
- items = items.Where(i => i.Id == id);
- }
-
- return items;
- }
-
private QueryResult<BaseItem> GetResult(IEnumerable<BaseItem> items, int? totalRecordLimit, NextUpQuery query)
{
var itemsArray = totalRecordLimit.HasValue ? items.Take(totalRecordLimit.Value).ToArray() : items.ToArray();