mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-06 19:37:55 +02:00
commit
6ce6600a3e
4 changed files with 88 additions and 66 deletions
|
@ -694,7 +694,7 @@ namespace Emby.Server.Core
|
||||||
|
|
||||||
displayPreferencesRepo.Initialize();
|
displayPreferencesRepo.Initialize();
|
||||||
|
|
||||||
var userDataRepo = new SqliteUserDataRepository(LogManager.GetLogger("SqliteUserDataRepository"), ApplicationPaths);
|
var userDataRepo = new SqliteUserDataRepository(LogManager.GetLogger("SqliteUserDataRepository"), ApplicationPaths, FileSystemManager);
|
||||||
|
|
||||||
((UserDataManager)UserDataManager).Repository = userDataRepo;
|
((UserDataManager)UserDataManager).Repository = userDataRepo;
|
||||||
itemRepo.Initialize(userDataRepo);
|
itemRepo.Initialize(userDataRepo);
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
private string _defaultWal;
|
private string _defaultWal;
|
||||||
|
|
||||||
protected SQLiteDatabaseConnection CreateConnection(bool isReadOnly = false, Action<SQLiteDatabaseConnection> onConnect = null)
|
protected SQLiteDatabaseConnection CreateConnection(bool isReadOnly = false)
|
||||||
{
|
{
|
||||||
if (!_versionLogged)
|
if (!_versionLogged)
|
||||||
{
|
{
|
||||||
|
@ -88,9 +88,8 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
var queries = new List<string>
|
var queries = new List<string>
|
||||||
{
|
{
|
||||||
"PRAGMA default_temp_store=memory",
|
"PRAGMA temp_store = memory",
|
||||||
"pragma temp_store = memory",
|
//"PRAGMA journal_mode=WAL"
|
||||||
"PRAGMA journal_mode=WAL"
|
|
||||||
//"PRAGMA cache size=-10000"
|
//"PRAGMA cache size=-10000"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -108,18 +107,19 @@ namespace Emby.Server.Implementations.Data
|
||||||
//Logger.Info("synchronous: " + db.Query("PRAGMA synchronous").SelectScalarString().First());
|
//Logger.Info("synchronous: " + db.Query("PRAGMA synchronous").SelectScalarString().First());
|
||||||
//Logger.Info("temp_store: " + db.Query("PRAGMA temp_store").SelectScalarString().First());
|
//Logger.Info("temp_store: " + db.Query("PRAGMA temp_store").SelectScalarString().First());
|
||||||
|
|
||||||
//if (!string.Equals(_defaultWal, "wal", StringComparison.OrdinalIgnoreCase) || onConnect != null)
|
if (!string.Equals(_defaultWal, "wal", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
queries.Add("PRAGMA journal_mode=WAL");
|
||||||
|
|
||||||
using (WriteLock.Write())
|
using (WriteLock.Write())
|
||||||
{
|
{
|
||||||
db.ExecuteAll(string.Join(";", queries.ToArray()));
|
db.ExecuteAll(string.Join(";", queries.ToArray()));
|
||||||
|
|
||||||
if (onConnect != null)
|
|
||||||
{
|
|
||||||
onConnect(db);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
db.ExecuteAll(string.Join(";", queries.ToArray()));
|
||||||
|
}
|
||||||
|
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
|
@ -357,23 +357,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
//await Vacuum(_connection).ConfigureAwait(false);
|
//await Vacuum(_connection).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private SQLiteDatabaseConnection CreateConnection(bool readOnly, bool attachUserdata)
|
|
||||||
{
|
|
||||||
Action<SQLiteDatabaseConnection> onConnect = null;
|
|
||||||
|
|
||||||
if (attachUserdata)
|
|
||||||
{
|
|
||||||
onConnect =
|
|
||||||
c => SqliteExtensions.Attach(c, Path.Combine(_config.ApplicationPaths.DataPath, "userdata_v2.db"),
|
|
||||||
"UserDataDb");
|
|
||||||
}
|
|
||||||
|
|
||||||
var conn = CreateConnection(readOnly, onConnect);
|
|
||||||
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly string[] _retriveItemColumns =
|
private readonly string[] _retriveItemColumns =
|
||||||
{
|
{
|
||||||
"type",
|
"type",
|
||||||
|
@ -2265,13 +2248,13 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
if (EnableJoinUserData(query))
|
if (EnableJoinUserData(query))
|
||||||
{
|
{
|
||||||
list.Add("UserDataDb.UserData.UserId");
|
list.Add("UserData.UserId");
|
||||||
list.Add("UserDataDb.UserData.lastPlayedDate");
|
list.Add("UserData.lastPlayedDate");
|
||||||
list.Add("UserDataDb.UserData.playbackPositionTicks");
|
list.Add("UserData.playbackPositionTicks");
|
||||||
list.Add("UserDataDb.UserData.playcount");
|
list.Add("UserData.playcount");
|
||||||
list.Add("UserDataDb.UserData.isFavorite");
|
list.Add("UserData.isFavorite");
|
||||||
list.Add("UserDataDb.UserData.played");
|
list.Add("UserData.played");
|
||||||
list.Add("UserDataDb.UserData.rating");
|
list.Add("UserData.rating");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.SimilarTo != null)
|
if (query.SimilarTo != null)
|
||||||
|
@ -2336,7 +2319,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
return " left join UserDataDb.UserData on UserDataKey=UserDataDb.UserData.Key And (UserId=@UserId)";
|
return " left join UserData on UserDataKey=UserData.Key And (UserId=@UserId)";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetGroupBy(InternalItemsQuery query)
|
private string GetGroupBy(InternalItemsQuery query)
|
||||||
|
@ -2412,7 +2395,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var connection = CreateConnection(true, EnableJoinUserData(query)))
|
using (var connection = CreateConnection(true))
|
||||||
{
|
{
|
||||||
using (WriteLock.Read())
|
using (WriteLock.Read())
|
||||||
{
|
{
|
||||||
|
@ -2581,7 +2564,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var connection = CreateConnection(true, EnableJoinUserData(query)))
|
using (var connection = CreateConnection(true))
|
||||||
{
|
{
|
||||||
using (WriteLock.Read())
|
using (WriteLock.Read())
|
||||||
{
|
{
|
||||||
|
@ -2811,7 +2794,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
var list = new List<Guid>();
|
var list = new List<Guid>();
|
||||||
|
|
||||||
using (var connection = CreateConnection(true, EnableJoinUserData(query)))
|
using (var connection = CreateConnection(true))
|
||||||
{
|
{
|
||||||
using (WriteLock.Read())
|
using (WriteLock.Read())
|
||||||
{
|
{
|
||||||
|
@ -2882,7 +2865,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
var list = new List<Tuple<Guid, string>>();
|
var list = new List<Tuple<Guid, string>>();
|
||||||
|
|
||||||
using (var connection = CreateConnection(true, EnableJoinUserData(query)))
|
using (var connection = CreateConnection(true))
|
||||||
{
|
{
|
||||||
using (WriteLock.Read())
|
using (WriteLock.Read())
|
||||||
{
|
{
|
||||||
|
@ -2972,7 +2955,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
var list = new List<Guid>();
|
var list = new List<Guid>();
|
||||||
|
|
||||||
using (var connection = CreateConnection(true, EnableJoinUserData(query)))
|
using (var connection = CreateConnection(true))
|
||||||
{
|
{
|
||||||
using (WriteLock.Read())
|
using (WriteLock.Read())
|
||||||
{
|
{
|
||||||
|
@ -4880,7 +4863,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
var list = new List<Tuple<BaseItem, ItemCounts>>();
|
var list = new List<Tuple<BaseItem, ItemCounts>>();
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
|
||||||
using (var connection = CreateConnection(true, EnableJoinUserData(query)))
|
using (var connection = CreateConnection(true))
|
||||||
{
|
{
|
||||||
using (WriteLock.Read())
|
using (WriteLock.Read())
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using SQLitePCL.pretty;
|
using SQLitePCL.pretty;
|
||||||
|
|
||||||
|
@ -14,10 +15,15 @@ namespace Emby.Server.Implementations.Data
|
||||||
{
|
{
|
||||||
public class SqliteUserDataRepository : BaseSqliteRepository, IUserDataRepository
|
public class SqliteUserDataRepository : BaseSqliteRepository, IUserDataRepository
|
||||||
{
|
{
|
||||||
public SqliteUserDataRepository(ILogger logger, IApplicationPaths appPaths)
|
private readonly string _importFile;
|
||||||
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
|
public SqliteUserDataRepository(ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem)
|
||||||
: base(logger)
|
: base(logger)
|
||||||
{
|
{
|
||||||
DbFilePath = Path.Combine(appPaths.DataPath, "userdata_v2.db");
|
_fileSystem = fileSystem;
|
||||||
|
DbFilePath = Path.Combine(appPaths.DataPath, "library.db");
|
||||||
|
_importFile = Path.Combine(appPaths.DataPath, "userdata_v2.db");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -43,32 +49,24 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
using (var connection = CreateConnection())
|
using (var connection = CreateConnection())
|
||||||
{
|
{
|
||||||
connection.ExecuteAll(string.Join(";", new[]
|
|
||||||
{
|
|
||||||
"PRAGMA page_size=4096",
|
|
||||||
"pragma default_temp_store = memory",
|
|
||||||
"pragma temp_store = memory"
|
|
||||||
}));
|
|
||||||
|
|
||||||
string[] queries = {
|
string[] queries = {
|
||||||
|
|
||||||
"PRAGMA locking_mode=NORMAL",
|
|
||||||
|
|
||||||
"create table if not exists UserDataDb.userdata (key nvarchar, userId GUID, rating float null, played bit, playCount int, isFavorite bit, playbackPositionTicks bigint, lastPlayedDate datetime null)",
|
|
||||||
|
|
||||||
"drop index if exists UserDataDb.idx_userdata",
|
|
||||||
"drop index if exists UserDataDb.idx_userdata1",
|
|
||||||
"drop index if exists UserDataDb.idx_userdata2",
|
|
||||||
"drop index if exists UserDataDb.userdataindex1",
|
|
||||||
|
|
||||||
"create unique index if not exists UserDataDb.userdataindex on userdata (key, userId)",
|
|
||||||
"create index if not exists UserDataDb.userdataindex2 on userdata (key, userId, played)",
|
|
||||||
"create index if not exists UserDataDb.userdataindex3 on userdata (key, userId, playbackPositionTicks)",
|
|
||||||
"create index if not exists UserDataDb.userdataindex4 on userdata (key, userId, isFavorite)",
|
|
||||||
|
|
||||||
//pragmas
|
|
||||||
"pragma temp_store = memory",
|
"pragma temp_store = memory",
|
||||||
|
|
||||||
|
"create table if not exists userdata (key nvarchar, userId GUID, rating float null, played bit, playCount int, isFavorite bit, playbackPositionTicks bigint, lastPlayedDate datetime null)",
|
||||||
|
|
||||||
|
"create table if not exists DataSettings (IsUserDataImported bit)",
|
||||||
|
|
||||||
|
"drop index if exists idx_userdata",
|
||||||
|
"drop index if exists idx_userdata1",
|
||||||
|
"drop index if exists idx_userdata2",
|
||||||
|
"drop index if exists userdataindex1",
|
||||||
|
|
||||||
|
"create unique index if not exists userdataindex on userdata (key, userId)",
|
||||||
|
"create index if not exists userdataindex2 on userdata (key, userId, played)",
|
||||||
|
"create index if not exists userdataindex3 on userdata (key, userId, playbackPositionTicks)",
|
||||||
|
"create index if not exists userdataindex4 on userdata (key, userId, isFavorite)",
|
||||||
|
|
||||||
"pragma shrink_memory"
|
"pragma shrink_memory"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,9 +79,50 @@ namespace Emby.Server.Implementations.Data
|
||||||
AddColumn(db, "userdata", "AudioStreamIndex", "int", existingColumnNames);
|
AddColumn(db, "userdata", "AudioStreamIndex", "int", existingColumnNames);
|
||||||
AddColumn(db, "userdata", "SubtitleStreamIndex", "int", existingColumnNames);
|
AddColumn(db, "userdata", "SubtitleStreamIndex", "int", existingColumnNames);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ImportUserDataIfNeeded(connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ImportUserDataIfNeeded(IDatabaseConnection connection)
|
||||||
|
{
|
||||||
|
if (!_fileSystem.FileExists(_importFile))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileToImport = _importFile;
|
||||||
|
var isImported = connection.Query("select IsUserDataImported from DataSettings").SelectScalarBool().FirstOrDefault();
|
||||||
|
|
||||||
|
if (isImported)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportUserData(connection, fileToImport);
|
||||||
|
|
||||||
|
connection.RunInTransaction(db =>
|
||||||
|
{
|
||||||
|
using (var statement = db.PrepareStatement("replace into DataSettings (IsUserDataImported) values (@IsUserDataImported)"))
|
||||||
|
{
|
||||||
|
statement.TryBind("@IsUserDataImported", true);
|
||||||
|
statement.MoveNext();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ImportUserData(IDatabaseConnection connection, string file)
|
||||||
|
{
|
||||||
|
SqliteExtensions.Attach(connection, file, "UserDataBackup");
|
||||||
|
|
||||||
|
var columns = "key, userId, rating, played, playCount, isFavorite, playbackPositionTicks, lastPlayedDate, AudioStreamIndex, SubtitleStreamIndex";
|
||||||
|
|
||||||
|
connection.RunInTransaction(db =>
|
||||||
|
{
|
||||||
|
db.Execute("REPLACE INTO userdata(" + columns + ") SELECT " + columns + " FROM UserDataBackup.userdata;");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the user data.
|
/// Saves the user data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
Loading…
Reference in a new issue