Skip to content

Commit

Permalink
fix bug #10 + commenting and refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
rofr committed Sep 25, 2014
1 parent d10059d commit bb8ed4d
Show file tree
Hide file tree
Showing 21 changed files with 272 additions and 189 deletions.
3 changes: 1 addition & 2 deletions OrigoDb.Core.nuspec
Expand Up @@ -22,7 +22,6 @@
<files>
<file src="build/OrigoDB.Core.dll" target="lib\net40" />
<file src="build/OrigoDB.Core.pdb" target="lib\net40" />
<file src="build/OrigoDB.Core.XML" target="lib\net40" />
<file src="src/OrigoDB.Core/**/*.cs" target="src" />
</files>
</package>
</package>
1 change: 0 additions & 1 deletion src/OrigoDB.Core.Test/FileStoreTest.cs
Expand Up @@ -2,7 +2,6 @@
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using OrigoDB.Core;

namespace OrigoDB.Core.Test
{
Expand Down
23 changes: 23 additions & 0 deletions src/OrigoDB.Core.UnitTests/EngineConfigurationTest.cs
Expand Up @@ -8,6 +8,29 @@
namespace OrigoDB.Core.Test
{

[TestFixture]
public class EngineLoadTest
{
[Test]
public void CanLoadAndCreateRepeatedly()
{
var config = EngineConfiguration.Create().WithRandomLocation();
try
{
var engine = Engine.LoadOrCreate<TestModel>(config);
engine.Execute(new TestCommandWithResult());
engine.Close();
engine = Engine.LoadOrCreate<TestModel>(config);
engine.Close();
}
finally
{
if (config.CreateCommandStore() is FileCommandStore)
Directory.Delete(config.Location.OfJournal, true);
}
}
}

[TestFixture]
public class EngineConfigurationTest
{
Expand Down
36 changes: 15 additions & 21 deletions src/OrigoDB.Core/Engine.cs
Expand Up @@ -69,7 +69,11 @@ protected Engine(Model model, EngineConfiguration config)
Thread.Sleep(TimeSpan.FromMilliseconds(10));
}

CommandExecuted += (s, e) => HandleSnapshotPersistence();
if (_config.PersistenceMode == PersistenceMode.SnapshotPerTransaction)
{
CommandExecuted += (s, e) => CreateSnapshot();
}


Core.Config.Engines.AddEngine(config.Location.OfJournal, this);
}
Expand Down Expand Up @@ -124,7 +128,7 @@ public object Execute(Query query)
/// </summary>
public TResult Execute<TModel, TResult>(Func<TModel, TResult> lambdaQuery) where TModel : Model
{
EnsureRunning();
EnsureNotDisposed();
EnsureAuthorized(lambdaQuery);
return ExecuteQuery(new DelegateQuery<TModel, TResult>(lambdaQuery));
}
Expand All @@ -134,7 +138,7 @@ public object Execute(Query query)
/// </summary>
public TRresult Execute<TModel, TRresult>(Query<TModel, TRresult> query) where TModel : Model
{
EnsureRunning();
EnsureNotDisposed();
EnsureAuthorized(query);
return ExecuteQuery(query);
}
Expand All @@ -144,7 +148,7 @@ public object Execute(Query query)
/// </summary>
public object Execute(Command command)
{
EnsureRunning();
EnsureNotDisposed();
EnsureAuthorized(command);
FireExecutingEvent(command);

Expand All @@ -153,7 +157,11 @@ public object Execute(Command command)
command.Timestamp = DateTime.Now;
bool exceptionThrown = false;
_executionTimer.Restart();
ulong lastEntryId = PersistIfJournaling(command);

ulong lastEntryId = (_config.PersistenceMode == PersistenceMode.Journaling)
? _journalAppender.Append(command)
: 0;

try
{
_capturedEvents.Clear();
Expand Down Expand Up @@ -195,21 +203,6 @@ private void FireExecutingEvent(Command command)
}


private ulong PersistIfJournaling(Command command)
{
return _config.PersistenceMode == PersistenceMode.Journaling
? _journalAppender.Append(command)
: 0;
}

private void HandleSnapshotPersistence()
{
if (_config.PersistenceMode == PersistenceMode.SnapshotPerTransaction)
{
CreateSnapshot();
}
}

private void EnsureAuthorized(object securable)
{
var principal = Thread.CurrentPrincipal;
Expand Down Expand Up @@ -266,6 +259,7 @@ private void Dispose(bool disposing)
if (_isDisposed) return;
if (disposing)
{
_journalAppender.Dispose();
//todo: bad dependency, use events instead
Core.Config.Engines.Remove(this);
if (_config.SnapshotBehavior == SnapshotBehavior.OnShutdown) CreateSnapshot();
Expand All @@ -289,7 +283,7 @@ public void Close()
Dispose(true);
}

private void EnsureRunning()
private void EnsureNotDisposed()
{
if (_isDisposed) throw new ObjectDisposedException(GetType().FullName);
}
Expand Down
6 changes: 5 additions & 1 deletion src/OrigoDB.Core/Journaling/IJournalWriter.cs
Expand Up @@ -2,9 +2,13 @@

namespace OrigoDB.Core
{
/// <summary>
/// Journal writers write JournalEntry objects to the journal
/// </summary>
public interface IJournalWriter : IDisposable
{
void Write(JournalEntry item);
void Close();

void Close();
}
}
7 changes: 6 additions & 1 deletion src/OrigoDB.Core/Journaling/JournalAppender.cs
Expand Up @@ -8,7 +8,7 @@ namespace OrigoDB.Core
/// Wraps objects in JournalEntry and sends to an underlying writer.
/// Responsible for maintaining the sequence number.
/// </summary>
public class JournalAppender
public class JournalAppender : IDisposable
{
readonly IJournalWriter _writer;
private ulong _nextEntryId;
Expand Down Expand Up @@ -88,5 +88,10 @@ public static JournalAppender Create(ulong nextEntryId, IJournalWriter writer)
{
return new JournalAppender(nextEntryId, writer);
}

public void Dispose()
{
_writer.Dispose();
}
}
}
2 changes: 0 additions & 2 deletions src/OrigoDB.Core/Model.cs
@@ -1,6 +1,4 @@
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;

namespace OrigoDB.Core
{
Expand Down
8 changes: 6 additions & 2 deletions src/OrigoDB.Core/OrigoDB.Core.csproj
Expand Up @@ -87,6 +87,10 @@
<Compile Include="Events\IEvent.cs" />
<Compile Include="Events\IHandleEvents.cs" />
<Compile Include="Events\ISelectEvents.cs" />
<Compile Include="Storage\Rollover\CompositeRolloverStrategy.cs" />
<Compile Include="Storage\Rollover\MaxBytesRolloverStrategy.cs" />
<Compile Include="Storage\Rollover\MaxEntriesRolloverStrategy.cs" />
<Compile Include="Storage\Rollover\ScheduledRolloverStrategy.cs" />
<Compile Include="Utilities\Utils.Converters.cs" />
<Compile Include="Journaling\JournalAppender.cs" />
<Compile Include="Journaling\ModelCreated.cs" />
Expand All @@ -99,7 +103,7 @@
<Compile Include="Storage\FileSnapshot.cs" />
<Compile Include="Storage\FileSnapshotStore.cs" />
<Compile Include="Storage\FormatterExtensions.cs" />
<Compile Include="Storage\Initialized.cs" />
<Compile Include="Storage\Initializable.cs" />
<Compile Include="Storage\InMemorySnapshotStore.cs" />
<Compile Include="Storage\ISnapshotStore.cs" />
<Compile Include="Storage\ModelLoader.cs" />
Expand Down Expand Up @@ -158,7 +162,7 @@
<Compile Include="Utilities\Disposable[T].cs" />
<Compile Include="Linq\CachingLinqCompiler.cs" />
<Compile Include="Linq\CompiledLinqExtensions.cs" />
<Compile Include="Storage\RolloverStrategy.cs" />
<Compile Include="Storage\Rollover\RolloverStrategy.cs" />
<Compile Include="Proxy\ModelProxy.cs" />
<Compile Include="Proxy\ProxyMethodAttribute.cs" />
<Compile Include="Proxy\ProxyCommand.cs" />
Expand Down
97 changes: 59 additions & 38 deletions src/OrigoDB.Core/Storage/CommandStore.cs
Expand Up @@ -8,18 +8,42 @@
namespace OrigoDB.Core.Storage
{

public abstract class CommandStore : Initialized, ICommandStore
/// <summary>
/// Base class with common behavior for CommandStore implementations
/// </summary>
public abstract class CommandStore : Initializable, ICommandStore
{
protected static ILogger _log = LogProvider.Factory.GetLoggerForCallingType();

protected EngineConfiguration _config;
protected IFormatter _formatter;


protected abstract IJournalWriter CreateStoreSpecificJournalWriter();
public abstract IEnumerable<JournalEntry> GetJournalEntriesFrom(ulong entryId);
public abstract IEnumerable<JournalEntry> GetJournalEntriesBeforeOrAt(DateTime pointInTime);
/// <summary>
/// Read the sequence of entries with id greater than or equal to a given entryId
/// </summary>
protected abstract IEnumerable<JournalEntry> GetJournalEntriesFromImpl(ulong entryId);


/// <summary>
/// Get an append-only stream for writing journal entries
/// </summary>
public abstract Stream CreateJournalWriterStream(ulong firstEntryId = 1);

/// <summary>
/// Override if necessary
/// </summary>
/// <param name="pointInTime"></param>
/// <returns></returns>
public virtual IEnumerable<JournalEntry> GetJournalEntriesBeforeOrAt(DateTime pointInTime)
{
return GetJournalEntriesFrom(0).TakeWhile(e => e.Created <= pointInTime);
}


protected virtual IJournalWriter CreateStoreSpecificJournalWriter()
{
return new StreamJournalWriter(_config, CreateJournalWriterStream);
}


protected CommandStore(EngineConfiguration config)
Expand All @@ -28,16 +52,28 @@ protected CommandStore(EngineConfiguration config)
}



public virtual IEnumerable<JournalEntry> GetJournalEntries()
public IEnumerable<JournalEntry> GetJournalEntriesFrom(ulong entryId)
{
return GetJournalEntriesFrom(0);
bool firstEntry = true;
foreach (var entry in GetJournalEntriesFromImpl(entryId))
{
if (firstEntry && entry.Id > entryId && entryId > 0)
{
string msg = String.Format("requested journal entry missing [{0}]", entryId);
throw new InvalidOperationException(msg);
}
firstEntry = false;
yield return entry;
}
}


public JournalAppender CreateAppender(ulong nextRevision)
/// <summary>
/// Iterate all the entries in the journal
/// </summary>
/// <returns></returns>
public virtual IEnumerable<JournalEntry> GetJournalEntries()
{
return new JournalAppender(nextRevision, CreateJournalWriter(nextRevision));
return GetJournalEntriesFrom(0);
}

public virtual IJournalWriter CreateJournalWriter(ulong lastEntryId)
Expand All @@ -54,31 +90,37 @@ public override void Initialize()
base.Initialize();
}

public bool IsEmpty
/// <summary>
/// True if the journal is empty
/// </summary>
public virtual bool IsEmpty
{
get
{
return !GetJournalEntries().Any();
}
}

/// <summary>
/// Throw an exception unless the journal is empty
/// </summary>
protected void AssertEmpty()
{
if (!IsEmpty) throw new InvalidOperationException("Store must be empty");
if (!IsEmpty) throw new InvalidOperationException("Journal must be empty");
}

/// <summary>
/// Get commands beginning from a specific entry id (inclusive)
/// Get commited commands beginning from a specific entry id (inclusive)
/// </summary>
public IEnumerable<JournalEntry<Command>> CommandEntriesFrom(ulong entryId)
{
return CommittedCommandEntries(() => GetJournalEntriesFrom(entryId));
return CommittedCommandEntries(() => GetJournalEntriesFromImpl(entryId));
}

/// <summary>
/// Get non rolled back commands from a point in time
/// Get committed commands from a point in time
/// </summary>
public IEnumerable<JournalEntry<Command>> CommandEntriesFrom(DateTime pointInTime)
public IEnumerable<JournalEntry<Command>> CommandEntriesBeforeOrAt(DateTime pointInTime)
{
return CommittedCommandEntries(() => GetJournalEntriesBeforeOrAt(pointInTime));
}
Expand Down Expand Up @@ -112,26 +154,5 @@ public IEnumerable<JournalEntry<Command>> CommandEntries()
{
return CommandEntriesFrom(1);
}
//public virtual void Create<T>() where T : Model, new()
//{
// AssertEmpty();
// Create(typeof(T));
//}

//public virtual void Create(Type modelType)
//{
// AssertEmpty();
// var writer = CreateJournalWriter(0);
// var appender = new JournalAppender(1, writer);
// appender.AppendModelCreated(modelType);
// writer.Close();
//}

//public virtual void Create(Model model)
//{
// AssertEmpty();
// WriteSnapshotImpl(model, 0);
//}

}
}

0 comments on commit bb8ed4d

Please sign in to comment.