update item list page
This commit is contained in:
parent
a2c371ec60
commit
9ae7625d13
|
@ -98,7 +98,9 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public bool? IsCurrentSchema { get; set; }
|
public bool? IsCurrentSchema { get; set; }
|
||||||
public bool? HasDeadParentId { get; set; }
|
public bool? HasDeadParentId { get; set; }
|
||||||
|
public bool? IsOffline { get; set; }
|
||||||
|
public LocationType? LocationType { get; set; }
|
||||||
|
|
||||||
public InternalItemsQuery()
|
public InternalItemsQuery()
|
||||||
{
|
{
|
||||||
Tags = new string[] { };
|
Tags = new string[] { };
|
||||||
|
|
|
@ -169,6 +169,13 @@ namespace MediaBrowser.Controller.Persistence
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <returns>List<System.String>.</returns>
|
/// <returns>List<System.String>.</returns>
|
||||||
List<string> GetPeopleNames(InternalPeopleQuery query);
|
List<string> GetPeopleNames(InternalPeopleQuery query);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the item ids with path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query.</param>
|
||||||
|
/// <returns>QueryResult<Tuple<Guid, System.String>>.</returns>
|
||||||
|
QueryResult<Tuple<Guid, string>> GetItemIdsWithPath(InternalItemsQuery query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
using MediaBrowser.Common.Progress;
|
using MediaBrowser.Common.IO;
|
||||||
|
using MediaBrowser.Common.Progress;
|
||||||
using MediaBrowser.Common.ScheduledTasks;
|
using MediaBrowser.Common.ScheduledTasks;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.Persistence
|
namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
{
|
{
|
||||||
|
@ -19,13 +22,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
private readonly IItemRepository _itemRepo;
|
private readonly IItemRepository _itemRepo;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config)
|
public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_itemRepo = itemRepo;
|
_itemRepo = itemRepo;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
_fileSystem = fileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
|
@ -46,15 +51,18 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
|
public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
|
||||||
{
|
{
|
||||||
var innerProgress = new ActionableProgress<double>();
|
var innerProgress = new ActionableProgress<double>();
|
||||||
innerProgress.RegisterAction(p => progress.Report(.95 * p));
|
innerProgress.RegisterAction(p => progress.Report(.4 * p));
|
||||||
|
|
||||||
await UpdateToLatestSchema(cancellationToken, innerProgress).ConfigureAwait(false);
|
await UpdateToLatestSchema(cancellationToken, innerProgress).ConfigureAwait(false);
|
||||||
|
|
||||||
innerProgress = new ActionableProgress<double>();
|
innerProgress = new ActionableProgress<double>();
|
||||||
innerProgress.RegisterAction(p => progress.Report(95 + (.05 * p)));
|
innerProgress.RegisterAction(p => progress.Report(40 + (.05 * p)));
|
||||||
|
|
||||||
await CleanDeadItems(cancellationToken, innerProgress).ConfigureAwait(false);
|
await CleanDeadItems(cancellationToken, innerProgress).ConfigureAwait(false);
|
||||||
|
progress.Report(45);
|
||||||
|
|
||||||
|
innerProgress = new ActionableProgress<double>();
|
||||||
|
innerProgress.RegisterAction(p => progress.Report(45 + (.55 * p)));
|
||||||
|
await CleanDeletedItems(cancellationToken, innerProgress).ConfigureAwait(false);
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,11 +161,60 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task CleanDeletedItems(CancellationToken cancellationToken, IProgress<double> progress)
|
||||||
|
{
|
||||||
|
var result = _itemRepo.GetItemIdsWithPath(new InternalItemsQuery
|
||||||
|
{
|
||||||
|
IsOffline = false,
|
||||||
|
LocationType = LocationType.FileSystem,
|
||||||
|
//Limit = limit,
|
||||||
|
|
||||||
|
// These have their own cleanup routines
|
||||||
|
ExcludeItemTypes = new[] { typeof(Person).Name, typeof(Genre).Name, typeof(MusicGenre).Name, typeof(GameGenre).Name, typeof(Studio).Name, typeof(Year).Name }
|
||||||
|
});
|
||||||
|
|
||||||
|
var numComplete = 0;
|
||||||
|
var numItems = result.Items.Length;
|
||||||
|
|
||||||
|
foreach (var item in result.Items)
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
var path = item.Item2;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_fileSystem.FileExists(path) && !_fileSystem.DirectoryExists(path))
|
||||||
|
{
|
||||||
|
var libraryItem = _libraryManager.GetItemById(item.Item1);
|
||||||
|
|
||||||
|
await _libraryManager.DeleteItem(libraryItem, new DeleteOptions
|
||||||
|
{
|
||||||
|
DeleteFileLocation = false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error in CleanDeletedItems. File {0}", ex, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
numComplete++;
|
||||||
|
double percent = numComplete;
|
||||||
|
percent /= numItems;
|
||||||
|
progress.Report(percent * 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<ITaskTrigger> GetDefaultTriggers()
|
public IEnumerable<ITaskTrigger> GetDefaultTriggers()
|
||||||
{
|
{
|
||||||
return new ITaskTrigger[]
|
return new ITaskTrigger[]
|
||||||
{
|
{
|
||||||
new IntervalTrigger{ Interval = TimeSpan.FromDays(1)}
|
new IntervalTrigger{ Interval = TimeSpan.FromDays(7)}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
private IDbCommand _deletePeopleCommand;
|
private IDbCommand _deletePeopleCommand;
|
||||||
private IDbCommand _savePersonCommand;
|
private IDbCommand _savePersonCommand;
|
||||||
|
|
||||||
private const int LatestSchemaVersion = 6;
|
private const int LatestSchemaVersion = 7;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
|
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
|
||||||
|
@ -175,6 +175,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
|
|
||||||
_connection.AddColumn(_logger, "TypedBaseItems", "ForcedSortName", "Text");
|
_connection.AddColumn(_logger, "TypedBaseItems", "ForcedSortName", "Text");
|
||||||
_connection.AddColumn(_logger, "TypedBaseItems", "IsOffline", "BIT");
|
_connection.AddColumn(_logger, "TypedBaseItems", "IsOffline", "BIT");
|
||||||
|
_connection.AddColumn(_logger, "TypedBaseItems", "LocationType", "Text");
|
||||||
|
|
||||||
PrepareStatements();
|
PrepareStatements();
|
||||||
|
|
||||||
|
@ -245,7 +246,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
"DateCreated",
|
"DateCreated",
|
||||||
"DateModified",
|
"DateModified",
|
||||||
"ForcedSortName",
|
"ForcedSortName",
|
||||||
"IsOffline"
|
"IsOffline",
|
||||||
|
"LocationType"
|
||||||
};
|
};
|
||||||
_saveItemCommand = _connection.CreateCommand();
|
_saveItemCommand = _connection.CreateCommand();
|
||||||
_saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
|
_saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
|
||||||
|
@ -415,6 +417,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
|
|
||||||
_saveItemCommand.GetParameter(index++).Value = item.ForcedSortName;
|
_saveItemCommand.GetParameter(index++).Value = item.ForcedSortName;
|
||||||
_saveItemCommand.GetParameter(index++).Value = item.IsOffline;
|
_saveItemCommand.GetParameter(index++).Value = item.IsOffline;
|
||||||
|
_saveItemCommand.GetParameter(index++).Value = item.LocationType.ToString();
|
||||||
|
|
||||||
_saveItemCommand.Transaction = transaction;
|
_saveItemCommand.Transaction = transaction;
|
||||||
|
|
||||||
|
@ -617,7 +620,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
public Task SaveCriticReviews(Guid itemId, IEnumerable<ItemReview> criticReviews)
|
public Task SaveCriticReviews(Guid itemId, IEnumerable<ItemReview> criticReviews)
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(_criticReviewsPath);
|
Directory.CreateDirectory(_criticReviewsPath);
|
||||||
|
|
||||||
var path = Path.Combine(_criticReviewsPath, itemId + ".json");
|
var path = Path.Combine(_criticReviewsPath, itemId + ".json");
|
||||||
|
|
||||||
|
@ -950,6 +953,75 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryResult<Tuple<Guid, string>> GetItemIdsWithPath(InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
if (query == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("query");
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckDisposed();
|
||||||
|
|
||||||
|
using (var cmd = _connection.CreateCommand())
|
||||||
|
{
|
||||||
|
cmd.CommandText = "select guid,path from TypedBaseItems";
|
||||||
|
|
||||||
|
var whereClauses = GetWhereClauses(query, cmd, false);
|
||||||
|
|
||||||
|
var whereTextWithoutPaging = whereClauses.Count == 0 ?
|
||||||
|
string.Empty :
|
||||||
|
" where " + string.Join(" AND ", whereClauses.ToArray());
|
||||||
|
|
||||||
|
whereClauses = GetWhereClauses(query, cmd, true);
|
||||||
|
|
||||||
|
var whereText = whereClauses.Count == 0 ?
|
||||||
|
string.Empty :
|
||||||
|
" where " + string.Join(" AND ", whereClauses.ToArray());
|
||||||
|
|
||||||
|
cmd.CommandText += whereText;
|
||||||
|
|
||||||
|
cmd.CommandText += GetOrderByText(query);
|
||||||
|
|
||||||
|
if (query.Limit.HasValue)
|
||||||
|
{
|
||||||
|
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
|
||||||
|
|
||||||
|
var list = new List<Tuple<Guid, string>>();
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
_logger.Debug(cmd.CommandText);
|
||||||
|
|
||||||
|
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
var id = reader.GetGuid(0);
|
||||||
|
string path = null;
|
||||||
|
|
||||||
|
if (!reader.IsDBNull(1))
|
||||||
|
{
|
||||||
|
path = reader.GetString(1);
|
||||||
|
}
|
||||||
|
list.Add(new Tuple<Guid, string>(id, path));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.NextResult() && reader.Read())
|
||||||
|
{
|
||||||
|
count = reader.GetInt32(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryResult<Tuple<Guid, string>>()
|
||||||
|
{
|
||||||
|
Items = list.ToArray(),
|
||||||
|
TotalRecordCount = count
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public QueryResult<Guid> GetItemIds(InternalItemsQuery query)
|
public QueryResult<Guid> GetItemIds(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
if (query == null)
|
if (query == null)
|
||||||
|
@ -1028,6 +1100,16 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
}
|
}
|
||||||
cmd.Parameters.Add(cmd, "@SchemaVersion", DbType.Int32).Value = LatestSchemaVersion;
|
cmd.Parameters.Add(cmd, "@SchemaVersion", DbType.Int32).Value = LatestSchemaVersion;
|
||||||
}
|
}
|
||||||
|
if (query.IsOffline.HasValue)
|
||||||
|
{
|
||||||
|
whereClauses.Add("IsOffline=@IsOffline");
|
||||||
|
cmd.Parameters.Add(cmd, "@IsOffline", DbType.Boolean).Value = query.IsOffline;
|
||||||
|
}
|
||||||
|
if (query.LocationType.HasValue)
|
||||||
|
{
|
||||||
|
whereClauses.Add("LocationType=@LocationType");
|
||||||
|
cmd.Parameters.Add(cmd, "@LocationType", DbType.String).Value = query.LocationType.Value;
|
||||||
|
}
|
||||||
if (query.IsMovie.HasValue)
|
if (query.IsMovie.HasValue)
|
||||||
{
|
{
|
||||||
whereClauses.Add("IsMovie=@IsMovie");
|
whereClauses.Add("IsMovie=@IsMovie");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user