less intrusive cache prevention.

more tests.
pull/3113/head
kay.one 12 years ago
parent 5dbaaee005
commit 9f829c1442

@ -1,12 +1,8 @@
using System.Linq; using System.Linq;
using System;
using System.Collections.Generic;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Model;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using Db4objects.Db4o.Linq; using Db4objects.Db4o.Linq;
@ -18,7 +14,7 @@ namespace NzbDrone.Core.Test.Datastore
[SetUp] [SetUp]
public void SetUp() public void SetUp()
{ {
WithObjectDb(); WithObjectDb(false);
} }
[Test] [Test]
@ -27,7 +23,7 @@ namespace NzbDrone.Core.Test.Datastore
var series = Builder<Series>.CreateNew().Build(); var series = Builder<Series>.CreateNew().Build();
ObjDb.Save(series); ObjDb.Create(series);
ObjDb.Ext().Purge(); ObjDb.Ext().Purge();
@ -41,14 +37,76 @@ namespace NzbDrone.Core.Test.Datastore
var episode = Builder<Episode>.CreateNew().Build(); var episode = Builder<Episode>.CreateNew().Build();
//Save series without episode attached //Save series without episode attached
ObjDb.Save(episode); ObjDb.Create(episode);
ObjDb.AsQueryable<Episode>().Single().Series.Should().BeNull(); ObjDb.AsQueryable<Episode>().Single().Series.Should().BeNull();
episode.Series = Builder<Series>.CreateNew().Build(); episode.Series = Builder<Series>.CreateNew().Build();
ObjDb.AsQueryable<Episode>().Single().Series.Should().BeNull(); ObjDb.AsQueryable<Episode>().Single().Series.Should().BeNull();
}
[Test]
public void rollback_should_reset_state()
{
var episode = Builder<Episode>.CreateNew().Build();
ObjDb.Create(episode);
ObjDb.AsQueryable<Episode>().Should().HaveCount(1);
ObjDb.Rollback();
ObjDb.AsQueryable<Episode>().Should().HaveCount(0);
}
[Test]
public void roolback_should_only_roll_back_what_is_not_commited()
{
var episode = Builder<Episode>.CreateNew().Build();
var series = Builder<Series>.CreateNew().Build();
ObjDb.Create(episode);
ObjDb.Commit();
ObjDb.Create(series);
ObjDb.Rollback();
ObjDb.AsQueryable<Episode>().Should().HaveCount(1);
ObjDb.AsQueryable<Series>().Should().HaveCount(0);
}
[Test]
public void should_store_nested_objects()
{
var episode = Builder<Episode>.CreateNew().Build();
episode.Series = Builder<Series>.CreateNew().Build();
ObjDb.Create(episode);
ObjDb.AsQueryable<Episode>().Should().HaveCount(1);
ObjDb.AsQueryable<Episode>().Single().Series.Should().NotBeNull();
}
[Test]
public void should_update_nested_objects()
{
var episode = Builder<Episode>.CreateNew().Build();
episode.Series = Builder<Series>.CreateNew().Build();
ObjDb.Create(episode);
episode.Series.Title = "UpdatedTitle";
ObjDb.Update(episode,2);
ObjDb.AsQueryable<Episode>().Should().HaveCount(1);
ObjDb.AsQueryable<Episode>().Single().Series.Should().NotBeNull();
ObjDb.AsQueryable<Episode>().Single().Series.Title.Should().Be("UpdatedTitle");
} }
} }
} }

@ -93,9 +93,17 @@ namespace NzbDrone.Core.Test.Framework
Mocker.SetConstant(Db); 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); Mocker.SetConstant(ObjDb);
} }

@ -1,9 +1,6 @@
using System; using System;
using System.Data.Common; using System.Data.Common;
using System.Data.SqlServerCe; using System.Data.SqlServerCe;
using Db4objects.Db4o;
using Db4objects.Db4o.IO;
using Db4objects.Db4o.Internal;
using Db4objects.Db4o.Internal.Config; using Db4objects.Db4o.Internal.Config;
using StackExchange.Profiling; using StackExchange.Profiling;
using StackExchange.Profiling.Data; using StackExchange.Profiling.Data;
@ -27,23 +24,4 @@ namespace NzbDrone.Core.Datastore
return connection; 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);
}
}
} }

@ -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;
}
}
}

@ -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);
}
}
}

@ -4,14 +4,13 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Db4objects.Db4o; using Db4objects.Db4o;
using Db4objects.Db4o.Internal; using Db4objects.Db4o.Internal;
using Db4objects.Db4o.Internal.References;
namespace NzbDrone.Core.Datastore namespace NzbDrone.Core.Datastore
{ {
public interface IObjectDbSession : IObjectContainer public interface IObjectDbSession : IObjectContainer
{ {
void Save(object obj); void Create(object obj);
void Save(object obj, int depth); void Create(object obj, int depth);
void SaveAll<T>(Transaction transaction, IEnumerator<T> objects); void SaveAll<T>(Transaction transaction, IEnumerator<T> objects);
void Update(object obj); void Update(object obj);
@ -22,54 +21,47 @@ namespace NzbDrone.Core.Datastore
public class ObjectDbSession : ObjectContainerSession, IObjectDbSession public class ObjectDbSession : ObjectContainerSession, IObjectDbSession
{ {
private NoCahceRefrenceSystem _noCacheRefSystem;
public ObjectDbSession(ObjectContainerBase server) 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); _transaction.SetOutSideRepresentation(this);
_noCacheRefSystem = (NoCahceRefrenceSystem)_transaction.ReferenceSystem();
} }
public override void Store(object obj) 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) 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) 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); 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); base.Store(obj, depth);
Commit();
} }
public void SaveAll<T>(Transaction transaction, IEnumerator<T> objects) public void SaveAll<T>(Transaction transaction, IEnumerator<T> objects)
{ {
var obj = objects.ToIEnumerable().ToList(); var obj = objects.ToIEnumerable().ToList();
obj.ForEach(c => ValidateSave(c)); obj.ForEach(c => ValidateCreate(c));
base.StoreAll(transaction, obj.GetEnumerator()); base.StoreAll(transaction, obj.GetEnumerator());
Commit();
} }
@ -77,14 +69,12 @@ namespace NzbDrone.Core.Datastore
{ {
ValidateUpdate(obj); ValidateUpdate(obj);
base.Store(obj); base.Store(obj);
Commit();
} }
public void Update(object obj, int depth) public void Update(object obj, int depth)
{ {
ValidateUpdate(obj); ValidateUpdate(obj);
base.Store(obj, depth); base.Store(obj, depth);
Commit();
} }
public void UpdateAll<T>(Transaction transaction, IEnumerator<T> objects) public void UpdateAll<T>(Transaction transaction, IEnumerator<T> objects)
@ -93,7 +83,6 @@ namespace NzbDrone.Core.Datastore
obj.ForEach(c => ValidateUpdate(c)); obj.ForEach(c => ValidateUpdate(c));
base.StoreAll(transaction, obj.GetEnumerator()); base.StoreAll(transaction, obj.GetEnumerator());
Commit();
} }
public void UpdateAll(Transaction transaction, IEnumerator objects) public void UpdateAll(Transaction transaction, IEnumerator objects)
@ -101,12 +90,8 @@ namespace NzbDrone.Core.Datastore
throw new NotImplementedException(); throw new NotImplementedException();
} }
public new void Purge()
{
_noCacheRefSystem.Reset();
}
private void ValidateSave(object obj) private void ValidateCreate(object obj)
{ {
if (IsAttached(obj)) if (IsAttached(obj))
{ {

@ -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);
}
}
}

@ -235,8 +235,8 @@
<Compile Include="Constants.cs" /> <Compile Include="Constants.cs" />
<Compile Include="ContainerExtentions.cs" /> <Compile Include="ContainerExtentions.cs" />
<Compile Include="Datastore\ConnectionFactory.cs" /> <Compile Include="Datastore\ConnectionFactory.cs" />
<Compile Include="Datastore\NoCahceRefrenceSystem.cs" /> <Compile Include="Datastore\NoCacheReferenceSystem.cs" />
<Compile Include="Datastore\IObjectDbSession.cs" /> <Compile Include="Datastore\ObjectDbSession.cs" />
<Compile Include="Datastore\MigrationLogger.cs" /> <Compile Include="Datastore\MigrationLogger.cs" />
<Compile Include="Datastore\MigrationsHelper.cs" /> <Compile Include="Datastore\MigrationsHelper.cs" />
<Compile Include="Datastore\CustomeMapper.cs" /> <Compile Include="Datastore\CustomeMapper.cs" />
@ -270,6 +270,7 @@
<Compile Include="Datastore\Migrations\Migration20121223.cs" /> <Compile Include="Datastore\Migrations\Migration20121223.cs" />
<Compile Include="Datastore\Migrations\NzbDroneMigration.cs" /> <Compile Include="Datastore\Migrations\NzbDroneMigration.cs" />
<Compile Include="Datastore\Migrations\SchemaInfo.cs" /> <Compile Include="Datastore\Migrations\SchemaInfo.cs" />
<Compile Include="Datastore\ObjectDbSessionFactory.cs" />
<Compile Include="Datastore\PetaPoco\EpisodeSeasonRelator.cs" /> <Compile Include="Datastore\PetaPoco\EpisodeSeasonRelator.cs" />
<Compile Include="Fluent.cs" /> <Compile Include="Fluent.cs" />
<Compile Include="Helpers\Converters\EpochDateTimeConverter.cs" /> <Compile Include="Helpers\Converters\EpochDateTimeConverter.cs" />

@ -366,7 +366,7 @@
<WebProjectProperties> <WebProjectProperties>
<UseIIS>False</UseIIS> <UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort> <AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>59157</DevelopmentServerPort> <DevelopmentServerPort>17584</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath> <DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:62182/</IISUrl> <IISUrl>http://localhost:62182/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication> <NTLMAuthentication>False</NTLMAuthentication>

Loading…
Cancel
Save