Exemple #1
0
        public void Commit(CommitLogRecord commit)
        {
            if (_threadId.HasValue && _threadId != Thread.CurrentThread.ManagedThreadId)
            {
                Debugger.Break();
                throw new Exception("Access to commit from multiple threads.");
            }
            _threadId = Thread.CurrentThread.ManagedThreadId;

            _tableIndex.CommitCheckpoint.Write(commit.LogPosition);

            bool   first         = true;
            int    number        = -1;
            uint   streamHash    = 0;
            string eventStreamId = null;

            foreach (var prepare in GetTransactionPrepares(commit.TransactionPosition))
            {
                if (first)
                {
                    streamHash    = _hasher.Hash(prepare.EventStreamId);
                    eventStreamId = prepare.EventStreamId;
                    first         = false;
                }
                else
                {
                    Debug.Assert(prepare.EventStreamId == eventStreamId);
                }

                bool addToIndex = false;
                if ((prepare.Flags & PrepareFlags.StreamDelete) != 0)
                {
                    //Debug.Assert(number == -1);
                    number = EventNumber.DeletedStream;

                    if (commit.LogPosition > _persistedCommitCheckpoint ||
                        commit.LogPosition == _persistedCommitCheckpoint && prepare.LogPosition > _persistedPrepareCheckpoint)
                    {
                        addToIndex = true;
                    }
                }
                else if ((prepare.Flags & PrepareFlags.Data) != 0)
                {
                    if (prepare.ExpectedVersion == ExpectedVersion.Any)
                    {
                        if (number == -1)
                        {
                            number = commit.EventNumber - 1;
                        }
                        number = number + 1;
                    }
                    else
                    {
                        Debug.Assert(number == -1 || number == prepare.ExpectedVersion);
                        number = prepare.ExpectedVersion + 1;
                    }

                    if (commit.LogPosition > _persistedCommitCheckpoint ||
                        commit.LogPosition == _persistedCommitCheckpoint && prepare.LogPosition > _persistedPrepareCheckpoint)
                    {
                        addToIndex = true;
                    }
                }
                // could be just empty prepares for TransactionBegin and TransactionEnd, for instance
                if (addToIndex)
                {
                    long pos;
                    if (_tableIndex.TryGetOneValue(streamHash, number, out pos))
                    {
                        EventRecord rec;
                        if (TryReadRecord(eventStreamId, number, out rec) == SingleReadResult.Success)
                        {
                            Debugger.Break();
                            throw new Exception(
                                      string.Format(
                                          "Trying to add duplicate event #{0} for stream {1}(hash {2})\nCommit: {3}\nPrepare: {4}.",
                                          number,
                                          eventStreamId,
                                          streamHash,
                                          commit,
                                          prepare));
                        }
                    }
                    _tableIndex.Add(streamHash, number, prepare.LogPosition);
                    _bus.Publish(new ReplicationMessage.EventCommited(commit.LogPosition, number, prepare));
                }
            }
        }
Exemple #2
0
        public void Commit(CommitLogRecord commit)
        {
            bool   first         = true;
            int    eventNumber   = -1;
            uint   streamHash    = 0;
            string eventStreamId = null;

            foreach (var prepare in GetTransactionPrepares(commit.TransactionPosition))
            {
                if (first)
                {
                    streamHash    = _hasher.Hash(prepare.EventStreamId);
                    eventStreamId = prepare.EventStreamId;
                    first         = false;
                }
                else
                {
                    Debug.Assert(prepare.EventStreamId == eventStreamId);
                }

                bool addToIndex = false;
                if ((prepare.Flags & PrepareFlags.StreamDelete) != 0)
                {
                    eventNumber = EventNumber.DeletedStream;
                    _committedEvents.PutRecord(prepare.EventId, Tuple.Create(eventStreamId, eventNumber), throwOnDuplicate: false);
                    addToIndex = commit.LogPosition > _persistedCommitCheckpoint ||
                                 commit.LogPosition == _persistedCommitCheckpoint && prepare.LogPosition > _persistedPrepareCheckpoint;
                }
                else if ((prepare.Flags & PrepareFlags.Data) != 0)
                {
                    eventNumber = commit.EventNumber + prepare.TransactionOffset;
                    _committedEvents.PutRecord(prepare.EventId, Tuple.Create(eventStreamId, eventNumber), throwOnDuplicate: false);
                    addToIndex = commit.LogPosition > _persistedCommitCheckpoint ||
                                 commit.LogPosition == _persistedCommitCheckpoint && prepare.LogPosition > _persistedPrepareCheckpoint;
                }

                // could be just empty prepares for TransactionBegin and TransactionEnd, for instance
                // or records which are rebuilt but are already in PTables
                if (addToIndex)
                {
#if DEBUG
                    long pos;
                    if (_tableIndex.TryGetOneValue(streamHash, eventNumber, out pos))
                    {
                        EventRecord rec;
                        if (ReadEvent(eventStreamId, eventNumber, out rec) == SingleReadResult.Success)
                        {
                            Debugger.Break();
                            throw new Exception(
                                      string.Format(
                                          "Trying to add duplicate event #{0} for stream {1}(hash {2})\nCommit: {3}\nPrepare: {4}.",
                                          eventNumber,
                                          eventStreamId,
                                          streamHash,
                                          commit,
                                          prepare));
                        }
                    }
#endif
                    _tableIndex.Add(commit.LogPosition, streamHash, eventNumber, prepare.LogPosition);
                    _bus.Publish(new ReplicationMessage.EventCommited(commit.LogPosition, eventNumber, prepare));
                }
                _lastCommitPosition = Math.Max(_lastCommitPosition, commit.LogPosition);
            }
        }
Exemple #3
0
        public void Commit(CommitLogRecord commit)
        {
            var lastCommitPosition = Interlocked.Read(ref _lastCommitPosition);

            if (commit.LogPosition < lastCommitPosition || (commit.LogPosition == lastCommitPosition && !_indexRebuild))
            {
                return;  // already committed
            }
            bool   first       = true;
            int    eventNumber = -1;
            uint   streamHash  = 0;
            string streamId    = null;

            foreach (var prepare in GetTransactionPrepares(commit.TransactionPosition))
            {
                if (first)
                {
                    streamHash = _hasher.Hash(prepare.EventStreamId);
                    streamId   = prepare.EventStreamId;
                    first      = false;
                }
                else
                {
                    Debug.Assert(prepare.EventStreamId == streamId);
                }

                bool addToIndex = false;
                if ((prepare.Flags & PrepareFlags.StreamDelete) != 0)
                {
                    eventNumber = EventNumber.DeletedStream;
                    _committedEvents.PutRecord(prepare.EventId, Tuple.Create(streamId, eventNumber), throwOnDuplicate: false);
                    addToIndex = commit.LogPosition > _persistedCommitCheckpoint ||
                                 commit.LogPosition == _persistedCommitCheckpoint && prepare.LogPosition > _persistedPrepareCheckpoint;
                }
                else if ((prepare.Flags & PrepareFlags.Data) != 0)
                {
                    eventNumber = commit.EventNumber + prepare.TransactionOffset;
                    _committedEvents.PutRecord(prepare.EventId, Tuple.Create(streamId, eventNumber), throwOnDuplicate: false);
                    addToIndex = commit.LogPosition > _persistedCommitCheckpoint ||
                                 commit.LogPosition == _persistedCommitCheckpoint && prepare.LogPosition > _persistedPrepareCheckpoint;
                }

                // could be just empty prepares for TransactionBegin and TransactionEnd, for instance
                // or records which are rebuilt but are already in PTables
                if (addToIndex)
                {
#if CHECK_COMMIT_DUPLICATES
                    long pos;
                    if (_tableIndex.TryGetOneValue(streamHash, eventNumber, out pos))
                    {
                        ReadEventResult res = ((IReadIndex)this).ReadEvent(eventStreamId, eventNumber);
                        if (res.Result == SingleReadResult.Success)
                        {
                            Debugger.Break();
                            throw new Exception(
                                      string.Format(
                                          "Trying to add duplicate event #{0} for stream {1}(hash {2})\nCommit: {3}\nPrepare: {4}.",
                                          eventNumber,
                                          eventStreamId,
                                          streamHash,
                                          commit,
                                          prepare));
                        }
                    }
#endif
                    _tableIndex.Add(commit.LogPosition, streamHash, eventNumber, prepare.LogPosition);
                    _bus.Publish(new StorageMessage.EventCommited(commit.LogPosition, eventNumber, prepare));
                }
            }

            if (first)
            {
                throw new Exception("No prepares for commit found!");
            }

            var newLastCommitPosition = commit.LogPosition > lastCommitPosition ? commit.LogPosition : lastCommitPosition;
            if (Interlocked.CompareExchange(ref _lastCommitPosition, newLastCommitPosition, lastCommitPosition) != lastCommitPosition)
            {
                throw new Exception("Concurrency error in ReadIndex.Commit: _lastCommitPosition was modified during Commit execution!");
            }

            _streamInfoCache.Put(streamId,
                                 key => new StreamCacheInfo(eventNumber, null),
                                 (key, old) => new StreamCacheInfo(eventNumber, old.Metadata));
        }