private PrepareLogRecord ReadPrepareInternal(TFReaderLease reader, string streamId, int eventNumber) { // we assume that you already did check for stream deletion Ensure.NotNullOrEmpty(streamId, "streamId"); Ensure.Nonnegative(eventNumber, "eventNumber"); var streamHash = _hasher.Hash(streamId); long position; if (_tableIndex.TryGetOneValue(streamHash, eventNumber, out position)) { var rec = ReadPrepareInternal(reader, position); if (rec != null && rec.EventStreamId == streamId) { return(rec); } foreach (var indexEntry in _tableIndex.GetRange(streamHash, eventNumber, eventNumber)) { Interlocked.Increment(ref _hashCollisions); if (indexEntry.Position == position) // already checked that { continue; } rec = ReadPrepareInternal(reader, indexEntry.Position); if (rec != null && rec.EventStreamId == streamId) { return(rec); } } } return(null); }
public RangeReadResult ReadStreamEventsForward(string streamId, int fromEventNumber, int maxCount, out EventRecord[] records) { Ensure.NotNull(streamId, "streamId"); Ensure.Nonnegative(fromEventNumber, "fromEventNumber"); Ensure.Positive(maxCount, "maxCount"); records = EmptyRecords; var streamHash = _hasher.Hash(streamId); var reader = GetReader(); try { if (IsStreamDeletedInternal(reader, streamId)) { return(RangeReadResult.StreamDeleted); } StreamMetadata metadata; bool streamExists; bool useMetadata = GetStreamMetadataInternal(reader, streamId, out streamExists, out metadata); if (!streamExists) { return(RangeReadResult.NoStream); } int startEventNumber = fromEventNumber; int endEventNumber = fromEventNumber + maxCount - 1; if (useMetadata && metadata.MaxCount.HasValue) { var lastStreamEventNumber = GetLastStreamEventNumberInternal(reader, streamId); var minEventNumber = lastStreamEventNumber - metadata.MaxCount.Value + 1; if (minEventNumber > endEventNumber) { return(RangeReadResult.Success); } startEventNumber = Math.Max(startEventNumber, minEventNumber); } var recordsQuery = _tableIndex.GetRange(streamHash, startEventNumber, endEventNumber) .Select(x => GetEventRecord(reader, x)) .Where(x => x.EventStreamId == streamId); if (useMetadata && metadata.MaxAge.HasValue) { var ageThreshold = DateTime.UtcNow - metadata.MaxAge.Value; recordsQuery = recordsQuery.Where(x => x.TimeStamp >= ageThreshold); } records = recordsQuery.Reverse().ToArray(); return(RangeReadResult.Success); } finally { ReturnReader(reader); } }
private PrepareLogRecord ReadPrepare(TFReaderLease reader, string streamId, long eventNumber) { var recordsQuery = _tableIndex.GetRange(streamId, eventNumber, eventNumber) .Select(x => new { x.Version, Prepare = ReadPrepareInternal(reader, x.Position) }) .Where(x => x.Prepare != null && x.Prepare.EventStreamId == streamId) .GroupBy(x => x.Version).Select(x => x.Last()).ToList(); if (recordsQuery.Count() == 1) { return(recordsQuery.First().Prepare); } return(null); }
private void CheckDuplicateEvents(uint streamHash, CommitLogRecord commit, IList <IndexEntry> indexEntries, IList <PrepareLogRecord> prepares) { using (var reader = _backend.BorrowReader()) { var entries = _tableIndex.GetRange(streamHash, indexEntries[0].Version, indexEntries[indexEntries.Count - 1].Version); foreach (var indexEntry in entries) { var prepare = prepares[indexEntry.Version - indexEntries[0].Version]; PrepareLogRecord indexedPrepare = GetPrepare(reader, indexEntry.Position); if (indexedPrepare != null && indexedPrepare.EventStreamId == prepare.EventStreamId) { if (Debugger.IsAttached) { Debugger.Break(); } else { throw new Exception( string.Format("Trying to add duplicate event #{0} to stream {1} (hash {2})\nCommit: {3}\n" + "Prepare: {4}\nIndexed prepare: {5}.", indexEntry.Version, prepare.EventStreamId, streamHash, commit, prepare, indexedPrepare)); } } } } }
private PrepareLogRecord ReadPrepareInternal(TFReaderLease reader, string streamId, int eventNumber) { // we assume that you already did check for stream deletion Ensure.NotNullOrEmpty(streamId, "streamId"); Ensure.Nonnegative(eventNumber, "eventNumber"); var recordsQuery = _tableIndex.GetRange(streamId, eventNumber, eventNumber) .Select(x => new { x.Version, Prepare = ReadPrepareInternal(reader, x.Position) }) .Where(x => x.Prepare != null && x.Prepare.EventStreamId == streamId) .GroupBy(x => x.Version).Select(x => x.Last()); if (recordsQuery.Count() == 1) { return(recordsQuery.First().Prepare); } return(null); }
public RangeReadResult TryReadEventsForward(string eventStreamId, int fromEventNumber, int maxCount, out EventRecord[] records) { Ensure.NotNull(eventStreamId, "eventStreamId"); Ensure.Nonnegative(fromEventNumber, "fromEventNumber"); Ensure.Positive(maxCount, "maxCount"); records = EmptyRecords; var streamHash = _hasher.Hash(eventStreamId); var reader = GetReader(); try { if (IsStreamDeletedInternal(reader, eventStreamId)) { return(RangeReadResult.StreamDeleted); } records = _tableIndex.GetRange(streamHash, fromEventNumber, fromEventNumber + maxCount - 1) .Select(x => ReadEventRecord(reader, x)) .Where(x => x.EventStreamId == eventStreamId) .Reverse() .ToArray(); if (records.Length > 0) { return(RangeReadResult.Success); } if (fromEventNumber == 0) { return(RangeReadResult.NoStream); } EventRecord record; return(TryGetRecordInternal(reader, eventStreamId, 0, out record) ? RangeReadResult.Success : RangeReadResult.NoStream); } finally { ReturnReader(reader); } }
ReadStreamResult IReadIndex.ReadStreamEventsForward(string streamId, int fromEventNumber, int maxCount) { Ensure.NotNull(streamId, "streamId"); Ensure.Nonnegative(fromEventNumber, "fromEventNumber"); Ensure.Positive(maxCount, "maxCount"); var streamHash = _hasher.Hash(streamId); var reader = GetReader(); try { var lastEventNumber = GetLastStreamEventNumberCached(reader, streamId); if (lastEventNumber == EventNumber.DeletedStream) { return(new ReadStreamResult(RangeReadResult.StreamDeleted)); } if (lastEventNumber == ExpectedVersion.NoStream) { return(new ReadStreamResult(RangeReadResult.NoStream)); } StreamMetadata metadata; bool useMetadata = GetStreamMetadataCached(reader, streamId, out metadata); int startEventNumber = fromEventNumber; int endEventNumber = (int)Math.Min(int.MaxValue, (long)fromEventNumber + maxCount - 1); if (useMetadata && metadata.MaxCount.HasValue) { var minEventNumber = lastEventNumber - metadata.MaxCount.Value + 1; if (endEventNumber < minEventNumber) { return(new ReadStreamResult(RangeReadResult.Success, EmptyRecords, minEventNumber, lastEventNumber, isEndOfStream: false)); } startEventNumber = Math.Max(startEventNumber, minEventNumber); } var recordsQuery = _tableIndex.GetRange(streamHash, startEventNumber, endEventNumber) .Select(x => GetEventRecord(reader, x)) .Where(x => x.EventStreamId == streamId); if (useMetadata && metadata.MaxAge.HasValue) { var ageThreshold = DateTime.UtcNow - metadata.MaxAge.Value; recordsQuery = recordsQuery.Where(x => x.TimeStamp >= ageThreshold); } var records = recordsQuery.Reverse().ToArray(); int nextEventNumber = Math.Min(endEventNumber + 1, lastEventNumber + 1); if (records.Length > 0) { nextEventNumber = records[records.Length - 1].EventNumber + 1; } var isEndOfStream = endEventNumber >= lastEventNumber; return(new ReadStreamResult(RangeReadResult.Success, records, nextEventNumber, lastEventNumber, isEndOfStream)); } finally { ReturnReader(reader); } }