Ejemplo n.º 1
0
        // in v2 this checks if the first character is '$'
        // system streams can be created dynamically at runtime
        // e.g. "$persistentsubscription-" + _eventStreamId + "::" + _groupName + "-parked"
        // so we can either allocate a range of numbers (how many?) for them, or look up the name and see if it begins with $.
        // for now do the latter because (1) allocating a range of numbers will probably get fiddly
        // and (2) i expect we will find that at the point we are trying to determine if a stream is a system stream then
        // we will have already looked up its info in the stream index, so this call will become trivial or unnecessary.
        public bool IsSystemStream(StreamId streamId)
        {
            if (IsVirtualStream(streamId) ||
                _metastreams.IsMetaStream(streamId) ||
                streamId == NoSystemStream)
            {
                return(true);
            }

            if (streamId == NoUserStream)
            {
                return(false);
            }

            var streamName = _streamNames.LookupName(streamId);

            return(SystemStreams.IsSystemStream(streamName));
        }
Ejemplo n.º 2
0
        private IndexReadAllResult ReadAllEventsForwardInternal(TFPos pos, int maxCount, int maxSearchWindow,
                                                                IEventFilter eventFilter)
        {
            var records = new List <CommitEventRecord>();
            var nextPos = pos;
            // in case we are at position after which there is no commit at all, in that case we have to force
            // PreparePosition to long.MaxValue, so if you decide to read backwards from PrevPos,
            // you will receive all prepares.
            var prevPos = new TFPos(pos.CommitPosition, long.MaxValue);
            var consideredEventsCount = 0L;
            var firstCommit           = true;
            var reachedEndOfStream    = false;

            using (var reader = _backend.BorrowReader()) {
                long nextCommitPos = pos.CommitPosition;
                while (records.Count < maxCount && consideredEventsCount < maxSearchWindow)
                {
                    if (nextCommitPos > _indexCommitter.LastIndexedPosition)
                    {
                        reachedEndOfStream = true;
                        break;
                    }

                    reader.Reposition(nextCommitPos);

                    SeqReadResult result;
                    while ((result = reader.TryReadNext()).Success && !IsCommitAlike(result.LogRecord))
                    {
                        // skip until commit
                    }

                    if (!result.Success)                     // no more records in TF
                    {
                        break;
                    }

                    nextCommitPos = result.RecordPostPosition;

                    switch (result.LogRecord.RecordType)
                    {
                    case LogRecordType.Prepare:
                    case LogRecordType.Stream: {
                        var prepare = (IPrepareLogRecord <TStreamId>)result.LogRecord;
                        if (firstCommit)
                        {
                            firstCommit = false;
                            prevPos     = new TFPos(result.RecordPrePosition, result.RecordPrePosition);
                        }

                        if (prepare.Flags.HasAnyOf(PrepareFlags.Data | PrepareFlags.StreamDelete) &&
                            new TFPos(prepare.LogPosition, prepare.LogPosition) >= pos)
                        {
                            var streamName  = _streamNames.LookupName(prepare.EventStreamId);
                            var eventRecord = new EventRecord(eventNumber: prepare.ExpectedVersion + 1,
                                                              prepare, streamName);
                            consideredEventsCount++;
                            if (eventFilter.IsEventAllowed(eventRecord))
                            {
                                records.Add(new CommitEventRecord(eventRecord, prepare.LogPosition));
                            }

                            nextPos = new TFPos(result.RecordPostPosition, 0);
                        }

                        break;
                    }

                    case LogRecordType.Commit: {
                        var commit = (CommitLogRecord)result.LogRecord;
                        if (firstCommit)
                        {
                            firstCommit = false;
                            // for backward pass we want to allow read the same commit and skip read prepares,
                            // so we put post-position of commit and post-position of prepare as TFPos for backward pass
                            prevPos = new TFPos(result.RecordPostPosition, pos.PreparePosition);
                        }

                        reader.Reposition(commit.TransactionPosition);
                        while (consideredEventsCount < maxCount)
                        {
                            result = reader.TryReadNext();
                            if (!result.Success)                                     // no more records in TF
                            {
                                break;
                            }
                            // prepare with TransactionEnd could be scavenged already
                            // so we could reach the same commit record. In that case have to stop
                            if (result.LogRecord.LogPosition >= commit.LogPosition)
                            {
                                break;
                            }
                            if (result.LogRecord.RecordType != LogRecordType.Prepare)
                            {
                                continue;
                            }

                            var prepare = (IPrepareLogRecord <TStreamId>)result.LogRecord;
                            if (prepare.TransactionPosition != commit.TransactionPosition)                                     // wrong prepare
                            {
                                continue;
                            }

                            // prepare with useful data or delete tombstone
                            if (prepare.Flags.HasAnyOf(PrepareFlags.Data | PrepareFlags.StreamDelete) &&
                                new TFPos(commit.LogPosition, prepare.LogPosition) >= pos)
                            {
                                var streamName  = _streamNames.LookupName(prepare.EventStreamId);
                                var eventRecord =
                                    new EventRecord(commit.FirstEventNumber + prepare.TransactionOffset,
                                                    prepare, streamName);
                                consideredEventsCount++;
                                if (eventFilter.IsEventAllowed(eventRecord))
                                {
                                    records.Add(new CommitEventRecord(eventRecord, commit.LogPosition));
                                }

                                // for forward pass position is inclusive,
                                // so we put pre-position of commit and post-position of prepare
                                nextPos = new TFPos(commit.LogPosition, result.RecordPostPosition);
                            }

                            if (prepare.Flags.HasAnyOf(PrepareFlags.TransactionEnd))
                            {
                                break;
                            }
                        }

                        break;
                    }

                    default:
                        throw new Exception(string.Format("Unexpected log record type: {0}.",
                                                          result.LogRecord.RecordType));
                    }
                }

                return(new IndexReadAllResult(records, pos, nextPos, prevPos, reachedEndOfStream, consideredEventsCount));
            }
        }
Ejemplo n.º 3
0
 string IReadIndex <TStreamId> .GetStreamName(TStreamId streamId)
 {
     return(_streamNames.LookupName(streamId));
 }