diff --git a/NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs b/NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs index b5c0c6f46..c8a651b0a 100644 --- a/NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs +++ b/NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs @@ -1,12 +1,8 @@ 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; @@ -18,7 +14,7 @@ namespace NzbDrone.Core.Test.Datastore [SetUp] public void SetUp() { - WithObjectDb(); + WithObjectDb(false); } [Test] @@ -27,7 +23,7 @@ namespace NzbDrone.Core.Test.Datastore var series = Builder.CreateNew().Build(); - ObjDb.Save(series); + ObjDb.Create(series); ObjDb.Ext().Purge(); @@ -41,14 +37,76 @@ namespace NzbDrone.Core.Test.Datastore var episode = Builder.CreateNew().Build(); //Save series without episode attached - ObjDb.Save(episode); + ObjDb.Create(episode); ObjDb.AsQueryable().Single().Series.Should().BeNull(); episode.Series = Builder.CreateNew().Build(); ObjDb.AsQueryable().Single().Series.Should().BeNull(); + } + + [Test] + public void rollback_should_reset_state() + { + var episode = Builder.CreateNew().Build(); + + ObjDb.Create(episode); + + ObjDb.AsQueryable().Should().HaveCount(1); + + ObjDb.Rollback(); + + ObjDb.AsQueryable().Should().HaveCount(0); + } + + [Test] + public void roolback_should_only_roll_back_what_is_not_commited() + { + var episode = Builder.CreateNew().Build(); + var series = Builder.CreateNew().Build(); + + ObjDb.Create(episode); + + ObjDb.Commit(); + + ObjDb.Create(series); + + ObjDb.Rollback(); + + ObjDb.AsQueryable().Should().HaveCount(1); + ObjDb.AsQueryable().Should().HaveCount(0); + } + + + [Test] + public void should_store_nested_objects() + { + var episode = Builder.CreateNew().Build(); + episode.Series = Builder.CreateNew().Build(); + + ObjDb.Create(episode); + + ObjDb.AsQueryable().Should().HaveCount(1); + ObjDb.AsQueryable().Single().Series.Should().NotBeNull(); + } + + [Test] + public void should_update_nested_objects() + { + var episode = Builder.CreateNew().Build(); + episode.Series = Builder.CreateNew().Build(); + + ObjDb.Create(episode); + + episode.Series.Title = "UpdatedTitle"; + + ObjDb.Update(episode,2); + + ObjDb.AsQueryable().Should().HaveCount(1); + ObjDb.AsQueryable().Single().Series.Should().NotBeNull(); + ObjDb.AsQueryable().Single().Series.Title.Should().Be("UpdatedTitle"); } } } diff --git a/NzbDrone.Core.Test/Framework/CoreTest.cs b/NzbDrone.Core.Test/Framework/CoreTest.cs index 49c76790a..9e0190682 100644 --- a/NzbDrone.Core.Test/Framework/CoreTest.cs +++ b/NzbDrone.Core.Test/Framework/CoreTest.cs @@ -93,9 +93,17 @@ namespace NzbDrone.Core.Test.Framework Mocker.SetConstant(Db); } - protected void WithObjectDb() + protected void WithObjectDb(bool memory = true) { - _objDb = new ObjectDbSessionFactory().Create(new PagingMemoryStorage()); + if (memory) + { + _objDb = new ObjectDbSessionFactory().Create(new PagingMemoryStorage()); + } + else + { + _objDb = new ObjectDbSessionFactory().Create(dbName: Guid.NewGuid().ToString()); + } + Mocker.SetConstant(ObjDb); } diff --git a/NzbDrone.Core/Datastore/DbProviderFactory.cs b/NzbDrone.Core/Datastore/DbProviderFactory.cs index 697296550..c34673469 100644 --- a/NzbDrone.Core/Datastore/DbProviderFactory.cs +++ b/NzbDrone.Core/Datastore/DbProviderFactory.cs @@ -1,9 +1,6 @@ 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; @@ -27,23 +24,4 @@ namespace NzbDrone.Core.Datastore 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); - } - } } diff --git a/NzbDrone.Core/Datastore/NoCacheReferenceSystem.cs b/NzbDrone.Core/Datastore/NoCacheReferenceSystem.cs new file mode 100644 index 000000000..c645f0599 --- /dev/null +++ b/NzbDrone.Core/Datastore/NoCacheReferenceSystem.cs @@ -0,0 +1,15 @@ +using System.Linq; +using Db4objects.Db4o.Internal; +using Db4objects.Db4o.Internal.References; + +namespace NzbDrone.Core.Datastore +{ + public class NoCacheReferenceSystem : HashcodeReferenceSystem + { + public override ObjectReference ReferenceForId(int id) + { + //never return an in memory instance of objects as query result. always go to db. + return null; + } + } +} diff --git a/NzbDrone.Core/Datastore/NoCahceRefrenceSystem.cs b/NzbDrone.Core/Datastore/NoCahceRefrenceSystem.cs deleted file mode 100644 index 73e5eac1b..000000000 --- a/NzbDrone.Core/Datastore/NoCahceRefrenceSystem.cs +++ /dev/null @@ -1,116 +0,0 @@ -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); - } - - } -} diff --git a/NzbDrone.Core/Datastore/IObjectDbSession.cs b/NzbDrone.Core/Datastore/ObjectDbSession.cs similarity index 77% rename from NzbDrone.Core/Datastore/IObjectDbSession.cs rename to NzbDrone.Core/Datastore/ObjectDbSession.cs index e1eace60d..ba11a6ceb 100644 --- a/NzbDrone.Core/Datastore/IObjectDbSession.cs +++ b/NzbDrone.Core/Datastore/ObjectDbSession.cs @@ -4,14 +4,13 @@ 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 Create(object obj); + void Create(object obj, int depth); void SaveAll(Transaction transaction, IEnumerator objects); void Update(object obj); @@ -22,54 +21,47 @@ namespace NzbDrone.Core.Datastore public class ObjectDbSession : ObjectContainerSession, IObjectDbSession { - private NoCahceRefrenceSystem _noCacheRefSystem; public ObjectDbSession(ObjectContainerBase server) - : base(server, server.NewTransaction(server.SystemTransaction(), new NoCahceRefrenceSystem(), false)) + : base(server, server.NewTransaction(server.SystemTransaction(), new NoCacheReferenceSystem(), 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()"); + throw new InvalidOperationException("Store is not supported. please use Create() or Update()"); } public override void StoreAll(Transaction transaction, IEnumerator objects) { - throw new InvalidOperationException("Store is not supported. please use Save() or Update()"); + throw new InvalidOperationException("Store is not supported. please use Create() or Update()"); } public override void Store(object obj, int depth) { - throw new InvalidOperationException("Store is not supported. please use Save() or Update()"); + throw new InvalidOperationException("Store is not supported. please use Create() or Update()"); } - public void Save(object obj) + public void Create(object obj) { - ValidateSave(obj); + ValidateCreate(obj); base.Store(obj); - Commit(); } - public void Save(object obj, int depth) + public void Create(object obj, int depth) { - ValidateSave(obj); + ValidateCreate(obj); base.Store(obj, depth); - Commit(); - } public void SaveAll(Transaction transaction, IEnumerator objects) { var obj = objects.ToIEnumerable().ToList(); - obj.ForEach(c => ValidateSave(c)); + obj.ForEach(c => ValidateCreate(c)); base.StoreAll(transaction, obj.GetEnumerator()); - Commit(); - } @@ -77,14 +69,12 @@ namespace NzbDrone.Core.Datastore { ValidateUpdate(obj); base.Store(obj); - Commit(); } public void Update(object obj, int depth) { ValidateUpdate(obj); base.Store(obj, depth); - Commit(); } public void UpdateAll(Transaction transaction, IEnumerator objects) @@ -93,7 +83,6 @@ namespace NzbDrone.Core.Datastore obj.ForEach(c => ValidateUpdate(c)); base.StoreAll(transaction, obj.GetEnumerator()); - Commit(); } public void UpdateAll(Transaction transaction, IEnumerator objects) @@ -101,12 +90,8 @@ namespace NzbDrone.Core.Datastore throw new NotImplementedException(); } - public new void Purge() - { - _noCacheRefSystem.Reset(); - } - private void ValidateSave(object obj) + private void ValidateCreate(object obj) { if (IsAttached(obj)) { diff --git a/NzbDrone.Core/Datastore/ObjectDbSessionFactory.cs b/NzbDrone.Core/Datastore/ObjectDbSessionFactory.cs new file mode 100644 index 000000000..00262ae2c --- /dev/null +++ b/NzbDrone.Core/Datastore/ObjectDbSessionFactory.cs @@ -0,0 +1,25 @@ +using System.Linq; +using Db4objects.Db4o; +using Db4objects.Db4o.IO; +using Db4objects.Db4o.Internal; + +namespace NzbDrone.Core.Datastore +{ + public class ObjectDbSessionFactory + { + public IObjectDbSession Create(IStorage storage = null, string dbName = "nzbdrone.db4o") + { + if (storage == null) + { + storage = new FileStorage(); + } + + var config = Db4oEmbedded.NewConfiguration(); + config.File.Storage = storage; + + + var objectContainer = Db4oEmbedded.OpenFile(config, dbName); + return new ObjectDbSession((ObjectContainerBase)objectContainer); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index a63b19dc8..c5c15ffe3 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -235,8 +235,8 @@ - - + + @@ -270,6 +270,7 @@ + diff --git a/NzbDrone.Services/NzbDrone.Services.Service/NzbDrone.Services.Service.csproj b/NzbDrone.Services/NzbDrone.Services.Service/NzbDrone.Services.Service.csproj index b2b576e4d..91f000b84 100644 --- a/NzbDrone.Services/NzbDrone.Services.Service/NzbDrone.Services.Service.csproj +++ b/NzbDrone.Services/NzbDrone.Services.Service/NzbDrone.Services.Service.csproj @@ -366,7 +366,7 @@ False True - 59157 + 17584 / http://localhost:62182/ False