From bb8ed4d54a2d68607137a3799318a9b4b5744a10 Mon Sep 17 00:00:00 2001 From: rofr Date: Thu, 25 Sep 2014 13:29:42 +0200 Subject: [PATCH] fix bug #10 + commenting and refactoring --- OrigoDb.Core.nuspec | 3 +- src/OrigoDB.Core.Test/FileStoreTest.cs | 1 - .../EngineConfigurationTest.cs | 23 +++++ src/OrigoDB.Core/Engine.cs | 36 +++---- src/OrigoDB.Core/Journaling/IJournalWriter.cs | 6 +- .../Journaling/JournalAppender.cs | 7 +- src/OrigoDB.Core/Model.cs | 2 - src/OrigoDB.Core/OrigoDB.Core.csproj | 8 +- src/OrigoDB.Core/Storage/CommandStore.cs | 97 +++++++++++-------- src/OrigoDB.Core/Storage/FileCommandStore.cs | 44 ++------- .../Storage/InMemoryCommandStore.cs | 29 +++--- .../{Initialized.cs => Initializable.cs} | 2 +- .../Rollover/CompositeRolloverStrategy.cs | 28 ++++++ .../Rollover/MaxBytesRolloverStrategy.cs | 21 ++++ .../Rollover/MaxEntriesRolloverStrategy.cs | 21 ++++ .../Storage/Rollover/RolloverStrategy.cs | 12 +++ .../Rollover/ScheduledRolloverStrategy.cs | 44 +++++++++ src/OrigoDB.Core/Storage/RolloverStrategy.cs | 67 ------------- src/OrigoDB.Core/Storage/SnapshotStore.cs | 2 +- .../Synchronization/NullSynchronizer.cs | 4 + src/SharedAssemblyInfo.cs | 4 +- 21 files changed, 272 insertions(+), 189 deletions(-) rename src/OrigoDB.Core/Storage/{Initialized.cs => Initializable.cs} (87%) create mode 100644 src/OrigoDB.Core/Storage/Rollover/CompositeRolloverStrategy.cs create mode 100644 src/OrigoDB.Core/Storage/Rollover/MaxBytesRolloverStrategy.cs create mode 100644 src/OrigoDB.Core/Storage/Rollover/MaxEntriesRolloverStrategy.cs create mode 100644 src/OrigoDB.Core/Storage/Rollover/RolloverStrategy.cs create mode 100644 src/OrigoDB.Core/Storage/Rollover/ScheduledRolloverStrategy.cs delete mode 100644 src/OrigoDB.Core/Storage/RolloverStrategy.cs diff --git a/OrigoDb.Core.nuspec b/OrigoDb.Core.nuspec index c4f99bb..f688f14 100644 --- a/OrigoDb.Core.nuspec +++ b/OrigoDb.Core.nuspec @@ -22,7 +22,6 @@ - - \ No newline at end of file + diff --git a/src/OrigoDB.Core.Test/FileStoreTest.cs b/src/OrigoDB.Core.Test/FileStoreTest.cs index d8990bb..3c111bc 100644 --- a/src/OrigoDB.Core.Test/FileStoreTest.cs +++ b/src/OrigoDB.Core.Test/FileStoreTest.cs @@ -2,7 +2,6 @@ using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; -using OrigoDB.Core; namespace OrigoDB.Core.Test { diff --git a/src/OrigoDB.Core.UnitTests/EngineConfigurationTest.cs b/src/OrigoDB.Core.UnitTests/EngineConfigurationTest.cs index 4d68c3a..80bbe94 100644 --- a/src/OrigoDB.Core.UnitTests/EngineConfigurationTest.cs +++ b/src/OrigoDB.Core.UnitTests/EngineConfigurationTest.cs @@ -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(config); + engine.Execute(new TestCommandWithResult()); + engine.Close(); + engine = Engine.LoadOrCreate(config); + engine.Close(); + } + finally + { + if (config.CreateCommandStore() is FileCommandStore) + Directory.Delete(config.Location.OfJournal, true); + } + } + } + [TestFixture] public class EngineConfigurationTest { diff --git a/src/OrigoDB.Core/Engine.cs b/src/OrigoDB.Core/Engine.cs index 11e9dbf..4ec7c69 100644 --- a/src/OrigoDB.Core/Engine.cs +++ b/src/OrigoDB.Core/Engine.cs @@ -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); } @@ -124,7 +128,7 @@ public object Execute(Query query) /// public TResult Execute(Func lambdaQuery) where TModel : Model { - EnsureRunning(); + EnsureNotDisposed(); EnsureAuthorized(lambdaQuery); return ExecuteQuery(new DelegateQuery(lambdaQuery)); } @@ -134,7 +138,7 @@ public object Execute(Query query) /// public TRresult Execute(Query query) where TModel : Model { - EnsureRunning(); + EnsureNotDisposed(); EnsureAuthorized(query); return ExecuteQuery(query); } @@ -144,7 +148,7 @@ public object Execute(Query query) /// public object Execute(Command command) { - EnsureRunning(); + EnsureNotDisposed(); EnsureAuthorized(command); FireExecutingEvent(command); @@ -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(); @@ -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; @@ -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(); @@ -289,7 +283,7 @@ public void Close() Dispose(true); } - private void EnsureRunning() + private void EnsureNotDisposed() { if (_isDisposed) throw new ObjectDisposedException(GetType().FullName); } diff --git a/src/OrigoDB.Core/Journaling/IJournalWriter.cs b/src/OrigoDB.Core/Journaling/IJournalWriter.cs index a265e35..6200207 100644 --- a/src/OrigoDB.Core/Journaling/IJournalWriter.cs +++ b/src/OrigoDB.Core/Journaling/IJournalWriter.cs @@ -2,9 +2,13 @@ namespace OrigoDB.Core { + /// + /// Journal writers write JournalEntry objects to the journal + /// public interface IJournalWriter : IDisposable { void Write(JournalEntry item); - void Close(); + + void Close(); } } diff --git a/src/OrigoDB.Core/Journaling/JournalAppender.cs b/src/OrigoDB.Core/Journaling/JournalAppender.cs index 15a33b6..638f6b7 100644 --- a/src/OrigoDB.Core/Journaling/JournalAppender.cs +++ b/src/OrigoDB.Core/Journaling/JournalAppender.cs @@ -8,7 +8,7 @@ namespace OrigoDB.Core /// Wraps objects in JournalEntry and sends to an underlying writer. /// Responsible for maintaining the sequence number. /// - public class JournalAppender + public class JournalAppender : IDisposable { readonly IJournalWriter _writer; private ulong _nextEntryId; @@ -88,5 +88,10 @@ public static JournalAppender Create(ulong nextEntryId, IJournalWriter writer) { return new JournalAppender(nextEntryId, writer); } + + public void Dispose() + { + _writer.Dispose(); + } } } \ No newline at end of file diff --git a/src/OrigoDB.Core/Model.cs b/src/OrigoDB.Core/Model.cs index a0ffa2c..2bd8234 100644 --- a/src/OrigoDB.Core/Model.cs +++ b/src/OrigoDB.Core/Model.cs @@ -1,6 +1,4 @@ using System; -using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; namespace OrigoDB.Core { diff --git a/src/OrigoDB.Core/OrigoDB.Core.csproj b/src/OrigoDB.Core/OrigoDB.Core.csproj index df72d9d..e5bee27 100644 --- a/src/OrigoDB.Core/OrigoDB.Core.csproj +++ b/src/OrigoDB.Core/OrigoDB.Core.csproj @@ -87,6 +87,10 @@ + + + + @@ -99,7 +103,7 @@ - + @@ -158,7 +162,7 @@ - + diff --git a/src/OrigoDB.Core/Storage/CommandStore.cs b/src/OrigoDB.Core/Storage/CommandStore.cs index 39dc618..863bba5 100644 --- a/src/OrigoDB.Core/Storage/CommandStore.cs +++ b/src/OrigoDB.Core/Storage/CommandStore.cs @@ -8,18 +8,42 @@ namespace OrigoDB.Core.Storage { - public abstract class CommandStore : Initialized, ICommandStore + /// + /// Base class with common behavior for CommandStore implementations + /// + 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 GetJournalEntriesFrom(ulong entryId); - public abstract IEnumerable GetJournalEntriesBeforeOrAt(DateTime pointInTime); + /// + /// Read the sequence of entries with id greater than or equal to a given entryId + /// + protected abstract IEnumerable GetJournalEntriesFromImpl(ulong entryId); + + + /// + /// Get an append-only stream for writing journal entries + /// public abstract Stream CreateJournalWriterStream(ulong firstEntryId = 1); + + /// + /// Override if necessary + /// + /// + /// + public virtual IEnumerable GetJournalEntriesBeforeOrAt(DateTime pointInTime) + { + return GetJournalEntriesFrom(0).TakeWhile(e => e.Created <= pointInTime); + } + + + protected virtual IJournalWriter CreateStoreSpecificJournalWriter() + { + return new StreamJournalWriter(_config, CreateJournalWriterStream); + } protected CommandStore(EngineConfiguration config) @@ -28,16 +52,28 @@ protected CommandStore(EngineConfiguration config) } - - public virtual IEnumerable GetJournalEntries() + public IEnumerable 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) + /// + /// Iterate all the entries in the journal + /// + /// + public virtual IEnumerable GetJournalEntries() { - return new JournalAppender(nextRevision, CreateJournalWriter(nextRevision)); + return GetJournalEntriesFrom(0); } public virtual IJournalWriter CreateJournalWriter(ulong lastEntryId) @@ -54,7 +90,10 @@ public override void Initialize() base.Initialize(); } - public bool IsEmpty + /// + /// True if the journal is empty + /// + public virtual bool IsEmpty { get { @@ -62,23 +101,26 @@ public bool IsEmpty } } + /// + /// Throw an exception unless the journal is empty + /// protected void AssertEmpty() { - if (!IsEmpty) throw new InvalidOperationException("Store must be empty"); + if (!IsEmpty) throw new InvalidOperationException("Journal must be empty"); } /// - /// Get commands beginning from a specific entry id (inclusive) + /// Get commited commands beginning from a specific entry id (inclusive) /// public IEnumerable> CommandEntriesFrom(ulong entryId) { - return CommittedCommandEntries(() => GetJournalEntriesFrom(entryId)); + return CommittedCommandEntries(() => GetJournalEntriesFromImpl(entryId)); } /// - /// Get non rolled back commands from a point in time + /// Get committed commands from a point in time /// - public IEnumerable> CommandEntriesFrom(DateTime pointInTime) + public IEnumerable> CommandEntriesBeforeOrAt(DateTime pointInTime) { return CommittedCommandEntries(() => GetJournalEntriesBeforeOrAt(pointInTime)); } @@ -112,26 +154,5 @@ public IEnumerable> CommandEntries() { return CommandEntriesFrom(1); } - //public virtual void Create() 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); - //} - } } diff --git a/src/OrigoDB.Core/Storage/FileCommandStore.cs b/src/OrigoDB.Core/Storage/FileCommandStore.cs index 5651243..bae7d10 100644 --- a/src/OrigoDB.Core/Storage/FileCommandStore.cs +++ b/src/OrigoDB.Core/Storage/FileCommandStore.cs @@ -15,10 +15,7 @@ public sealed class FileCommandStore : CommandStore public IEnumerable JournalFiles { - get - { - foreach (var journalFile in _journalFiles) yield return journalFile; - } + get { return _journalFiles; } } public FileCommandStore(EngineConfiguration config) : base(config) @@ -27,7 +24,7 @@ public FileCommandStore(EngineConfiguration config) : base(config) /// - /// Read journal files + /// Read and cache journal file names /// public override void Initialize() { @@ -40,33 +37,24 @@ public override void Initialize() _journalFiles.Add(JournalFile.Parse(fileName)); } - _journalFiles.Sort((a,b) => a.FileSequenceNumber.CompareTo(b.FileSequenceNumber)); + _journalFiles.Sort((a, b) => a.FileSequenceNumber.CompareTo(b.FileSequenceNumber)); } - public override IEnumerable GetJournalEntriesFrom(ulong entryId) + protected override IEnumerable GetJournalEntriesFromImpl(ulong entryId) { - bool firstEntry = true; - //Scroll to the correct file int offset = 0; - while (_journalFiles.Count > offset + 1 && _journalFiles[offset + 1].StartingEntryId < entryId) - offset++; + while (_journalFiles.Count > offset + 1 && _journalFiles[offset + 1].StartingEntryId < entryId) + offset++; foreach (var journalFile in _journalFiles.Skip(offset)) { string path = Path.Combine(_config.Location.OfJournal, journalFile.Name); using (Stream stream = GetReadStream(path)) { - foreach (var entry in _formatter.ReadToEnd(stream)) + foreach (var entry in _formatter.ReadToEnd(stream).SkipWhile(e => e.Id < entryId)) { - if (firstEntry && entry.Id > entryId) - { - string msg = String.Format("requested: {0}, first: {1}", entryId, entry.Id); - throw new InvalidOperationException(msg); - } - firstEntry = false; - if (entry.Id < entryId) continue; yield return entry; } } @@ -74,18 +62,11 @@ public override IEnumerable GetJournalEntriesFrom(ulong entryId) } - public override IEnumerable GetJournalEntriesBeforeOrAt(DateTime pointInTime) - { - return GetJournalEntries() - .Where(journalEntry => journalEntry.Created <= pointInTime); - } - - /// /// Create a new journal writer stream. The first entry written to the /// stream will have the specified sequenceNumber /// - /// An open stream + /// A writeable stream public override Stream CreateJournalWriterStream(ulong firstEntryId = 1) { var current = _journalFiles.LastOrDefault() ?? new JournalFile(0, 0); @@ -93,7 +74,7 @@ public override Stream CreateJournalWriterStream(ulong firstEntryId = 1) _journalFiles.Add(next); string fileName = next.Name; string path = Path.Combine(_config.Location.OfJournal, fileName); - return new FileStream(path, FileMode.Append, FileAccess.Write); + return new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.None); } @@ -107,12 +88,7 @@ private void EnsureDirectoryExists(string directory) private Stream GetReadStream(string fileName) { - return File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - } - - protected override IJournalWriter CreateStoreSpecificJournalWriter() - { - return new StreamJournalWriter(_config, CreateJournalWriterStream); + return File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); } } } diff --git a/src/OrigoDB.Core/Storage/InMemoryCommandStore.cs b/src/OrigoDB.Core/Storage/InMemoryCommandStore.cs index 13a259b..cec2215 100644 --- a/src/OrigoDB.Core/Storage/InMemoryCommandStore.cs +++ b/src/OrigoDB.Core/Storage/InMemoryCommandStore.cs @@ -8,8 +8,12 @@ namespace OrigoDB.Core.Test { /// /// The InMemoryCommandStore is a non durable CommandStore implementation - /// intended for integration/system tests + /// intended for integration/system tests. /// + /// + /// It's implemented using a list of memory streams to mimic + /// the behavior of FileCommandStore as closely as possible. + /// public class InMemoryCommandStore : CommandStore { /// @@ -25,7 +29,8 @@ public InMemoryCommandStoreState() } } - //State mementos by Location.OfJournal + //State mementos by Location.OfJournal. + //this pattern enables persistence across consecutive instances based on the location static readonly Dictionary _states = new Dictionary(); @@ -42,15 +47,7 @@ public InMemoryCommandStore(EngineConfiguration config) _state = _states[key]; } - - - protected override IJournalWriter CreateStoreSpecificJournalWriter() - { - return new StreamJournalWriter(_config, CreateJournalWriterStream); - } - - - public override IEnumerable GetJournalEntriesFrom(ulong entryId) + protected override IEnumerable GetJournalEntriesFromImpl(ulong entryId) { return _state.Journal.SelectMany( journalSegment => _formatter @@ -58,11 +55,11 @@ public override IEnumerable GetJournalEntriesFrom(ulong entryId) .SkipWhile(e => e.Id < entryId)); } - public override IEnumerable GetJournalEntriesBeforeOrAt(DateTime pointInTime) - { - return GetJournalEntriesFrom(0).TakeWhile(entry => entry.Created <= pointInTime); - } - + /// + /// Sets up and returns a MemoryStream for writing journal entries + /// + /// + /// public override Stream CreateJournalWriterStream(ulong startId = 1) { var stream = new MemoryStream(); diff --git a/src/OrigoDB.Core/Storage/Initialized.cs b/src/OrigoDB.Core/Storage/Initializable.cs similarity index 87% rename from src/OrigoDB.Core/Storage/Initialized.cs rename to src/OrigoDB.Core/Storage/Initializable.cs index 90440fd..78551db 100644 --- a/src/OrigoDB.Core/Storage/Initialized.cs +++ b/src/OrigoDB.Core/Storage/Initializable.cs @@ -1,6 +1,6 @@ namespace OrigoDB.Core.Storage { - public abstract class Initialized + public abstract class Initializable { protected bool IsInitialized = false; diff --git a/src/OrigoDB.Core/Storage/Rollover/CompositeRolloverStrategy.cs b/src/OrigoDB.Core/Storage/Rollover/CompositeRolloverStrategy.cs new file mode 100644 index 0000000..5a1c4dd --- /dev/null +++ b/src/OrigoDB.Core/Storage/Rollover/CompositeRolloverStrategy.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Linq; + +namespace OrigoDB.Core +{ + /// + /// Combines multiple strategies. Signals rollover if any child signals. + /// + public class CompositeRolloverStrategy : RolloverStrategy + { + private readonly List _childStrategies; + + public CompositeRolloverStrategy() + { + _childStrategies = new List(); + } + + public void AddStrategy(RolloverStrategy strategy) + { + _childStrategies.Add(strategy); + } + + public override bool Rollover(long bytesWritten, long entriesWritten) + { + return _childStrategies.Any(strategy => strategy.Rollover(bytesWritten, entriesWritten)); + } + } +} \ No newline at end of file diff --git a/src/OrigoDB.Core/Storage/Rollover/MaxBytesRolloverStrategy.cs b/src/OrigoDB.Core/Storage/Rollover/MaxBytesRolloverStrategy.cs new file mode 100644 index 0000000..486207a --- /dev/null +++ b/src/OrigoDB.Core/Storage/Rollover/MaxBytesRolloverStrategy.cs @@ -0,0 +1,21 @@ +namespace OrigoDB.Core +{ + /// + /// Signals rollover when number of bytes written exceeds a given limit + /// + public class MaxBytesRolloverStrategy : RolloverStrategy + { + public readonly long MaxBytes; + public const long DefaultMaxBytes = 1024 * 1024 * 4; + + public MaxBytesRolloverStrategy(long maxBytes = DefaultMaxBytes) + { + MaxBytes = maxBytes; + } + + public override bool Rollover(long bytesWritten, long entriesWritten) + { + return bytesWritten >= MaxBytes; + } + } +} \ No newline at end of file diff --git a/src/OrigoDB.Core/Storage/Rollover/MaxEntriesRolloverStrategy.cs b/src/OrigoDB.Core/Storage/Rollover/MaxEntriesRolloverStrategy.cs new file mode 100644 index 0000000..d529728 --- /dev/null +++ b/src/OrigoDB.Core/Storage/Rollover/MaxEntriesRolloverStrategy.cs @@ -0,0 +1,21 @@ +namespace OrigoDB.Core +{ + /// + /// Signals rollover when number of entries exceeds a given limit + /// + public class MaxEntriesRolloverStrategy : RolloverStrategy + { + public readonly long MaxEntries; + public const long DefaultMaxEntries = 1000; + + public MaxEntriesRolloverStrategy(long maxEntries = DefaultMaxEntries) + { + MaxEntries = maxEntries; + } + + public override bool Rollover(long bytesWritten, long entriesWritten) + { + return entriesWritten >= MaxEntries; + } + } +} \ No newline at end of file diff --git a/src/OrigoDB.Core/Storage/Rollover/RolloverStrategy.cs b/src/OrigoDB.Core/Storage/Rollover/RolloverStrategy.cs new file mode 100644 index 0000000..3a2e51f --- /dev/null +++ b/src/OrigoDB.Core/Storage/Rollover/RolloverStrategy.cs @@ -0,0 +1,12 @@ +namespace OrigoDB.Core +{ + + /// + /// RolloverStrategy decides when it's time to create + /// a new journal segment. + /// + public abstract class RolloverStrategy + { + public abstract bool Rollover(long bytesWritten, long entriesWritten); + } +} diff --git a/src/OrigoDB.Core/Storage/Rollover/ScheduledRolloverStrategy.cs b/src/OrigoDB.Core/Storage/Rollover/ScheduledRolloverStrategy.cs new file mode 100644 index 0000000..a159563 --- /dev/null +++ b/src/OrigoDB.Core/Storage/Rollover/ScheduledRolloverStrategy.cs @@ -0,0 +1,44 @@ +using System; + +namespace OrigoDB.Core +{ + /// + /// Rolls over at given intervals of time, default is every midnight + /// + public class ScheduledRolloverStrategy : RolloverStrategy + { + /// + /// Rollover when this period of time has elapsed + /// + public readonly TimeSpan Interval; + + /// + /// Initial time or last rollover + /// + public DateTime ReferenceTime; + + /// + /// Constructor + /// + /// Reference time, defaults to previous midnight + /// Defaults to 24 hours + public ScheduledRolloverStrategy(DateTime? initial = null, TimeSpan? interval = null) + { + Interval = interval ?? TimeSpan.FromHours(24); + ReferenceTime = initial ?? DateTime.Today; + } + + /// + /// Checks if interval has elapsed and updates reference time if so + /// + /// unused + /// unused + /// + public override bool Rollover(long bytesWritten, long entriesWritten) + { + var intervalElapsed = DateTime.Now > ReferenceTime + Interval; + if (intervalElapsed) ReferenceTime += Interval; + return intervalElapsed; + } + } +} \ No newline at end of file diff --git a/src/OrigoDB.Core/Storage/RolloverStrategy.cs b/src/OrigoDB.Core/Storage/RolloverStrategy.cs deleted file mode 100644 index cfbca35..0000000 --- a/src/OrigoDB.Core/Storage/RolloverStrategy.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace OrigoDB.Core -{ - - public abstract class RolloverStrategy - { - public abstract bool Rollover(long bytesWritten, long entriesWritten); - } - - public class CompositeRolloverStrategy : RolloverStrategy - { - private List _childStrategies; - - public CompositeRolloverStrategy() - { - _childStrategies = new List(); - } - - public void AddStrategy(RolloverStrategy strategy) - { - _childStrategies.Add(strategy); - } - - public override bool Rollover(long bytesWritten, long entriesWritten) - { - return _childStrategies.Any(strategy => strategy.Rollover(bytesWritten, entriesWritten)); - } - } - - - public class MaxEntriesRolloverStrategy : RolloverStrategy - { - public readonly long MaxEntries; - public const long DefaultMaxEntries = 1000; - - public MaxEntriesRolloverStrategy(long maxEntries = DefaultMaxEntries) - { - MaxEntries = maxEntries; - } - - public override bool Rollover(long bytesWritten, long entriesWritten) - { - return entriesWritten >= MaxEntries; - } - } - - public class MaxBytesRolloverStrategy : RolloverStrategy - { - public readonly long MaxBytes; - public const long DefaultMaxBytes = 1024 * 1024 * 4; - - public MaxBytesRolloverStrategy(long maxBytes = DefaultMaxBytes) - { - MaxBytes = maxBytes; - } - - public override bool Rollover(long bytesWritten, long entriesWritten) - { - return bytesWritten >= MaxBytes; - } - } - -} diff --git a/src/OrigoDB.Core/Storage/SnapshotStore.cs b/src/OrigoDB.Core/Storage/SnapshotStore.cs index 417f5b3..9031a8a 100644 --- a/src/OrigoDB.Core/Storage/SnapshotStore.cs +++ b/src/OrigoDB.Core/Storage/SnapshotStore.cs @@ -7,7 +7,7 @@ namespace OrigoDB.Core.Storage /// /// Base class for concrete Snapshot store implementations /// - public abstract class SnapshotStore : Initialized, ISnapshotStore + public abstract class SnapshotStore : Initializable, ISnapshotStore { protected IFormatter _formatter; diff --git a/src/OrigoDB.Core/Synchronization/NullSynchronizer.cs b/src/OrigoDB.Core/Synchronization/NullSynchronizer.cs index 0935191..1fc6c0f 100644 --- a/src/OrigoDB.Core/Synchronization/NullSynchronizer.cs +++ b/src/OrigoDB.Core/Synchronization/NullSynchronizer.cs @@ -6,6 +6,10 @@ namespace OrigoDB.Core { + /// + /// No synchronization at all. + /// + public class NullSynchronizer : ISynchronizer { diff --git a/src/SharedAssemblyInfo.cs b/src/SharedAssemblyInfo.cs index d049f7b..7f3199d 100644 --- a/src/SharedAssemblyInfo.cs +++ b/src/SharedAssemblyInfo.cs @@ -14,8 +14,8 @@ [assembly: ComVisible(false)] -[assembly: AssemblyVersion("0.15.0")] -[assembly: AssemblyFileVersion("0.15.0")] +[assembly: AssemblyVersion("0.16.0")] +[assembly: AssemblyFileVersion("0.16.0")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("OrigoDB.Enterprise")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("OrigoDB.Test.MSTest")]