Ejemplo n.º 1
0
        /// <summary>
        /// Adds a gtid value to the GtidSet.
        /// </summary>
        public bool AddGtid(IGtid value)
        {
            var     gtid = (Gtid)value;
            UuidSet uuidSet;

            if (!UuidSets.TryGetValue(gtid.SourceId, out uuidSet))
            {
                uuidSet = new UuidSet(gtid.SourceId, new List <Interval>());
                UuidSets[gtid.SourceId] = uuidSet;
            }
            return(uuidSet.AddGtid(gtid));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Replicates binlog events from the server
        /// </summary>
        /// <param name="handleEvent">Client callback function</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Task completed when last event is read in non-blocking mode</returns>
        public async Task ReplicateAsync(Func <IBinlogEvent, Task> handleEvent, CancellationToken cancellationToken = default)
        {
            await ConnectAsync(cancellationToken);

            // Clear on reconnect
            _gtid        = null;
            _transaction = false;

            await AdjustStartingPosition(cancellationToken);
            await SetMasterHeartbeat(cancellationToken);
            await SetMasterBinlogChecksum(cancellationToken);

            await _databaseProvider.DumpBinlogAsync(_channel, _options, cancellationToken);

            await ReadEventStreamAsync(handleEvent, cancellationToken);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Adds a gtid value to the GtidList.
        /// </summary>
        public bool AddGtid(IGtid gtidRaw)
        {
            var gtid = (Gtid)gtidRaw;

            for (int i = 0; i < Gtids.Count; i++)
            {
                if (Gtids[i].DomainId == gtid.DomainId)
                {
                    Gtids[i] = gtid;
                    return(false);
                }
            }

            Gtids.Add(gtid);
            return(true);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Replicates binlog events from the server
        /// </summary>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Task completed when last event is read in non-blocking mode</returns>
        public async IAsyncEnumerable <IBinlogEvent> Replicate([EnumeratorCancellation] CancellationToken cancellationToken = default)
        {
            await ConnectAsync(cancellationToken);

            // Clear on reconnect
            _gtid        = null;
            _transaction = false;

            await AdjustStartingPosition(cancellationToken);
            await SetMasterHeartbeat(cancellationToken);
            await SetMasterBinlogChecksum(cancellationToken);

            await _databaseProvider.DumpBinlogAsync(_channel, _options, cancellationToken);

            var eventStreamReader = new EventStreamReader(_databaseProvider.Deserializer);
            var channel           = new EventStreamChannel(eventStreamReader, _channel.Stream);
            var timeout           = _options.HeartbeatInterval.Add(TimeSpan.FromMilliseconds(TimeoutConstants.Delta));

            await foreach (var packet in channel.ReadPacketAsync(timeout, cancellationToken).WithCancellation(cancellationToken))
            {
                if (packet is IBinlogEvent binlogEvent)
                {
                    // We stop replication if client code throws an exception
                    // As a derived database may end up in an inconsistent state.
                    yield return(binlogEvent);

                    // Commit replication state if there is no exception.
                    UpdateGtidPosition(binlogEvent);
                    UpdateBinlogPosition(binlogEvent);
                }
                else if (packet is EndOfFilePacket && !_options.Blocking)
                {
                    yield break;
                }
                else if (packet is ErrorPacket error)
                {
                    throw new InvalidOperationException($"Event stream error. {error.ToString()}");
                }
                else
                {
                    throw new InvalidOperationException($"Event stream unexpected error.");
                }
            }
        }
Ejemplo n.º 5
0
        private void UpdateGtidPosition(IBinlogEvent binlogEvent)
        {
            if (_options.Binlog.StartingStrategy != StartingStrategy.FromGtid)
            {
                return;
            }

            if (binlogEvent is GtidEvent gtidEvent)
            {
                _gtid = gtidEvent.Gtid;
            }
            else if (binlogEvent is XidEvent xidEvent)
            {
                CommitGtid();
            }
            else if (binlogEvent is QueryEvent queryEvent)
            {
                if (string.IsNullOrWhiteSpace(queryEvent.SqlStatement))
                {
                    return;
                }

                if (queryEvent.SqlStatement == "BEGIN")
                {
                    _transaction = true;
                }
                else if (queryEvent.SqlStatement == "COMMIT" || queryEvent.SqlStatement == "ROLLBACK")
                {
                    CommitGtid();
                }
                else if (!_transaction)
                {
                    // Auto-commit query like DDL
                    CommitGtid();
                }
            }
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Creates a new <see cref="GtidEvent"/>.
 /// </summary>
 public GtidEvent(EventHeader header, IGtid gtid, int flags) : base(header)
 {
     Gtid  = gtid;
     Flags = flags;
 }