protected override void Given()
            {
                base.Given();
                AllWritesSucceed();

                _tfPos1 = ExistingEvent("test-stream", "type1", "{}", "{Data: 1}");
                _tfPos2 = ExistingEvent("test-stream", "type1", "{}", "{Data: 2}");
                _tfPos3 = ExistingEvent("test-stream", "type2", "{}", "{Data: 3}");

                GivenInitialIndexState();

                _subscriptionId = Guid.NewGuid();
                _sourceDefinition = new QuerySourcesDefinition
                {
                    AllStreams = true,
                    Events = new[] {"type1", "type2"},
                    Options = new QuerySourcesDefinitionOptions {}
                };
                _readerStrategy = ReaderStrategy.Create(
                    "test",
                    0,
                    _sourceDefinition,
                    _timeProvider,
                    stopOnEof: false,
                    runAs: null);

                _readerSubscriptionOptions = new ReaderSubscriptionOptions(
                    checkpointUnhandledBytesThreshold: 10000, checkpointProcessedEventsThreshold: 100, stopOnEof: false,
                    stopAfterNEvents: null);
            }
コード例 #2
0
            protected override void Given()
            {
                base.Given();
                AllWritesSucceed();
                _tfPos1 = ExistingEvent("test-stream", "type1", "{}", "{Data: 1}");
                _tfPos2 = ExistingEvent("test-stream", "type1", "{}", "{Data: 2}");
                _tfPos3 = ExistingEvent("test-stream2", "type1", "{}", "{Data: 3}");
                ExistingEvent("test-stream2", "type1", "{}", "{Data: 4}");
                ExistingEvent("test-stream3", "type1", "{}", "{Data: 5}");
                ExistingEvent("test-stream3", "type1", "{}", "{Data: 6}");
                ExistingEvent("test-stream4", "type1", "{}", "{Data: 7}");

                ExistingEvent("catalog", "$>", null, "0@test-stream");
                ExistingEvent("catalog", "$>", null, "0@test-stream2");
                ExistingEvent("catalog", "$>", null, "0@test-stream3");

                _subscriptionId = Guid.NewGuid();
                _sourceDefinition = new QuerySourcesDefinition
                {
                    CatalogStream = "catalog",
                    AllEvents = true,
                    ByStreams = true,
                    Options = new QuerySourcesDefinitionOptions { }
                };
                _readerStrategy = ReaderStrategy.Create(0, _sourceDefinition, _timeProvider, stopOnEof: true, runAs: null);
                _readerSubscriptionOptions = new ReaderSubscriptionOptions(
                    checkpointUnhandledBytesThreshold: 10000, checkpointProcessedEventsThreshold: 100, stopOnEof: true,
                    stopAfterNEvents: null);
            }
コード例 #3
0
ファイル: ResolvedEvent.cs プロジェクト: msbahrul/EventStore
        public ResolvedEvent(
            string positionStreamId, int positionSequenceNumber, string eventStreamId, int eventSequenceNumber,
            bool resolvedLinkTo, TFPos position, Guid eventId, string eventType, bool isJson, string data,
            string metadata, string positionMetadata = null, string streamMetadata = null)
        {
            DateTime timestamp = default(DateTime);
            if (Guid.Empty == eventId)
                throw new ArgumentException("Empty eventId provided.");
            if (string.IsNullOrEmpty(eventType))
                throw new ArgumentException("Empty eventType provided.");

            _positionStreamId = positionStreamId;
            _positionSequenceNumber = positionSequenceNumber;
            _eventStreamId = eventStreamId;
            _eventSequenceNumber = eventSequenceNumber;
            _resolvedLinkTo = resolvedLinkTo;
            _position = position;
            EventId = eventId;
            EventType = eventType;
            IsJson = isJson;
            Timestamp = timestamp;

            Data = data;
            Metadata = metadata;
            PositionMetadata = positionMetadata;
            StreamMetadata = streamMetadata;
        }
コード例 #4
0
        public ResolvedEvent(
            string positionStreamId, int positionSequenceNumber, string eventStreamId, int eventSequenceNumber,
            bool resolvedLinkTo, TFPos position, TFPos originalPosition, Guid eventId, string eventType, bool isJson, byte[] data,
            byte[] metadata, byte[] positionMetadata, DateTime timestamp)
        {
            if (Guid.Empty == eventId)
                throw new ArgumentException("Empty eventId provided.");
            if (string.IsNullOrEmpty(eventType))
                throw new ArgumentException("Empty eventType provided.");

            _positionStreamId = positionStreamId;
            _positionSequenceNumber = positionSequenceNumber;
            _eventStreamId = eventStreamId;
            _eventSequenceNumber = eventSequenceNumber;
            _resolvedLinkTo = resolvedLinkTo;
            _position = position;
            _originalPosition = originalPosition;
            EventId = eventId;
            EventType = eventType;
            IsJson = isJson;
            Timestamp = timestamp;

            //TODO: handle utf-8 conversion exception
            Data = Helper.UTF8NoBom.GetString(data);
            Metadata = Helper.UTF8NoBom.GetString(metadata);
            PositionMetadata = positionMetadata != null ? Helper.UTF8NoBom.GetString(positionMetadata) : null;
        }
 public void read_all_backward_from_beginning_of_second_chunk_returns_no_records()
 {
     var pos = new TFPos(10000, 10000);
     var events = ReadIndex.ReadAllEventsBackward(pos, 100).Records.Select(r => r.Event).ToArray();
     Assert.AreEqual(1, events.Length);
     Assert.AreEqual(_event1, events[0]);
 }
        protected override void Given()
        {
            base.Given();
            NoOtherStreams();
            _message1Position = ExistingEvent("stream1", "message1", null, "{}");

            _projectionSource = @"fromAll().when({message1: function(s,e){ throw 1; }});";
        }
        public void read_all_events_backward_returns_all_events_in_correct_order()
        {
            var pos = new TFPos(Db.Config.WriterCheckpoint.Read(), Db.Config.WriterCheckpoint.Read());
            var records = ReadIndex.ReadAllEventsBackward(pos, 10, false).Records;

            Assert.AreEqual(2, records.Count);
            Assert.AreEqual(_id1, records[1].Event.EventId);
            Assert.AreEqual(_id2, records[0].Event.EventId);
        }
コード例 #8
0
        public IndexReadAllResult(List<CommitEventRecord> records, TFPos currentPos, TFPos nextPos, TFPos prevPos)
        {
            Ensure.NotNull(records, "records");

            Records = records;
            CurrentPos = currentPos;
            NextPos = nextPos;
            PrevPos = prevPos;
        }
コード例 #9
0
 public SubscribeAwake(
     IEnvelope envelope, Guid correlationId, string streamId, TFPos @from, Message replyWithMessage)
 {
     StreamId = streamId;
     From = @from;
     ReplyWithMessage = replyWithMessage;
     Envelope = envelope;
     CorrelationId = correlationId;
 }
コード例 #10
0
        public ReadAllResult(ResolvedEvent[] events, int maxCount, TFPos currentPos, TFPos nextPos, TFPos prevPos, long tfEofPosition)
        {
            Ensure.NotNull(events, "events");

            Events = events;
            MaxCount = maxCount;
            CurrentPos = currentPos;
            NextPos = nextPos;
            PrevPos = prevPos;
            TfEofPosition = tfEofPosition;
        }
コード例 #11
0
ファイル: ReadAllResult.cs プロジェクト: robashton/EventStore
        public ReadAllResult(ResolvedEventRecord[] records, int maxCount, TFPos currentPos, TFPos nextPos, TFPos prevPos, long tfEofPosition)
        {
            Ensure.NotNull(records, "records");

            Records = records;
            MaxCount = maxCount;
            CurrentPos = currentPos;
            NextPos = nextPos;
            PrevPos = prevPos;
            TfEofPosition = tfEofPosition;
        }
コード例 #12
0
 public void GetAllBefore(HttpEntity entity, TFPos position, int count)
 {
     var envelope = new SendToHttpEnvelope(entity,
                                           Format.Atom.ReadAllEventsBackwardCompleted,
                                           Configure.ReadAllEventsBackwardCompleted);
     Publish(new ClientMessage.ReadAllEventsBackward(Guid.NewGuid(),
                                                     envelope,
                                                     position.CommitPosition,
                                                     position.PreparePosition,
                                                     count,
                                                     true));
 }
        public void all_records_can_be_read_sequentially_page_by_page_in_backward_pass()
        {
            var recs = new[] { _p5, _p3, _p1, _p4, _p2 }; // in reverse committed order

            int count = 0;
            var pos = new TFPos(Db.Config.WriterCheckpoint.Read(), Db.Config.WriterCheckpoint.Read());
            ReadAllResult result;
            while ((result = ReadIndex.ReadAllEventsBackward(pos, 1, false)).Records.Count != 0)
            {
                Assert.AreEqual(1, result.Records.Count);
                Assert.AreEqual(recs[count], result.Records[0].Event);
                pos = result.NextPos;
                count += 1;
            }
            Assert.AreEqual(recs.Length, count);
        }
        public void all_records_can_be_read_sequentially_page_by_page_in_forward_pass()
        {
            var recs = new[] {_p2, _p4, _p1, _p3, _p5}; // in committed order

            int count = 0;
            var pos = new TFPos(0, 0);
            ReadAllResult result;
            while ((result = ReadIndex.ReadAllEventsForward(pos, 1, false)).Records.Count != 0)
            {
                Assert.AreEqual(1, result.Records.Count);
                Assert.AreEqual(recs[count], result.Records[0].Event);
                pos = result.NextPos;
                count += 1;
            }
            Assert.AreEqual(recs.Length, count);
        }
コード例 #15
0
        public IndexReadAllResult(List<CommitEventRecord> records, 
                                  int maxCount, 
                                  TFPos currentPos, 
                                  TFPos nextPos, 
                                  TFPos prevPos, 
                                  long tfEofPosition)
        {
            Ensure.NotNull(records, "records");

            Records = records;
            MaxCount = maxCount;
            CurrentPos = currentPos;
            NextPos = nextPos;
            PrevPos = prevPos;
            TfEofPosition = tfEofPosition;
        }
コード例 #16
0
            protected override void Given()
            {
                base.Given();
                AllWritesSucceed();
                _tfPos1 = ExistingEvent("stream-a", "type1", "{}", "{Data: 1}");
                _tfPos2 = ExistingEvent("stream-b", "type1", "{}", "{Data: 2}");

                GivenOtherEvents();

                _subscriptionId = Guid.NewGuid();
                _sourceDefinition = new QuerySourcesDefinition
                    {
                        Streams =  new []{"stream-a", "stream-b"},
                        AllEvents = true,
                        Options = new QuerySourcesDefinitionOptions {ReorderEvents = true, ProcessingLag = 100}
                    };
                _readerStrategy = ReaderStrategy.Create(0, _sourceDefinition, _timeProvider, stopOnEof: false, runAs: null);
                _readerSubscriptionOptions = new ReaderSubscriptionOptions(
                    checkpointUnhandledBytesThreshold: 10000, checkpointProcessedEventsThreshold: 100, stopOnEof: false,
                    stopAfterNEvents: null);
            }
コード例 #17
0
            //private TFPos _tfPos2;
            //private TFPos _tfPos3;

            protected override void Given()
            {
                base.Given();
                _tfPos1 = ExistingEvent("test-stream", "type1", "{}", "{Data: 1}");
                //_tfPos2 = ExistingEvent("test-stream", "type1", "{}", "{Data: 2}");
                //_tfPos3 = ExistingEvent("test-stream", "type2", "{}", "{Data: 3}");

                ExistingEvent("$et-type1", "$>", TFPosToMetadata(_tfPos1), "0@test-stream");
                NoStream("$et-type2");
                NoStream("$et");
                //NOTE: the following events should be late written
                //ExistingEvent("$et-type2", "$>", "", "2@test-stream");
                //ExistingEvent("$et-type1", "$>", "", "1@test-stream");

                _querySourcesDefinition = new QuerySourcesDefinition
                    {
                        AllStreams = true,
                        Events = new[] {"type1", "type2"},
                        Options = new QuerySourcesDefinitionOptions {}
                    };
                _fromPosition = CheckpointTag.FromEventTypeIndexPositions(new TFPos(0, -1), new Dictionary<string, int>{{"type1", -1}, {"type2", -1}});
                _maxEvents = 1; // reading the first event
            }
コード例 #18
0
            protected override void Given()
            {
                base.Given();
                AllWritesSucceed();
                _tfPos1 = ExistingEvent("test-stream", "type1", "{}", "{Data: 1}");
                _tfPos2 = ExistingEvent("test-stream", "type1", "{}", "{Data: 2}");
                _tfPos3 = ExistingEvent("test-stream2", "type1", "{}", "{Data: 3}");
                ExistingEvent("test-stream2", "type1", "{}", "{Data: 4}");
                ExistingEvent("test-stream3", "type1", "{}", "{Data: 5}");
                ExistingEvent("test-stream3", "type1", "{}", "{Data: 6}");
                ExistingEvent("test-stream4", "type1", "{}", "{Data: 7}");

                ExistingEvent("$$test-stream", "$metadata", "", "{Meta: 1}");
                ExistingEvent("$$test-stream2", "$metadata", "", "{Meta: 2}");
                ExistingEvent("$$test-stream3", "$metadata", "", "{Meta: 3}");


                ExistingEvent("$streams", "$>", null, "0@test-stream");
                ExistingEvent("$streams", "$>", null, "0@test-stream2");
                ExistingEvent("$streams", "$>", null, "0@test-stream3");
                ExistingEvent("$streams", "$>", null, "0@test-stream4");
                NoOtherStreams();

                _subscriptionId = Guid.NewGuid();
                _sourceDefinition = new QuerySourcesDefinition
                {
                    CatalogStream = "$all",
                    AllEvents = true,
                    ByStreams = true,
                    Options = new QuerySourcesDefinitionOptions { }
                };
                _readerStrategy = new ParallelQueryAllStreamsMasterReaderStrategy(
                    0, SystemAccount.Principal, _timeProvider);
                _readerSubscriptionOptions = new ReaderSubscriptionOptions(
                    checkpointUnhandledBytesThreshold: 10000, checkpointProcessedEventsThreshold: 100, stopOnEof: true,
                    stopAfterNEvents: null);
            }
コード例 #19
0
ファイル: ResolvedEvent.cs プロジェクト: msbahrul/EventStore
        public ResolvedEvent(
            string positionStreamId, int positionSequenceNumber, string eventStreamId, int eventSequenceNumber,
            bool resolvedLinkTo, TFPos position, TFPos originalPosition, Guid eventId, string eventType, bool isJson, byte[] data,
            byte[] metadata, byte[] positionMetadata, byte[] streamMetadata, DateTime timestamp)
        {

            _positionStreamId = positionStreamId;
            _positionSequenceNumber = positionSequenceNumber;
            _eventStreamId = eventStreamId;
            _eventSequenceNumber = eventSequenceNumber;
            _resolvedLinkTo = resolvedLinkTo;
            _position = position;
            _originalPosition = originalPosition;
            EventId = eventId;
            EventType = eventType;
            IsJson = isJson;
            Timestamp = timestamp;

            //TODO: handle utf-8 conversion exception
            Data = data != null ? Helper.UTF8NoBom.GetString(data): null;
            Metadata = metadata != null ? Helper.UTF8NoBom.GetString(metadata): null;
            PositionMetadata = positionMetadata != null ? Helper.UTF8NoBom.GetString(positionMetadata) : null;
            StreamMetadata = streamMetadata != null ? Helper.UTF8NoBom.GetString(streamMetadata) : null;
        }
コード例 #20
0
ファイル: CheckpointTag.cs プロジェクト: tone81/EventStore
 public static CheckpointTag FromEventTypeIndexPositions(TFPos position, IDictionary <string, int> streams)
 {
     // streams cloned inside
     return(new CheckpointTag(streams, position));
 }
コード例 #21
0
 IndexReadAllResult IReadIndex.ReadAllEventsBackward(TFPos pos, int maxCount)
 {
     return _allReader.ReadAllEventsBackward(pos, maxCount);
 }
コード例 #22
0
        /// <summary>
        /// Returns event records in the sequence they were committed into TF.
        /// Positions is specified as pre-positions (pointer at the beginning of the record).
        /// </summary>
        IndexReadAllResult IReadIndex.ReadAllEventsForward(TFPos pos, int maxCount)
        {
            var lastCommitPosition = Interlocked.Read(ref _lastCommitPosition);

            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 int.MaxValue, so if you decide to read backwards from PrevPos, 
            // you will receive all prepares.
            var prevPos = new TFPos(pos.CommitPosition, int.MaxValue);
            var count = 0;
            bool firstCommit = true;
            ITransactionFileSequentialReader seqReader = GetSeqReader();
            try
            {
                long nextCommitPos = pos.CommitPosition;
                while (count < maxCount)
                {
                    seqReader.Reposition(nextCommitPos);

                    SeqReadResult result;
                    do
                    {
                        result = seqReader.TryReadNext();
                    }
                    while (result.Success && result.LogRecord.RecordType != LogRecordType.Commit); // skip until commit

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

                    nextCommitPos = result.RecordPostPosition;

                    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);
                    }

                    seqReader.Reposition(commit.TransactionPosition);
                    while (count < maxCount)
                    {
                        result = seqReader.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.Position >= commit.Position) 
                            break;
                        if (result.LogRecord.RecordType != LogRecordType.Prepare) 
                            continue;

                        var prepare = (PrepareLogRecord)result.LogRecord;
                        if (prepare.TransactionPosition != commit.TransactionPosition) // wrong prepare
                            continue;

                        // prepare with useful data or delete tombstone
                        if ((prepare.Flags & (PrepareFlags.Data | PrepareFlags.StreamDelete)) != 0) 
                        {
                            if (new TFPos(commit.Position, prepare.LogPosition) >= pos)
                            {
                                var eventRecord = new EventRecord(commit.FirstEventNumber + prepare.TransactionOffset, prepare);
                                records.Add(new CommitEventRecord(eventRecord, commit.Position));
                                count++;

                                // 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 & PrepareFlags.TransactionEnd) != 0)
                            break;
                    }
                }
            }
            finally
            {
                ReturnSeqReader(seqReader);
            }
            return new IndexReadAllResult(records, maxCount, pos, nextPos, prevPos, lastCommitPosition);
        }
コード例 #23
0
        private static List<List<PTable>> LoadPTables(StreamReader reader, string indexmapFilename, TFPos checkpoints)
        {
            var tables = new List<List<PTable>>();

            // all next lines are PTables sorted by levels
            string text;
            while ((text = reader.ReadLine()) != null)
            {
                if (checkpoints.PreparePosition < 0 || checkpoints.CommitPosition < 0)
                    throw new CorruptIndexException(
                        string.Format("Negative prepare/commit checkpoint in non-empty IndexMap: {0}.", checkpoints));

                PTable ptable = null;
                var pieces = text.Split(',');
                try
                {
                    var level = int.Parse(pieces[0]);
                    var position = int.Parse(pieces[1]);
                    var file = pieces[2];
                    var path = Path.GetDirectoryName(indexmapFilename);
                    var ptablePath = Path.Combine(path, file);

                    ptable = PTable.FromFile(ptablePath);
                    ptable.VerifyFileHash();

                    CreateIfNeeded(level, tables);
                    tables[level].Insert(position, ptable);
                }
                catch (Exception exc)
                {
                    // if PTable file path was correct, but data is corrupted, we still need to dispose opened streams
                    if (ptable != null)
                        ptable.Dispose();

                    // also dispose all previously loaded correct PTables
                    for (int i=0; i<tables.Count; ++i)
                    {
                        for (int j=0; j<tables[i].Count; ++j)
                        {
                            tables[i][j].Dispose();
                        }
                    }

                    throw new CorruptIndexException("Error while loading IndexMap.", exc);
                }
            }
            return tables;
        }
        public void position_returned_for_prev_page_when_traversing_backward_allow_to_traverse_forward_correctly()
        {
            var recs = new[] { _p5, _p3, _p1, _p4, _p2 }; // in reverse committed order

            int count = 0;
            var pos = new TFPos(Db.Config.WriterCheckpoint.Read(), Db.Config.WriterCheckpoint.Read());
            ReadAllResult result;
            while ((result = ReadIndex.ReadAllEventsBackward(pos, 1, false)).Records.Count != 0)
            {
                Assert.AreEqual(1, result.Records.Count);
                Assert.AreEqual(recs[count], result.Records[0].Event);

                var localPos = result.PrevPos;
                int localCount = 0;
                ReadAllResult localResult;
                while ((localResult = ReadIndex.ReadAllEventsForward(localPos, 1, false)).Records.Count != 0)
                {
                    Assert.AreEqual(1, localResult.Records.Count);
                    Assert.AreEqual(recs[count - 1 - localCount], localResult.Records[0].Event);
                    localPos = localResult.NextPos;
                    localCount += 1;
                }

                pos = result.NextPos;
                count += 1;
            }
            Assert.AreEqual(recs.Length, count);
        }
コード例 #25
0
ファイル: CheckpointTag.cs プロジェクト: tone81/EventStore
 private CheckpointTag(TFPos position)
 {
     Position = position;
     Mode_    = CalculateMode();
 }
コード例 #26
0
 private bool BeforeTheLastKnownIndexCheckpoint(TFPos tfPosition)
 {
     return(_lastKnownIndexCheckpointPosition != null && tfPosition <= _lastKnownIndexCheckpointPosition);
 }
コード例 #27
0
 protected TFPos GetBackwardReadPos()
 {
     var pos = new TFPos(WriterCheckpoint.ReadNonFlushed(), WriterCheckpoint.ReadNonFlushed());
     return pos;
 }
コード例 #28
0
        public ResolvedEvent(EventStore.Core.Data.ResolvedEvent resolvedEvent, byte[] streamMetadata)
        {
            var positionEvent = resolvedEvent.Link ?? resolvedEvent.Event;

            _linkOrEventPosition = resolvedEvent.OriginalPosition.GetValueOrDefault();
            var @event = resolvedEvent.Event;

            _positionStreamId       = positionEvent.EventStreamId;
            _positionSequenceNumber = positionEvent.EventNumber;
            _eventStreamId          = @event != null ? @event.EventStreamId : null;
            _eventSequenceNumber    = @event != null ? @event.EventNumber : -1;
            _resolvedLinkTo         = positionEvent != @event;
            _position = resolvedEvent.OriginalPosition ?? new TFPos(-1, positionEvent.LogPosition);
            EventId   = @event != null ? @event.EventId : Guid.Empty;
            EventType = @event != null ? @event.EventType : null;
            IsJson    = @event != null && (@event.Flags & PrepareFlags.IsJson) != 0;
            Timestamp = positionEvent.TimeStamp;

            //TODO: handle utf-8 conversion exception
            Data = @event != null && @event.Data != null?Helper.UTF8NoBom.GetString(@event.Data) : null;

            Metadata = @event != null && @event.Metadata != null?Helper.UTF8NoBom.GetString(@event.Metadata) : null;

            PositionMetadata = _resolvedLinkTo
                ? (positionEvent.Metadata != null ? Helper.UTF8NoBom.GetString(positionEvent.Metadata) : null)
                : null;
            StreamMetadata = streamMetadata != null?Helper.UTF8NoBom.GetString(streamMetadata) : null;

            TFPos eventOrLinkTargetPosition;

            if (_resolvedLinkTo)
            {
                Dictionary <string, JToken> extraMetadata = null;
                if (positionEvent.Metadata != null && positionEvent.Metadata.Length > 0)
                {
                    //TODO: parse JSON only when unresolved link and just tag otherwise
                    CheckpointTag tag;
                    if (resolvedEvent.Link != null && resolvedEvent.Event == null)
                    {
                        var checkpointTagJson =
                            positionEvent.Metadata.ParseCheckpointTagVersionExtraJson(default(ProjectionVersion));
                        tag           = checkpointTagJson.Tag;
                        extraMetadata = checkpointTagJson.ExtraMetadata;

                        var parsedPosition = tag.Position;

                        eventOrLinkTargetPosition = parsedPosition != new TFPos(long.MinValue, long.MinValue)
                            ? parsedPosition
                            : new TFPos(-1, positionEvent.LogPosition);
                    }
                    else
                    {
                        tag = positionEvent.Metadata.ParseCheckpointTagJson();
                        var parsedPosition = tag.Position;
                        if (parsedPosition == new TFPos(long.MinValue, long.MinValue) && @event.Metadata.IsValidJson())
                        {
                            tag = @event.Metadata.ParseCheckpointTagJson();
                            if (tag != null)
                            {
                                parsedPosition = tag.Position;
                            }
                        }

                        eventOrLinkTargetPosition = parsedPosition != new TFPos(long.MinValue, long.MinValue)
                            ? parsedPosition
                            : new TFPos(-1, resolvedEvent.Event.LogPosition);
                    }
                }
                else
                {
                    eventOrLinkTargetPosition = @event != null ? new TFPos(-1, @event.LogPosition) : new TFPos(-1, positionEvent.LogPosition);
                }

                JToken deletedValue;
                IsLinkToDeletedStreamTombstone = extraMetadata != null &&
                                                 extraMetadata.TryGetValue("$deleted", out deletedValue);
                if (resolvedEvent.ResolveResult == ReadEventResult.NoStream ||
                    resolvedEvent.ResolveResult == ReadEventResult.StreamDeleted || IsLinkToDeletedStreamTombstone)
                {
                    IsLinkToDeletedStream = true;
                    var streamId = SystemEventTypes.StreamReferenceEventToStreamId(
                        SystemEventTypes.LinkTo, resolvedEvent.Link.Data);
                    _eventStreamId = streamId;
                }
            }
            else
            {
                // not a link
                eventOrLinkTargetPosition = resolvedEvent.OriginalPosition ?? new TFPos(-1, positionEvent.LogPosition);
            }
            _eventOrLinkTargetPosition = eventOrLinkTargetPosition;
        }
コード例 #29
0
 public PendingEvent(EventStore.Core.Data.ResolvedEvent resolvedEvent, TFPos tfPosition, float progress)
 {
     ResolvedEvent = resolvedEvent;
     Progress      = progress;
     TfPosition    = tfPosition;
 }
コード例 #30
0
            public AllSubscriptionFiltered(IPublisher bus,
                                           Position?startPosition,
                                           bool resolveLinks,
                                           IEventFilter eventFilter,
                                           ClaimsPrincipal user,
                                           bool requiresLeader,
                                           IReadIndex readIndex,
                                           uint?maxSearchWindow,
                                           uint checkpointIntervalMultiplier,
                                           Func <Position, Task> checkpointReached,
                                           CancellationToken cancellationToken)
            {
                if (bus == null)
                {
                    throw new ArgumentNullException(nameof(bus));
                }

                if (eventFilter == null)
                {
                    throw new ArgumentNullException(nameof(eventFilter));
                }

                if (readIndex == null)
                {
                    throw new ArgumentNullException(nameof(readIndex));
                }

                if (checkpointReached == null)
                {
                    throw new ArgumentNullException(nameof(checkpointReached));
                }

                if (checkpointIntervalMultiplier == 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(checkpointIntervalMultiplier));
                }

                _subscriptionId      = Guid.NewGuid();
                _bus                 = bus;
                _resolveLinks        = resolveLinks;
                _eventFilter         = eventFilter;
                _user                = user;
                _requiresLeader      = requiresLeader;
                _maxSearchWindow     = maxSearchWindow ?? ReadBatchSize;
                _checkpointReached   = checkpointReached;
                _cancellationToken   = cancellationToken;
                _subscriptionStarted = new TaskCompletionSource <bool>();
                _channel             = Channel.CreateBounded <(ResolvedEvent?, Position?)>(BoundedChannelOptions);
                _checkpointInterval  = checkpointIntervalMultiplier * _maxSearchWindow;
                _semaphore           = new SemaphoreSlim(1, 1);
                _lastCheckpoint      = Position.Start;

                SubscriptionId = _subscriptionId.ToString();

                var lastIndexedPosition    = readIndex.LastIndexedPosition;
                var startPositionExclusive = startPosition == Position.End
                                        ? Position.FromInt64(lastIndexedPosition, lastIndexedPosition)
                                        : startPosition ?? Position.Start;

                _startPositionExclusive = new TFPos((long)startPositionExclusive.CommitPosition,
                                                    (long)startPositionExclusive.PreparePosition);

                Subscribe(startPositionExclusive, startPosition != Position.End);
            }
コード例 #31
0
ファイル: AllReader.cs プロジェクト: kirinse/EventStore
 public IndexReadAllResult FilteredReadAllEventsForward(TFPos pos, int maxCount, int maxSearchWindow,
                                                        IEventFilter eventFilter)
 {
     return(ReadAllEventsForwardInternal(pos, maxCount, maxSearchWindow, eventFilter));
 }
コード例 #32
0
ファイル: AllReader.cs プロジェクト: kirinse/EventStore
 public IndexReadAllResult ReadAllEventsForward(TFPos pos, int maxCount)
 {
     return(ReadAllEventsForwardInternal(pos, maxCount, maxCount, EventFilter.None));
 }
コード例 #33
0
 private void EmptyCache()
 {
     _lastMessages.Clear();
     _subscribeFromPosition = new TFPos(long.MaxValue, long.MaxValue);
 }
コード例 #34
0
            public void Handle(ClientMessage.ReadAllEventsForwardCompleted message)
            {
                if (_disposed)
                {
                    return;
                }
                if (message.CorrelationId != _pendingRequestCorrelationId)
                {
                    return;
                }

                if (message.Result == ReadAllResult.AccessDenied)
                {
                    SendNotAuthorized();
                    return;
                }

                if (!_tfEventsRequested)
                {
                    throw new InvalidOperationException("TF events has not been requested");
                }
                if (_reader.Paused)
                {
                    throw new InvalidOperationException("Paused");
                }
                _reader._lastPosition = message.TfLastCommitPosition;
                _tfEventsRequested    = false;
                switch (message.Result)
                {
                case ReadAllResult.Success:
                    var eof = message.Events.Length == 0;
                    _eof = eof;
                    var willDispose = _reader._stopOnEof && eof;
                    _fromTfPosition = message.NextPos;

                    if (!willDispose)
                    {
                        _reader.PauseOrContinueProcessing();
                    }

                    if (eof)
                    {
                        // the end
                        //TODO: is it safe to pass NEXT as last commit position here
                        DeliverLastCommitPosition(message.NextPos);
                        // allow joining heading distribution
                        SendIdle();
                        _reader.SendEof();
                    }
                    else
                    {
                        foreach (var @event in message.Events)
                        {
                            var    link     = @event.Link;
                            var    data     = @event.Event;
                            var    byStream = link != null && _streamToEventType.ContainsKey(link.EventStreamId);
                            string adjustedPositionStreamId;
                            var    isDeleteStreamEvent =
                                StreamDeletedHelper.IsStreamDeletedEvent(
                                    @event.OriginalStreamId, @event.OriginalEvent.EventType,
                                    @event.OriginalEvent.Data, out adjustedPositionStreamId);
                            if (data == null)
                            {
                                continue;
                            }
                            var eventType          = isDeleteStreamEvent ? "$deleted" : data.EventType;
                            var byEvent            = link == null && _eventTypes.Contains(eventType);
                            var originalTfPosition = @event.OriginalPosition.Value;
                            if (byStream)
                            {
                                // ignore data just update positions
                                _reader.UpdateNextStreamPosition(link.EventStreamId, link.EventNumber + 1);
                                // recover unresolved link event
                                var unresolvedLinkEvent =
                                    EventStore.Core.Data.ResolvedEvent.ForUnresolvedEvent(link,
                                                                                          originalTfPosition.CommitPosition);
                                DeliverEventRetrievedFromTf(
                                    unresolvedLinkEvent, 100.0f * link.LogPosition / message.TfLastCommitPosition,
                                    originalTfPosition);
                            }
                            else if (byEvent)
                            {
                                DeliverEventRetrievedFromTf(
                                    @event, 100.0f * data.LogPosition / message.TfLastCommitPosition,
                                    originalTfPosition);
                            }
                        }
                    }

                    if (_disposed)
                    {
                        return;
                    }

                    break;

                default:
                    throw new NotSupportedException(
                              String.Format("ReadEvents result code was not recognized. Code: {0}", message.Result));
                }
            }
コード例 #35
0
            protected override void Given()
            {
                base.Given();
                _tfPos1 = ExistingEvent("test-stream", "type1", "{}", "{Data: 1}");
                _tfPos2 = ExistingEvent("test-stream", "type1", "{}", "{Data: 2}");
                _tfPos3 = ExistingEvent("test-stream", "type2", "{}", "{Data: 3}");

                // writes reordered due to batching or timeouts in system projection
                ExistingEvent("$et-type1", "$>", TFPosToMetadata(_tfPos1), "0@test-stream");
                ExistingEvent("$et-type2", "$>", TFPosToMetadata(_tfPos3), "2@test-stream");
                ExistingEvent("$et-type1", "$>", TFPosToMetadata(_tfPos2), "1@test-stream");
                NoStream("$et");
                _querySourcesDefinition = new QuerySourcesDefinition
                    {
                        AllStreams = true,
                        Events = new[] {"type1", "type2"},
                        Options = new QuerySourcesDefinitionOptions {}
                    };
                _fromPosition = CheckpointTag.FromEventTypeIndexPositions(
                    new TFPos(0, -1), new Dictionary<string, int> {{"type1", -1}, {"type2", -1}});
                _maxEvents = 3;
            }
コード例 #36
0
 private ClientMessage.FilteredReadAllEventsForwardCompleted NoDataForFilteredCommand(
     ClientMessage.FilteredReadAllEventsForward msg, FilteredReadAllResult result, TFPos pos,
     long lastIndexedPosition, string error = null)
 {
     return(new ClientMessage.FilteredReadAllEventsForwardCompleted(
                msg.CorrelationId, result, error, ResolvedEvent.EmptyArray, null, false,
                msg.MaxCount, pos, TFPos.Invalid, TFPos.Invalid, lastIndexedPosition, false));
 }
コード例 #37
0
 protected Item(TFPos position)
 {
     Position = position;
 }
コード例 #38
0
        protected TFPos GetBackwardReadPos()
        {
            var pos = new TFPos(WriterCheckpoint.ReadNonFlushed(), WriterCheckpoint.ReadNonFlushed());

            return(pos);
        }
コード例 #39
0
ファイル: AllReader.cs プロジェクト: kirinse/EventStore
        private IndexReadAllResult ReadAllEventsBackwardInternal(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 0, so if you decide to read backwards from PrevPos,
            // you will receive all prepares.
            var  prevPos = new TFPos(pos.CommitPosition, 0);
            var  consideredEventsCount = 0L;
            bool firstCommit           = true;
            var  reachedEndOfStream    = false;

            using (var reader = _backend.BorrowReader()) {
                long nextCommitPostPos = pos.CommitPosition;
                while (records.Count < maxCount && consideredEventsCount < maxSearchWindow)
                {
                    reader.Reposition(nextCommitPostPos);

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

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

                    nextCommitPostPos = result.RecordPrePosition;

                    if (!IsReplicated(nextCommitPostPos))
                    {
                        continue;
                    }

                    switch (result.LogRecord.RecordType)
                    {
                    case LogRecordType.Prepare: {
                        var prepare = (PrepareLogRecord)result.LogRecord;
                        if (firstCommit)
                        {
                            firstCommit = false;
                            prevPos     = new TFPos(result.RecordPostPosition, result.RecordPostPosition);
                        }

                        if (prepare.Flags.HasAnyOf(PrepareFlags.Data | PrepareFlags.StreamDelete) &&
                            new TFPos(result.RecordPostPosition, result.RecordPostPosition) <= pos)
                        {
                            var eventRecord = new EventRecord(prepare.ExpectedVersion + 1 /* EventNumber */,
                                                              prepare);
                            consideredEventsCount++;

                            if (eventFilter.IsEventAllowed(eventRecord))
                            {
                                records.Add(new CommitEventRecord(eventRecord, prepare.LogPosition));
                            }

                            // for backward pass we allow read the same commit, but force to skip last read prepare
                            // so we put post-position of commit and pre-position of prepare
                            nextPos = new TFPos(result.RecordPrePosition, result.RecordPrePosition);
                        }

                        break;
                    }

                    case LogRecordType.Commit: {
                        var commit = (CommitLogRecord)result.LogRecord;
                        if (firstCommit)
                        {
                            firstCommit = false;
                            // for forward pass we allow read the same commit and as we have post-positions here
                            // we can put just prepare post-position as prepare pre-position for forward read
                            // so we put pre-position of commit and post-position of prepare
                            prevPos = new TFPos(commit.LogPosition, pos.PreparePosition);
                        }

                        var commitPostPos = result.RecordPostPosition;
                        // as we don't know exact position of the last record of transaction,
                        // we have to sequentially scan backwards, so no need to reposition
                        while (consideredEventsCount < maxCount)
                        {
                            result = reader.TryReadPrev();
                            if (!result.Success)                                     // no more records in TF
                            {
                                break;
                            }

                            // prepare with TransactionBegin could be scavenged already
                            // so we could reach beyond the start of transaction. In that case we have to stop.
                            if (result.LogRecord.LogPosition < commit.TransactionPosition)
                            {
                                break;
                            }
                            if (result.LogRecord.RecordType != LogRecordType.Prepare)
                            {
                                continue;
                            }

                            var prepare = (PrepareLogRecord)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(commitPostPos, result.RecordPostPosition) <= pos)
                            {
                                var eventRecord =
                                    new EventRecord(commit.FirstEventNumber + prepare.TransactionOffset, prepare);
                                consideredEventsCount++;

                                if (eventFilter.IsEventAllowed(eventRecord))
                                {
                                    records.Add(new CommitEventRecord(eventRecord, commit.LogPosition));
                                }

                                // for backward pass we allow read the same commit, but force to skip last read prepare
                                // so we put post-position of commit and pre-position of prepare
                                nextPos = new TFPos(commitPostPos, prepare.LogPosition);
                            }

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

                        break;
                    }

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

                return(new IndexReadAllResult(records, pos, nextPos, prevPos, reachedEndOfStream));
            }
        }
コード例 #40
0
        public ReadAllResult(ResolvedEventRecord[] records, int maxCount, TFPos currentPos, TFPos nextPos, TFPos prevPos, long tfEofPosition)
        {
            Ensure.NotNull(records, "records");

            Records       = records;
            MaxCount      = maxCount;
            CurrentPos    = currentPos;
            NextPos       = nextPos;
            PrevPos       = prevPos;
            TfEofPosition = tfEofPosition;
        }
コード例 #41
0
ファイル: CheckpointTag.cs プロジェクト: tone81/EventStore
 private CheckpointTag(long preparePosition)
 {
     Position = new TFPos(long.MinValue, preparePosition);
     Mode_    = CalculateMode();
 }
コード例 #42
0
        public IndexReadAllResult(List <CommitEventRecord> records, TFPos currentPos, TFPos nextPos, TFPos prevPos,
                                  bool isEndOfStream, long consideredEventsCount)
        {
            Ensure.NotNull(records, "records");

            Records               = records;
            CurrentPos            = currentPos;
            NextPos               = nextPos;
            PrevPos               = prevPos;
            IsEndOfStream         = isEndOfStream;
            ConsideredEventsCount = consideredEventsCount;
        }
コード例 #43
0
        /// <summary>
        /// Returns event records in the reverse sequence they were committed into TF.
        /// Positions is specified as post-positions (pointer after the end of record).
        /// </summary>
        IndexReadAllResult IReadIndex.ReadAllEventsBackward(TFPos pos, int maxCount)
        {
            var lastCommitPosition = Interlocked.Read(ref _lastCommitPosition);

            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 0, so if you decide to read backwards from PrevPos, 
            // you will receive all prepares.
            var prevPos = new TFPos(pos.CommitPosition, 0);
            var count = 0;
            bool firstCommit = true;            
            ITransactionFileSequentialReader seqReader = GetSeqReader();
            try
            {
                long nextCommitPostPos = pos.CommitPosition;
                while (count < maxCount)
                {
                    seqReader.Reposition(nextCommitPostPos);
                    
                    SeqReadResult result;
                    do
                    {
                        result = seqReader.TryReadPrev();
                    }
                    while (result.Success && result.LogRecord.RecordType != LogRecordType.Commit); // skip until commit
                    
                    if (!result.Success) // no more records in TF
                        break;

                    var commitPostPos = result.RecordPostPosition;
                    nextCommitPostPos = result.RecordPrePosition;

                    var commit = (CommitLogRecord)result.LogRecord;
                    if (firstCommit)
                    {
                        firstCommit = false;
                        // for forward pass we allow read the same commit and as we have post-positions here
                        // we can put just prepare post-position as prepare pre-position for forward read
                        // so we put pre-position of commit and post-position of prepare
                        prevPos = new TFPos(commit.LogPosition, pos.PreparePosition);
                    }

                    // as we don't know exact position of the last record of transaction,
                    // we have to sequentially scan backwards, so no need to reposition
                    //seqReader.Reposition(commitLogRecord.TransactionPosition);
                    while (count < maxCount)
                    {
                        result = seqReader.TryReadPrev();
                        if (!result.Success) // no more records in TF
                            break;
                        // prepare with TransactionBegin could be scavenged already
                        // so we could reach beyond the start of transaction. In that case we have to stop.
                        if (result.LogRecord.Position < commit.TransactionPosition)
                            break;
                        if (result.LogRecord.RecordType != LogRecordType.Prepare)
                            continue;

                        var prepare = (PrepareLogRecord)result.LogRecord;
                        if (prepare.TransactionPosition != commit.TransactionPosition) // wrong prepare
                            continue;

                        // prepare with useful data or delete tombstone
                        if ((prepare.Flags & (PrepareFlags.Data | PrepareFlags.StreamDelete)) != 0) 
                        {
                            if (new TFPos(commitPostPos, result.RecordPostPosition) <= pos)
                            {
                                var eventRecord = new EventRecord(commit.FirstEventNumber + prepare.TransactionOffset, prepare);
                                records.Add(new CommitEventRecord(eventRecord, commit.Position));
                                count++;

                                // for backward pass we allow read the same commit, but force to skip last read prepare
                                // so we put post-position of commit and pre-position of prepare
                                nextPos = new TFPos(commitPostPos, prepare.LogPosition);
                            }
                        }
                        if ((prepare.Flags & PrepareFlags.TransactionBegin) != 0)
                            break;
                    }
                }
            }
            finally
            {
                ReturnSeqReader(seqReader);
            }
            return new IndexReadAllResult(records, maxCount, pos, nextPos, prevPos, lastCommitPosition);
        }
コード例 #44
0
 private ClientMessage.ReadAllEventsBackwardCompleted NoData(ClientMessage.ReadAllEventsBackward msg, ReadAllResult result, TFPos pos, long lastCommitPosition, string error = null)
 {
     return(new ClientMessage.ReadAllEventsBackwardCompleted(
                msg.CorrelationId, result, error, ResolvedEvent.EmptyArray, null, false,
                msg.MaxCount, pos, TFPos.Invalid, TFPos.Invalid, lastCommitPosition));
 }
コード例 #45
0
ファイル: CheckpointTag.cs プロジェクト: tone81/EventStore
 internal CheckpointTag(TFPos position, Dictionary <string, int> streams)
 {
     Position = position;
     Streams  = streams;
     Mode_    = CalculateMode();
 }
コード例 #46
0
 public IndexReadAllResult ReadAllEventsForward(TFPos pos, int maxCount)
 {
     throw new System.NotImplementedException();
 }
コード例 #47
0
 protected static ResolvedEvent CreateSampleEvent(
     string streamId, int sequenceNumber, string eventType, string data, TFPos tfPos)
 {
     return new ResolvedEvent(
         streamId, sequenceNumber, streamId, sequenceNumber, true, tfPos, Guid.NewGuid(), eventType, true, data,
         "{}", "{\"position_meta\":1}");
 }
コード例 #48
0
ファイル: ReadIndex.cs プロジェクト: chchmatt/EventStore
 IndexReadAllResult IReadIndex.ReadAllEventsBackwardFiltered(TFPos pos, int maxCount, int maxSearchWindow,
                                                             IEventFilter eventFilter)
 {
     return(_allReader.FilteredReadAllEventsBackward(pos, maxCount, maxSearchWindow, eventFilter));
 }
コード例 #49
0
ファイル: CheckpointTag.cs プロジェクト: tone81/EventStore
 public static CheckpointTag FromPosition(TFPos position)
 {
     return(new CheckpointTag(position));
 }
コード例 #50
0
ファイル: ReadIndex.cs プロジェクト: chchmatt/EventStore
 IndexReadAllResult IReadIndex.ReadAllEventsBackward(TFPos pos, int maxCount)
 {
     return(_allReader.ReadAllEventsBackward(pos, maxCount));
 }
コード例 #51
0
 private string TFPosToMetadata(TFPos tfPos)
 {
     return string.Format(@"{{""$c"":{0},""$p"":{1}}}", tfPos.CommitPosition, tfPos.PreparePosition);
 }
コード例 #52
0
        public IndexReadAllResult ReadAllEventsForward(TFPos pos, int maxCount)
        {
            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);
            long count       = 0;
            bool firstCommit = true;

            using (var reader = _backend.BorrowReader())
            {
                long nextCommitPos = pos.CommitPosition;
                while (count < maxCount)
                {
                    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:
                    {
                        var prepare = (PrepareLogRecord)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 eventRecord = new EventRecord(prepare.ExpectedVersion + 1 /* EventNumber */, prepare);
                            records.Add(new CommitEventRecord(eventRecord, prepare.LogPosition));
                            count++;
                            nextPos = new TFPos(result.RecordPostPosition, result.RecordPostPosition);
                        }
                        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 (count < 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 = (PrepareLogRecord)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 eventRecord = new EventRecord(commit.FirstEventNumber + prepare.TransactionOffset, prepare);
                                records.Add(new CommitEventRecord(eventRecord, commit.LogPosition));
                                count++;

                                // 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));
            }
        }
コード例 #53
0
            public ReadAllEventsBackwardCompleted(Guid correlationId, ReadAllResult result, string error, ResolvedEvent[] events, 
                                                  StreamMetadata streamMetadata, bool isCachePublic, int maxCount,
                                                  TFPos currentPos, TFPos nextPos, TFPos prevPos, long tfLastCommitPosition)
            {
                Ensure.NotNull(events, "events");

                CorrelationId = correlationId;
                Result = result;
                Error = error;
                Events = events;
                StreamMetadata = streamMetadata;
                IsCachePublic = isCachePublic;
                MaxCount = maxCount;
                CurrentPos = currentPos;
                NextPos = nextPos;
                PrevPos = prevPos;
                TfLastCommitPosition = tfLastCommitPosition;
            }
コード例 #54
0
 private string TFPosToMetadata(TFPos tfPos)
 {
     return(string.Format(@"{{""$c"":{0},""$p"":{1}}}", tfPos.CommitPosition, tfPos.PreparePosition));
 }
        public void read_all_events_backward_returns_correct_events_starting_in_the_middle_of_tf()
        {
            var pos = new TFPos(_pos6, _p4.LogPosition); // p3 post-pos
            var res1 = ReadIndex.ReadAllEventsBackward(pos, 10, false);

            Assert.AreEqual(4, res1.Records.Count);
            Assert.AreEqual(_p3, res1.Records[0].Event);
            Assert.AreEqual(_p1, res1.Records[1].Event);
            Assert.AreEqual(_p4, res1.Records[2].Event);
            Assert.AreEqual(_p2, res1.Records[3].Event);

            var res2 = ReadIndex.ReadAllEventsForward(res1.PrevPos, 10, false);
            Assert.AreEqual(1, res2.Records.Count);
            Assert.AreEqual(_p5, res2.Records[0].Event);
        }
コード例 #56
0
ファイル: FakeReadIndex.cs プロジェクト: Ishvann/EventStore
 public IndexReadAllResult ReadAllEventsBackward(TFPos pos, int maxCount)
 {
     throw new NotImplementedException();
 }
コード例 #57
0
 public IndexReadAllResult ReadAllEventsBackwardFiltered(TFPos pos, int maxCount, int maxSearchWindow,
                                                         IEventFilter eventFilter)
 {
     throw new NotImplementedException();
 }
コード例 #58
0
ファイル: AllReader.cs プロジェクト: marodev/EventStore
 public IndexReadAllResult ReadAllEventsBackward(TFPos pos, int maxCount)
 {
     return(ReadAllEventsBackwardInternal(pos, maxCount, maxCount, EventFilter.DefaultAllFilter));
 }
コード例 #59
0
            private void GoLive(Position startPosition)
            {
                var liveEvents            = Channel.CreateBounded <ResolvedEvent>(BoundedChannelOptions);
                var caughtUpSource        = new TaskCompletionSource <TFPos>();
                var liveMessagesCancelled = 0;

                Log.Information(
                    "Live subscription {subscriptionId} to $all running from {position}...",
                    _subscriptionId, startPosition);

                _bus.Publish(new ClientMessage.SubscribeToStream(Guid.NewGuid(), _subscriptionId,
                                                                 new ContinuationEnvelope(OnSubscriptionMessage, _semaphore, _cancellationToken), _subscriptionId,
                                                                 string.Empty, _resolveLinks, _user));

                Task.Factory.StartNew(PumpLiveMessages, _cancellationToken);

                async Task PumpLiveMessages()
                {
                    await caughtUpSource.Task.ConfigureAwait(false);

                    await foreach (var @event in liveEvents.Reader.ReadAllAsync(_cancellationToken)
                                   .ConfigureAwait(false))
                    {
                        await _channel.Writer.WriteAsync(@event, _cancellationToken).ConfigureAwait(false);
                    }
                }

                async Task OnSubscriptionMessage(Message message, CancellationToken cancellationToken)
                {
                    if (message is ClientMessage.NotHandled notHandled &&
                        RpcExceptions.TryHandleNotHandled(notHandled, out var ex))
                    {
                        Fail(ex);
                        return;
                    }

                    switch (message)
                    {
                    case ClientMessage.SubscriptionConfirmation confirmed:
                        ConfirmSubscription();

                        var caughtUp = new TFPos(confirmed.LastIndexedPosition,
                                                 confirmed.LastIndexedPosition);
                        Log.Verbose(
                            "Live subscription {subscriptionId} to $all confirmed at {position}.",
                            _subscriptionId, caughtUp);

                        ReadHistoricalEvents(startPosition);

                        async Task OnHistoricalEventsMessage(Message message, CancellationToken ct)
                        {
                            if (message is ClientMessage.NotHandled notHandled &&
                                RpcExceptions.TryHandleNotHandled(notHandled, out var ex))
                            {
                                Fail(ex);
                                return;
                            }

                            if (!(message is ClientMessage.ReadAllEventsForwardCompleted completed))
                            {
                                Fail(
                                    RpcExceptions.UnknownMessage <ClientMessage.ReadAllEventsForwardCompleted>(
                                        message));
                                return;
                            }

                            switch (completed.Result)
                            {
                            case ReadAllResult.Success:
                                if (completed.Events.Length == 0 && completed.IsEndOfStream)
                                {
                                    NotifyCaughtUp(completed.CurrentPos);
                                    return;
                                }

                                foreach (var @event in completed.Events)
                                {
                                    var position = @event.OriginalPosition.Value;

                                    if (position > caughtUp)
                                    {
                                        NotifyCaughtUp(position);
                                        return;
                                    }

                                    await _channel.Writer.WriteAsync(@event, _cancellationToken)
                                    .ConfigureAwait(false);
                                }

                                ReadHistoricalEvents(Position.FromInt64(
                                                         completed.NextPos.CommitPosition,
                                                         completed.NextPos.PreparePosition));
                                return;

                                void NotifyCaughtUp(TFPos position)
                                {
                                    Log.Verbose(
                                        "Live subscription {subscriptionId} to $all caught up at {position} because the end of stream was reached.",
                                        _subscriptionId, position);
                                    caughtUpSource.TrySetResult(caughtUp);
                                }

                            case ReadAllResult.AccessDenied:
                                Fail(RpcExceptions.AccessDenied());
                                return;

                            default:
                                Fail(RpcExceptions.UnknownError(completed.Result));
                                return;
                            }
                        }

                        void ReadHistoricalEvents(Position fromPosition)
                        {
                            if (fromPosition == Position.End)
                            {
                                throw new ArgumentOutOfRangeException(nameof(fromPosition));
                            }

                            Log.Verbose(
                                "Live subscription {subscriptionId} to $all loading any missed events starting from {position}.",
                                _subscriptionId, fromPosition);

                            ReadPage(fromPosition, OnHistoricalEventsMessage);
                        }

                        return;

                    case ClientMessage.SubscriptionDropped dropped:
                        switch (dropped.Reason)
                        {
                        case SubscriptionDropReason.AccessDenied:
                            Fail(RpcExceptions.AccessDenied());
                            return;

                        case SubscriptionDropReason.Unsubscribed:
                            return;

                        default:
                            Fail(RpcExceptions.UnknownError(dropped.Reason));
                            return;
                        }

                    case ClientMessage.StreamEventAppeared appeared: {
                        if (liveMessagesCancelled == 1)
                        {
                            return;
                        }

                        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
                        try {
                            Log.Verbose(
                                "Live subscription {subscriptionId} to $all enqueuing live message {position}.",
                                _subscriptionId, appeared.Event.OriginalPosition);

                            await liveEvents.Writer.WriteAsync(appeared.Event, cts.Token)
                            .ConfigureAwait(false);
                        } catch (Exception e) {
                            if (Interlocked.Exchange(ref liveMessagesCancelled, 1) != 0)
                            {
                                return;
                            }

                            Log.Verbose(
                                e,
                                "Live subscription {subscriptionId} to $all timed out at {position}; unsubscribing...",
                                _subscriptionId, appeared.Event.OriginalPosition.GetValueOrDefault());

                            Unsubscribe();

                            liveEvents.Writer.Complete();

                            var originalPosition =
                                _current.GetValueOrDefault().OriginalPosition.GetValueOrDefault();
                            CatchUp(Position.FromInt64(
                                        originalPosition.CommitPosition,
                                        originalPosition.PreparePosition));
                        }

                        return;
                    }

                    default:
                        Fail(
                            RpcExceptions.UnknownMessage <ClientMessage.SubscriptionConfirmation>(message));
                        return;
                    }
                }

                void Fail(Exception exception)
                {
                    this.Fail(exception);
                    caughtUpSource.TrySetException(exception);
                }
            }
コード例 #60
0
        private static List <List <PTable> > LoadPTables(StreamReader reader, string indexmapFilename, TFPos checkpoints,
                                                         int cacheDepth, bool skipIndexVerify,
                                                         int threads,
                                                         int pTableMaxReaderCount)
        {
            var tables = new List <List <PTable> >();

            try {
                try {
                    Parallel.ForEach(
                        GetAllLines(reader)
                        .Reverse(),                                 // Reverse so we load the highest levels (biggest files) first - ensures we use concurrency in the most efficient way.
                        new ParallelOptions {
                        MaxDegreeOfParallelism = threads
                    },
                        indexMapEntry => {
                        if (checkpoints.PreparePosition < 0 || checkpoints.CommitPosition < 0)
                        {
                            throw new CorruptIndexException(
                                string.Format("Negative prepare/commit checkpoint in non-empty IndexMap: {0}.",
                                              checkpoints));
                        }

                        PTable ptable = null;
                        var pieces    = indexMapEntry.Split(',');
                        try {
                            var level      = int.Parse(pieces[0]);
                            var position   = int.Parse(pieces[1]);
                            var file       = pieces[2];
                            var path       = Path.GetDirectoryName(indexmapFilename);
                            var ptablePath = Path.Combine(path, file);

                            ptable = PTable.FromFile(ptablePath, ESConsts.PTableInitialReaderCount, pTableMaxReaderCount, cacheDepth, skipIndexVerify);

                            lock (tables) {
                                InsertTableToTables(tables, level, position, ptable);
                            }
                        } catch (Exception) {
                            // if PTable file path was correct, but data is corrupted, we still need to dispose opened streams
                            if (ptable != null)
                            {
                                ptable.Dispose();
                            }

                            throw;
                        }
                    });

                    // Verify map is correct
                    for (int i = 0; i < tables.Count; ++i)
                    {
                        for (int j = 0; j < tables[i].Count; ++j)
                        {
                            if (tables[i][j] == null)
                            {
                                throw new CorruptIndexException(
                                          $"indexmap is missing contiguous level,position {i},{j}");
                            }
                        }
                    }
                } catch (AggregateException aggEx) {
                    // We only care that *something* has gone wrong, throw the first exception
                    throw aggEx.InnerException;
                }
            } catch (Exception exc) {
                // also dispose all previously loaded correct PTables
                for (int i = 0; i < tables.Count; ++i)
                {
                    for (int j = 0; j < tables[i].Count; ++j)
                    {
                        if (tables[i][j] != null)
                        {
                            tables[i][j].Dispose();
                        }
                    }
                }

                throw new CorruptIndexException("Error while loading IndexMap.", exc);
            }

            return(tables);
        }