1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-09-19 16:01:46 +02:00

Fixed: A lot of memory issues, such as IDisposable leakage and leaking all the media covers. (#3227)

Thanks again to @Taloth
This commit is contained in:
Leonardo Galli 2019-01-10 08:36:34 +01:00 committed by GitHub
commit 02eb30b8ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 515 additions and 386 deletions

2
.gitignore vendored
View File

@ -104,7 +104,7 @@ _TeamCity*
# Radarr # Radarr
Backups/ Backups/
logs/ logs/
MediaCover/ #MediaCover/
UpdateLogs/ UpdateLogs/
xdg/ xdg/
config.xml config.xml

0
debian/rules vendored Executable file → Normal file
View File

View File

@ -941,21 +941,21 @@ protected virtual void Dispose(bool disposing)
{ {
if (disposing) if (disposing)
{ {
if (Command.Transaction != null) if (_command != null)
{ {
Command.Transaction.Dispose(); if (_command.Transaction != null)
Command.Transaction = null; {
_command.Transaction.Dispose();
_command.Transaction = null;
} }
if (Command.Connection != null) if (_command.Connection != null)
{ {
Command.Connection.Dispose(); _command.Connection.Dispose();
Command.Connection = null; _command.Connection = null;
} }
if (Command != null) _command.Dispose();
{
Command.Dispose();
_command = null; _command = null;
} }
} }

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Data.Common; using System.Data.Common;
@ -91,9 +91,11 @@ private void PrepareLazyLoadedProperties(object ent)
Type entType = ent.GetType(); Type entType = ent.GetType();
if (_repos.Relationships.ContainsKey(entType)) if (_repos.Relationships.ContainsKey(entType))
{ {
var provider = _db.ProviderFactory;
var connectionString = _db.ConnectionString;
Func<IDataMapper> dbCreate = () => Func<IDataMapper> dbCreate = () =>
{ {
var db = new DataMapper(_db.ProviderFactory, _db.ConnectionString); var db = new DataMapper(provider, connectionString);
db.SqlMode = SqlModes.Text; db.SqlMode = SqlModes.Text;
return db; return db;
}; };

View File

@ -123,27 +123,6 @@ public bool CanUseGDIPlus()
} }
} }
public bool IsValidGDIPlusImage(string filename)
{
if (!CanUseGDIPlus())
{
return true;
}
try
{
using (var bmp = new Bitmap(filename))
{
}
return true;
}
catch (Exception ex)
{
Logger.Debug(ex, "Corrupted image found at: {0}.", filename);
return false;
}
}
public bool FolderWritable(string path) public bool FolderWritable(string path)
{ {
Ensure.That(path, () => path).IsValidPath(); Ensure.That(path, () => path).IsValidPath();

View File

@ -20,7 +20,6 @@ public interface IDiskProvider
bool FileExists(string path); bool FileExists(string path);
bool FileExists(string path, StringComparison stringComparison); bool FileExists(string path, StringComparison stringComparison);
bool CanUseGDIPlus(); bool CanUseGDIPlus();
bool IsValidGDIPlusImage(string path);
bool FolderWritable(string path); bool FolderWritable(string path);
string[] GetDirectories(string path); string[] GetDirectories(string path);
string[] GetFiles(string path, SearchOption searchOption); string[] GetFiles(string path, SearchOption searchOption);

View File

@ -66,9 +66,9 @@ public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
lock (CurlGlobalHandle.Instance) lock (CurlGlobalHandle.Instance)
{ {
Stream responseStream = new MemoryStream(); using (Stream responseStream = new MemoryStream())
Stream headerStream = new MemoryStream(); using (Stream headerStream = new MemoryStream())
{
using (var curlEasy = new CurlEasy()) using (var curlEasy = new CurlEasy())
{ {
curlEasy.AutoReferer = false; curlEasy.AutoReferer = false;
@ -158,6 +158,7 @@ public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
} }
} }
} }
}
private void AddProxy(CurlEasy curlEasy, HttpRequest request) private void AddProxy(CurlEasy curlEasy, HttpRequest request)
{ {
@ -259,6 +260,7 @@ private string FixSetCookieHeader(string setCookie)
private byte[] ProcessResponseStream(HttpRequest request, Stream responseStream, WebHeaderCollection webHeaderCollection) private byte[] ProcessResponseStream(HttpRequest request, Stream responseStream, WebHeaderCollection webHeaderCollection)
{ {
byte[] bytes = null;
responseStream.Position = 0; responseStream.Position = 0;
if (responseStream.Length != 0) if (responseStream.Length != 0)
@ -268,21 +270,27 @@ private byte[] ProcessResponseStream(HttpRequest request, Stream responseStream,
{ {
if (encoding.IndexOf("gzip") != -1) if (encoding.IndexOf("gzip") != -1)
{ {
responseStream = new GZipStream(responseStream, CompressionMode.Decompress); using (var zipStream = new GZipStream(responseStream, CompressionMode.Decompress))
{
bytes = zipStream.ToBytes();
}
webHeaderCollection.Remove("Content-Encoding"); webHeaderCollection.Remove("Content-Encoding");
} }
else if (encoding.IndexOf("deflate") != -1) else if (encoding.IndexOf("deflate") != -1)
{ {
responseStream = new DeflateStream(responseStream, CompressionMode.Decompress); using (var deflateStream = new DeflateStream(responseStream, CompressionMode.Decompress))
{
bytes = deflateStream.ToBytes();
}
webHeaderCollection.Remove("Content-Encoding"); webHeaderCollection.Remove("Content-Encoding");
} }
} }
} }
return responseStream.ToBytes(); if (bytes == null) bytes = responseStream.ToBytes();
return bytes;
} }
} }

View File

@ -20,7 +20,11 @@ public ManagedHttpDispatcher(IHttpProxySettingsProvider proxySettingsProvider, I
public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies) public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
{ {
var webRequest = (HttpWebRequest)WebRequest.Create((Uri)request.Url); HttpWebResponse httpWebResponse = null;
HttpWebRequest webRequest = null;
try
{
webRequest = (HttpWebRequest) WebRequest.Create((Uri) request.Url);
// Deflate is not a standard and could break depending on implementation. // Deflate is not a standard and could break depending on implementation.
// we should just stick with the more compatible Gzip // we should just stick with the more compatible Gzip
@ -28,14 +32,16 @@ public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
webRequest.AutomaticDecompression = DecompressionMethods.GZip; webRequest.AutomaticDecompression = DecompressionMethods.GZip;
webRequest.Method = request.Method.ToString(); webRequest.Method = request.Method.ToString();
webRequest.UserAgent = request.UseSimplifiedUserAgent ? UserAgentBuilder.UserAgentSimplified : UserAgentBuilder.UserAgent; webRequest.UserAgent = request.UseSimplifiedUserAgent
? UserAgentBuilder.UserAgentSimplified
: UserAgentBuilder.UserAgent;
webRequest.KeepAlive = request.ConnectionKeepAlive; webRequest.KeepAlive = request.ConnectionKeepAlive;
webRequest.AllowAutoRedirect = false; webRequest.AllowAutoRedirect = false;
webRequest.CookieContainer = cookies; webRequest.CookieContainer = cookies;
if (request.RequestTimeout != TimeSpan.Zero) if (request.RequestTimeout != TimeSpan.Zero)
{ {
webRequest.Timeout = (int)Math.Ceiling(request.RequestTimeout.TotalMilliseconds); webRequest.Timeout = (int) Math.Ceiling(request.RequestTimeout.TotalMilliseconds);
} }
AddProxy(webRequest, request); AddProxy(webRequest, request);
@ -54,11 +60,9 @@ public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
} }
} }
HttpWebResponse httpWebResponse;
try try
{ {
httpWebResponse = (HttpWebResponse)webRequest.GetResponse(); httpWebResponse = (HttpWebResponse) webRequest.GetResponse();
} }
catch (WebException e) catch (WebException e)
{ {
@ -67,7 +71,7 @@ public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
SecurityProtocolPolicy.DisableTls12(); SecurityProtocolPolicy.DisableTls12();
} }
httpWebResponse = (HttpWebResponse)e.Response; httpWebResponse = (HttpWebResponse) e.Response;
if (httpWebResponse == null) if (httpWebResponse == null)
{ {
@ -85,7 +89,15 @@ public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
} }
} }
return new HttpResponse(request, new HttpHeader(httpWebResponse.Headers), data, httpWebResponse.StatusCode); return new HttpResponse(request, new HttpHeader(httpWebResponse.Headers), data,
httpWebResponse.StatusCode);
}
finally
{
webRequest = null;
(httpWebResponse as IDisposable)?.Dispose();
httpWebResponse = null;
}
} }
protected virtual void AddProxy(HttpWebRequest webRequest, HttpRequest request) protected virtual void AddProxy(HttpWebRequest webRequest, HttpRequest request)

View File

@ -226,12 +226,14 @@ public void DownloadFile(string url, string fileName)
_logger.Debug("Downloading [{0}] to [{1}]", url, fileName); _logger.Debug("Downloading [{0}] to [{1}]", url, fileName);
var stopWatch = Stopwatch.StartNew(); var stopWatch = Stopwatch.StartNew();
var webClient = new GZipWebClient(); using (var webClient = new GZipWebClient())
{
webClient.Headers.Add(HttpRequestHeader.UserAgent, UserAgentBuilder.UserAgent); webClient.Headers.Add(HttpRequestHeader.UserAgent, UserAgentBuilder.UserAgent);
webClient.DownloadFile(url, fileName); webClient.DownloadFile(url, fileName);
stopWatch.Stop(); stopWatch.Stop();
_logger.Debug("Downloading Completed. took {0:0}s", stopWatch.Elapsed.Seconds); _logger.Debug("Downloading Completed. took {0:0}s", stopWatch.Elapsed.Seconds);
} }
}
catch (WebException e) catch (WebException e)
{ {
_logger.Warn("Failed to get response from: {0} {1}", url, e.Message); _logger.Warn("Failed to get response from: {0} {1}", url, e.Message);

View File

@ -45,6 +45,8 @@ private static void HandleAppDomainException(object sender, UnhandledExceptionEv
} }
} }
Console.WriteLine(exception.StackTrace);
Console.WriteLine("EPIC FAIL: {0}", exception); Console.WriteLine("EPIC FAIL: {0}", exception);
Logger.Fatal(exception, "EPIC FAIL: " + exception.Message); Logger.Fatal(exception, "EPIC FAIL: " + exception.Message);
} }

View File

@ -37,15 +37,6 @@ private void GivenExistingFileSize(long bytes)
} }
private void GivenImageFileCorrupt(bool corrupt)
{
GivenFileExistsOnDisk();
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.IsValidGDIPlusImage(It.IsAny<string>()))
.Returns(!corrupt);
}
[Test] [Test]
public void should_return_false_if_file_not_exists() public void should_return_false_if_file_not_exists()
{ {
@ -61,21 +52,11 @@ public void should_return_false_if_file_exists_but_diffrent_size()
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeFalse(); Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeFalse();
} }
[Test]
public void should_return_false_if_file_exists_and_same_size_and_corrupt()
{
GivenExistingFileSize(100);
GivenImageFileCorrupt(true);
_httpResponse.Headers.ContentLength = 100;
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeFalse();
}
[Test] [Test]
public void should_return_true_if_file_exists_and_same_size_and_not_corrupt() public void should_return_true_if_file_exists_and_same_size_and_not_corrupt()
{ {
GivenExistingFileSize(100); GivenExistingFileSize(100);
GivenImageFileCorrupt(false);
_httpResponse.Headers.ContentLength = 100; _httpResponse.Headers.ContentLength = 100;
Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeTrue(); Subject.AlreadyExists("http://url", "c:\\file.exe").Should().BeTrue();
} }

View File

@ -8,6 +8,7 @@
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.MediaCover; using NzbDrone.Core.MediaCover;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Events; using NzbDrone.Core.Movies.Events;
@ -28,6 +29,18 @@ public void Setup()
.With(v => v.Id = 2) .With(v => v.Id = 2)
.With(v => v.Images = new List<MediaCover.MediaCover> { new MediaCover.MediaCover(MediaCoverTypes.Poster, "") }) .With(v => v.Images = new List<MediaCover.MediaCover> { new MediaCover.MediaCover(MediaCoverTypes.Poster, "") })
.Build(); .Build();
Mocker.GetMock<IMovieService>().Setup(m => m.GetMovie(It.Is<int>(id => id == _movie.Id))).Returns(_movie);
}
private void ExecuteAndVerifyCommand(Movie movie)
{
Subject.HandleAsync(new MovieUpdatedEvent(movie));
Mocker.GetMock<IManageCommandQueue>()
.Verify(v => v.Push(It.Is<EnsureMediaCoversCommand>(c => c.MovieId == movie.Id), It.IsAny<CommandPriority>(), It.IsAny<CommandTrigger>()), Times.Once());
Subject.Execute(new EnsureMediaCoversCommand(movie.Id));
} }
[Test] [Test]
@ -76,7 +89,7 @@ public void should_resize_covers_if_main_downloaded()
.Setup(v => v.FileExists(It.IsAny<string>())) .Setup(v => v.FileExists(It.IsAny<string>()))
.Returns(true); .Returns(true);
Subject.HandleAsync(new MovieUpdatedEvent(_movie)); ExecuteAndVerifyCommand(_movie);
Mocker.GetMock<IImageResizer>() Mocker.GetMock<IImageResizer>()
.Verify(v => v.Resize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()), Times.Exactly(2)); .Verify(v => v.Resize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()), Times.Exactly(2));
@ -93,7 +106,7 @@ public void should_resize_covers_if_missing()
.Setup(v => v.FileExists(It.IsAny<string>())) .Setup(v => v.FileExists(It.IsAny<string>()))
.Returns(false); .Returns(false);
Subject.HandleAsync(new MovieUpdatedEvent(_movie)); ExecuteAndVerifyCommand(_movie);
Mocker.GetMock<IImageResizer>() Mocker.GetMock<IImageResizer>()
.Verify(v => v.Resize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()), Times.Exactly(2)); .Verify(v => v.Resize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()), Times.Exactly(2));
@ -114,7 +127,7 @@ public void should_not_resize_covers_if_exists()
.Setup(v => v.GetFileSize(It.IsAny<string>())) .Setup(v => v.GetFileSize(It.IsAny<string>()))
.Returns(1000); .Returns(1000);
Subject.HandleAsync(new MovieUpdatedEvent(_movie)); ExecuteAndVerifyCommand(_movie);
Mocker.GetMock<IImageResizer>() Mocker.GetMock<IImageResizer>()
.Verify(v => v.Resize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()), Times.Never()); .Verify(v => v.Resize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()), Times.Never());
@ -135,7 +148,7 @@ public void should_resize_covers_if_existing_is_empty()
.Setup(v => v.GetFileSize(It.IsAny<string>())) .Setup(v => v.GetFileSize(It.IsAny<string>()))
.Returns(0); .Returns(0);
Subject.HandleAsync(new MovieUpdatedEvent(_movie)); ExecuteAndVerifyCommand(_movie);
Mocker.GetMock<IImageResizer>() Mocker.GetMock<IImageResizer>()
.Verify(v => v.Resize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()), Times.Exactly(2)); .Verify(v => v.Resize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()), Times.Exactly(2));
@ -156,7 +169,7 @@ public void should_log_error_if_resize_failed()
.Setup(v => v.Resize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>())) .Setup(v => v.Resize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()))
.Throws<ApplicationException>(); .Throws<ApplicationException>();
Subject.HandleAsync(new MovieUpdatedEvent(_movie)); ExecuteAndVerifyCommand(_movie);
Mocker.GetMock<IImageResizer>() Mocker.GetMock<IImageResizer>()
.Verify(v => v.Resize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()), Times.Exactly(2)); .Verify(v => v.Resize(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>()), Times.Exactly(2));

View File

@ -20,12 +20,12 @@ public UserRepository(IMainDatabase database, IEventAggregator eventAggregator)
public User FindUser(string username) public User FindUser(string username)
{ {
return Query.Where(u => u.Username == username).SingleOrDefault(); return Query(q => q.Where(u => u.Username == username).SingleOrDefault());
} }
public User FindUser(Guid identifier) public User FindUser(Guid identifier)
{ {
return Query.Where(u => u.Identifier == identifier).SingleOrDefault(); return Query(q => q.Where(u => u.Identifier == identifier).SingleOrDefault());
} }
} }
} }

View File

@ -26,7 +26,11 @@ public MakeDatabaseBackup(Logger logger)
public void BackupDatabase(IDatabase database, string targetDirectory) public void BackupDatabase(IDatabase database, string targetDirectory)
{ {
var sourceConnectionString = database.GetDataMapper().ConnectionString; var sourceConnectionString = "";
using (var db = database.GetDataMapper())
{
sourceConnectionString = db.ConnectionString;
}
var backupConnectionStringBuilder = new SQLiteConnectionStringBuilder(sourceConnectionString); var backupConnectionStringBuilder = new SQLiteConnectionStringBuilder(sourceConnectionString);
backupConnectionStringBuilder.DataSource = Path.Combine(targetDirectory, Path.GetFileName(backupConnectionStringBuilder.DataSource)); backupConnectionStringBuilder.DataSource = Path.Combine(targetDirectory, Path.GetFileName(backupConnectionStringBuilder.DataSource));

View File

@ -22,19 +22,19 @@ public BlacklistRepository(IMainDatabase database, IEventAggregator eventAggrega
public List<Blacklist> BlacklistedByTitle(int movieId, string sourceTitle) public List<Blacklist> BlacklistedByTitle(int movieId, string sourceTitle)
{ {
return Query.Where(e => e.MovieId == movieId) return Query(q => q.Where(e => e.MovieId == movieId)
.AndWhere(e => e.SourceTitle.Contains(sourceTitle)); .AndWhere(e => e.SourceTitle.Contains(sourceTitle)).ToList());
} }
public List<Blacklist> BlacklistedByTorrentInfoHash(int movieId, string torrentInfoHash) public List<Blacklist> BlacklistedByTorrentInfoHash(int movieId, string torrentInfoHash)
{ {
return Query.Where(e => e.MovieId == movieId) return Query(q => q.Where(e => e.MovieId == movieId)
.AndWhere(e => e.TorrentInfoHash.Contains(torrentInfoHash)); .AndWhere(e => e.TorrentInfoHash.Contains(torrentInfoHash)).ToList());
} }
public List<Blacklist> BlacklistedByMovie(int movieId) public List<Blacklist> BlacklistedByMovie(int movieId)
{ {
return Query.Where(b => b.MovieId == movieId); return Query(q => q.Where(b => b.MovieId == movieId).ToList());
} }
protected override SortBuilder<Blacklist> GetPagedQuery(QueryBuilder<Blacklist> query, PagingSpec<Blacklist> pagingSpec) protected override SortBuilder<Blacklist> GetPagedQuery(QueryBuilder<Blacklist> query, PagingSpec<Blacklist> pagingSpec)

View File

@ -21,7 +21,7 @@ public ConfigRepository(IMainDatabase database, IEventAggregator eventAggregator
public Config Get(string key) public Config Get(string key)
{ {
return Query.Where(c => c.Key == key).SingleOrDefault(); return Query(q => q.Where(c => c.Key == key).SingleOrDefault());
} }
public Config Upsert(string key, string value) public Config Upsert(string key, string value)

View File

@ -42,7 +42,10 @@ namespace NzbDrone.Core.Datastore
private readonly IDatabase _database; private readonly IDatabase _database;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
protected IDataMapper DataMapper => _database.GetDataMapper(); protected IDataMapper DataMapper()
{
return _database.GetDataMapper();
}
public BasicRepository(IDatabase database, IEventAggregator eventAggregator) public BasicRepository(IDatabase database, IEventAggregator eventAggregator)
{ {
@ -50,26 +53,40 @@ public BasicRepository(IDatabase database, IEventAggregator eventAggregator)
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
} }
protected QueryBuilder<TModel> Query => AddJoinQueries(DataMapper.Query<TModel>());
protected T Query<T>(Func<QueryBuilder<TModel>, T> finalizeQuery)
{
using (var mapper = DataMapper())
{
var query = AddJoinQueries(mapper.Query<TModel>());
return finalizeQuery(query);
}
}
protected void Delete(Expression<Func<TModel, bool>> filter) protected void Delete(Expression<Func<TModel, bool>> filter)
{ {
DataMapper.Delete(filter); using (var db = DataMapper())
{
db.Delete(filter);
}
} }
public IEnumerable<TModel> All() public IEnumerable<TModel> All()
{ {
return Query.ToList(); return Query((q => q.ToList()));
} }
public int Count() public int Count()
{ {
return DataMapper.Query<TModel>().GetRowCount(); using (var db = DataMapper())
{
return db.Query<TModel>().GetRowCount();
}
} }
public TModel Get(int id) public TModel Get(int id)
{ {
var model = Query.Where(c => c.Id == id).SingleOrDefault(); TModel model = Query(q => q.Where(c => c.Id == id).SingleOrDefault());
if (model == null) if (model == null)
{ {
@ -83,7 +100,7 @@ public IEnumerable<TModel> Get(IEnumerable<int> ids)
{ {
var idList = ids.ToList(); var idList = ids.ToList();
var query = string.Format("Id IN ({0})", string.Join(",", idList)); var query = string.Format("Id IN ({0})", string.Join(",", idList));
var result = Query.Where(m => m.Id.In(idList)).ToList(); var result = Query(q => q.Where(m => m.Id.In(idList)).ToList());
//var result = Query.Where(query).ToList(); //var result = Query.Where(query).ToList();
if (result.Count != idList.Count()) if (result.Count != idList.Count())
@ -111,7 +128,10 @@ public TModel Insert(TModel model)
throw new InvalidOperationException("Can't insert model with existing ID " + model.Id); throw new InvalidOperationException("Can't insert model with existing ID " + model.Id);
} }
DataMapper.Insert(model); using (var db = DataMapper())
{
db.Insert(model);
}
ModelCreated(model); ModelCreated(model);
@ -125,7 +145,10 @@ public TModel Update(TModel model)
throw new InvalidOperationException("Can't update model with ID 0"); throw new InvalidOperationException("Can't update model with ID 0");
} }
DataMapper.Update(model, c => c.Id == model.Id); using (var db = DataMapper())
{
db.Update(model, c => c.Id == model.Id);
}
ModelUpdated(model); ModelUpdated(model);
@ -139,7 +162,7 @@ public void Delete(TModel model)
public void InsertMany(IList<TModel> models) public void InsertMany(IList<TModel> models)
{ {
using (var unitOfWork = new UnitOfWork(() => DataMapper)) using (var unitOfWork = new UnitOfWork(() => DataMapper()))
{ {
unitOfWork.BeginTransaction(IsolationLevel.ReadCommitted); unitOfWork.BeginTransaction(IsolationLevel.ReadCommitted);
@ -154,7 +177,7 @@ public void InsertMany(IList<TModel> models)
public void UpdateMany(IList<TModel> models) public void UpdateMany(IList<TModel> models)
{ {
using (var unitOfWork = new UnitOfWork(() => DataMapper)) using (var unitOfWork = new UnitOfWork(() => DataMapper()))
{ {
unitOfWork.BeginTransaction(IsolationLevel.ReadCommitted); unitOfWork.BeginTransaction(IsolationLevel.ReadCommitted);
@ -192,12 +215,15 @@ public TModel Upsert(TModel model)
public void Delete(int id) public void Delete(int id)
{ {
DataMapper.Delete<TModel>(c => c.Id == id); using (var db = DataMapper())
{
db.Delete<TModel>(c => c.Id == id);
}
} }
public void DeleteMany(IEnumerable<int> ids) public void DeleteMany(IEnumerable<int> ids)
{ {
using (var unitOfWork = new UnitOfWork(() => DataMapper)) using (var unitOfWork = new UnitOfWork(() => DataMapper()))
{ {
unitOfWork.BeginTransaction(IsolationLevel.ReadCommitted); unitOfWork.BeginTransaction(IsolationLevel.ReadCommitted);
@ -214,7 +240,10 @@ public void DeleteMany(IEnumerable<int> ids)
public void Purge(bool vacuum = false) public void Purge(bool vacuum = false)
{ {
DataMapper.Delete<TModel>(c => c.Id > -1); using (var db = DataMapper())
{
db.Delete<TModel>(c => c.Id > -1);
}
if (vacuum) if (vacuum)
{ {
Vacuum(); Vacuum();
@ -238,20 +267,23 @@ public void SetFields(TModel model, params Expression<Func<TModel, object>>[] pr
throw new InvalidOperationException("Attempted to updated model without ID"); throw new InvalidOperationException("Attempted to updated model without ID");
} }
DataMapper.Update<TModel>() using (var db = DataMapper())
{
db.Update<TModel>()
.Where(c => c.Id == model.Id) .Where(c => c.Id == model.Id)
.ColumnsIncluding(properties) .ColumnsIncluding(properties)
.Entity(model) .Entity(model)
.Execute(); .Execute();
}
ModelUpdated(model); ModelUpdated(model);
} }
public virtual PagingSpec<TModel> GetPaged(PagingSpec<TModel> pagingSpec) public virtual PagingSpec<TModel> GetPaged(PagingSpec<TModel> pagingSpec)
{ {
pagingSpec.Records = GetPagedQuery(Query, pagingSpec).Skip(pagingSpec.PagingOffset()) pagingSpec.Records = Query(q => GetPagedQuery(q, pagingSpec).Skip(pagingSpec.PagingOffset())
.Take(pagingSpec.PageSize).ToList(); .Take(pagingSpec.PageSize).ToList());
pagingSpec.TotalRecords = GetPagedQuery(Query, pagingSpec).GetRowCount(); pagingSpec.TotalRecords = Query(q => GetPagedQuery(q, pagingSpec).GetRowCount());
return pagingSpec; return pagingSpec;
} }
@ -285,7 +317,7 @@ private void PublishModelEvent(TModel model, ModelAction action)
} }
} }
protected virtual QueryBuilder<TModel> AddJoinQueries(QueryBuilder<TModel> baseQuery) protected virtual QueryBuilder<TActual> AddJoinQueries<TActual>(QueryBuilder<TActual> baseQuery)
{ {
return baseQuery; return baseQuery;
} }

View File

@ -35,7 +35,7 @@ private static string GetConnectionString(string dbPath)
var connectionBuilder = new SQLiteConnectionStringBuilder(); var connectionBuilder = new SQLiteConnectionStringBuilder();
connectionBuilder.DataSource = dbPath; connectionBuilder.DataSource = dbPath;
connectionBuilder.CacheSize = (int)-10.Megabytes(); connectionBuilder.CacheSize = (int)-20000;
connectionBuilder.DateTimeKind = DateTimeKind.Utc; connectionBuilder.DateTimeKind = DateTimeKind.Utc;
connectionBuilder.JournalMode = OsInfo.IsOsx ? SQLiteJournalModeEnum.Truncate : SQLiteJournalModeEnum.Wal; connectionBuilder.JournalMode = OsInfo.IsOsx ? SQLiteJournalModeEnum.Truncate : SQLiteJournalModeEnum.Wal;
connectionBuilder.Pooling = true; connectionBuilder.Pooling = true;

View File

@ -34,17 +34,23 @@ public Version Version
{ {
get get
{ {
var version = _datamapperFactory().ExecuteScalar("SELECT sqlite_version()").ToString(); using (var db = _datamapperFactory())
{
var version = db.ExecuteScalar("SELECT sqlite_version()").ToString();
return new Version(version); return new Version(version);
} }
} }
}
public void Vacuum() public void Vacuum()
{ {
try try
{ {
_logger.Info("Vacuuming {0} database", _databaseName); _logger.Info("Vacuuming {0} database", _databaseName);
_datamapperFactory().ExecuteNonQuery("Vacuum;"); using (var db = _datamapperFactory())
{
db.ExecuteNonQuery("Vacuum;");
}
_logger.Info("{0} database compressed", _databaseName); _logger.Info("{0} database compressed", _databaseName);
} }
catch (Exception e) catch (Exception e)

View File

@ -24,7 +24,7 @@ public void DeleteByMovieId(int movieId)
public List<PendingRelease> AllByMovieId(int movieId) public List<PendingRelease> AllByMovieId(int movieId)
{ {
return Query.Where(p => p.MovieId == movieId); return Query(q => q.Where(p => p.MovieId == movieId).ToList());
} }
} }
} }

View File

@ -34,17 +34,17 @@ public void DeleteForMovieFile(int movieFileId)
public List<TExtraFile> GetFilesByMovie(int movieId) public List<TExtraFile> GetFilesByMovie(int movieId)
{ {
return Query.Where(c => c.MovieId == movieId); return Query(q => q.Where(c => c.MovieId == movieId).ToList());
} }
public List<TExtraFile> GetFilesByMovieFile(int movieFileId) public List<TExtraFile> GetFilesByMovieFile(int movieFileId)
{ {
return Query.Where(c => c.MovieFileId == movieFileId); return Query(q => q.Where(c => c.MovieFileId == movieFileId).ToList());
} }
public TExtraFile FindByPath(string path) public TExtraFile FindByPath(string path)
{ {
return Query.Where(c => c.RelativePath == path).SingleOrDefault(); return Query(q => q.Where(c => c.RelativePath == path).SingleOrDefault());
} }
} }
} }

View File

@ -30,37 +30,37 @@ public HistoryRepository(IMainDatabase database, IEventAggregator eventAggregato
public List<QualityModel> GetBestQualityInHistory(int movieId) public List<QualityModel> GetBestQualityInHistory(int movieId)
{ {
var history = Query.Where(c => c.MovieId == movieId); var history = Query(q => q.Where(c => c.MovieId == movieId).ToList());
return history.Select(h => h.Quality).ToList(); return history.Select(h => h.Quality).ToList();
} }
public History MostRecentForDownloadId(string downloadId) public History MostRecentForDownloadId(string downloadId)
{ {
return Query.Where(h => h.DownloadId == downloadId) return Query(q => q.Where(h => h.DownloadId == downloadId)
.OrderByDescending(h => h.Date) .OrderByDescending(h => h.Date)
.FirstOrDefault(); .FirstOrDefault());
} }
public List<History> FindByDownloadId(string downloadId) public List<History> FindByDownloadId(string downloadId)
{ {
return Query.Where(h => h.DownloadId == downloadId); return Query(q => q.Where(h => h.DownloadId == downloadId).ToList());
} }
public List<History> FindDownloadHistory(int idMovieId, QualityModel quality) public List<History> FindDownloadHistory(int idMovieId, QualityModel quality)
{ {
return Query.Where(h => return Query(q => q.Where(h =>
h.MovieId == idMovieId && h.MovieId == idMovieId &&
h.Quality == quality && h.Quality == quality &&
(h.EventType == HistoryEventType.Grabbed || (h.EventType == HistoryEventType.Grabbed ||
h.EventType == HistoryEventType.DownloadFailed || h.EventType == HistoryEventType.DownloadFailed ||
h.EventType == HistoryEventType.DownloadFolderImported) h.EventType == HistoryEventType.DownloadFolderImported)
).ToList(); ).ToList());
} }
public List<History> FindByMovieId(int movieId) public List<History> FindByMovieId(int movieId)
{ {
return Query.Where(h => h.MovieId == movieId); return Query(q => q.Where(h => h.MovieId == movieId).ToList());
} }
public void DeleteForMovie(int movieId) public void DeleteForMovie(int movieId)
@ -77,9 +77,9 @@ protected override SortBuilder<History> GetPagedQuery(QueryBuilder<History> quer
public History MostRecentForMovie(int movieId) public History MostRecentForMovie(int movieId)
{ {
return Query.Where(h => h.MovieId == movieId) return Query(q => q.Where(h => h.MovieId == movieId)
.OrderByDescending(h => h.Date) .OrderByDescending(h => h.Date)
.FirstOrDefault(); .FirstOrDefault());
} }
} }
} }

View File

@ -13,8 +13,8 @@ public CleanupAbsolutePathMetadataFiles(IMainDatabase database)
public void Clean() public void Clean()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles
WHERE Id IN ( WHERE Id IN (
SELECT Id FROM MetadataFiles SELECT Id FROM MetadataFiles
@ -27,4 +27,5 @@ OR RelativePath
)"); )");
} }
} }
}
} }

View File

@ -13,7 +13,8 @@ public CleanupAdditionalNamingSpecs(IMainDatabase database)
public void Clean() public void Clean()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM NamingConfig mapper.ExecuteNonQuery(@"DELETE FROM NamingConfig
WHERE ID NOT IN ( WHERE ID NOT IN (
@ -21,4 +22,5 @@ SELECT ID FROM NamingConfig
LIMIT 1)"); LIMIT 1)");
} }
} }
}
} }

View File

@ -13,7 +13,8 @@ public CleanupAdditionalUsers(IMainDatabase database)
public void Clean() public void Clean()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM Users mapper.ExecuteNonQuery(@"DELETE FROM Users
WHERE ID NOT IN ( WHERE ID NOT IN (
@ -21,5 +22,6 @@ SELECT ID FROM Users
LIMIT 1)"); LIMIT 1)");
} }
} }
}
} }

View File

@ -19,7 +19,8 @@ public void Clean()
private void DeleteDuplicateMovieMetadata() private void DeleteDuplicateMovieMetadata()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles
WHERE Id IN ( WHERE Id IN (
@ -29,10 +30,12 @@ SELECT Id FROM MetadataFiles
HAVING COUNT(MovieId) > 1 HAVING COUNT(MovieId) > 1
)"); )");
} }
}
private void DeleteDuplicateMovieFileMetadata() private void DeleteDuplicateMovieFileMetadata()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles
WHERE Id IN ( WHERE Id IN (
@ -43,4 +46,5 @@ HAVING COUNT(MovieFileId) > 1
)"); )");
} }
} }
}
} }

View File

@ -13,7 +13,8 @@ public CleanupOrphanedAlternativeTitles(IMainDatabase database)
public void Clean() public void Clean()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM AlternativeTitles mapper.ExecuteNonQuery(@"DELETE FROM AlternativeTitles
WHERE Id IN ( WHERE Id IN (
@ -23,4 +24,5 @@ LEFT OUTER JOIN Movies
WHERE Movies.Id IS NULL)"); WHERE Movies.Id IS NULL)");
} }
} }
}
} }

View File

@ -13,7 +13,8 @@ public CleanupOrphanedBlacklist(IMainDatabase database)
public void Clean() public void Clean()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM Blacklist mapper.ExecuteNonQuery(@"DELETE FROM Blacklist
WHERE Id IN ( WHERE Id IN (
@ -23,4 +24,5 @@ LEFT OUTER JOIN Movies
WHERE Movies.Id IS NULL)"); WHERE Movies.Id IS NULL)");
} }
} }
}
} }

View File

@ -18,7 +18,8 @@ public void Clean()
private void CleanupOrphanedByMovie() private void CleanupOrphanedByMovie()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM History mapper.ExecuteNonQuery(@"DELETE FROM History
WHERE Id IN ( WHERE Id IN (
@ -28,4 +29,5 @@ LEFT OUTER JOIN Movies
WHERE Movies.Id IS NULL)"); WHERE Movies.Id IS NULL)");
} }
} }
}
} }

View File

@ -13,7 +13,8 @@ public CleanupOrphanedIndexerStatus(IMainDatabase database)
public void Clean() public void Clean()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM IndexerStatus mapper.ExecuteNonQuery(@"DELETE FROM IndexerStatus
WHERE Id IN ( WHERE Id IN (
@ -23,4 +24,5 @@ LEFT OUTER JOIN Indexers
WHERE Indexers.Id IS NULL)"); WHERE Indexers.Id IS NULL)");
} }
} }
}
} }

View File

@ -20,7 +20,8 @@ public void Clean()
private void DeleteOrphanedByMovie() private void DeleteOrphanedByMovie()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles
WHERE Id IN ( WHERE Id IN (
@ -29,10 +30,12 @@ LEFT OUTER JOIN Movies
ON MetadataFiles.MovieId = Movies.Id ON MetadataFiles.MovieId = Movies.Id
WHERE Movies.Id IS NULL)"); WHERE Movies.Id IS NULL)");
} }
}
private void DeleteOrphanedByMovieFile() private void DeleteOrphanedByMovieFile()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles
WHERE Id IN ( WHERE Id IN (
@ -42,10 +45,12 @@ LEFT OUTER JOIN MovieFiles
WHERE MetadataFiles.MovieFileId > 0 WHERE MetadataFiles.MovieFileId > 0
AND MovieFiles.Id IS NULL)"); AND MovieFiles.Id IS NULL)");
} }
}
private void DeleteWhereMovieFileIsZero() private void DeleteWhereMovieFileIsZero()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles mapper.ExecuteNonQuery(@"DELETE FROM MetadataFiles
WHERE Id IN ( WHERE Id IN (
@ -54,4 +59,5 @@ WHERE Type IN (1, 2)
AND MovieFileId = 0)"); AND MovieFileId = 0)");
} }
} }
}
} }

View File

@ -13,8 +13,8 @@ public CleanupOrphanedMovieFiles(IMainDatabase database)
public void Clean() public void Clean()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM MovieFiles mapper.ExecuteNonQuery(@"DELETE FROM MovieFiles
WHERE Id IN ( WHERE Id IN (
SELECT MovieFiles.Id FROM MovieFiles SELECT MovieFiles.Id FROM MovieFiles
@ -23,4 +23,5 @@ LEFT OUTER JOIN Movies
WHERE Movies.Id IS NULL)"); WHERE Movies.Id IS NULL)");
} }
} }
}
} }

View File

@ -13,7 +13,8 @@ public CleanupOrphanedPendingReleases(IMainDatabase database)
public void Clean() public void Clean()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.ExecuteNonQuery(@"DELETE FROM PendingReleases mapper.ExecuteNonQuery(@"DELETE FROM PendingReleases
WHERE Id IN ( WHERE Id IN (
@ -23,4 +24,5 @@ LEFT OUTER JOIN Movies
WHERE Movies.Id IS NULL)"); WHERE Movies.Id IS NULL)");
} }
} }
}
} }

View File

@ -17,9 +17,10 @@ public CleanupUnusedTags(IMainDatabase database)
public void Clean() public void Clean()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
var usedTags = new[] { "Movies", "Notifications", "DelayProfiles", "Restrictions" } var usedTags = new[] {"Movies", "Notifications", "DelayProfiles", "Restrictions"}
.SelectMany(v => GetUsedTags(v, mapper)) .SelectMany(v => GetUsedTags(v, mapper))
.Distinct() .Distinct()
.ToArray(); .ToArray();
@ -28,6 +29,7 @@ public void Clean()
mapper.ExecuteNonQuery($"DELETE FROM Tags WHERE NOT Id IN ({usedTagsList})"); mapper.ExecuteNonQuery($"DELETE FROM Tags WHERE NOT Id IN ({usedTagsList})");
} }
}
private int[] GetUsedTags(string table, IDataMapper mapper) private int[] GetUsedTags(string table, IDataMapper mapper)
{ {

View File

@ -23,7 +23,8 @@ public void Clean()
_logger.Debug("Not running scheduled task last execution cleanup during debug"); _logger.Debug("Not running scheduled task last execution cleanup during debug");
} }
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.AddParameter("time", DateTime.UtcNow); mapper.AddParameter("time", DateTime.UtcNow);
mapper.ExecuteNonQuery(@"UPDATE ScheduledTasks mapper.ExecuteNonQuery(@"UPDATE ScheduledTasks
@ -31,4 +32,5 @@ public void Clean()
WHERE LastExecution > @time"); WHERE LastExecution > @time");
} }
} }
}
} }

View File

@ -20,7 +20,7 @@ public IndexerStatusRepository(IMainDatabase database, IEventAggregator eventAgg
public IndexerStatus FindByIndexerId(int indexerId) public IndexerStatus FindByIndexerId(int indexerId)
{ {
return Query.Where(c => c.IndexerId == indexerId).SingleOrDefault(); return Query(q => q.Where(c => c.IndexerId == indexerId).SingleOrDefault());
} }
} }
} }

View File

@ -15,13 +15,14 @@ public class DatabaseTarget : TargetWithLayout, IHandle<ApplicationShutdownReque
{ {
private readonly SQLiteConnection _connection; private readonly SQLiteConnection _connection;
private readonly IConnectionStringFactory _connectionStringFactory;
const string INSERT_COMMAND = "INSERT INTO [Logs]([Message],[Time],[Logger],[Exception],[ExceptionType],[Level]) " + const string INSERT_COMMAND = "INSERT INTO [Logs]([Message],[Time],[Logger],[Exception],[ExceptionType],[Level]) " +
"VALUES(@Message,@Time,@Logger,@Exception,@ExceptionType,@Level)"; "VALUES(@Message,@Time,@Logger,@Exception,@ExceptionType,@Level)";
public DatabaseTarget(IConnectionStringFactory connectionStringFactory) public DatabaseTarget(IConnectionStringFactory connectionStringFactory)
{ {
_connection = new SQLiteConnection(connectionStringFactory.LogDbConnectionString); _connectionStringFactory = connectionStringFactory;
_connection.Open();
} }
public void Register() public void Register()
@ -84,8 +85,14 @@ protected override void Write(LogEventInfo logEvent)
log.Level = logEvent.Level.Name; log.Level = logEvent.Level.Name;
var sqlCommand = new SQLiteCommand(INSERT_COMMAND, _connection); using (var connection =
SQLiteFactory.Instance.CreateConnection())
{
connection.ConnectionString = _connectionStringFactory.LogDbConnectionString;
connection.Open();
using (var sqlCommand = connection.CreateCommand())
{
sqlCommand.CommandText = INSERT_COMMAND;
sqlCommand.Parameters.Add(new SQLiteParameter("Message", DbType.String) { Value = log.Message }); sqlCommand.Parameters.Add(new SQLiteParameter("Message", DbType.String) { Value = log.Message });
sqlCommand.Parameters.Add(new SQLiteParameter("Time", DbType.DateTime) { Value = log.Time.ToUniversalTime() }); sqlCommand.Parameters.Add(new SQLiteParameter("Time", DbType.DateTime) { Value = log.Time.ToUniversalTime() });
sqlCommand.Parameters.Add(new SQLiteParameter("Logger", DbType.String) { Value = log.Logger }); sqlCommand.Parameters.Add(new SQLiteParameter("Logger", DbType.String) { Value = log.Logger });
@ -95,6 +102,9 @@ protected override void Write(LogEventInfo logEvent)
sqlCommand.ExecuteNonQuery(); sqlCommand.ExecuteNonQuery();
} }
}
}
catch (SQLiteException ex) catch (SQLiteException ex)
{ {
InternalLogger.Error("Unable to save log event to database: {0}", ex); InternalLogger.Error("Unable to save log event to database: {0}", ex);
@ -104,7 +114,7 @@ protected override void Write(LogEventInfo logEvent)
public void Handle(ApplicationShutdownRequested message) public void Handle(ApplicationShutdownRequested message)
{ {
if (LogManager.Configuration.LoggingRules.Contains(Rule)) if (LogManager.Configuration?.LoggingRules?.Contains(Rule) == true)
{ {
UnRegister(); UnRegister();
} }

View File

@ -22,7 +22,7 @@ public ScheduledTaskRepository(IMainDatabase database, IEventAggregator eventAgg
public ScheduledTask GetDefinition(Type type) public ScheduledTask GetDefinition(Type type)
{ {
return Query.Where(c => c.TypeName == type.FullName).Single(); return Query(q => q.Where(c => c.TypeName == type.FullName).Single());
} }
public void SetLastExecutionTime(int id, DateTime executionTime) public void SetLastExecutionTime(int id, DateTime executionTime)

View File

@ -31,12 +31,6 @@ public bool AlreadyExists(string url, string path)
return false; return false;
} }
if (!_diskProvider.IsValidGDIPlusImage(path))
{
_diskProvider.DeleteFile(path);
return false;
}
var headers = _httpClient.Head(new HttpRequest(url)).Headers; var headers = _httpClient.Head(new HttpRequest(url)).Headers;
var fileSize = _diskProvider.GetFileSize(path); var fileSize = _diskProvider.GetFileSize(path);
return fileSize == headers.ContentLength; return fileSize == headers.ContentLength;

View File

@ -0,0 +1,19 @@
using NzbDrone.Core.Messaging.Commands;
namespace NzbDrone.Core.MediaCover
{
public class EnsureMediaCoversCommand : Command
{
public int MovieId { get; set; }
public EnsureMediaCoversCommand()
{
}
public EnsureMediaCoversCommand(int movieId)
{
MovieId = movieId;
}
}
}

View File

@ -8,6 +8,7 @@
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Events; using NzbDrone.Core.Movies.Events;
@ -24,6 +25,7 @@ public class MediaCoverService :
IHandleAsync<MovieUpdatedEvent>, IHandleAsync<MovieUpdatedEvent>,
IHandleAsync<MovieAddedEvent>, IHandleAsync<MovieAddedEvent>,
IHandleAsync<MovieDeletedEvent>, IHandleAsync<MovieDeletedEvent>,
IExecute<EnsureMediaCoversCommand>,
IMapCoversToLocal IMapCoversToLocal
{ {
private readonly IImageResizer _resizer; private readonly IImageResizer _resizer;
@ -32,6 +34,8 @@ public class MediaCoverService :
private readonly ICoverExistsSpecification _coverExistsSpecification; private readonly ICoverExistsSpecification _coverExistsSpecification;
private readonly IConfigFileProvider _configFileProvider; private readonly IConfigFileProvider _configFileProvider;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly IManageCommandQueue _commandQueue;
private readonly IMovieService _movieService;
private readonly Logger _logger; private readonly Logger _logger;
private readonly string _coverRootFolder; private readonly string _coverRootFolder;
@ -43,6 +47,8 @@ public MediaCoverService(IImageResizer resizer,
ICoverExistsSpecification coverExistsSpecification, ICoverExistsSpecification coverExistsSpecification,
IConfigFileProvider configFileProvider, IConfigFileProvider configFileProvider,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
IManageCommandQueue commandQueue,
IMovieService movieService,
Logger logger) Logger logger)
{ {
_resizer = resizer; _resizer = resizer;
@ -51,6 +57,8 @@ public MediaCoverService(IImageResizer resizer,
_coverExistsSpecification = coverExistsSpecification; _coverExistsSpecification = coverExistsSpecification;
_configFileProvider = configFileProvider; _configFileProvider = configFileProvider;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_commandQueue = commandQueue;
_movieService = movieService;
_logger = logger; _logger = logger;
_coverRootFolder = appFolderInfo.GetMediaCoverPath(); _coverRootFolder = appFolderInfo.GetMediaCoverPath();
@ -109,7 +117,7 @@ private void EnsureCovers(Movie movie, int retried = 0)
_logger.Warn(e, string.Format("Couldn't download media cover for {0}. {1}", movie, e.Message)); _logger.Warn(e, string.Format("Couldn't download media cover for {0}. {1}", movie, e.Message));
if (retried < 3) if (retried < 3)
{ {
retried = +1; retried += 1;
_logger.Warn("Retrying for the {0}. time in ten seconds.", retried); _logger.Warn("Retrying for the {0}. time in ten seconds.", retried);
System.Threading.Thread.Sleep(10 * 1000); System.Threading.Thread.Sleep(10 * 1000);
EnsureCovers(movie, retried); EnsureCovers(movie, retried);
@ -182,16 +190,26 @@ private void EnsureResizedCovers(Movie movie, MediaCover cover, bool forceResize
} }
} }
public void Execute(EnsureMediaCoversCommand command)
{
var movie = _movieService.GetMovie(command.MovieId);
EnsureCovers(movie);
_eventAggregator.PublishEvent(new MediaCoversUpdatedEvent(movie));
}
public void HandleAsync(MovieUpdatedEvent message) public void HandleAsync(MovieUpdatedEvent message)
{ {
EnsureCovers(message.Movie); //EnsureCovers(message.Movie);
_eventAggregator.PublishEvent(new MediaCoversUpdatedEvent(message.Movie)); _logger.Info("Testing: {0}, {1}", _commandQueue, message.Movie.Id);
_commandQueue.Push(new EnsureMediaCoversCommand(message.Movie.Id));
//_eventAggregator.PublishEvent(new MediaCoversUpdatedEvent(message.Movie));
} }
public void HandleAsync(MovieAddedEvent message) public void HandleAsync(MovieAddedEvent message)
{ {
EnsureCovers(message.Movie); //EnsureCovers(message.Movie);
_eventAggregator.PublishEvent(new MediaCoversUpdatedEvent(message.Movie)); _commandQueue.Push(new EnsureMediaCoversCommand(message.Movie.Id));
//_eventAggregator.PublishEvent(new MediaCoversUpdatedEvent(message.Movie));
} }
public void HandleAsync(MovieDeletedEvent message) public void HandleAsync(MovieDeletedEvent message)

View File

@ -21,12 +21,12 @@ public MediaFileRepository(IMainDatabase database, IEventAggregator eventAggrega
public List<MovieFile> GetFilesByMovie(int movieId) public List<MovieFile> GetFilesByMovie(int movieId)
{ {
return Query.Where(c => c.MovieId == movieId).ToList(); return Query(q => q.Where(c => c.MovieId == movieId).ToList());
} }
public List<MovieFile> GetFilesWithoutMediaInfo() public List<MovieFile> GetFilesWithoutMediaInfo()
{ {
return Query.Where(c => c.MediaInfo == null).ToList(); return Query(q => q.Where(c => c.MediaInfo == null).ToList());
} }
} }
} }

View File

@ -37,37 +37,39 @@ public void Trim()
public void OrphanStarted() public void OrphanStarted()
{ {
var mapper = _database.GetDataMapper(); using (var mapper = _database.GetDataMapper())
{
mapper.Parameters.Add(new SQLiteParameter("@orphaned", (int)CommandStatus.Orphaned)); mapper.Parameters.Add(new SQLiteParameter("@orphaned", (int) CommandStatus.Orphaned));
mapper.Parameters.Add(new SQLiteParameter("@started", (int)CommandStatus.Started)); mapper.Parameters.Add(new SQLiteParameter("@started", (int) CommandStatus.Started));
mapper.Parameters.Add(new SQLiteParameter("@ended", DateTime.UtcNow)); mapper.Parameters.Add(new SQLiteParameter("@ended", DateTime.UtcNow));
mapper.ExecuteNonQuery(@"UPDATE Commands mapper.ExecuteNonQuery(@"UPDATE Commands
SET Status = @orphaned, EndedAt = @ended SET Status = @orphaned, EndedAt = @ended
WHERE Status = @started"); WHERE Status = @started");
} }
}
public List<CommandModel> FindCommands(string name) public List<CommandModel> FindCommands(string name)
{ {
return Query.Where(c => c.Name == name).ToList(); return Query(q => q.Where(c => c.Name == name).ToList());
} }
public List<CommandModel> FindQueuedOrStarted(string name) public List<CommandModel> FindQueuedOrStarted(string name)
{ {
return Query.Where(c => c.Name == name) return Query(q => q.Where(c => c.Name == name)
.AndWhere("[Status] IN (0,1)") .AndWhere("[Status] IN (0,1)")
.ToList(); .ToList());
} }
public List<CommandModel> Queued() public List<CommandModel> Queued()
{ {
return Query.Where(c => c.Status == CommandStatus.Queued); return Query(q => q.Where(c => c.Status == CommandStatus.Queued).ToList());
} }
public List<CommandModel> Started() public List<CommandModel> Started()
{ {
return Query.Where(c => c.Status == CommandStatus.Started); return Query(q => q.Where(c => c.Status == CommandStatus.Started).ToList());
} }
public void Start(CommandModel command) public void Start(CommandModel command)

View File

@ -25,17 +25,17 @@ public AlternativeTitleRepository(IMainDatabase database, IEventAggregator event
public AlternativeTitle FindBySourceId(int sourceId) public AlternativeTitle FindBySourceId(int sourceId)
{ {
return Query.Where(t => t.SourceId == sourceId).FirstOrDefault(); return Query(q => q.Where(t => t.SourceId == sourceId).FirstOrDefault());
} }
public List<AlternativeTitle> FindBySourceIds(List<int> sourceIds) public List<AlternativeTitle> FindBySourceIds(List<int> sourceIds)
{ {
return Query.Where(t => t.SourceId.In(sourceIds)).ToList(); return Query(q => q.Where(t => t.SourceId.In(sourceIds)).ToList());
} }
public List<AlternativeTitle> FindByMovieId(int movieId) public List<AlternativeTitle> FindByMovieId(int movieId)
{ {
return Query.Where(t => t.MovieId == movieId).ToList(); return Query(q => q.Where(t => t.MovieId == movieId).ToList());
} }
} }
} }

View File

@ -41,7 +41,7 @@ public MovieRepository(IMainDatabase database, IEventAggregator eventAggregator)
public bool MoviePathExists(string path) public bool MoviePathExists(string path)
{ {
return Query.Where(c => c.Path == path).Any(); return Query(q => q.Where(c => c.Path == path).Any());
} }
public Movie FindByTitle(string cleanTitle) public Movie FindByTitle(string cleanTitle)
@ -57,12 +57,12 @@ public Movie FindByTitle(string cleanTitle, int year)
public Movie FindByImdbId(string imdbid) public Movie FindByImdbId(string imdbid)
{ {
var imdbIdWithPrefix = Parser.Parser.NormalizeImdbId(imdbid); var imdbIdWithPrefix = Parser.Parser.NormalizeImdbId(imdbid);
return Query.Where(s => s.ImdbId == imdbIdWithPrefix).SingleOrDefault(); return Query(q => q.Where(s => s.ImdbId == imdbIdWithPrefix).SingleOrDefault());
} }
public List<Movie> GetMoviesByFileId(int fileId) public List<Movie> GetMoviesByFileId(int fileId)
{ {
return Query.Where(m => m.MovieFileId == fileId).ToList(); return Query(q => q.Where(m => m.MovieFileId == fileId).ToList());
} }
public void SetFileId(int fileId, int movieId) public void SetFileId(int fileId, int movieId)
@ -72,12 +72,16 @@ public void SetFileId(int fileId, int movieId)
public Movie FindByTitleSlug(string slug) public Movie FindByTitleSlug(string slug)
{ {
return Query.FirstOrDefault(m => m.TitleSlug == slug); return Query(q => q.Where(m => m.TitleSlug == slug).FirstOrDefault());
} }
public List<Movie> MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored) public List<Movie> MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored)
{ {
var query = Query.Where(m => (m.InCinemas >= start && m.InCinemas <= end) || (m.PhysicalRelease >= start && m.PhysicalRelease <= end)); return Query(q =>
{
var query = q.Where(m =>
(m.InCinemas >= start && m.InCinemas <= end) ||
(m.PhysicalRelease >= start && m.PhysicalRelease <= end));
if (!includeUnmonitored) if (!includeUnmonitored)
{ {
@ -85,19 +89,20 @@ public List<Movie> MoviesBetweenDates(DateTime start, DateTime end, bool include
} }
return query.ToList(); return query.ToList();
});
} }
public List<Movie> MoviesWithFiles(int movieId) public List<Movie> MoviesWithFiles(int movieId)
{ {
return Query.Join<Movie, MovieFile>(JoinType.Inner, m => m.MovieFile, (m, mf) => m.MovieFileId == mf.Id) return Query(q => q.Join<Movie, MovieFile>(JoinType.Inner, m => m.MovieFile, (m, mf) => m.MovieFileId == mf.Id)
.Where(m => m.Id == movieId); .Where(m => m.Id == movieId).ToList());
} }
public PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec) public PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec)
{ {
pagingSpec.TotalRecords = GetMoviesWithoutFilesQuery(pagingSpec).GetRowCount(); pagingSpec.TotalRecords = Query(q => GetMoviesWithoutFilesQuery(q, pagingSpec).GetRowCount());
pagingSpec.Records = GetMoviesWithoutFilesQuery(pagingSpec).ToList(); pagingSpec.Records = Query(q => GetMoviesWithoutFilesQuery(q, pagingSpec).ToList());
return pagingSpec; return pagingSpec;
} }
@ -157,7 +162,7 @@ public PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec)
return newQuery; return newQuery;
}*/ }*/
public SortBuilder<Movie> GetMoviesWithoutFilesQuery(PagingSpec<Movie> pagingSpec) public SortBuilder<Movie> GetMoviesWithoutFilesQuery(QueryBuilder<Movie> Query, PagingSpec<Movie> pagingSpec)
{ {
return Query.Where(pagingSpec.FilterExpression) return Query.Where(pagingSpec.FilterExpression)
.AndWhere(m => m.MovieFileId == 0) .AndWhere(m => m.MovieFileId == 0)
@ -168,13 +173,13 @@ public SortBuilder<Movie> GetMoviesWithoutFilesQuery(PagingSpec<Movie> pagingSpe
public PagingSpec<Movie> MoviesWhereCutoffUnmet(PagingSpec<Movie> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff) public PagingSpec<Movie> MoviesWhereCutoffUnmet(PagingSpec<Movie> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff)
{ {
pagingSpec.TotalRecords = MoviesWhereCutoffUnmetQuery(pagingSpec, qualitiesBelowCutoff).GetRowCount(); pagingSpec.TotalRecords = Query(q => MoviesWhereCutoffUnmetQuery(q, pagingSpec, qualitiesBelowCutoff).GetRowCount());
pagingSpec.Records = MoviesWhereCutoffUnmetQuery(pagingSpec, qualitiesBelowCutoff).ToList(); pagingSpec.Records = Query(q => MoviesWhereCutoffUnmetQuery(q, pagingSpec, qualitiesBelowCutoff).ToList());
return pagingSpec; return pagingSpec;
} }
private SortBuilder<Movie> MoviesWhereCutoffUnmetQuery(PagingSpec<Movie> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff) private SortBuilder<Movie> MoviesWhereCutoffUnmetQuery(QueryBuilder<Movie> Query, PagingSpec<Movie> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff)
{ {
return Query.Where(pagingSpec.FilterExpression) return Query.Where(pagingSpec.FilterExpression)
.AndWhere(m => m.MovieFileId != 0) .AndWhere(m => m.MovieFileId != 0)
@ -229,12 +234,15 @@ private Movie FindByTitle(string cleanTitle, int? year)
cleanTitleWithArabicNumbers = cleanTitleWithArabicNumbers.Replace(romanNumber, arabicNumber); cleanTitleWithArabicNumbers = cleanTitleWithArabicNumbers.Replace(romanNumber, arabicNumber);
} }
Movie result = Query.Where(s => s.CleanTitle == cleanTitle).FirstWithYear(year); return Query(q =>
{
Movie result = q.Where(s => s.CleanTitle == cleanTitle).FirstWithYear(year);
if (result == null) if (result == null)
{ {
result = Query.Where(movie => movie.CleanTitle == cleanTitleWithArabicNumbers).FirstWithYear(year) ?? result =
Query.Where(movie => movie.CleanTitle == cleanTitleWithRomanNumbers).FirstWithYear(year); q.Where(movie => movie.CleanTitle == cleanTitleWithArabicNumbers).FirstWithYear(year) ??
q.Where(movie => movie.CleanTitle == cleanTitleWithRomanNumbers).FirstWithYear(year);
if (result == null) if (result == null)
{ {
@ -250,13 +258,17 @@ private Movie FindByTitle(string cleanTitle, int? year)
//result = Query.Join<Movie, AlternativeTitle>(JoinType.Inner, m => m._newAltTitles, //result = Query.Join<Movie, AlternativeTitle>(JoinType.Inner, m => m._newAltTitles,
//(m, t) => m.Id == t.MovieId && (t.CleanTitle == cleanTitle)).FirstWithYear(year); //(m, t) => m.Id == t.MovieId && (t.CleanTitle == cleanTitle)).FirstWithYear(year);
result = Query.Where<AlternativeTitle>(t => result = q.Where<AlternativeTitle>(t =>
t.CleanTitle == cleanTitle || t.CleanTitle == cleanTitleWithArabicNumbers t.CleanTitle == cleanTitle || t.CleanTitle == cleanTitleWithArabicNumbers
|| t.CleanTitle == cleanTitleWithRomanNumbers).FirstWithYear(year); || t.CleanTitle == cleanTitleWithRomanNumbers)
.FirstWithYear(year);
} }
} }
return result; return result;
});
/*return year.HasValue /*return year.HasValue
? results?.FirstOrDefault(movie => movie.Year == year.Value) ? results?.FirstOrDefault(movie => movie.Year == year.Value)
@ -264,7 +276,7 @@ private Movie FindByTitle(string cleanTitle, int? year)
: results?.FirstOrDefault();*/ : results?.FirstOrDefault();*/
} }
protected override QueryBuilder<Movie> AddJoinQueries(QueryBuilder<Movie> baseQuery) protected override QueryBuilder<TActual> AddJoinQueries<TActual>(QueryBuilder<TActual> baseQuery)
{ {
baseQuery = base.AddJoinQueries(baseQuery); baseQuery = base.AddJoinQueries(baseQuery);
baseQuery = baseQuery.Join<Movie, AlternativeTitle>(JoinType.Left, m => m.AlternativeTitles, baseQuery = baseQuery.Join<Movie, AlternativeTitle>(JoinType.Left, m => m.AlternativeTitles,
@ -276,7 +288,7 @@ protected override QueryBuilder<Movie> AddJoinQueries(QueryBuilder<Movie> baseQu
public Movie FindByTmdbId(int tmdbid) public Movie FindByTmdbId(int tmdbid)
{ {
return Query.Where(m => m.TmdbId == tmdbid).FirstOrDefault(); return Query(q => q.Where(m => m.TmdbId == tmdbid).FirstOrDefault());
} }
} }
} }

View File

@ -8,7 +8,7 @@ public static class QueryExtensions
{ {
public static Movie FirstWithYear(this SortBuilder<Movie> query, int? year) public static Movie FirstWithYear(this SortBuilder<Movie> query, int? year)
{ {
return year.HasValue ? query.FirstOrDefault(movie => movie.Year == year || movie.SecondaryYear == year) : query.FirstOrDefault(); return year.HasValue ? query.AndWhere(movie => movie.Year == year || movie.SecondaryYear == year).FirstOrDefault() : query.FirstOrDefault();
} }
} }

View File

@ -30,12 +30,12 @@ public ImportExclusionsRepository(IMainDatabase database, IEventAggregator event
public bool IsMovieExcluded(int tmdbid) public bool IsMovieExcluded(int tmdbid)
{ {
return Query.Where(ex => ex.TmdbId == tmdbid).Any(); return Query(q => q.Where(ex => ex.TmdbId == tmdbid).Any());
} }
public ImportExclusion GetByTmdbid(int tmdbid) public ImportExclusion GetByTmdbid(int tmdbid)
{ {
return Query.Where(ex => ex.TmdbId == tmdbid).First(); return Query(q => q.Where(ex => ex.TmdbId == tmdbid).First());
} }
} }
} }

View File

@ -153,6 +153,7 @@
<Compile Include="Extras\Others\OtherExtraFileRenamer.cs" /> <Compile Include="Extras\Others\OtherExtraFileRenamer.cs" />
<Compile Include="HealthCheck\Checks\PTPOldSettingsCheck.cs" /> <Compile Include="HealthCheck\Checks\PTPOldSettingsCheck.cs" />
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedAlternativeTitles.cs" /> <Compile Include="Housekeeping\Housekeepers\CleanupOrphanedAlternativeTitles.cs" />
<Compile Include="MediaCover\EnsureMediaCoversCommand.cs" />
<Compile Include="MediaFiles\Commands\UpdateMovieFileQualityCommand.cs" /> <Compile Include="MediaFiles\Commands\UpdateMovieFileQualityCommand.cs" />
<Compile Include="MediaFiles\MovieImport\Specifications\GrabbedReleaseQualitySpecification.cs" /> <Compile Include="MediaFiles\MovieImport\Specifications\GrabbedReleaseQualitySpecification.cs" />
<Compile Include="MediaFiles\MovieImport\Specifications\SameFileSpecification.cs" /> <Compile Include="MediaFiles\MovieImport\Specifications\SameFileSpecification.cs" />

View File

@ -17,7 +17,10 @@ public ProfileRepository(IMainDatabase database, IEventAggregator eventAggregato
public bool Exists(int id) public bool Exists(int id)
{ {
return DataMapper.Query<Profile>().Where(p => p.Id == id).GetRowCount() == 1; using (var mapper = DataMapper())
{
return mapper.Query<Profile>().Where(p => p.Id == id).GetRowCount() == 1;
}
} }
} }
} }

View File

@ -19,7 +19,7 @@ public TagRepository(IMainDatabase database, IEventAggregator eventAggregator)
public Tag GetByLabel(string label) public Tag GetByLabel(string label)
{ {
var model = Query.Where(c => c.Label == label).SingleOrDefault(); var model = Query(q => q.Where(c => c.Label == label).SingleOrDefault());
if (model == null) if (model == null)
{ {