mirror of
https://github.com/Radarr/Radarr.git
synced 2024-11-09 04:22:30 +01:00
Added db4o.
Added guards against most problematic areas.
This commit is contained in:
parent
b6a4e6c32c
commit
5dbaaee005
54
NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs
Normal file
54
NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.Repository.Quality;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using Db4objects.Db4o.Linq;
|
||||
|
||||
namespace NzbDrone.Core.Test.Datastore
|
||||
{
|
||||
[TestFixture]
|
||||
public class ObjectDatabaseFixture : CoreTest
|
||||
{
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
WithObjectDb();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_write_to_database()
|
||||
{
|
||||
|
||||
var series = Builder<Series>.CreateNew().Build();
|
||||
|
||||
ObjDb.Save(series);
|
||||
|
||||
ObjDb.Ext().Purge();
|
||||
|
||||
ObjDb.AsQueryable<Series>().Should().HaveCount(1);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_store_dirty_data_in_cache()
|
||||
{
|
||||
var episode = Builder<Episode>.CreateNew().Build();
|
||||
|
||||
//Save series without episode attached
|
||||
ObjDb.Save(episode);
|
||||
|
||||
ObjDb.AsQueryable<Episode>().Single().Series.Should().BeNull();
|
||||
|
||||
episode.Series = Builder<Series>.CreateNew().Build();
|
||||
|
||||
ObjDb.AsQueryable<Episode>().Single().Series.Should().BeNull();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Db4objects.Db4o.IO;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Model.Notification;
|
||||
@ -9,14 +10,14 @@
|
||||
|
||||
namespace NzbDrone.Core.Test.Framework
|
||||
{
|
||||
public class CoreTest : TestBase
|
||||
public abstract class CoreTest : TestBase
|
||||
{
|
||||
private string _dbTemplateName;
|
||||
|
||||
[SetUp]
|
||||
public void CoreTestSetup()
|
||||
{
|
||||
if(NCrunch.Framework.NCrunchEnvironment.NCrunchIsResident())
|
||||
if (NCrunch.Framework.NCrunchEnvironment.NCrunchIsResident())
|
||||
{
|
||||
_dbTemplateName = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()) + ".sdf";
|
||||
}
|
||||
@ -24,6 +25,7 @@ public void CoreTestSetup()
|
||||
{
|
||||
_dbTemplateName = "db_template.sdf";
|
||||
}
|
||||
|
||||
CreateDataBaseTemplate();
|
||||
}
|
||||
|
||||
@ -71,12 +73,32 @@ protected IDatabase Db
|
||||
}
|
||||
}
|
||||
|
||||
private IObjectDbSession _objDb;
|
||||
protected IObjectDbSession ObjDb
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_objDb == null)
|
||||
throw new InvalidOperationException("Test object database doesn't exists. Make sure you call WithRealDb() if you intend to use an actual database.");
|
||||
|
||||
return _objDb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void WithRealDb()
|
||||
{
|
||||
_db = GetEmptyDatabase();
|
||||
Mocker.SetConstant(Db);
|
||||
}
|
||||
|
||||
protected void WithObjectDb()
|
||||
{
|
||||
_objDb = new ObjectDbSessionFactory().Create(new PagingMemoryStorage());
|
||||
Mocker.SetConstant(ObjDb);
|
||||
}
|
||||
|
||||
protected static ProgressNotification MockNotification
|
||||
{
|
||||
get
|
||||
@ -106,6 +128,11 @@ public void CoreTestTearDown()
|
||||
}
|
||||
catch (IOException) { }
|
||||
}
|
||||
|
||||
if (_objDb != null)
|
||||
{
|
||||
_objDb.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,15 @@
|
||||
<Reference Include="AutoMoq">
|
||||
<HintPath>..\packages\AutoMoq.1.6.1\lib\AutoMoq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Db4objects.Db4o">
|
||||
<HintPath>..\packages\db4o-devel.8.1.184.15492\lib\net40\Db4objects.Db4o.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Db4objects.Db4o.Data.Services">
|
||||
<HintPath>..\packages\db4o-devel.8.1.184.15492\lib\net40\Db4objects.Db4o.Data.Services.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Db4objects.Db4o.Linq">
|
||||
<HintPath>..\packages\db4o-devel.8.1.184.15492\lib\net40\Db4objects.Db4o.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DeskMetrics.NET, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Libraries\DeskMetrics\DeskMetrics.NET.dll</HintPath>
|
||||
@ -88,6 +97,9 @@
|
||||
<Reference Include="Microsoft.Practices.Unity.Configuration">
|
||||
<HintPath>..\packages\Unity.2.1.505.2\lib\NET35\Microsoft.Practices.Unity.Configuration.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Reflection">
|
||||
<HintPath>..\packages\db4o-devel.8.1.184.15492\lib\net40\Mono.Reflection.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
@ -134,6 +146,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Datastore\ObjectDatabaseFixture.cs" />
|
||||
<Compile Include="Framework\CoreTestTSubject.cs" />
|
||||
<Compile Include="HelperTests\XElementHelperTests\ConvertToTFixture.cs" />
|
||||
<Compile Include="IndexerTests\NzbxFixture.cs" />
|
||||
|
@ -3,6 +3,7 @@
|
||||
<package id="Autofac" version="2.6.3.862" targetFramework="net40" />
|
||||
<package id="AutoMoq" version="1.6.1" targetFramework="net40" />
|
||||
<package id="CommonServiceLocator" version="1.0" targetFramework="net40" />
|
||||
<package id="db4o-devel" version="8.1.184.15492" targetFramework="net40" />
|
||||
<package id="FluentAssertions" version="2.0.0.1" targetFramework="net40" />
|
||||
<package id="Microsoft.SqlServer.Compact" version="4.0.8876.1" targetFramework="net40" />
|
||||
<package id="Moq" version="4.0.10827" />
|
||||
|
@ -1,6 +1,10 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.Data.SqlServerCe;
|
||||
using Db4objects.Db4o;
|
||||
using Db4objects.Db4o.IO;
|
||||
using Db4objects.Db4o.Internal;
|
||||
using Db4objects.Db4o.Internal.Config;
|
||||
using StackExchange.Profiling;
|
||||
using StackExchange.Profiling.Data;
|
||||
|
||||
@ -23,4 +27,23 @@ public override DbConnection CreateConnection()
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ObjectDbSessionFactory
|
||||
{
|
||||
public IObjectDbSession Create(IStorage storage = null)
|
||||
{
|
||||
if (storage == null)
|
||||
{
|
||||
storage = new FileStorage();
|
||||
}
|
||||
|
||||
var config = Db4oEmbedded.NewConfiguration();
|
||||
config.File.Storage = storage;
|
||||
|
||||
|
||||
var objectContainer = Db4oEmbedded.OpenFile(config, "nzbdrone.db4o");
|
||||
return new ObjectDbSession((ObjectContainerBase)objectContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
142
NzbDrone.Core/Datastore/IObjectDbSession.cs
Normal file
142
NzbDrone.Core/Datastore/IObjectDbSession.cs
Normal file
@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Db4objects.Db4o;
|
||||
using Db4objects.Db4o.Internal;
|
||||
using Db4objects.Db4o.Internal.References;
|
||||
|
||||
namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
public interface IObjectDbSession : IObjectContainer
|
||||
{
|
||||
void Save(object obj);
|
||||
void Save(object obj, int depth);
|
||||
void SaveAll<T>(Transaction transaction, IEnumerator<T> objects);
|
||||
|
||||
void Update(object obj);
|
||||
void Update(object obj, int depth);
|
||||
void UpdateAll<T>(Transaction transaction, IEnumerator<T> objects);
|
||||
}
|
||||
|
||||
|
||||
public class ObjectDbSession : ObjectContainerSession, IObjectDbSession
|
||||
{
|
||||
private NoCahceRefrenceSystem _noCacheRefSystem;
|
||||
|
||||
public ObjectDbSession(ObjectContainerBase server)
|
||||
: base(server, server.NewTransaction(server.SystemTransaction(), new NoCahceRefrenceSystem(), false))
|
||||
{
|
||||
_transaction.SetOutSideRepresentation(this);
|
||||
_noCacheRefSystem = (NoCahceRefrenceSystem)_transaction.ReferenceSystem();
|
||||
}
|
||||
|
||||
public override void Store(object obj)
|
||||
{
|
||||
throw new InvalidOperationException("Store is not supported. please use Save() or Update()");
|
||||
}
|
||||
|
||||
public override void StoreAll(Transaction transaction, IEnumerator objects)
|
||||
{
|
||||
throw new InvalidOperationException("Store is not supported. please use Save() or Update()");
|
||||
|
||||
}
|
||||
|
||||
public override void Store(object obj, int depth)
|
||||
{
|
||||
throw new InvalidOperationException("Store is not supported. please use Save() or Update()");
|
||||
}
|
||||
|
||||
public void Save(object obj)
|
||||
{
|
||||
ValidateSave(obj);
|
||||
base.Store(obj);
|
||||
Commit();
|
||||
}
|
||||
|
||||
public void Save(object obj, int depth)
|
||||
{
|
||||
ValidateSave(obj);
|
||||
base.Store(obj, depth);
|
||||
Commit();
|
||||
|
||||
}
|
||||
|
||||
public void SaveAll<T>(Transaction transaction, IEnumerator<T> objects)
|
||||
{
|
||||
var obj = objects.ToIEnumerable().ToList();
|
||||
obj.ForEach(c => ValidateSave(c));
|
||||
|
||||
base.StoreAll(transaction, obj.GetEnumerator());
|
||||
Commit();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void Update(object obj)
|
||||
{
|
||||
ValidateUpdate(obj);
|
||||
base.Store(obj);
|
||||
Commit();
|
||||
}
|
||||
|
||||
public void Update(object obj, int depth)
|
||||
{
|
||||
ValidateUpdate(obj);
|
||||
base.Store(obj, depth);
|
||||
Commit();
|
||||
}
|
||||
|
||||
public void UpdateAll<T>(Transaction transaction, IEnumerator<T> objects)
|
||||
{
|
||||
var obj = objects.ToIEnumerable().ToList();
|
||||
obj.ForEach(c => ValidateUpdate(c));
|
||||
|
||||
base.StoreAll(transaction, obj.GetEnumerator());
|
||||
Commit();
|
||||
}
|
||||
|
||||
public void UpdateAll(Transaction transaction, IEnumerator objects)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public new void Purge()
|
||||
{
|
||||
_noCacheRefSystem.Reset();
|
||||
}
|
||||
|
||||
private void ValidateSave(object obj)
|
||||
{
|
||||
if (IsAttached(obj))
|
||||
{
|
||||
throw new InvalidOperationException("Attempted to save an object that is already attached to database");
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateUpdate(object obj)
|
||||
{
|
||||
if (!IsAttached(obj))
|
||||
{
|
||||
throw new InvalidOperationException("Attempted to update an object that is not attached to database");
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsAttached(object obj)
|
||||
{
|
||||
return base.Ext().GetID(obj) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Ext
|
||||
{
|
||||
public static IEnumerable<T> ToIEnumerable<T>(this IEnumerator<T> enumerator)
|
||||
{
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
yield return enumerator.Current;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
116
NzbDrone.Core/Datastore/NoCahceRefrenceSystem.cs
Normal file
116
NzbDrone.Core/Datastore/NoCahceRefrenceSystem.cs
Normal file
@ -0,0 +1,116 @@
|
||||
using System.Linq;
|
||||
using Db4objects.Db4o;
|
||||
using Db4objects.Db4o.Foundation;
|
||||
using Db4objects.Db4o.Internal;
|
||||
using Db4objects.Db4o.Internal.References;
|
||||
|
||||
namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
public class NoCahceRefrenceSystem : IReferenceSystem
|
||||
{
|
||||
private ObjectReference _hashCodeTree;
|
||||
private ObjectReference _idTree;
|
||||
|
||||
internal NoCahceRefrenceSystem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void AddNewReference(ObjectReference @ref)
|
||||
{
|
||||
AddReference(@ref);
|
||||
}
|
||||
|
||||
public virtual void AddExistingReference(ObjectReference @ref)
|
||||
{
|
||||
AddReference(@ref);
|
||||
}
|
||||
|
||||
public virtual void Commit()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public virtual ObjectReference ReferenceForId(int id)
|
||||
{
|
||||
if (DTrace.enabled)
|
||||
DTrace.GetYapobject.Log(id);
|
||||
if (_idTree == null)
|
||||
return null;
|
||||
if (!ObjectReference.IsValidId(id))
|
||||
return null;
|
||||
else
|
||||
return _idTree.Id_find(id);
|
||||
}
|
||||
|
||||
public virtual ObjectReference ReferenceForObject(object obj)
|
||||
{
|
||||
if (_hashCodeTree == null)
|
||||
return null;
|
||||
else
|
||||
return _hashCodeTree.Hc_find(obj);
|
||||
}
|
||||
|
||||
public virtual void RemoveReference(ObjectReference @ref)
|
||||
{
|
||||
if (DTrace.enabled)
|
||||
DTrace.ReferenceRemoved.Log(@ref.GetID());
|
||||
if (_hashCodeTree != null)
|
||||
_hashCodeTree = _hashCodeTree.Hc_remove(@ref);
|
||||
if (_idTree == null)
|
||||
return;
|
||||
_idTree = _idTree.Id_remove(@ref);
|
||||
}
|
||||
|
||||
public virtual void Rollback()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public virtual void TraverseReferences(IVisitor4 visitor)
|
||||
{
|
||||
if (_hashCodeTree == null)
|
||||
return;
|
||||
_hashCodeTree.Hc_traverse(visitor);
|
||||
}
|
||||
|
||||
public virtual void Discarded()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_hashCodeTree = null;
|
||||
_idTree = null;
|
||||
}
|
||||
|
||||
private void AddReference(ObjectReference @ref)
|
||||
{
|
||||
@ref.Ref_init();
|
||||
IdAdd(@ref);
|
||||
HashCodeAdd(@ref);
|
||||
}
|
||||
|
||||
private void HashCodeAdd(ObjectReference @ref)
|
||||
{
|
||||
if (_hashCodeTree == null)
|
||||
_hashCodeTree = @ref;
|
||||
else
|
||||
_hashCodeTree = _hashCodeTree.Hc_add(@ref);
|
||||
}
|
||||
|
||||
private void IdAdd(ObjectReference @ref)
|
||||
{
|
||||
if (DTrace.enabled)
|
||||
DTrace.IdTreeAdd.Log(@ref.GetID());
|
||||
if (_idTree == null)
|
||||
_idTree = @ref;
|
||||
else
|
||||
_idTree = _idTree.Id_add(@ref);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -133,6 +133,15 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\DataTables.Mvc.Core.0.1.0.85\lib\DataTables.Mvc.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Db4objects.Db4o">
|
||||
<HintPath>..\packages\db4o-devel.8.1.184.15492\lib\net40\Db4objects.Db4o.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Db4objects.Db4o.Data.Services">
|
||||
<HintPath>..\packages\db4o-devel.8.1.184.15492\lib\net40\Db4objects.Db4o.Data.Services.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Db4objects.Db4o.Linq">
|
||||
<HintPath>..\packages\db4o-devel.8.1.184.15492\lib\net40\Db4objects.Db4o.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DeskMetrics.NET">
|
||||
<HintPath>..\Libraries\DeskMetrics\DeskMetrics.NET.dll</HintPath>
|
||||
</Reference>
|
||||
@ -168,6 +177,9 @@
|
||||
<Reference Include="MiniProfiler">
|
||||
<HintPath>..\packages\MiniProfiler.2.0.2\lib\net40\MiniProfiler.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Reflection">
|
||||
<HintPath>..\packages\db4o-devel.8.1.184.15492\lib\net40\Mono.Reflection.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
@ -223,6 +235,8 @@
|
||||
<Compile Include="Constants.cs" />
|
||||
<Compile Include="ContainerExtentions.cs" />
|
||||
<Compile Include="Datastore\ConnectionFactory.cs" />
|
||||
<Compile Include="Datastore\NoCahceRefrenceSystem.cs" />
|
||||
<Compile Include="Datastore\IObjectDbSession.cs" />
|
||||
<Compile Include="Datastore\MigrationLogger.cs" />
|
||||
<Compile Include="Datastore\MigrationsHelper.cs" />
|
||||
<Compile Include="Datastore\CustomeMapper.cs" />
|
||||
|
@ -2,6 +2,7 @@
|
||||
<packages>
|
||||
<package id="Autofac" version="2.6.3.862" targetFramework="net40" />
|
||||
<package id="DataTables.Mvc.Core" version="0.1.0.85" />
|
||||
<package id="db4o-devel" version="8.1.184.15492" targetFramework="net40" />
|
||||
<package id="DotNetZip" version="1.9.1.8" />
|
||||
<package id="Growl" version="0.6" />
|
||||
<package id="MediaInfoNet" version="0.3" targetFramework="net40" />
|
||||
|
@ -16,7 +16,7 @@
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.8.0" newVersion="4.0.8.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.5.0.0" newVersion="4.5.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
|
@ -8,9 +8,8 @@
|
||||
|
||||
namespace NzbDrone.Test.Common
|
||||
{
|
||||
public class TestBase : LoggingTest
|
||||
public abstract class TestBase : LoggingTest
|
||||
{
|
||||
|
||||
protected const string INTEGRATION_TEST = "Integration Test";
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user