Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
 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));
                 }
             }
         }
     }
 }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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);
            }
        }
Beispiel #7
0
        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);
            }
        }