public int Commit(CommitLogRecord commit) { int eventNumber = EventNumber.Invalid; var lastCommitPosition = Interlocked.Read(ref _lastCommitPosition); if (commit.LogPosition < lastCommitPosition || (commit.LogPosition == lastCommitPosition && !_indexRebuild)) { return(eventNumber); // already committed } string streamId = null; uint streamHash = 0; var indexEntries = new List <IndexEntry>(); var prepares = new List <PrepareLogRecord>(); foreach (var prepare in GetTransactionPrepares(commit.TransactionPosition, commit.LogPosition)) { if (prepare.Flags.HasNoneOf(PrepareFlags.StreamDelete | PrepareFlags.Data)) { continue; } if (streamId == null) { streamId = prepare.EventStreamId; streamHash = _hasher.Hash(prepare.EventStreamId); } else { if (prepare.EventStreamId != streamId) { throw new Exception(string.Format("Expected stream: {0}, actual: {1}.", streamId, prepare.EventStreamId)); } } eventNumber = prepare.Flags.HasAllOf(PrepareFlags.StreamDelete) ? EventNumber.DeletedStream : commit.FirstEventNumber + prepare.TransactionOffset; if (new TFPos(commit.LogPosition, prepare.LogPosition) > new TFPos(_persistedCommitPos, _persistedPreparePos)) { indexEntries.Add(new IndexEntry(streamHash, eventNumber, prepare.LogPosition)); prepares.Add(prepare); } } if (indexEntries.Count > 0) { if (_additionalCommitChecks) { CheckStreamVersion(streamId, indexEntries[0].Version, commit); CheckDuplicateEvents(streamHash, commit, indexEntries, prepares); } _tableIndex.AddEntries(commit.LogPosition, indexEntries); // atomically add a whole bulk of entries } if (eventNumber != EventNumber.Invalid) { if (eventNumber < 0) { throw new Exception(string.Format("EventNumber {0} is incorrect.", eventNumber)); } _backend.SetStreamLastEventNumber(streamId, eventNumber); if (SystemStreams.IsMetastream(streamId)) { _backend.SetStreamMetadata(SystemStreams.OriginalStreamOf(streamId), null); // invalidate cached metadata } if (streamId == SystemStreams.SettingsStream) { _backend.SetSystemSettings(DeserializeSystemSettings(prepares[prepares.Count - 1].Data)); } } var newLastCommitPosition = Math.Max(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!"); } for (int i = 0, n = indexEntries.Count; i < n; ++i) { _bus.Publish(new StorageMessage.EventCommited(commit.LogPosition, new EventRecord(indexEntries[i].Version, prepares[i]))); } return(eventNumber); }