public PartitionManager(
     ITransactionFileReader reader, ITransactionFileWriter writer, LogV3RecordFactory recordFactory)
 {
     _reader        = reader;
     _writer        = writer;
     _recordFactory = recordFactory;
 }
示例#2
0
        private SingleReadResult TryReadRecordInternal(ITransactionFileReader reader,
                                                       string eventStreamId,
                                                       int version,
                                                       out EventRecord record)
        {
            Ensure.NotNull(eventStreamId, "eventStreamId");
            Ensure.Nonnegative(version, "version");

            record = null;

            if (IsStreamDeletedInternal(reader, eventStreamId))
            {
                return(SingleReadResult.StreamDeleted);
            }

            var success = TryGetRecordInternal(reader, eventStreamId, version, out record);

            if (success)
            {
                return(SingleReadResult.Success);
            }

            if (version == 0)
            {
                return(SingleReadResult.NoStream);
            }

            EventRecord rec;

            return(TryGetRecordInternal(reader, eventStreamId, 0, out rec)
                            ? SingleReadResult.NotFound
                            : SingleReadResult.NoStream);
        }
        public virtual void TestFixtureSetUp()
        {
            _logFormat  = LogFormatHelper <TLogFormat, TStreamId> .LogFormat;
            _publisher  = new InMemoryBus("publisher");
            _tfReader   = new FakeInMemoryTfReader(RecordOffset);
            _tableIndex = new FakeInMemoryTableIndex <TStreamId>();
            _readerPool = new ObjectPool <ITransactionFileReader>(
                "ReadIndex readers pool", 5, 100,
                () => _tfReader);
            _indexBackend = new IndexBackend <TStreamId>(_readerPool, 100000, 100000);
            var logFormat = LogFormatHelper <TLogFormat, TStreamId> .LogFormat;

            _streamIds     = logFormat.StreamIds;
            _streamNames   = logFormat.StreamNames;
            _systemStreams = logFormat.SystemStreams;
            _factory       = logFormat.StreamNamesProvider;
            _validator     = logFormat.StreamIdValidator;
            var emptyStreamId = logFormat.EmptyStreamId;

            _sizer          = logFormat.StreamIdSizer;
            _indexReader    = new IndexReader <TStreamId>(_indexBackend, _tableIndex, _factory, _validator, new StreamMetadata(maxCount: 100000), 100, false);
            _indexWriter    = new IndexWriter <TStreamId>(_indexBackend, _indexReader, _streamIds, _streamNames, _systemStreams, emptyStreamId, _sizer);
            _indexCommitter = new Core.Services.Storage.ReaderIndex.IndexCommitter <TStreamId>(_publisher, _indexBackend, _indexReader, _tableIndex, _streamNames, _systemStreams, new InMemoryCheckpoint(-1), false);

            WriteEvents();
        }
示例#4
0
        private int GetLastStreamEventNumberInternal(ITransactionFileReader reader, string eventStreamId)
        {
            Ensure.NotNull(eventStreamId, "eventStreamId");

            var        streamHash = _hasher.Hash(eventStreamId);
            IndexEntry latestEntry;

            if (!_tableIndex.TryGetLatestEntry(streamHash, out latestEntry))
            {
                return(ExpectedVersion.NoStream);
            }

            var prepare = GetPrepareInternal(reader, latestEntry.Position);

            if (prepare.EventStreamId == eventStreamId) // LUCKY!!!
            {
                return(latestEntry.Version);
            }

            foreach (var indexEntry in _tableIndex.GetRange(streamHash, 0, int.MaxValue))
            {
                var p = GetPrepareInternal(reader, indexEntry.Position);
                if (p.EventStreamId == eventStreamId)
                {
                    return(indexEntry.Version); // AT LAST!!!
                }
            }
            return(ExpectedVersion.NoStream); // no such event stream
        }
示例#5
0
        private static EventRecord GetEventRecord(ITransactionFileReader reader, IndexEntry indexEntry)
        {
            var prepare     = ReadPrepareInternal(reader, indexEntry.Position);
            var eventRecord = new EventRecord(indexEntry.Version, prepare);

            return(eventRecord);
        }
示例#6
0
        private int GetLastStreamEventNumberInternal(ITransactionFileReader reader, string streamId)
        {
            Ensure.NotNull(streamId, "streamId");

            var        streamHash = _hasher.Hash(streamId);
            IndexEntry latestEntry;

            if (!_tableIndex.TryGetLatestEntry(streamHash, out latestEntry))
            {
                return(ExpectedVersion.NoStream);
            }

            var prepare = ReadPrepareInternal(reader, latestEntry.Position);

            if (prepare.EventStreamId == streamId) // LUCKY!!!
            {
                return(latestEntry.Version);
            }

            // TODO AN here lie the problem of out of memory if the stream have A LOT of events in them
            foreach (var indexEntry in _tableIndex.GetRange(streamHash, 0, int.MaxValue))
            {
                var p = ReadPrepareInternal(reader, indexEntry.Position);
                if (p.EventStreamId == streamId)
                {
                    return(indexEntry.Version); // AT LAST!!!
                }
            }
            return(ExpectedVersion.NoStream); // no such event stream
        }
        public override async Task TestFixtureSetUp()
        {
            await base.TestFixtureSetUp();

            _logFormat = LogFormatHelper <TLogFormat, TStreamId> .LogFormatFactory.Create(new() {
                IndexDirectory = GetFilePathFor("index"),
            });

            _provider   = _logFormat.StreamNamesProvider;
            _publisher  = new InMemoryBus("publisher");
            _tfReader   = new FakeInMemoryTfReader(RecordOffset);
            _tableIndex = new FakeInMemoryTableIndex <TStreamId>();
            _provider.SetTableIndex(_tableIndex);
            _readerPool = new ObjectPool <ITransactionFileReader>(
                "ReadIndex readers pool", 5, 100,
                () => _tfReader);
            _indexBackend = new IndexBackend <TStreamId>(_readerPool, 100000, 100000);
            _streamIds    = _logFormat.StreamIds;
            _validator    = _logFormat.StreamIdValidator;
            var emptyStreamId = _logFormat.EmptyStreamId;

            _sizer       = _logFormat.StreamIdSizer;
            _indexReader = new IndexReader <TStreamId>(_indexBackend, _tableIndex, _provider, _validator,
                                                       _logFormat.StreamExistenceFilterReader, new StreamMetadata(maxCount: 100000), 100, false);
            _streamNames   = _logFormat.StreamNames;
            _systemStreams = _logFormat.SystemStreams;
            _indexWriter   = new IndexWriter <TStreamId>(_indexBackend, _indexReader, _streamIds, _streamNames,
                                                         _systemStreams, emptyStreamId, _sizer);
            _indexCommitter = new IndexCommitter <TStreamId>(_publisher, _indexBackend, _indexReader, _tableIndex,
                                                             _logFormat.StreamNameIndexConfirmer, _streamNames, _logFormat.EventTypeIndexConfirmer, _logFormat.EventTypes,
                                                             _systemStreams, _logFormat.StreamExistenceFilter, _logFormat.StreamExistenceFilterInitializer, new InMemoryCheckpoint(-1), false);

            WriteEvents();
        }
示例#8
0
        private EventRecord ResolveLinkToEventInternal(ITransactionFileReader reader, EventRecord eventRecord)
        {
            EventRecord record = null;

            if (eventRecord.EventType == SystemEventTypes.LinkTo)
            {
                bool   faulted     = false;
                int    eventNumber = -1;
                string streamId    = null;
                try
                {
                    string[] parts = Encoding.UTF8.GetString(eventRecord.Data).Split('@');
                    eventNumber = int.Parse(parts[0]);
                    streamId    = parts[1];
                }
                catch (Exception exc)
                {
                    faulted = true;
                    Log.ErrorException(exc, "Error while resolving link for event record: {0}", eventRecord.ToString());
                }
                if (faulted)
                {
                    return(null);
                }
                GetStreamRecord(reader, streamId, eventNumber, out record);
            }
            return(record);
        }
示例#9
0
        private PrepareLogRecord GetPrepareInternal(ITransactionFileReader reader, long pos)
        {
            var result = reader.TryReadAt(pos);

            if (!result.Success)
            {
                throw new InvalidOperationException("Couldn't read record which is supposed to be in file.");
            }
            Debug.Assert(result.LogRecord.RecordType == LogRecordType.Prepare, "Incorrect type of log record, expected Prepare record.");
            return((PrepareLogRecord)result.LogRecord);
        }
示例#10
0
        private static PrepareLogRecord ReadPrepareInternal(ITransactionFileReader reader, long pos)
        {
            var result = reader.TryReadAt(pos);

            // TODO AN need to change this to account for possibly scavenged records, shouldn't throw exception,
            // TODO AN rather return meaningful result
            if (!result.Success)
            {
                throw new InvalidOperationException("Couldn't read record which is supposed to be in file.");
            }
            Debug.Assert(result.LogRecord.RecordType == LogRecordType.Prepare, "Incorrect type of log record, expected Prepare record.");
            return((PrepareLogRecord)result.LogRecord);
        }
示例#11
0
        public virtual void TestFixtureSetUp()
        {
            _publisher  = new InMemoryBus("publisher");
            _tfReader   = new FakeInMemoryTfReader(RecordOffset);
            _tableIndex = new FakeInMemoryTableIndex();
            _readerPool = new ObjectPool <ITransactionFileReader>(
                "ReadIndex readers pool", 5, 100,
                () => _tfReader);
            _indexBackend   = new IndexBackend(_readerPool, 100000, 100000);
            _indexReader    = new IndexReader(_indexBackend, _tableIndex, new StreamMetadata(maxCount: 100000), 100, false);
            _indexWriter    = new IndexWriter(_indexBackend, _indexReader);
            _indexCommitter = new IndexCommitter(_publisher, _indexBackend, _indexReader, _tableIndex, false);

            WriteEvents();
        }
示例#12
0
        private SingleReadResult ReadEventInternal(ITransactionFileReader reader, string streamId, int version, out EventRecord record)
        {
            Ensure.NotNull(streamId, "streamId");
            Ensure.Nonnegative(version, "eventNumber");

            record = null;
            if (IsStreamDeletedInternal(reader, streamId))
            {
                return(SingleReadResult.StreamDeleted);
            }

            StreamMetadata metadata;
            bool           streamExists;
            bool           useMetadata = GetStreamMetadataInternal(reader, streamId, out streamExists, out metadata);

            if (!streamExists)
            {
                return(SingleReadResult.NoStream);
            }

            if (useMetadata && metadata.MaxCount.HasValue)
            {
                var lastStreamEventNumber = GetLastStreamEventNumberInternal(reader, streamId);
                var minEventNumber        = lastStreamEventNumber - metadata.MaxCount.Value + 1;

                if (version < minEventNumber || version > lastStreamEventNumber)
                {
                    return(SingleReadResult.NotFound);
                }
            }

            EventRecord rec;
            var         success = GetStreamRecord(reader, streamId, version, out rec);

            if (success)
            {
                if (useMetadata && metadata.MaxAge.HasValue && rec.TimeStamp < DateTime.UtcNow - metadata.MaxAge.Value)
                {
                    return(SingleReadResult.NotFound);
                }
                record = rec;
                return(SingleReadResult.Success);
            }

            return(SingleReadResult.NotFound);
        }
示例#13
0
        private bool GetStreamMetadataInternal(ITransactionFileReader reader,
                                               string streamId,
                                               out bool streamExists,
                                               out StreamMetadata metadata)
        {
            metadata     = new StreamMetadata(null, null);
            streamExists = false;
            EventRecord record;

            if (!GetStreamRecord(reader, streamId, 0, out record))
            {
                return(false);
            }
            streamExists = true;
            if (record.Metadata == null || record.Metadata.Length == 0)
            {
                return(false);
            }
            try
            {
                var json = Encoding.UTF8.GetString(record.Metadata);
                var jObj = JObject.Parse(json);

                int maxAge   = -1;
                int maxCount = -1;

                JToken prop;
                if (jObj.TryGetValue(SystemMetadata.MaxAge, out prop) && prop.Type == JTokenType.Integer)
                {
                    maxAge = prop.Value <int>();
                }
                if (jObj.TryGetValue(SystemMetadata.MaxCount, out prop) && prop.Type == JTokenType.Integer)
                {
                    maxCount = prop.Value <int>();
                }

                metadata = new StreamMetadata(maxCount > 0 ? maxCount : (int?)null,
                                              maxAge > 0 ? TimeSpan.FromSeconds(maxAge) : (TimeSpan?)null);
                return(true);
            }
            catch (Exception)
            {
                return(false);
            }
        }
示例#14
0
        private bool TryGetRecordInternal(ITransactionFileReader reader,
                                          string eventStreamId,
                                          int version,
                                          out EventRecord record)
        {
            // we assume that you already did check for stream deletion
            Ensure.NotNull(eventStreamId, "eventStreamId");
            Ensure.Nonnegative(version, "version");

            record = null;

            var streamHash = _hasher.Hash(eventStreamId);

            long position;

            if (_tableIndex.TryGetOneValue(streamHash, version, out position))
            {
                record = ReadEventRecord(reader, new IndexEntry(streamHash, version, position));
                if (record.EventStreamId == eventStreamId)
                {
                    _succReadCount += 1;
                    return(true);
                }
                _failedReadCount += 1;

                foreach (var indexEntry in _tableIndex.GetRange(streamHash, version, version))
                {
                    if (indexEntry.Position == record.LogPosition) // already checked that
                    {
                        continue;
                    }

                    record = ReadEventRecord(reader, indexEntry);
                    if (record.EventStreamId == eventStreamId)
                    {
                        _succReadCount += 1;
                        return(true);
                    }
                    _failedReadCount += 1;
                }
            }

            return(false);
        }
示例#15
0
        private bool GetStreamMetadataUncached(ITransactionFileReader reader,
                                               string streamId,
                                               out StreamMetadata metadata)
        {
            EventRecord record;

            if (!GetStreamRecord(reader, streamId, 0, out record))
            {
                throw new Exception("GetStreamMetadata couldn't find 0th event on stream. That should never happen.");
            }

            metadata = new StreamMetadata(null, null);
            if (record.Metadata == null || record.Metadata.Length == 0)
            {
                return(false);
            }
            try
            {
                var json = Encoding.UTF8.GetString(record.Metadata);
                var jObj = JObject.Parse(json);

                int maxAge   = -1;
                int maxCount = -1;

                JToken prop;
                if (jObj.TryGetValue(SystemMetadata.MaxAge, out prop) && prop.Type == JTokenType.Integer)
                {
                    maxAge = prop.Value <int>();
                }
                if (jObj.TryGetValue(SystemMetadata.MaxCount, out prop) && prop.Type == JTokenType.Integer)
                {
                    maxCount = prop.Value <int>();
                }

                metadata = new StreamMetadata(maxCount > 0 ? maxCount : (int?)null,
                                              maxAge > 0 ? TimeSpan.FromSeconds(maxAge) : (TimeSpan?)null);
                return(true);
            }
            catch (Exception)
            {
                return(false);
            }
        }
示例#16
0
        private void TestMethodRoFile(ITransactionFileReader reader)
        {
            // Arrange
            const string resourceFile = "Tranzactii_pe_perioada.csv";

            // Act
            var transactions = reader.Read(GlobalSettings.GetResourceFilePath(resourceFile), new CultureInfo("ro-RO"));

            // Assert
            Assert.IsTrue(transactions.Count == 3);
            var lastTransaction = transactions[transactions.Count - 1];

            Assert.IsTrue((lastTransaction.TransactionDate == new DateTime(2016, 4, 29)) &&
                          (lastTransaction.TransactionType == TransactionType.Debit) &&
                          (lastTransaction.TransactionDetails == "Cumparare POS") && (lastTransaction.Amount == 13.9m));
            var totalDebits = transactions.Where(t => t.TransactionType == TransactionType.Debit).Sum(t => t.Amount);

            Assert.IsTrue(totalDebits == 257.57m);
        }
示例#17
0
        private ReadEventResult ReadEventInternal(ITransactionFileReader reader, string streamId, int version)
        {
            Ensure.NotNull(streamId, "streamId");
            Ensure.Nonnegative(version, "eventNumber");

            var lastEventNumber = GetLastStreamEventNumberCached(reader, streamId);

            if (lastEventNumber == EventNumber.DeletedStream)
            {
                return(new ReadEventResult(SingleReadResult.StreamDeleted));
            }
            if (lastEventNumber == ExpectedVersion.NoStream)
            {
                return(new ReadEventResult(SingleReadResult.NoStream));
            }

            StreamMetadata metadata;
            bool           useMetadata = GetStreamMetadataCached(reader, streamId, out metadata);

            if (useMetadata && metadata.MaxCount.HasValue)
            {
                var minEventNumber = lastEventNumber - metadata.MaxCount.Value + 1;
                if (version < minEventNumber || version > lastEventNumber)
                {
                    return(new ReadEventResult(SingleReadResult.NotFound));
                }
            }

            EventRecord record;
            var         success = GetStreamRecord(reader, streamId, version, out record);

            if (success)
            {
                if (useMetadata && metadata.MaxAge.HasValue && record.TimeStamp < DateTime.UtcNow - metadata.MaxAge.Value)
                {
                    return(new ReadEventResult(SingleReadResult.NotFound));
                }
                return(new ReadEventResult(SingleReadResult.Success, record));
            }

            return(new ReadEventResult(SingleReadResult.NotFound));
        }
示例#18
0
        private void TestMethodEnFile(ITransactionFileReader reader)
        {
            // Arrange
            const string resourceFile = "Inquiry_statements.csv";

            // Act
            var transactions = reader.Read(GlobalSettings.GetResourceFilePath(resourceFile), new CultureInfo("en-US"));

            // Assert
            var firstTransaction = transactions[0];

            Assert.IsTrue((firstTransaction.TransactionDate == new DateTime(2016, 4, 1)) &&
                          (firstTransaction.TransactionType == TransactionType.Debit) &&
                          (firstTransaction.TransactionDetails == "Foreign exchange Home'Bank") &&
                          (firstTransaction.Amount == 693.17M));
            var lastTransaction = transactions[transactions.Count - 1];

            Assert.IsTrue((lastTransaction.TransactionDate == new DateTime(2016, 2, 4)) &&
                          (lastTransaction.TransactionType == TransactionType.Credit) &&
                          (lastTransaction.TransactionDetails == "Incoming funds") && (lastTransaction.Amount == 2500m));
        }
示例#19
0
        private EpochRecord ReadEpochAt(ITransactionFileReader reader, long epochPos)
        {
            var result = reader.TryReadAt(epochPos);

            if (!result.Success)
            {
                throw new Exception($"Could not find Epoch record at LogPosition {epochPos}.");
            }
            if (result.LogRecord.RecordType != LogRecordType.System)
            {
                throw new Exception($"LogRecord is not SystemLogRecord: {result.LogRecord}.");
            }

            var sysRec = (SystemLogRecord)result.LogRecord;

            if (sysRec.SystemRecordType != SystemRecordType.Epoch)
            {
                throw new Exception($"SystemLogRecord is not of Epoch sub-type: {result.LogRecord}.");
            }

            return(sysRec.GetEpochRecord());
        }
示例#20
0
        private bool GetStreamMetadataCached(ITransactionFileReader reader,
                                             string streamId,
                                             out StreamMetadata metadata)
        {
            StreamCacheInfo streamInfo;

            if (_streamInfoCache.TryGet(streamId, out streamInfo) && streamInfo.Metadata.HasValue)
            {
                metadata = streamInfo.Metadata.Value;
                return(true);
            }

            if (GetStreamMetadataUncached(reader, streamId, out metadata))
            {
                var meta = metadata;
                _streamInfoCache.Put(streamId,
                                     key => new StreamCacheInfo(null, meta),
                                     (key, oldValue) => new StreamCacheInfo(oldValue.LastEventNumber, meta));
                return(true);
            }
            return(false);
        }
示例#21
0
        private int GetLastStreamEventNumberCached(ITransactionFileReader reader, string streamId)
        {
            Ensure.NotNull(streamId, "streamId");

            StreamCacheInfo streamInfo;

            if (_streamInfoCache.TryGet(streamId, out streamInfo) && streamInfo.LastEventNumber.HasValue)
            {
                return(streamInfo.LastEventNumber.Value);
            }

            var lastEventNumber = GetLastStreamEventNumberUncached(reader, streamId);

            if (lastEventNumber != ExpectedVersion.NoStream)
            {
                // we should take Max on LastEventNumber because there could be a commit happening in parallel thread
                // so we should not overwrite the actual LastEventNumber updated by Commit method with our stale one
                _streamInfoCache.Put(
                    streamId,
                    key => new StreamCacheInfo(lastEventNumber, null),
                    (key, old) => new StreamCacheInfo(Math.Max(lastEventNumber, old.LastEventNumber ?? -1), old.Metadata));
            }
            return(lastEventNumber);
        }
        private StreamMetadata GetStreamMetadataUncached(ITransactionFileReader reader, string streamId)
        {
            EventRecord record;
            if (!GetStreamRecord(reader, streamId, 0, out record))
                throw new Exception("GetStreamMetadata couldn't find 0th event on stream. That should never happen.");

            if (record.Metadata == null || record.Metadata.Length == 0 || (record.Flags & PrepareFlags.IsJson) == 0)
                return new StreamMetadata(null, null);

            try
            {
                var json = Encoding.UTF8.GetString(record.Metadata);
                var jObj = JObject.Parse(json);

                int maxAge = -1;
                int maxCount = -1;

                JToken prop;
                if (jObj.TryGetValue(SystemMetadata.MaxAge, out prop) && prop.Type == JTokenType.Integer)
                    maxAge = prop.Value<int>();
                if (jObj.TryGetValue(SystemMetadata.MaxCount, out prop) && prop.Type == JTokenType.Integer)
                    maxCount = prop.Value<int>();

                return new StreamMetadata(maxCount > 0 ? maxCount : (int?) null,
                                          maxAge > 0 ? TimeSpan.FromSeconds(maxAge) : (TimeSpan?) null);
            }
            catch (Exception)
            {
                return new StreamMetadata(null, null);
            }
        }
示例#23
0
        private bool IsStreamDeletedInternal(ITransactionFileReader reader, string streamId)
        {
            EventRecord record;

            return(GetStreamRecord(reader, streamId, int.MaxValue, out record));
        }
示例#24
0
        private StreamMetadata GetStreamMetadataUncached(ITransactionFileReader reader, string streamId)
        {
            Interlocked.Increment(ref _notCachedStreamInfo);

            var metastreamId = SystemStreams.MetastreamOf(streamId);
            var metaEventNumber = GetLastStreamEventNumberCached(reader, metastreamId);
            if (metaEventNumber == ExpectedVersion.NoStream || metaEventNumber == EventNumber.DeletedStream)
                return StreamMetadata.Empty;

            EventRecord record;
            if (!GetStreamRecord(reader, metastreamId, metaEventNumber, out record))
                throw new Exception(string.Format("GetStreamRecord couldn't find metaevent #{0} on metastream '{1}'. That should never happen.", metaEventNumber, metastreamId));

            if (record.Data.Length == 0 || (record.Flags & PrepareFlags.IsJson) == 0)
                return StreamMetadata.Empty;

            try
            {
                return StreamMetadata.FromJsonBytes(record.Data);
            }
            catch (Exception)
            {
                return StreamMetadata.Empty;
            }
        }
示例#25
0
        private IndexReadEventResult ReadEventInternal(ITransactionFileReader reader, string streamId, int eventNumber)
        {
            Ensure.NotNull(streamId, "streamId");
            if (eventNumber < -1) throw new ArgumentOutOfRangeException("eventNumber");

            var lastEventNumber = GetLastStreamEventNumberCached(reader, streamId);
            if (lastEventNumber == EventNumber.DeletedStream)
                return new IndexReadEventResult(ReadEventResult.StreamDeleted, null);
            if (lastEventNumber == ExpectedVersion.NoStream)
                return new IndexReadEventResult(ReadEventResult.NoStream, null);

            if (eventNumber == -1) 
                eventNumber = lastEventNumber;
            
            var metadata = GetStreamMetadataCached(reader, streamId);
            if (metadata.MaxCount.HasValue)
            {
                var minEventNumber = lastEventNumber - metadata.MaxCount.Value + 1;
                if (eventNumber < minEventNumber || eventNumber > lastEventNumber)
                    return new IndexReadEventResult(ReadEventResult.NotFound, metadata);
            }

            EventRecord record;
            var success = GetStreamRecord(reader, streamId, eventNumber, out record);
            if (success)
            {
                if (metadata.MaxAge.HasValue && record.TimeStamp < DateTime.UtcNow - metadata.MaxAge.Value)
                    return new IndexReadEventResult(ReadEventResult.NotFound, metadata);
                return new IndexReadEventResult(ReadEventResult.Success, record, metadata);
            }

            return new IndexReadEventResult(ReadEventResult.NotFound, metadata);
        }
示例#26
0
        private int GetLastStreamEventNumberCached(ITransactionFileReader reader, string streamId)
        {
            Ensure.NotNull(streamId, "streamId");

            // if this is metastream -- check if original stream was deleted, if yes -- metastream is deleted as well
            if (SystemStreams.IsMetastream(streamId) 
                && GetLastStreamEventNumberCached(reader, SystemStreams.OriginalStreamOf(streamId)) == EventNumber.DeletedStream)
                return EventNumber.DeletedStream;

            StreamCacheInfo streamCacheInfo;
            if (_streamInfoCache.TryGet(streamId, out streamCacheInfo) && streamCacheInfo.LastEventNumber.HasValue)
            {
                Interlocked.Increment(ref _cachedStreamInfo);
                return streamCacheInfo.LastEventNumber.Value;
            }

            var lastEventNumber = GetLastStreamEventNumberUncached(reader, streamId);
            if (lastEventNumber != ExpectedVersion.NoStream)
            {
                // we should take Max on LastEventNumber because there could be a commit happening in parallel thread
                // so we should not overwrite the actual LastEventNumber updated by Commit method with our stale one
                _streamInfoCache.Put(
                    streamId,
                    key => new StreamCacheInfo(lastEventNumber, null),
                    (key, old) => new StreamCacheInfo(Math.Max(lastEventNumber, old.LastEventNumber ?? -1), old.Metadata));
            }
            return lastEventNumber;
        }
        private IndexReadEventResult ReadEventInternal(ITransactionFileReader reader, string streamId, int version)
        {
            Ensure.NotNull(streamId, "streamId");
            Ensure.Nonnegative(version, "eventNumber");

            var lastEventNumber = GetLastStreamEventNumberCached(reader, streamId);
            if (lastEventNumber == EventNumber.DeletedStream)
                return new IndexReadEventResult(ReadEventResult.StreamDeleted);
            if (lastEventNumber == ExpectedVersion.NoStream)
                return new IndexReadEventResult(ReadEventResult.NoStream);

            var metadata = GetStreamMetadataCached(reader, streamId);
            if (metadata.MaxCount.HasValue)
            {
                var minEventNumber = lastEventNumber - metadata.MaxCount.Value + 1;
                if (version < minEventNumber || version > lastEventNumber)
                    return new IndexReadEventResult(ReadEventResult.NotFound);
            }

            EventRecord record;
            var success = GetStreamRecord(reader, streamId, version, out record);
            if (success)
            {
                if (metadata.MaxAge.HasValue && record.TimeStamp < DateTime.UtcNow - metadata.MaxAge.Value)
                    return new IndexReadEventResult(ReadEventResult.NotFound);
                return new IndexReadEventResult(ReadEventResult.Success, record);
            }

            return new IndexReadEventResult(ReadEventResult.NotFound);
        }
 public TransactionsManager(IUnitOfWork unitOfWork, ITransactionFileReader fileReader)
 {
     _unitOfWork = unitOfWork;
     _fileReader = fileReader;
 }
 public TFReaderLease(ObjectPool<ITransactionFileReader> pool)
 {
     _pool = pool;
     Reader = pool.Get();
 }
 public TFReaderLease(ITransactionFileReader reader)
 {
     _pool  = null;
     Reader = reader;
 }
 public TFReaderLease(ObjectPool <ITransactionFileReader> pool)
 {
     _pool  = pool;
     Reader = pool.Get();
 }
        private bool GetStreamRecord(ITransactionFileReader reader, string streamId, int version, out EventRecord record)
        {
            // we assume that you already did check for stream deletion
            Ensure.NotNullOrEmpty(streamId, "streamId");
            Ensure.Nonnegative(version, "eventNumber");

            var streamHash = _hasher.Hash(streamId);

            long position;
            if (_tableIndex.TryGetOneValue(streamHash, version, out position))
            {
                var res = GetEventRecord(reader, new IndexEntry(streamHash, version, position));
                if (res.Success && res.Record.EventStreamId == streamId)
                {
                    _succReadCount += 1;
                    record = res.Record;
                    return true;
                }
                _failedReadCount += 1;

                foreach (var indexEntry in _tableIndex.GetRange(streamHash, version, version))
                {
                    if (indexEntry.Position == position) // already checked that
                        continue;

                    res = GetEventRecord(reader, indexEntry);
                    if (res.Success && res.Record.EventStreamId == streamId)
                    {
                        _succReadCount += 1;
                        record = res.Record;
                        return true;
                    }
                    _failedReadCount += 1;
                }
            }
            record = null;
            return false;
        }
示例#33
0
        private StreamAccessResult CheckStreamAccessInternal(ITransactionFileReader reader, string streamId, 
                                                             StreamAccessType streamAccessType, IPrincipal user)
        {
            if (SystemStreams.IsMetastream(streamId))
            {
                switch (streamAccessType)
                {
                    case StreamAccessType.Read:
                        return CheckStreamAccessInternal(reader, SystemStreams.OriginalStreamOf(streamId), StreamAccessType.MetaRead, user);
                    case StreamAccessType.Write:
                        return CheckStreamAccessInternal(reader, SystemStreams.OriginalStreamOf(streamId), StreamAccessType.MetaWrite, user);
                    case StreamAccessType.Delete:
                    case StreamAccessType.MetaRead:
                    case StreamAccessType.MetaWrite:
                        return StreamAccessResult.Denied;
                    default:
                        throw new ArgumentOutOfRangeException("streamAccessType");
                }
            }

            if ((streamAccessType == StreamAccessType.Write || streamAccessType == StreamAccessType.Delete)
                && streamId == SystemStreams.AllStream)
                return StreamAccessResult.Denied;

            if (user != null && user.IsInRole(SystemUserGroups.Admins))
                return StreamAccessResult.Granted;

            var meta = GetStreamMetadataCached(reader, streamId);
            var isSystemStream = SystemStreams.IsSystemStream(streamId);
            switch (streamAccessType)
            {
                case StreamAccessType.Read: 
                    return CheckRoleAccess(meta.Acl == null ? null : meta.Acl.ReadRole, user, isSystemStream);
                case StreamAccessType.Write:
                    return CheckRoleAccess(meta.Acl == null ? null : meta.Acl.WriteRole, user, isSystemStream);
                case StreamAccessType.Delete:
                    return CheckRoleAccess(meta.Acl == null ? null : meta.Acl.DeleteRole, user, isSystemStream);
                case StreamAccessType.MetaRead:
                    return CheckRoleAccess(meta.Acl == null ? null : meta.Acl.MetaReadRole, user, isSystemStream);
                case StreamAccessType.MetaWrite:
                    return CheckRoleAccess(meta.Acl == null ? null : meta.Acl.MetaWriteRole, user, isSystemStream);
                default: throw new ArgumentOutOfRangeException("streamAccessType");
            }
        }
 private static EventResult GetEventRecord(ITransactionFileReader reader, IndexEntry indexEntry)
 {
     var res = ReadPrepareInternal(reader, indexEntry.Position);
     if (!res.Success)
         return new EventResult(false, null);
     var eventRecord = new EventRecord(indexEntry.Version, res.Record);
     return new EventResult(true, eventRecord);
 }
示例#35
0
 private void ReturnReader(ITransactionFileReader reader)
 {
     _readers.Push(reader);
 }
 private static PrepareResult ReadPrepareInternal(ITransactionFileReader reader, long pos)
 {
     RecordReadResult result = reader.TryReadAt(pos);
     if (!result.Success)
         return new PrepareResult(false, null);
     Debug.Assert(result.LogRecord.RecordType == LogRecordType.Prepare, "Incorrect type of log record, expected Prepare record.");
     return new PrepareResult(true, (PrepareLogRecord)result.LogRecord);
 }
示例#37
0
        private StreamMetadata GetStreamMetadataCached(ITransactionFileReader reader, string streamId)
        {
            if (SystemStreams.IsMetastream(streamId))
                return _metastreamMetadata;

            StreamCacheInfo streamCacheInfo;
            if (_streamInfoCache.TryGet(streamId, out streamCacheInfo) && streamCacheInfo.Metadata != null)
            {
                Interlocked.Increment(ref _cachedStreamInfo);
                return streamCacheInfo.Metadata;
            }

            var metadata = GetStreamMetadataUncached(reader, streamId);
            _streamInfoCache.Put(streamId,
                                 key => new StreamCacheInfo(null, metadata),
                                 // we keep previous metadata, if present by this time, because it was added on commit and is more up to date
                                 (key, oldValue) => new StreamCacheInfo(oldValue.LastEventNumber, oldValue.Metadata ?? metadata));
            return metadata;
        }
        private int GetLastStreamEventNumberCached(ITransactionFileReader reader, string streamId)
        {
            Ensure.NotNull(streamId, "streamId");

            StreamCacheInfo streamCacheInfo;
            if (_streamInfoCache.TryGet(streamId, out streamCacheInfo) && streamCacheInfo.LastEventNumber.HasValue)
                return streamCacheInfo.LastEventNumber.Value;

            var lastEventNumber = GetLastStreamEventNumberUncached(reader, streamId);
            if (lastEventNumber != ExpectedVersion.NoStream)
            {
                // we should take Max on LastEventNumber because there could be a commit happening in parallel thread
                // so we should not overwrite the actual LastEventNumber updated by Commit method with our stale one
                _streamInfoCache.Put(
                    streamId,
                    key => new StreamCacheInfo(lastEventNumber, null),
                    (key, old) => new StreamCacheInfo(Math.Max(lastEventNumber, old.LastEventNumber ?? -1), old.Metadata));
            }
            return lastEventNumber;
        }
        private int GetLastStreamEventNumberUncached(ITransactionFileReader reader, string streamId)
        {
            var streamHash = _hasher.Hash(streamId);
            IndexEntry latestEntry;
            if (!_tableIndex.TryGetLatestEntry(streamHash, out latestEntry))
                return ExpectedVersion.NoStream;

            var res = ReadPrepareInternal(reader, latestEntry.Position);
            if (!res.Success)
                throw new Exception("Couldn't read latest stream's prepare! That shouldn't happen EVER!");
            if (res.Record.EventStreamId == streamId) // LUCKY!!!
                return latestEntry.Version;

            // TODO AN here lies the problem of out of memory if the stream has A LOT of events in them
            foreach (var indexEntry in _tableIndex.GetRange(streamHash, 0, int.MaxValue))
            {
                var r = ReadPrepareInternal(reader, indexEntry.Position);
                if (r.Success && r.Record.EventStreamId == streamId)
                    return indexEntry.Version; // AT LAST!!!
            }
            return ExpectedVersion.NoStream; // no such event stream
        }
        private StreamMetadata GetStreamMetadataCached(ITransactionFileReader reader, string streamId)
        {
            StreamCacheInfo streamCacheInfo;
            if (_streamInfoCache.TryGet(streamId, out streamCacheInfo) && streamCacheInfo.Metadata.HasValue)
                return streamCacheInfo.Metadata.Value;

            var metadata = GetStreamMetadataUncached(reader, streamId);
            _streamInfoCache.Put(streamId,
                                 key => new StreamCacheInfo(null, metadata),
                                 (key, oldValue) => new StreamCacheInfo(oldValue.LastEventNumber, metadata));
            return metadata;
        }
 private void ReturnReader(ITransactionFileReader reader)
 {
     _readers.Push(reader);
 }
 public TFReaderLease(ITransactionFileReader reader)
 {
     _pool = null;
     Reader = reader;
 }