From f777e6486a336a6ff20fefff3ae5afd170ba2b2a Mon Sep 17 00:00:00 2001 From: dongmen <414110582@qq.com> Date: Wed, 6 May 2026 14:18:46 +0800 Subject: [PATCH 1/2] *: skip syncpoint in maintainer Signed-off-by: dongmen <414110582@qq.com> --- .gitignore | 1 + .../dispatcher/basic_dispatcher.go | 8 +- .../dispatcher/basic_dispatcher_info.go | 26 +- .../dispatchermanager/dispatcher_manager.go | 41 +- .../dispatcher_manager_test.go | 34 + .../dispatchermanager/heartbeat_collector.go | 16 + downstreamadapter/dispatchermanager/helper.go | 57 + .../dispatcher_orchestrator.go | 9 +- heartbeatpb/heartbeat.pb.go | 1136 +++++++++++++---- heartbeatpb/heartbeat.proto | 14 + maintainer/barrier.go | 65 +- maintainer/barrier_event.go | 43 +- maintainer/barrier_test.go | 184 +++ maintainer/maintainer.go | 74 ++ maintainer/maintainer_controller.go | 36 +- maintainer/maintainer_controller_bootstrap.go | 4 + maintainer/maintainer_test.go | 98 +- pkg/messaging/message.go | 7 + 18 files changed, 1579 insertions(+), 274 deletions(-) diff --git a/.gitignore b/.gitignore index 5012978619..e224245024 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ tools/bin tools/include tools/workload/bin +.design .issue .vscode .idea diff --git a/downstreamadapter/dispatcher/basic_dispatcher.go b/downstreamadapter/dispatcher/basic_dispatcher.go index ad4b7c88a5..31cd0be382 100644 --- a/downstreamadapter/dispatcher/basic_dispatcher.go +++ b/downstreamadapter/dispatcher/basic_dispatcher.go @@ -706,8 +706,14 @@ func (d *BasicDispatcher) handleEvents(dispatcherEvents []DispatcherEvent, wakeC log.Panic("sync point event should only be singly handled", zap.Stringer("dispatcherID", d.id)) } - block = true syncPoint := event.(*commonEvent.SyncPointEvent) + if d.ShouldSkipSyncPoint(syncPoint.GetCommitTs()) { + log.Debug("dispatcher skip sync point event by control window", + zap.Stringer("dispatcher", d.id), + zap.Uint64("commitTs", syncPoint.GetCommitTs())) + continue + } + block = true log.Info("dispatcher receive sync point event", zap.Stringer("dispatcher", d.id), zap.Uint64("commitTs", syncPoint.GetCommitTs()), diff --git a/downstreamadapter/dispatcher/basic_dispatcher_info.go b/downstreamadapter/dispatcher/basic_dispatcher_info.go index 731d82d5a1..15021c7380 100644 --- a/downstreamadapter/dispatcher/basic_dispatcher_info.go +++ b/downstreamadapter/dispatcher/basic_dispatcher_info.go @@ -42,7 +42,8 @@ type SharedInfo struct { // the config of filter filterConfig *eventpb.FilterConfig // if syncPointInfo is not nil, means enable Sync Point feature, - syncPointConfig *syncpoint.SyncPointConfig + syncPointConfig *syncpoint.SyncPointConfig + syncPointControl atomic.Pointer[common.SyncPointControl] // The atomicity level of a transaction. txnAtomicity config.AtomicityLevel @@ -121,6 +122,8 @@ func NewSharedInfo( } else { sharedInfo.txnAtomicity = config.DefaultAtomicityLevel() } + disabled := common.NewDisabledSyncPointControl() + sharedInfo.syncPointControl.Store(&disabled) return sharedInfo } @@ -223,6 +226,10 @@ func (d *BasicDispatcher) GetSyncPointInterval() time.Duration { return time.Duration(0) } +func (d *BasicDispatcher) ShouldSkipSyncPoint(commitTs uint64) bool { + return d.sharedInfo.ShouldSkipSyncPoint(commitTs) +} + func (d *BasicDispatcher) GetTableSpan() *heartbeatpb.TableSpan { return d.tableSpan } @@ -258,6 +265,23 @@ func (s *SharedInfo) IsOutputRawChangeEvent() bool { return s.outputRawChangeEvent } +func (s *SharedInfo) SetSyncPointControl(control common.SyncPointControl) { + clone := control.Clone() + s.syncPointControl.Store(&clone) +} + +func (s *SharedInfo) GetSyncPointControl() common.SyncPointControl { + control := s.syncPointControl.Load() + if control == nil { + return common.NewDisabledSyncPointControl() + } + return control.Clone() +} + +func (s *SharedInfo) ShouldSkipSyncPoint(commitTs uint64) bool { + return s.GetSyncPointControl().Contains(commitTs) +} + func (s *SharedInfo) GetStatusesChan() chan TableSpanStatusWithSeq { return s.statusesChan } diff --git a/downstreamadapter/dispatchermanager/dispatcher_manager.go b/downstreamadapter/dispatchermanager/dispatcher_manager.go index fdf222ef25..3aadf9b7ab 100644 --- a/downstreamadapter/dispatchermanager/dispatcher_manager.go +++ b/downstreamadapter/dispatchermanager/dispatcher_manager.go @@ -156,6 +156,8 @@ type DispatcherManager struct { // Shared info for all dispatchers sharedInfo *dispatcher.SharedInfo + // appliedSyncPointControl is the current syncpoint skip control installed on this dispatcher manager. + appliedSyncPointControl atomic.Pointer[common.SyncPointControl] metricTableTriggerEventDispatcherCount prometheus.Gauge metricEventDispatcherCount prometheus.Gauge @@ -182,6 +184,7 @@ func NewDispatcherManager( startTs uint64, maintainerID node.ID, newChangefeed bool, + syncPointControl *heartbeatpb.SyncPointControl, ) (*DispatcherManager, error) { failpoint.Inject("NewDispatcherManagerDelay", nil) @@ -275,6 +278,7 @@ func NewDispatcherManager( make(chan *heartbeatpb.TableSpanBlockStatus, 1024*1024), make(chan error, 1), ) + manager.SetSyncPointControl(syncPointControl) // Register Event Dispatcher Manager in HeartBeatCollector, // which is responsible for communication with the maintainer. @@ -738,10 +742,11 @@ func (e *DispatcherManager) collectComponentStatusWhenChanged(ctx context.Contex // Returns a HeartBeatRequest containing the aggregated information. func (e *DispatcherManager) aggregateDispatcherHeartbeats(needCompleteStatus bool) *heartbeatpb.HeartBeatRequest { message := heartbeatpb.HeartBeatRequest{ - ChangefeedID: e.changefeedID.ToPB(), - CompeleteStatus: needCompleteStatus, - Watermark: heartbeatpb.NewMaxWatermark(), - RedoWatermark: heartbeatpb.NewMaxWatermark(), + ChangefeedID: e.changefeedID.ToPB(), + CompeleteStatus: needCompleteStatus, + Watermark: heartbeatpb.NewMaxWatermark(), + RedoWatermark: heartbeatpb.NewMaxWatermark(), + SyncPointControl: e.GetSyncPointControl().ToPB(), } toCleanMap := make([]*cleanMap, 0) @@ -813,6 +818,34 @@ func (e *DispatcherManager) aggregateDispatcherHeartbeats(needCompleteStatus boo return &message } +func (e *DispatcherManager) SetSyncPointControl(control *heartbeatpb.SyncPointControl) { + newControl := common.NewSyncPointControlFromPB(control) + current := e.appliedSyncPointControl.Load() + if current != nil && current.Epoch > newControl.Epoch { + return + } + if current != nil && current.Epoch == newControl.Epoch && !current.Equal(newControl) { + log.Warn("ignore syncpoint control with same epoch but different window", + zap.Stringer("changefeedID", e.changefeedID), + zap.Uint64("epoch", newControl.Epoch), + zap.Uint64("currentSkipStartTs", current.SkipStartTs), + zap.Uint64("currentSkipEndTs", current.SkipEndTs), + zap.Uint64("newSkipStartTs", newControl.SkipStartTs), + zap.Uint64("newSkipEndTs", newControl.SkipEndTs)) + return + } + e.sharedInfo.SetSyncPointControl(newControl) + e.appliedSyncPointControl.Store(&newControl) +} + +func (e *DispatcherManager) GetSyncPointControl() common.SyncPointControl { + control := e.appliedSyncPointControl.Load() + if control == nil { + return common.NewDisabledSyncPointControl() + } + return control.Clone() +} + func (e *DispatcherManager) MergeDispatcher(dispatcherIDs []common.DispatcherID, mergedDispatcherID common.DispatcherID, mode int64) *MergeCheckTask { if common.IsRedoMode(mode) { return e.mergeRedoDispatcher(dispatcherIDs, mergedDispatcherID) diff --git a/downstreamadapter/dispatchermanager/dispatcher_manager_test.go b/downstreamadapter/dispatchermanager/dispatcher_manager_test.go index a91e2560a0..e54dfce320 100644 --- a/downstreamadapter/dispatchermanager/dispatcher_manager_test.go +++ b/downstreamadapter/dispatchermanager/dispatcher_manager_test.go @@ -223,6 +223,40 @@ func TestCollectComponentStatusWhenChangedWatermarkSeqNoFallback(t *testing.T) { require.Equal(t, uint64(200), req.Request.RedoWatermark.Seq) } +func TestAggregateDispatcherHeartbeatsCarriesSyncPointControl(t *testing.T) { + manager := createTestManager(t) + manager.SetSyncPointControl(&heartbeatpb.SyncPointControl{ + Epoch: 3, + SkipStartTs: 100, + SkipEndTs: 200, + }) + + msg := manager.aggregateDispatcherHeartbeats(false) + require.NotNil(t, msg.SyncPointControl) + require.Equal(t, uint64(3), msg.SyncPointControl.Epoch) + require.Equal(t, uint64(100), msg.SyncPointControl.SkipStartTs) + require.Equal(t, uint64(200), msg.SyncPointControl.SkipEndTs) +} + +func TestSetSyncPointControlIgnoreSameEpochDifferentWindow(t *testing.T) { + manager := createTestManager(t) + manager.SetSyncPointControl(&heartbeatpb.SyncPointControl{ + Epoch: 3, + SkipStartTs: 100, + SkipEndTs: 200, + }) + manager.SetSyncPointControl(&heartbeatpb.SyncPointControl{ + Epoch: 3, + SkipStartTs: 150, + SkipEndTs: 250, + }) + + control := manager.GetSyncPointControl() + require.Equal(t, uint64(3), control.Epoch) + require.Equal(t, uint64(100), control.SkipStartTs) + require.Equal(t, uint64(200), control.SkipEndTs) +} + func TestMergeDispatcherNormal(t *testing.T) { manager := createTestManager(t) diff --git a/downstreamadapter/dispatchermanager/heartbeat_collector.go b/downstreamadapter/dispatchermanager/heartbeat_collector.go index 99ef678b14..f39df1a239 100644 --- a/downstreamadapter/dispatchermanager/heartbeat_collector.go +++ b/downstreamadapter/dispatchermanager/heartbeat_collector.go @@ -55,6 +55,7 @@ type HeartBeatCollector struct { heartBeatResponseDynamicStream dynstream.DynamicStream[int, common.GID, HeartBeatResponse, *DispatcherManager, *HeartBeatResponseHandler] schedulerDispatcherRequestDynamicStream dynstream.DynamicStream[int, common.GID, SchedulerDispatcherRequest, *DispatcherManager, *SchedulerDispatcherRequestHandler] checkpointTsMessageDynamicStream dynstream.DynamicStream[int, common.GID, CheckpointTsMessage, *DispatcherManager, *CheckpointTsMessageHandler] + syncPointControlMessageDynamicStream dynstream.DynamicStream[int, common.GID, SyncPointControlMessage, *DispatcherManager, *SyncPointControlMessageHandler] redoResolvedTsForwardMessageDynamicStream dynstream.DynamicStream[int, common.GID, RedoResolvedTsForwardMessage, *DispatcherManager, *RedoResolvedTsForwardMessageHandler] redoMetaMessageDynamicStream dynstream.DynamicStream[int, common.GID, RedoMetaMessage, *DispatcherManager, *RedoMetaMessageHandler] mergeDispatcherRequestDynamicStream dynstream.DynamicStream[int, common.GID, MergeDispatcherRequest, *DispatcherManager, *MergeDispatcherRequestHandler] @@ -75,6 +76,7 @@ func NewHeartBeatCollector(serverId node.ID) *HeartBeatCollector { heartBeatResponseDynamicStream: newHeartBeatResponseDynamicStream(dStatusDS), schedulerDispatcherRequestDynamicStream: newSchedulerDispatcherRequestDynamicStream(), checkpointTsMessageDynamicStream: newCheckpointTsMessageDynamicStream(), + syncPointControlMessageDynamicStream: newSyncPointControlMessageDynamicStream(), redoResolvedTsForwardMessageDynamicStream: newRedoResolvedTsForwardMessageDynamicStream(), redoMetaMessageDynamicStream: newRedoMetaMessageDynamicStream(), mergeDispatcherRequestDynamicStream: newMergeDispatcherRequestDynamicStream(), @@ -124,6 +126,10 @@ func (c *HeartBeatCollector) RegisterDispatcherManager(m *DispatcherManager) err if err != nil { return errors.Trace(err) } + err = c.syncPointControlMessageDynamicStream.AddPath(m.changefeedID.Id, m) + if err != nil { + return errors.Trace(err) + } err = c.mergeDispatcherRequestDynamicStream.AddPath(m.changefeedID.Id, m) if err != nil { return errors.Trace(err) @@ -166,6 +172,10 @@ func (c *HeartBeatCollector) RemoveDispatcherManager(id common.ChangeFeedID) err if err != nil { return errors.Trace(err) } + err = c.syncPointControlMessageDynamicStream.RemovePath(id.Id) + if err != nil { + return errors.Trace(err) + } err = c.mergeDispatcherRequestDynamicStream.RemovePath(id.Id) if err != nil { return errors.Trace(err) @@ -275,6 +285,11 @@ func (c *HeartBeatCollector) RecvMessages(_ context.Context, msg *messaging.Targ c.checkpointTsMessageDynamicStream.Push( common.NewChangefeedGIDFromPB(checkpointTsMessage.ChangefeedID), NewCheckpointTsMessage(checkpointTsMessage)) + case messaging.TypeSyncPointControlMessage: + syncPointControlMessage := msg.Message[0].(*heartbeatpb.SyncPointControlMessage) + c.syncPointControlMessageDynamicStream.Push( + common.NewChangefeedGIDFromPB(syncPointControlMessage.ChangefeedID), + NewSyncPointControlMessage(syncPointControlMessage)) case messaging.TypeRedoResolvedTsForwardMessage: redoMessage := msg.Message[0].(*heartbeatpb.RedoResolvedTsForwardMessage) c.redoResolvedTsForwardMessageDynamicStream.Push( @@ -306,6 +321,7 @@ func (c *HeartBeatCollector) Close() { c.isClosed.Store(true) c.checkpointTsMessageDynamicStream.Close() + c.syncPointControlMessageDynamicStream.Close() c.redoResolvedTsForwardMessageDynamicStream.Close() c.redoMetaMessageDynamicStream.Close() c.heartBeatResponseDynamicStream.Close() diff --git a/downstreamadapter/dispatchermanager/helper.go b/downstreamadapter/dispatchermanager/helper.go index 35e07a4765..bf77eeb8e6 100644 --- a/downstreamadapter/dispatchermanager/helper.go +++ b/downstreamadapter/dispatchermanager/helper.go @@ -629,6 +629,63 @@ func (h *CheckpointTsMessageHandler) OnDrop(event CheckpointTsMessage) interface return nil } +func newSyncPointControlMessageDynamicStream() dynstream.DynamicStream[int, common.GID, SyncPointControlMessage, *DispatcherManager, *SyncPointControlMessageHandler] { + ds := dynstream.NewParallelDynamicStream("syncpoint-control", + &SyncPointControlMessageHandler{}) + ds.Start() + return ds +} + +type SyncPointControlMessage struct { + *heartbeatpb.SyncPointControlMessage +} + +func NewSyncPointControlMessage(msg *heartbeatpb.SyncPointControlMessage) SyncPointControlMessage { + return SyncPointControlMessage{msg} +} + +type SyncPointControlMessageHandler struct{} + +func (h *SyncPointControlMessageHandler) Path(msg SyncPointControlMessage) common.GID { + return common.NewChangefeedGIDFromPB(msg.ChangefeedID) +} + +func (h *SyncPointControlMessageHandler) Handle(dispatcherManager *DispatcherManager, messages ...SyncPointControlMessage) bool { + if len(messages) != 1 { + panic("invalid message count") + } + dispatcherManager.SetSyncPointControl(messages[0].Control) + return false +} + +func (h *SyncPointControlMessageHandler) GetSize(event SyncPointControlMessage) int { + return 0 +} + +func (h *SyncPointControlMessageHandler) IsPaused(event SyncPointControlMessage) bool { + return false +} + +func (h *SyncPointControlMessageHandler) GetArea(path common.GID, dest *DispatcherManager) int { + return 0 +} + +func (h *SyncPointControlMessageHandler) GetMetricLabel(dest *DispatcherManager) string { + return dest.changefeedID.String() +} + +func (h *SyncPointControlMessageHandler) GetTimestamp(event SyncPointControlMessage) dynstream.Timestamp { + return 0 +} + +func (h *SyncPointControlMessageHandler) GetType(event SyncPointControlMessage) dynstream.EventType { + return dynstream.DefaultEventType +} + +func (h *SyncPointControlMessageHandler) OnDrop(event SyncPointControlMessage) interface{} { + return nil +} + // RedoResolvedTsForwardMessageDynamicStream is responsible for push RedoResolvedTsForwardMessage to the corresponding table trigger event dispatcher. func newRedoResolvedTsForwardMessageDynamicStream() dynstream.DynamicStream[int, common.GID, RedoResolvedTsForwardMessage, *DispatcherManager, *RedoResolvedTsForwardMessageHandler] { ds := dynstream.NewParallelDynamicStream("redo-resolved-ts", diff --git a/downstreamadapter/dispatcherorchestrator/dispatcher_orchestrator.go b/downstreamadapter/dispatcherorchestrator/dispatcher_orchestrator.go index 2876b968c9..b29ca60128 100644 --- a/downstreamadapter/dispatcherorchestrator/dispatcher_orchestrator.go +++ b/downstreamadapter/dispatcherorchestrator/dispatcher_orchestrator.go @@ -176,6 +176,7 @@ func (m *DispatcherOrchestrator) handleBootstrapRequest( req.StartTs, from, req.IsNewChangefeed, + req.SyncPointControl, ) // Fast return the error to maintainer. if err != nil { @@ -203,6 +204,9 @@ func (m *DispatcherOrchestrator) handleBootstrapRequest( m.mutex.Unlock() metrics.DispatcherManagerGauge.WithLabelValues(cfId.Keyspace(), cfId.Name()).Inc() } else { + if req.SyncPointControl != nil { + manager.SetSyncPointControl(req.SyncPointControl) + } // Check and potentially add a table trigger event dispatcher. // This is necessary during maintainer node migration, as the existing // dispatcher manager on the new node may not have a table trigger @@ -368,8 +372,9 @@ func createBootstrapResponse( startTs, redoStartTs uint64, ) *heartbeatpb.MaintainerBootstrapResponse { response := &heartbeatpb.MaintainerBootstrapResponse{ - ChangefeedID: changefeedID, - Spans: make([]*heartbeatpb.BootstrapTableSpan, 0, manager.GetDispatcherMap().Len()), + ChangefeedID: changefeedID, + Spans: make([]*heartbeatpb.BootstrapTableSpan, 0, manager.GetDispatcherMap().Len()), + SyncPointControl: manager.GetSyncPointControl().ToPB(), } // table trigger event dispatcher startTs diff --git a/heartbeatpb/heartbeat.pb.go b/heartbeatpb/heartbeat.pb.go index 20a83a7f0b..1525a9f886 100644 --- a/heartbeatpb/heartbeat.pb.go +++ b/heartbeatpb/heartbeat.pb.go @@ -348,12 +348,13 @@ func (m *TableSpan) GetKeyspaceID() uint32 { } type HeartBeatRequest struct { - ChangefeedID *ChangefeedID `protobuf:"bytes,1,opt,name=changefeedID,proto3" json:"changefeedID,omitempty"` - Watermark *Watermark `protobuf:"bytes,2,opt,name=watermark,proto3" json:"watermark,omitempty"` - RedoWatermark *Watermark `protobuf:"bytes,3,opt,name=redoWatermark,proto3" json:"redoWatermark,omitempty"` - Statuses []*TableSpanStatus `protobuf:"bytes,4,rep,name=statuses,proto3" json:"statuses,omitempty"` - CompeleteStatus bool `protobuf:"varint,5,opt,name=compeleteStatus,proto3" json:"compeleteStatus,omitempty"` - Err *RunningError `protobuf:"bytes,6,opt,name=err,proto3" json:"err,omitempty"` + ChangefeedID *ChangefeedID `protobuf:"bytes,1,opt,name=changefeedID,proto3" json:"changefeedID,omitempty"` + Watermark *Watermark `protobuf:"bytes,2,opt,name=watermark,proto3" json:"watermark,omitempty"` + RedoWatermark *Watermark `protobuf:"bytes,3,opt,name=redoWatermark,proto3" json:"redoWatermark,omitempty"` + Statuses []*TableSpanStatus `protobuf:"bytes,4,rep,name=statuses,proto3" json:"statuses,omitempty"` + CompeleteStatus bool `protobuf:"varint,5,opt,name=compeleteStatus,proto3" json:"compeleteStatus,omitempty"` + Err *RunningError `protobuf:"bytes,6,opt,name=err,proto3" json:"err,omitempty"` + SyncPointControl *SyncPointControl `protobuf:"bytes,7,opt,name=sync_point_control,json=syncPointControl,proto3" json:"sync_point_control,omitempty"` } func (m *HeartBeatRequest) Reset() { *m = HeartBeatRequest{} } @@ -431,6 +432,13 @@ func (m *HeartBeatRequest) GetErr() *RunningError { return nil } +func (m *HeartBeatRequest) GetSyncPointControl() *SyncPointControl { + if m != nil { + return m.SyncPointControl + } + return nil +} + type Watermark struct { CheckpointTs uint64 `protobuf:"varint,1,opt,name=checkpointTs,proto3" json:"checkpointTs,omitempty"` ResolvedTs uint64 `protobuf:"varint,2,opt,name=resolvedTs,proto3" json:"resolvedTs,omitempty"` @@ -914,6 +922,118 @@ func (m *CheckpointTsMessage) GetCheckpointTs() uint64 { return 0 } +type SyncPointControl struct { + Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + SkipStartTs uint64 `protobuf:"varint,2,opt,name=skip_start_ts,json=skipStartTs,proto3" json:"skip_start_ts,omitempty"` + SkipEndTs uint64 `protobuf:"varint,3,opt,name=skip_end_ts,json=skipEndTs,proto3" json:"skip_end_ts,omitempty"` +} + +func (m *SyncPointControl) Reset() { *m = SyncPointControl{} } +func (m *SyncPointControl) String() string { return proto.CompactTextString(m) } +func (*SyncPointControl) ProtoMessage() {} +func (*SyncPointControl) Descriptor() ([]byte, []int) { + return fileDescriptor_6d584080fdadb670, []int{10} +} +func (m *SyncPointControl) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SyncPointControl) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SyncPointControl.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SyncPointControl) XXX_Merge(src proto.Message) { + xxx_messageInfo_SyncPointControl.Merge(m, src) +} +func (m *SyncPointControl) XXX_Size() int { + return m.Size() +} +func (m *SyncPointControl) XXX_DiscardUnknown() { + xxx_messageInfo_SyncPointControl.DiscardUnknown(m) +} + +var xxx_messageInfo_SyncPointControl proto.InternalMessageInfo + +func (m *SyncPointControl) GetEpoch() uint64 { + if m != nil { + return m.Epoch + } + return 0 +} + +func (m *SyncPointControl) GetSkipStartTs() uint64 { + if m != nil { + return m.SkipStartTs + } + return 0 +} + +func (m *SyncPointControl) GetSkipEndTs() uint64 { + if m != nil { + return m.SkipEndTs + } + return 0 +} + +type SyncPointControlMessage struct { + ChangefeedID *ChangefeedID `protobuf:"bytes,1,opt,name=changefeedID,proto3" json:"changefeedID,omitempty"` + Control *SyncPointControl `protobuf:"bytes,2,opt,name=control,proto3" json:"control,omitempty"` +} + +func (m *SyncPointControlMessage) Reset() { *m = SyncPointControlMessage{} } +func (m *SyncPointControlMessage) String() string { return proto.CompactTextString(m) } +func (*SyncPointControlMessage) ProtoMessage() {} +func (*SyncPointControlMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_6d584080fdadb670, []int{11} +} +func (m *SyncPointControlMessage) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SyncPointControlMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SyncPointControlMessage.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SyncPointControlMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_SyncPointControlMessage.Merge(m, src) +} +func (m *SyncPointControlMessage) XXX_Size() int { + return m.Size() +} +func (m *SyncPointControlMessage) XXX_DiscardUnknown() { + xxx_messageInfo_SyncPointControlMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_SyncPointControlMessage proto.InternalMessageInfo + +func (m *SyncPointControlMessage) GetChangefeedID() *ChangefeedID { + if m != nil { + return m.ChangefeedID + } + return nil +} + +func (m *SyncPointControlMessage) GetControl() *SyncPointControl { + if m != nil { + return m.Control + } + return nil +} + // RedoMetaMessage used to send unflushed ts to update redo meta // from maintainer to dispatcher manager type RedoMetaMessage struct { @@ -926,7 +1046,7 @@ func (m *RedoMetaMessage) Reset() { *m = RedoMetaMessage{} } func (m *RedoMetaMessage) String() string { return proto.CompactTextString(m) } func (*RedoMetaMessage) ProtoMessage() {} func (*RedoMetaMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{10} + return fileDescriptor_6d584080fdadb670, []int{12} } func (m *RedoMetaMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -987,7 +1107,7 @@ func (m *RedoResolvedTsProgressMessage) Reset() { *m = RedoResolvedTsPro func (m *RedoResolvedTsProgressMessage) String() string { return proto.CompactTextString(m) } func (*RedoResolvedTsProgressMessage) ProtoMessage() {} func (*RedoResolvedTsProgressMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{11} + return fileDescriptor_6d584080fdadb670, []int{13} } func (m *RedoResolvedTsProgressMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1041,7 +1161,7 @@ func (m *RedoResolvedTsForwardMessage) Reset() { *m = RedoResolvedTsForw func (m *RedoResolvedTsForwardMessage) String() string { return proto.CompactTextString(m) } func (*RedoResolvedTsForwardMessage) ProtoMessage() {} func (*RedoResolvedTsForwardMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{12} + return fileDescriptor_6d584080fdadb670, []int{14} } func (m *RedoResolvedTsForwardMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1101,7 +1221,7 @@ func (m *DispatcherConfig) Reset() { *m = DispatcherConfig{} } func (m *DispatcherConfig) String() string { return proto.CompactTextString(m) } func (*DispatcherConfig) ProtoMessage() {} func (*DispatcherConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{13} + return fileDescriptor_6d584080fdadb670, []int{15} } func (m *DispatcherConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1183,7 +1303,7 @@ func (m *ScheduleDispatcherRequest) Reset() { *m = ScheduleDispatcherReq func (m *ScheduleDispatcherRequest) String() string { return proto.CompactTextString(m) } func (*ScheduleDispatcherRequest) ProtoMessage() {} func (*ScheduleDispatcherRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{14} + return fileDescriptor_6d584080fdadb670, []int{16} } func (m *ScheduleDispatcherRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1251,7 +1371,7 @@ func (m *MergeDispatcherRequest) Reset() { *m = MergeDispatcherRequest{} func (m *MergeDispatcherRequest) String() string { return proto.CompactTextString(m) } func (*MergeDispatcherRequest) ProtoMessage() {} func (*MergeDispatcherRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{15} + return fileDescriptor_6d584080fdadb670, []int{17} } func (m *MergeDispatcherRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1316,7 +1436,7 @@ func (m *MaintainerHeartbeat) Reset() { *m = MaintainerHeartbeat{} } func (m *MaintainerHeartbeat) String() string { return proto.CompactTextString(m) } func (*MaintainerHeartbeat) ProtoMessage() {} func (*MaintainerHeartbeat) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{16} + return fileDescriptor_6d584080fdadb670, []int{18} } func (m *MaintainerHeartbeat) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1372,7 +1492,7 @@ func (m *DrainProgress) Reset() { *m = DrainProgress{} } func (m *DrainProgress) String() string { return proto.CompactTextString(m) } func (*DrainProgress) ProtoMessage() {} func (*DrainProgress) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{17} + return fileDescriptor_6d584080fdadb670, []int{19} } func (m *DrainProgress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1446,7 +1566,7 @@ func (m *MaintainerStatus) Reset() { *m = MaintainerStatus{} } func (m *MaintainerStatus) String() string { return proto.CompactTextString(m) } func (*MaintainerStatus) ProtoMessage() {} func (*MaintainerStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{18} + return fileDescriptor_6d584080fdadb670, []int{20} } func (m *MaintainerStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1545,7 +1665,7 @@ func (m *NodeHeartbeat) Reset() { *m = NodeHeartbeat{} } func (m *NodeHeartbeat) String() string { return proto.CompactTextString(m) } func (*NodeHeartbeat) ProtoMessage() {} func (*NodeHeartbeat) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{19} + return fileDescriptor_6d584080fdadb670, []int{21} } func (m *NodeHeartbeat) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1612,7 +1732,7 @@ func (m *SetNodeLivenessRequest) Reset() { *m = SetNodeLivenessRequest{} func (m *SetNodeLivenessRequest) String() string { return proto.CompactTextString(m) } func (*SetNodeLivenessRequest) ProtoMessage() {} func (*SetNodeLivenessRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{20} + return fileDescriptor_6d584080fdadb670, []int{22} } func (m *SetNodeLivenessRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1665,7 +1785,7 @@ func (m *SetNodeLivenessResponse) Reset() { *m = SetNodeLivenessResponse func (m *SetNodeLivenessResponse) String() string { return proto.CompactTextString(m) } func (*SetNodeLivenessResponse) ProtoMessage() {} func (*SetNodeLivenessResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{21} + return fileDescriptor_6d584080fdadb670, []int{23} } func (m *SetNodeLivenessResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1719,7 +1839,7 @@ func (m *SetDispatcherDrainTargetRequest) Reset() { *m = SetDispatcherDr func (m *SetDispatcherDrainTargetRequest) String() string { return proto.CompactTextString(m) } func (*SetDispatcherDrainTargetRequest) ProtoMessage() {} func (*SetDispatcherDrainTargetRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{22} + return fileDescriptor_6d584080fdadb670, []int{24} } func (m *SetDispatcherDrainTargetRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1770,7 +1890,7 @@ func (m *CoordinatorBootstrapRequest) Reset() { *m = CoordinatorBootstra func (m *CoordinatorBootstrapRequest) String() string { return proto.CompactTextString(m) } func (*CoordinatorBootstrapRequest) ProtoMessage() {} func (*CoordinatorBootstrapRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{23} + return fileDescriptor_6d584080fdadb670, []int{25} } func (m *CoordinatorBootstrapRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1814,7 +1934,7 @@ func (m *CoordinatorBootstrapResponse) Reset() { *m = CoordinatorBootstr func (m *CoordinatorBootstrapResponse) String() string { return proto.CompactTextString(m) } func (*CoordinatorBootstrapResponse) ProtoMessage() {} func (*CoordinatorBootstrapResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{24} + return fileDescriptor_6d584080fdadb670, []int{26} } func (m *CoordinatorBootstrapResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1862,7 +1982,7 @@ func (m *AddMaintainerRequest) Reset() { *m = AddMaintainerRequest{} } func (m *AddMaintainerRequest) String() string { return proto.CompactTextString(m) } func (*AddMaintainerRequest) ProtoMessage() {} func (*AddMaintainerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{25} + return fileDescriptor_6d584080fdadb670, []int{27} } func (m *AddMaintainerRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1937,7 +2057,7 @@ func (m *RemoveMaintainerRequest) Reset() { *m = RemoveMaintainerRequest func (m *RemoveMaintainerRequest) String() string { return proto.CompactTextString(m) } func (*RemoveMaintainerRequest) ProtoMessage() {} func (*RemoveMaintainerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{26} + return fileDescriptor_6d584080fdadb670, []int{28} } func (m *RemoveMaintainerRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1995,20 +2115,21 @@ func (m *RemoveMaintainerRequest) GetKeyspaceId() uint32 { } type MaintainerBootstrapRequest struct { - ChangefeedID *ChangefeedID `protobuf:"bytes,1,opt,name=changefeedID,proto3" json:"changefeedID,omitempty"` - Config []byte `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` - StartTs uint64 `protobuf:"varint,3,opt,name=start_ts,json=startTs,proto3" json:"start_ts,omitempty"` - TableTriggerEventDispatcherId *DispatcherID `protobuf:"bytes,4,opt,name=table_trigger_event_dispatcher_id,json=tableTriggerEventDispatcherId,proto3" json:"table_trigger_event_dispatcher_id,omitempty"` - IsNewChangefeed bool `protobuf:"varint,5,opt,name=is_new_changefeed,json=isNewChangefeed,proto3" json:"is_new_changefeed,omitempty"` - TableTriggerRedoDispatcherId *DispatcherID `protobuf:"bytes,6,opt,name=table_trigger_redo_dispatcher_id,json=tableTriggerRedoDispatcherId,proto3" json:"table_trigger_redo_dispatcher_id,omitempty"` - KeyspaceId uint32 `protobuf:"varint,7,opt,name=keyspace_id,json=keyspaceId,proto3" json:"keyspace_id,omitempty"` + ChangefeedID *ChangefeedID `protobuf:"bytes,1,opt,name=changefeedID,proto3" json:"changefeedID,omitempty"` + Config []byte `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` + StartTs uint64 `protobuf:"varint,3,opt,name=start_ts,json=startTs,proto3" json:"start_ts,omitempty"` + TableTriggerEventDispatcherId *DispatcherID `protobuf:"bytes,4,opt,name=table_trigger_event_dispatcher_id,json=tableTriggerEventDispatcherId,proto3" json:"table_trigger_event_dispatcher_id,omitempty"` + IsNewChangefeed bool `protobuf:"varint,5,opt,name=is_new_changefeed,json=isNewChangefeed,proto3" json:"is_new_changefeed,omitempty"` + TableTriggerRedoDispatcherId *DispatcherID `protobuf:"bytes,6,opt,name=table_trigger_redo_dispatcher_id,json=tableTriggerRedoDispatcherId,proto3" json:"table_trigger_redo_dispatcher_id,omitempty"` + KeyspaceId uint32 `protobuf:"varint,7,opt,name=keyspace_id,json=keyspaceId,proto3" json:"keyspace_id,omitempty"` + SyncPointControl *SyncPointControl `protobuf:"bytes,8,opt,name=sync_point_control,json=syncPointControl,proto3" json:"sync_point_control,omitempty"` } func (m *MaintainerBootstrapRequest) Reset() { *m = MaintainerBootstrapRequest{} } func (m *MaintainerBootstrapRequest) String() string { return proto.CompactTextString(m) } func (*MaintainerBootstrapRequest) ProtoMessage() {} func (*MaintainerBootstrapRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{27} + return fileDescriptor_6d584080fdadb670, []int{29} } func (m *MaintainerBootstrapRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2086,6 +2207,13 @@ func (m *MaintainerBootstrapRequest) GetKeyspaceId() uint32 { return 0 } +func (m *MaintainerBootstrapRequest) GetSyncPointControl() *SyncPointControl { + if m != nil { + return m.SyncPointControl + } + return nil +} + type MaintainerBootstrapResponse struct { ChangefeedID *ChangefeedID `protobuf:"bytes,1,opt,name=changefeedID,proto3" json:"changefeedID,omitempty"` Spans []*BootstrapTableSpan `protobuf:"bytes,2,rep,name=spans,proto3" json:"spans,omitempty"` @@ -2103,13 +2231,14 @@ type MaintainerBootstrapResponse struct { // It will be used when redo enable. RedoCheckpointTs uint64 `protobuf:"varint,5,opt,name=redo_checkpoint_ts,json=redoCheckpointTs,proto3" json:"redo_checkpoint_ts,omitempty"` Operators []*ScheduleDispatcherRequest `protobuf:"bytes,6,rep,name=operators,proto3" json:"operators,omitempty"` + SyncPointControl *SyncPointControl `protobuf:"bytes,7,opt,name=sync_point_control,json=syncPointControl,proto3" json:"sync_point_control,omitempty"` } func (m *MaintainerBootstrapResponse) Reset() { *m = MaintainerBootstrapResponse{} } func (m *MaintainerBootstrapResponse) String() string { return proto.CompactTextString(m) } func (*MaintainerBootstrapResponse) ProtoMessage() {} func (*MaintainerBootstrapResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{28} + return fileDescriptor_6d584080fdadb670, []int{30} } func (m *MaintainerBootstrapResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2180,6 +2309,13 @@ func (m *MaintainerBootstrapResponse) GetOperators() []*ScheduleDispatcherReques return nil } +func (m *MaintainerBootstrapResponse) GetSyncPointControl() *SyncPointControl { + if m != nil { + return m.SyncPointControl + } + return nil +} + type MaintainerPostBootstrapRequest struct { ChangefeedID *ChangefeedID `protobuf:"bytes,1,opt,name=changefeedID,proto3" json:"changefeedID,omitempty"` TableTriggerEventDispatcherId *DispatcherID `protobuf:"bytes,2,opt,name=table_trigger_event_dispatcher_id,json=tableTriggerEventDispatcherId,proto3" json:"table_trigger_event_dispatcher_id,omitempty"` @@ -2191,7 +2327,7 @@ func (m *MaintainerPostBootstrapRequest) Reset() { *m = MaintainerPostBo func (m *MaintainerPostBootstrapRequest) String() string { return proto.CompactTextString(m) } func (*MaintainerPostBootstrapRequest) ProtoMessage() {} func (*MaintainerPostBootstrapRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{29} + return fileDescriptor_6d584080fdadb670, []int{31} } func (m *MaintainerPostBootstrapRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2258,7 +2394,7 @@ func (m *MaintainerPostBootstrapResponse) Reset() { *m = MaintainerPostB func (m *MaintainerPostBootstrapResponse) String() string { return proto.CompactTextString(m) } func (*MaintainerPostBootstrapResponse) ProtoMessage() {} func (*MaintainerPostBootstrapResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{30} + return fileDescriptor_6d584080fdadb670, []int{32} } func (m *MaintainerPostBootstrapResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2318,7 +2454,7 @@ func (m *SchemaInfo) Reset() { *m = SchemaInfo{} } func (m *SchemaInfo) String() string { return proto.CompactTextString(m) } func (*SchemaInfo) ProtoMessage() {} func (*SchemaInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{31} + return fileDescriptor_6d584080fdadb670, []int{33} } func (m *SchemaInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2377,7 +2513,7 @@ func (m *TableInfo) Reset() { *m = TableInfo{} } func (m *TableInfo) String() string { return proto.CompactTextString(m) } func (*TableInfo) ProtoMessage() {} func (*TableInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{32} + return fileDescriptor_6d584080fdadb670, []int{34} } func (m *TableInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2434,7 +2570,7 @@ func (m *BootstrapTableSpan) Reset() { *m = BootstrapTableSpan{} } func (m *BootstrapTableSpan) String() string { return proto.CompactTextString(m) } func (*BootstrapTableSpan) ProtoMessage() {} func (*BootstrapTableSpan) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{33} + return fileDescriptor_6d584080fdadb670, []int{35} } func (m *BootstrapTableSpan) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2522,7 +2658,7 @@ func (m *MaintainerCloseRequest) Reset() { *m = MaintainerCloseRequest{} func (m *MaintainerCloseRequest) String() string { return proto.CompactTextString(m) } func (*MaintainerCloseRequest) ProtoMessage() {} func (*MaintainerCloseRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{34} + return fileDescriptor_6d584080fdadb670, []int{36} } func (m *MaintainerCloseRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2574,7 +2710,7 @@ func (m *MaintainerCloseResponse) Reset() { *m = MaintainerCloseResponse func (m *MaintainerCloseResponse) String() string { return proto.CompactTextString(m) } func (*MaintainerCloseResponse) ProtoMessage() {} func (*MaintainerCloseResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{35} + return fileDescriptor_6d584080fdadb670, []int{37} } func (m *MaintainerCloseResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2629,7 +2765,7 @@ func (m *InfluencedTables) Reset() { *m = InfluencedTables{} } func (m *InfluencedTables) String() string { return proto.CompactTextString(m) } func (*InfluencedTables) ProtoMessage() {} func (*InfluencedTables) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{36} + return fileDescriptor_6d584080fdadb670, []int{38} } func (m *InfluencedTables) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2689,7 +2825,7 @@ func (m *Table) Reset() { *m = Table{} } func (m *Table) String() string { return proto.CompactTextString(m) } func (*Table) ProtoMessage() {} func (*Table) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{37} + return fileDescriptor_6d584080fdadb670, []int{39} } func (m *Table) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2749,7 +2885,7 @@ func (m *SchemaIDChange) Reset() { *m = SchemaIDChange{} } func (m *SchemaIDChange) String() string { return proto.CompactTextString(m) } func (*SchemaIDChange) ProtoMessage() {} func (*SchemaIDChange) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{38} + return fileDescriptor_6d584080fdadb670, []int{40} } func (m *SchemaIDChange) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2814,7 +2950,7 @@ func (m *State) Reset() { *m = State{} } func (m *State) String() string { return proto.CompactTextString(m) } func (*State) ProtoMessage() {} func (*State) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{39} + return fileDescriptor_6d584080fdadb670, []int{41} } func (m *State) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2909,7 +3045,7 @@ func (m *TableSpanBlockStatus) Reset() { *m = TableSpanBlockStatus{} } func (m *TableSpanBlockStatus) String() string { return proto.CompactTextString(m) } func (*TableSpanBlockStatus) ProtoMessage() {} func (*TableSpanBlockStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{40} + return fileDescriptor_6d584080fdadb670, []int{42} } func (m *TableSpanBlockStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2971,7 +3107,7 @@ func (m *TableSpanStatus) Reset() { *m = TableSpanStatus{} } func (m *TableSpanStatus) String() string { return proto.CompactTextString(m) } func (*TableSpanStatus) ProtoMessage() {} func (*TableSpanStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{41} + return fileDescriptor_6d584080fdadb670, []int{43} } func (m *TableSpanStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3045,7 +3181,7 @@ func (m *BlockStatusRequest) Reset() { *m = BlockStatusRequest{} } func (m *BlockStatusRequest) String() string { return proto.CompactTextString(m) } func (*BlockStatusRequest) ProtoMessage() {} func (*BlockStatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{42} + return fileDescriptor_6d584080fdadb670, []int{44} } func (m *BlockStatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3106,7 +3242,7 @@ func (m *RunningError) Reset() { *m = RunningError{} } func (m *RunningError) String() string { return proto.CompactTextString(m) } func (*RunningError) ProtoMessage() {} func (*RunningError) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{43} + return fileDescriptor_6d584080fdadb670, []int{45} } func (m *RunningError) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3172,7 +3308,7 @@ func (m *DispatcherID) Reset() { *m = DispatcherID{} } func (m *DispatcherID) String() string { return proto.CompactTextString(m) } func (*DispatcherID) ProtoMessage() {} func (*DispatcherID) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{44} + return fileDescriptor_6d584080fdadb670, []int{46} } func (m *DispatcherID) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3226,7 +3362,7 @@ func (m *ChangefeedID) Reset() { *m = ChangefeedID{} } func (m *ChangefeedID) String() string { return proto.CompactTextString(m) } func (*ChangefeedID) ProtoMessage() {} func (*ChangefeedID) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{45} + return fileDescriptor_6d584080fdadb670, []int{47} } func (m *ChangefeedID) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3291,7 +3427,7 @@ func (m *LogCoordinatorResolvedTsRequest) Reset() { *m = LogCoordinatorR func (m *LogCoordinatorResolvedTsRequest) String() string { return proto.CompactTextString(m) } func (*LogCoordinatorResolvedTsRequest) ProtoMessage() {} func (*LogCoordinatorResolvedTsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{46} + return fileDescriptor_6d584080fdadb670, []int{48} } func (m *LogCoordinatorResolvedTsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3336,7 +3472,7 @@ func (m *LogCoordinatorResolvedTsResponse) Reset() { *m = LogCoordinator func (m *LogCoordinatorResolvedTsResponse) String() string { return proto.CompactTextString(m) } func (*LogCoordinatorResolvedTsResponse) ProtoMessage() {} func (*LogCoordinatorResolvedTsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{47} + return fileDescriptor_6d584080fdadb670, []int{49} } func (m *LogCoordinatorResolvedTsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3390,7 +3526,7 @@ func (m *ChecksumMeta) Reset() { *m = ChecksumMeta{} } func (m *ChecksumMeta) String() string { return proto.CompactTextString(m) } func (*ChecksumMeta) ProtoMessage() {} func (*ChecksumMeta) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{48} + return fileDescriptor_6d584080fdadb670, []int{50} } func (m *ChecksumMeta) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3445,7 +3581,7 @@ func (m *DispatcherSetChecksum) Reset() { *m = DispatcherSetChecksum{} } func (m *DispatcherSetChecksum) String() string { return proto.CompactTextString(m) } func (*DispatcherSetChecksum) ProtoMessage() {} func (*DispatcherSetChecksum) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{49} + return fileDescriptor_6d584080fdadb670, []int{51} } func (m *DispatcherSetChecksum) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3522,7 +3658,7 @@ func (m *DispatcherSetChecksumAckResponse) Reset() { *m = DispatcherSetC func (m *DispatcherSetChecksumAckResponse) String() string { return proto.CompactTextString(m) } func (*DispatcherSetChecksumAckResponse) ProtoMessage() {} func (*DispatcherSetChecksumAckResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{50} + return fileDescriptor_6d584080fdadb670, []int{52} } func (m *DispatcherSetChecksumAckResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3593,7 +3729,7 @@ func (m *DispatcherSetChecksumUpdateRequest) Reset() { *m = DispatcherSe func (m *DispatcherSetChecksumUpdateRequest) String() string { return proto.CompactTextString(m) } func (*DispatcherSetChecksumUpdateRequest) ProtoMessage() {} func (*DispatcherSetChecksumUpdateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6d584080fdadb670, []int{51} + return fileDescriptor_6d584080fdadb670, []int{53} } func (m *DispatcherSetChecksumUpdateRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3676,6 +3812,8 @@ func init() { proto.RegisterType((*DispatcherStatus)(nil), "heartbeatpb.DispatcherStatus") proto.RegisterType((*HeartBeatResponse)(nil), "heartbeatpb.HeartBeatResponse") proto.RegisterType((*CheckpointTsMessage)(nil), "heartbeatpb.CheckpointTsMessage") + proto.RegisterType((*SyncPointControl)(nil), "heartbeatpb.SyncPointControl") + proto.RegisterType((*SyncPointControlMessage)(nil), "heartbeatpb.SyncPointControlMessage") proto.RegisterType((*RedoMetaMessage)(nil), "heartbeatpb.RedoMetaMessage") proto.RegisterType((*RedoResolvedTsProgressMessage)(nil), "heartbeatpb.RedoResolvedTsProgressMessage") proto.RegisterType((*RedoResolvedTsForwardMessage)(nil), "heartbeatpb.RedoResolvedTsForwardMessage") @@ -3723,180 +3861,187 @@ func init() { func init() { proto.RegisterFile("heartbeatpb/heartbeat.proto", fileDescriptor_6d584080fdadb670) } var fileDescriptor_6d584080fdadb670 = []byte{ - // 2768 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5a, 0xcd, 0x8f, 0x1c, 0x47, - 0x15, 0x77, 0xf7, 0x7c, 0xed, 0xbc, 0xd9, 0x59, 0xb7, 0xcb, 0xf6, 0x7a, 0x63, 0xaf, 0xd7, 0x9b, - 0x26, 0xa0, 0x65, 0x13, 0x6c, 0xec, 0xc4, 0x7c, 0x84, 0x90, 0x30, 0x9e, 0x71, 0xe2, 0x91, 0xbd, - 0x1f, 0xaa, 0xd9, 0x60, 0x08, 0x87, 0xa1, 0xb7, 0xbb, 0x3c, 0xdb, 0xd9, 0x99, 0xae, 0x76, 0x77, - 0x8f, 0xd7, 0xb6, 0x14, 0x10, 0x8a, 0xb8, 0x71, 0x00, 0x09, 0x24, 0x38, 0x70, 0x40, 0xfc, 0x03, - 0x48, 0x88, 0x23, 0x77, 0x24, 0x2e, 0x39, 0xa1, 0x70, 0x02, 0x25, 0x77, 0x84, 0xe0, 0xc0, 0x15, - 0xd5, 0x47, 0x77, 0x57, 0x7f, 0xec, 0xae, 0xad, 0x1d, 0xf9, 0x56, 0xaf, 0xfa, 0xf7, 0x5e, 0xbd, - 0x7a, 0xf5, 0xea, 0xd5, 0xab, 0x57, 0x0d, 0x97, 0xf6, 0x88, 0x15, 0x44, 0xbb, 0xc4, 0x8a, 0xfc, - 0xdd, 0x6b, 0x49, 0xfb, 0xaa, 0x1f, 0xd0, 0x88, 0xa2, 0x96, 0xf2, 0xd1, 0x7c, 0x02, 0xcd, 0x1d, - 0x6b, 0x77, 0x4c, 0x06, 0xbe, 0xe5, 0xa1, 0x25, 0x68, 0x70, 0xa2, 0xdf, 0x5b, 0xd2, 0x56, 0xb5, - 0xb5, 0x0a, 0x8e, 0x49, 0x74, 0x11, 0xe6, 0x06, 0x91, 0x15, 0x44, 0x77, 0xc9, 0x93, 0x25, 0x7d, - 0x55, 0x5b, 0x9b, 0xc7, 0x09, 0x8d, 0x16, 0xa1, 0x7e, 0xdb, 0x73, 0xd8, 0x97, 0x0a, 0xff, 0x22, - 0x29, 0xb4, 0x02, 0x70, 0x97, 0x3c, 0x09, 0x7d, 0xcb, 0x66, 0x02, 0xab, 0xab, 0xda, 0x5a, 0x1b, - 0x2b, 0x3d, 0xe6, 0xdf, 0x74, 0x30, 0xee, 0x30, 0x55, 0x6e, 0x11, 0x2b, 0xc2, 0xe4, 0xe1, 0x94, - 0x84, 0x11, 0xfa, 0x36, 0xcc, 0xdb, 0x7b, 0x96, 0x37, 0x22, 0x0f, 0x08, 0x71, 0xa4, 0x1e, 0xad, - 0x1b, 0x2f, 0x5d, 0x55, 0x74, 0xbe, 0xda, 0x55, 0x00, 0x38, 0x03, 0x47, 0x6f, 0x40, 0xf3, 0xc0, - 0x8a, 0x48, 0x30, 0xb1, 0x82, 0x7d, 0xae, 0x68, 0xeb, 0xc6, 0x62, 0x86, 0xf7, 0x7e, 0xfc, 0x15, - 0xa7, 0x40, 0xf4, 0x16, 0xb4, 0x03, 0xe2, 0xd0, 0xe4, 0x1b, 0x9f, 0xc8, 0xe1, 0x9c, 0x59, 0x30, - 0xfa, 0x06, 0xcc, 0x85, 0x91, 0x15, 0x4d, 0x43, 0x12, 0x2e, 0x55, 0x57, 0x2b, 0x6b, 0xad, 0x1b, - 0xcb, 0x19, 0xc6, 0xc4, 0xbe, 0x03, 0x8e, 0xc2, 0x09, 0x1a, 0xad, 0xc1, 0x69, 0x9b, 0x4e, 0x7c, - 0x32, 0x26, 0x11, 0x11, 0x1f, 0x97, 0x6a, 0xab, 0xda, 0xda, 0x1c, 0xce, 0x77, 0xa3, 0x57, 0xa1, - 0x42, 0x82, 0x60, 0xa9, 0x5e, 0x62, 0x0d, 0x3c, 0xf5, 0x3c, 0xd7, 0x1b, 0xdd, 0x0e, 0x02, 0x1a, - 0x60, 0x86, 0x32, 0x7f, 0xaa, 0x41, 0x33, 0x55, 0xcf, 0x64, 0x16, 0x25, 0xf6, 0xbe, 0x4f, 0x5d, - 0x2f, 0xda, 0x09, 0xb9, 0x45, 0xab, 0x38, 0xd3, 0xc7, 0x96, 0x2a, 0x20, 0x21, 0x1d, 0x3f, 0x22, - 0xce, 0x4e, 0xc8, 0xed, 0x56, 0xc5, 0x4a, 0x0f, 0x32, 0xa0, 0x12, 0x92, 0x87, 0xdc, 0x2c, 0x55, - 0xcc, 0x9a, 0x4c, 0xea, 0xd8, 0x0a, 0xa3, 0xc1, 0x13, 0xcf, 0xe6, 0x3c, 0x55, 0x21, 0x55, 0xed, - 0x33, 0x3f, 0x02, 0xa3, 0xe7, 0x86, 0xbe, 0x15, 0xd9, 0x7b, 0x24, 0xe8, 0xd8, 0x91, 0x4b, 0x3d, - 0xf4, 0x2a, 0xd4, 0x2d, 0xde, 0xe2, 0x7a, 0x2c, 0xdc, 0x38, 0x9b, 0x99, 0x8b, 0x00, 0x61, 0x09, - 0x61, 0x5e, 0xd7, 0xa5, 0x93, 0x89, 0x1b, 0x25, 0x4a, 0x25, 0x34, 0x5a, 0x85, 0x56, 0x3f, 0x64, - 0x43, 0x6d, 0xb3, 0x39, 0x70, 0xd5, 0xe6, 0xb0, 0xda, 0x65, 0x76, 0xa1, 0xd2, 0xe9, 0xde, 0xcd, - 0x08, 0xd1, 0x8e, 0x16, 0xa2, 0x17, 0x85, 0x60, 0x40, 0xfd, 0x91, 0x47, 0x03, 0xe2, 0xdc, 0x1a, - 0x53, 0x7b, 0x5f, 0x2e, 0xc7, 0xc9, 0x64, 0x7e, 0xac, 0xc3, 0xf9, 0xbe, 0xf7, 0x60, 0x3c, 0x25, - 0xcc, 0x50, 0xa9, 0x89, 0x42, 0xf4, 0x1d, 0x68, 0x27, 0x1f, 0x76, 0x9e, 0xf8, 0x44, 0x1a, 0xe9, - 0x62, 0xc6, 0x48, 0x19, 0x04, 0xce, 0x32, 0xa0, 0x77, 0xa0, 0x9d, 0x0a, 0xec, 0xf7, 0x98, 0xdd, - 0x2a, 0x05, 0x97, 0x51, 0x11, 0x38, 0x8b, 0xe7, 0x3b, 0xdd, 0xde, 0x23, 0x13, 0xab, 0xdf, 0xe3, - 0x46, 0xad, 0xe0, 0x84, 0x46, 0x77, 0xe1, 0x2c, 0x79, 0x6c, 0x8f, 0xa7, 0x0e, 0x51, 0x78, 0x1c, - 0xbe, 0xf6, 0x47, 0x0e, 0x51, 0xc6, 0x65, 0xfe, 0x5a, 0x57, 0xdd, 0x43, 0x1a, 0xf6, 0x7b, 0x70, - 0xde, 0x2d, 0xb3, 0x8c, 0x8c, 0x03, 0x66, 0xb9, 0x21, 0x54, 0x24, 0x2e, 0x17, 0x80, 0x6e, 0x26, - 0x8e, 0x27, 0xc2, 0xc2, 0xe5, 0x43, 0xd4, 0xcd, 0xb9, 0xa0, 0x09, 0x15, 0xcb, 0x8e, 0x03, 0x82, - 0x91, 0x75, 0xd6, 0xee, 0x5d, 0xcc, 0x3e, 0xa2, 0x2d, 0x40, 0x6e, 0xc1, 0x47, 0xa4, 0x55, 0xae, - 0x64, 0x35, 0x2e, 0xc0, 0x70, 0x09, 0xab, 0xf9, 0x27, 0x0d, 0xce, 0x28, 0x91, 0x31, 0xf4, 0xa9, - 0x17, 0x92, 0x93, 0x86, 0xc6, 0x0d, 0x40, 0x4e, 0xce, 0xdc, 0x24, 0x76, 0x8f, 0xc3, 0x8c, 0x11, - 0xeb, 0x58, 0x64, 0x44, 0x08, 0xaa, 0x13, 0xea, 0x10, 0xe9, 0x23, 0xbc, 0x6d, 0x3e, 0x86, 0xb3, - 0x5d, 0x25, 0xac, 0x6c, 0x90, 0x30, 0xb4, 0x46, 0x27, 0x56, 0x3c, 0x1f, 0xc0, 0xf4, 0x62, 0x00, - 0x33, 0x7f, 0xa9, 0xc1, 0x69, 0x4c, 0x1c, 0xba, 0x41, 0x22, 0x6b, 0x46, 0xc3, 0x1e, 0x17, 0x13, - 0xf3, 0x6a, 0x55, 0x4a, 0xd4, 0xfa, 0x11, 0x5c, 0x66, 0x5a, 0xe1, 0x84, 0x6b, 0x3b, 0xa0, 0xa3, - 0x80, 0x84, 0xe1, 0x8b, 0xd1, 0xd1, 0xfc, 0x08, 0x96, 0xb3, 0xe3, 0xbf, 0x4b, 0x83, 0x03, 0x2b, - 0x70, 0x5e, 0xd0, 0xf0, 0xff, 0xd5, 0xd4, 0x2d, 0xde, 0xa5, 0xde, 0x03, 0x77, 0x84, 0xd6, 0xa1, - 0x1a, 0xfa, 0x96, 0x27, 0xc7, 0x5a, 0x2c, 0x3f, 0x2a, 0x31, 0xc7, 0xb0, 0x84, 0x24, 0x64, 0x69, - 0x46, 0x22, 0x3d, 0x26, 0x99, 0xe6, 0x8e, 0x12, 0x62, 0xe4, 0x06, 0x3d, 0x22, 0x06, 0x65, 0xe0, - 0x2c, 0xca, 0x85, 0x71, 0x94, 0xab, 0x8a, 0x28, 0x17, 0xd3, 0x89, 0x67, 0xd7, 0x52, 0xcf, 0x46, - 0xeb, 0x60, 0x84, 0xfb, 0xae, 0xdf, 0xdb, 0xb8, 0xd7, 0x09, 0x07, 0x52, 0xa3, 0x3a, 0x8f, 0xec, - 0x85, 0x7e, 0xf3, 0x57, 0x3a, 0xbc, 0xc4, 0x42, 0xa6, 0x33, 0x1d, 0x2b, 0x11, 0x6f, 0x46, 0x09, - 0xce, 0x4d, 0xa8, 0xdb, 0xdc, 0x8e, 0xc7, 0x84, 0x31, 0x61, 0x6c, 0x2c, 0xc1, 0xa8, 0x0b, 0x0b, - 0xa1, 0x54, 0x49, 0x04, 0x38, 0x6e, 0xb0, 0x85, 0x1b, 0x97, 0x32, 0xec, 0x83, 0x0c, 0x04, 0xe7, - 0x58, 0x98, 0xea, 0xd4, 0x27, 0x81, 0x15, 0xd1, 0x80, 0x1f, 0x4e, 0x55, 0x2e, 0x22, 0xab, 0xfa, - 0x96, 0x02, 0xc0, 0x19, 0xb8, 0xf9, 0x3f, 0x0d, 0x16, 0x37, 0x48, 0x30, 0x9a, 0xbd, 0x51, 0xde, - 0x81, 0xb6, 0xf3, 0x9c, 0x87, 0x5e, 0x06, 0x8f, 0xfa, 0x80, 0x26, 0x4c, 0x33, 0xa7, 0xf7, 0x5c, - 0x3e, 0x55, 0xc2, 0x94, 0x78, 0x4f, 0x55, 0x89, 0x8b, 0xdb, 0x70, 0x76, 0xc3, 0x72, 0xbd, 0xc8, - 0x72, 0x3d, 0x12, 0xdc, 0x89, 0xa5, 0xa1, 0x6f, 0x2a, 0x89, 0xa3, 0x56, 0x12, 0x87, 0x53, 0x9e, - 0x7c, 0xe6, 0x68, 0x7e, 0xaa, 0x41, 0xbb, 0x17, 0x58, 0xae, 0x17, 0x07, 0x14, 0xf4, 0x0a, 0x2c, - 0x44, 0x56, 0x30, 0x22, 0xd1, 0xd0, 0xa3, 0x0e, 0x19, 0xba, 0x0e, 0x37, 0x62, 0x13, 0xcf, 0x8b, - 0xde, 0x4d, 0xea, 0x90, 0xbe, 0x83, 0x5e, 0x06, 0x49, 0x0f, 0x89, 0x4f, 0xed, 0x3d, 0xb9, 0xab, - 0x5a, 0xa2, 0xef, 0x36, 0xeb, 0x42, 0x5f, 0x83, 0x0b, 0x12, 0x92, 0xda, 0x68, 0x68, 0xd3, 0xa9, - 0x4c, 0xb2, 0xda, 0xf8, 0xbc, 0xf8, 0xac, 0xfa, 0xda, 0xd4, 0x8b, 0xd0, 0xbb, 0xb0, 0x2a, 0xf9, - 0xd8, 0x01, 0xec, 0x8e, 0xf6, 0xa2, 0xa1, 0xc3, 0x34, 0x1c, 0x4e, 0xe8, 0x23, 0x22, 0x05, 0x88, - 0x4b, 0xc0, 0xb2, 0xc0, 0xf5, 0x25, 0x8c, 0xcf, 0x63, 0x83, 0x3e, 0x22, 0x5c, 0x8e, 0xf9, 0x71, - 0x05, 0x8c, 0xfc, 0xcc, 0x4f, 0xea, 0x20, 0x97, 0x01, 0x58, 0x6b, 0xc8, 0xec, 0x47, 0xf8, 0xa4, - 0x9b, 0xb8, 0xc9, 0x7a, 0x98, 0x78, 0x82, 0xae, 0x43, 0x4d, 0x7c, 0x29, 0xdb, 0x14, 0x5d, 0x3a, - 0xf1, 0xa9, 0x47, 0xbc, 0x88, 0x63, 0xb1, 0x40, 0xa2, 0x2f, 0x40, 0x3b, 0x8d, 0xf4, 0xc3, 0x28, - 0x49, 0x80, 0x33, 0x69, 0xb5, 0xcc, 0xda, 0x6b, 0x25, 0xde, 0x58, 0xc8, 0xda, 0xd1, 0x17, 0x61, - 0x61, 0x97, 0xd2, 0x28, 0x8c, 0x02, 0xcb, 0x1f, 0x3a, 0xd4, 0x23, 0x32, 0xc0, 0xb4, 0x93, 0xde, - 0x1e, 0xf5, 0x48, 0x21, 0xf1, 0x6e, 0x14, 0x13, 0x6f, 0xd4, 0x81, 0x05, 0x61, 0x7a, 0x5f, 0x7a, - 0xc7, 0xd2, 0x1c, 0xb7, 0x57, 0x36, 0x8f, 0xcc, 0xf8, 0x0f, 0x6e, 0x3b, 0x2a, 0x69, 0xfe, 0x4b, - 0x83, 0x36, 0xf3, 0x99, 0xd4, 0x5b, 0x6f, 0xc2, 0xdc, 0xd8, 0x7d, 0x44, 0x3c, 0x26, 0x4e, 0x2b, - 0xd9, 0xf9, 0x0c, 0x7d, 0x4f, 0x02, 0x70, 0x02, 0x65, 0xa6, 0xe7, 0x0e, 0xa9, 0xfa, 0x5b, 0x93, - 0xf5, 0x08, 0x6f, 0xeb, 0xc1, 0x15, 0xc5, 0xcd, 0x84, 0xd6, 0x39, 0x3f, 0xae, 0xf0, 0xe5, 0xba, - 0x94, 0xc2, 0xb8, 0xe2, 0x3b, 0xaa, 0x5b, 0x77, 0xe0, 0xf2, 0x61, 0x52, 0xc4, 0xb8, 0x62, 0x75, - 0x2e, 0x96, 0xca, 0xe0, 0x8a, 0x98, 0x1f, 0xc2, 0xe2, 0x40, 0xc8, 0x4b, 0x26, 0x21, 0x83, 0xd3, - 0x75, 0xa8, 0x0b, 0x59, 0xc7, 0x4f, 0x5b, 0x02, 0x8f, 0x99, 0xb4, 0x39, 0x81, 0x0b, 0x85, 0xb1, - 0x64, 0x92, 0xf7, 0x3a, 0x34, 0x2c, 0xdf, 0x1f, 0xbb, 0xc4, 0x39, 0x7e, 0xb4, 0x18, 0x79, 0xdc, - 0x70, 0x1f, 0xc2, 0x95, 0x81, 0xba, 0x5f, 0x95, 0xb9, 0xc7, 0x73, 0x9c, 0x55, 0xf4, 0x30, 0xbf, - 0x0e, 0x97, 0xba, 0x94, 0x06, 0x8e, 0xeb, 0xb1, 0xb8, 0x7f, 0x2b, 0x76, 0xdd, 0x78, 0x9c, 0x25, - 0x68, 0x3c, 0x22, 0x41, 0x18, 0xdf, 0xff, 0x2a, 0x38, 0x26, 0xcd, 0xef, 0xc3, 0x72, 0x39, 0xa3, - 0x34, 0xcc, 0x09, 0x82, 0xe5, 0x5f, 0x35, 0x38, 0xd7, 0x71, 0x9c, 0x14, 0x11, 0x6b, 0xf3, 0x65, - 0xd0, 0xe5, 0x4c, 0x8f, 0x8c, 0x25, 0xba, 0xeb, 0xa0, 0xc5, 0xcc, 0xb9, 0x3b, 0x9f, 0x1c, 0xac, - 0x85, 0x38, 0x50, 0x92, 0x06, 0xa2, 0x75, 0x38, 0xe3, 0x86, 0x43, 0x8f, 0x1c, 0x0c, 0xd3, 0xa8, - 0xc4, 0x5d, 0x72, 0x0e, 0x9f, 0x76, 0xc3, 0x4d, 0x72, 0x90, 0x0e, 0x87, 0xae, 0x40, 0x6b, 0x5f, - 0xd6, 0x48, 0xd8, 0x32, 0xd4, 0x44, 0xd9, 0x24, 0xee, 0xea, 0x3b, 0xe6, 0x6f, 0x34, 0xb8, 0x80, - 0x09, 0x0b, 0xaa, 0x27, 0x9a, 0xd0, 0x12, 0x34, 0x6c, 0x2b, 0xb4, 0x2d, 0x87, 0xc8, 0x2b, 0x6a, - 0x4c, 0xb2, 0x2f, 0x01, 0x97, 0xef, 0xc8, 0x5b, 0x75, 0x4c, 0xe6, 0x75, 0xab, 0x16, 0x74, 0xfb, - 0x7d, 0x05, 0x2e, 0xa6, 0x5a, 0x15, 0x56, 0xff, 0x84, 0x51, 0xfc, 0xb0, 0x35, 0x78, 0x89, 0xbb, - 0x46, 0xa0, 0x98, 0x3f, 0x49, 0x13, 0x6d, 0x78, 0x39, 0x62, 0x39, 0xe5, 0x30, 0x0a, 0xdc, 0xd1, - 0x88, 0x04, 0x43, 0xf2, 0x88, 0x78, 0x99, 0x93, 0xcd, 0x7d, 0x86, 0xfb, 0xeb, 0x65, 0x2e, 0x63, - 0x47, 0x88, 0xb8, 0xcd, 0x24, 0xa8, 0x37, 0xd9, 0xf2, 0xe5, 0xad, 0x95, 0x2f, 0xaf, 0xc5, 0x4e, - 0x49, 0x55, 0xa1, 0x80, 0x38, 0x34, 0xa7, 0x4f, 0xfd, 0x38, 0x7d, 0x96, 0x55, 0x7d, 0x58, 0x82, - 0x9f, 0x51, 0x27, 0xb7, 0x4a, 0x8d, 0xc2, 0x2a, 0xfd, 0x5d, 0x87, 0x4b, 0xa5, 0xab, 0x34, 0x9b, - 0x8b, 0xe6, 0x4d, 0xa8, 0xb1, 0xe4, 0x3d, 0xce, 0xc2, 0xb2, 0x37, 0xe0, 0x64, 0xb4, 0x34, 0xd5, - 0x17, 0xe8, 0xf8, 0xb0, 0xac, 0x3c, 0x4b, 0x89, 0xeb, 0xd9, 0x8e, 0xdf, 0xd7, 0x00, 0x71, 0xeb, - 0x66, 0x91, 0x35, 0x8e, 0x34, 0xd8, 0x17, 0xf5, 0xb2, 0x8a, 0x7a, 0xd0, 0x8c, 0xd3, 0x55, 0x96, - 0xdb, 0x33, 0xd5, 0xbf, 0x54, 0x9a, 0x1d, 0x17, 0xd2, 0x57, 0x9c, 0x32, 0x9a, 0x7f, 0xd4, 0x61, - 0x25, 0xb5, 0xed, 0x36, 0x0d, 0xa3, 0x59, 0xef, 0x82, 0x67, 0x72, 0x69, 0xfd, 0x84, 0x2e, 0x7d, - 0x1d, 0x1a, 0xe2, 0x3e, 0xc4, 0x76, 0x14, 0x33, 0xc5, 0x85, 0x82, 0x29, 0x26, 0x56, 0xdf, 0x7b, - 0x40, 0x71, 0x8c, 0x43, 0x6f, 0xc2, 0x3c, 0xb7, 0x76, 0xcc, 0x57, 0x3d, 0x9a, 0xaf, 0xc5, 0xc0, - 0x82, 0x0e, 0xcd, 0xff, 0x68, 0x70, 0xe5, 0x50, 0xab, 0xcd, 0xc6, 0x2b, 0x5f, 0x88, 0xd9, 0x9e, - 0xc7, 0x87, 0xcd, 0xc7, 0x00, 0xa9, 0x3d, 0x32, 0x75, 0x37, 0x2d, 0x57, 0x77, 0x5b, 0x89, 0x91, - 0x9b, 0xd6, 0x24, 0x4e, 0x5f, 0x95, 0x1e, 0x74, 0x15, 0xea, 0x7c, 0x3b, 0xc5, 0x8b, 0x55, 0x72, - 0xa9, 0xe6, 0x36, 0x97, 0x28, 0xb3, 0x2b, 0x8b, 0xfe, 0x7c, 0xe0, 0xc3, 0x8b, 0xfe, 0xcb, 0x12, - 0xa6, 0x8c, 0x9a, 0x76, 0x98, 0x7f, 0xd6, 0x01, 0x15, 0x77, 0x33, 0x3b, 0x82, 0x0e, 0x59, 0x9c, - 0x8c, 0x21, 0x75, 0xf9, 0xa8, 0x10, 0x4f, 0x59, 0xcf, 0x4d, 0x39, 0xae, 0x12, 0x54, 0x9e, 0xa1, - 0x4a, 0xf0, 0x2e, 0x18, 0x76, 0x9c, 0xa4, 0x0f, 0xc3, 0xb4, 0xfa, 0x76, 0x4c, 0x26, 0x7f, 0xda, - 0x56, 0xe9, 0x69, 0x58, 0x0c, 0x2a, 0xb5, 0x92, 0xa0, 0xf2, 0x3a, 0xb4, 0x76, 0xc7, 0xd4, 0xde, - 0x97, 0x77, 0x09, 0x11, 0xab, 0x51, 0xd6, 0xcb, 0xb9, 0x78, 0xd8, 0x8d, 0x2b, 0x7a, 0x24, 0xb9, - 0x14, 0x36, 0x94, 0x4b, 0xe1, 0x43, 0x58, 0x4c, 0x5d, 0xbe, 0x3b, 0xa6, 0x21, 0x99, 0x51, 0x80, - 0x50, 0xce, 0x6f, 0x3d, 0x73, 0x7e, 0x9b, 0x01, 0x5c, 0x28, 0x0c, 0x39, 0x9b, 0xdd, 0xb5, 0x04, - 0x8d, 0x70, 0x6a, 0xdb, 0xec, 0x6e, 0x20, 0xc7, 0x94, 0xa4, 0xf9, 0x33, 0x0d, 0x8c, 0xb4, 0x50, - 0x2b, 0x1c, 0x70, 0x06, 0x75, 0xee, 0x8b, 0x30, 0x27, 0xdd, 0x54, 0x9c, 0x33, 0x15, 0x9c, 0xd0, - 0x47, 0x95, 0xb0, 0xcd, 0x1f, 0x40, 0x8d, 0xe3, 0x8e, 0x79, 0xeb, 0x3a, 0xcc, 0x2d, 0x97, 0xa1, - 0x39, 0xf0, 0xc7, 0x2e, 0x8f, 0x02, 0x32, 0x3b, 0x4a, 0x3b, 0x4c, 0x0f, 0x16, 0x62, 0xa4, 0xb0, - 0xd5, 0x11, 0xa3, 0xac, 0x42, 0x6b, 0x6b, 0xec, 0xe4, 0x06, 0x52, 0xbb, 0x18, 0x62, 0x93, 0x1c, - 0xe4, 0x66, 0xa2, 0x76, 0x99, 0xbf, 0xab, 0x40, 0x4d, 0x38, 0xd8, 0x32, 0x34, 0xfb, 0x21, 0x2f, - 0x21, 0xcb, 0x8b, 0xc3, 0x1c, 0x4e, 0x3b, 0x98, 0x16, 0xbc, 0x99, 0x96, 0xd1, 0x24, 0x89, 0xde, - 0x81, 0x96, 0x68, 0xc6, 0xe1, 0xa3, 0x58, 0x53, 0xca, 0x2f, 0x1e, 0x56, 0x39, 0xd0, 0x5d, 0x38, - 0xb3, 0x49, 0x88, 0xd3, 0x0b, 0xa8, 0xef, 0xc7, 0x08, 0x99, 0x50, 0x1d, 0x23, 0xa6, 0xc8, 0x87, - 0xde, 0x82, 0xd3, 0xac, 0xb3, 0xe3, 0x38, 0x89, 0x28, 0x71, 0x77, 0x46, 0xc5, 0xfd, 0x8f, 0xf3, - 0x50, 0xd4, 0x85, 0x85, 0xf7, 0x7d, 0xc7, 0x8a, 0x88, 0x34, 0x61, 0x7c, 0x8a, 0x5f, 0x2a, 0x3b, - 0x82, 0xe4, 0x02, 0xe1, 0x1c, 0x4b, 0xfe, 0xf5, 0xa6, 0x51, 0x78, 0xbd, 0x41, 0x5f, 0xe1, 0xc5, - 0x82, 0x11, 0xe1, 0x77, 0xea, 0x85, 0xdc, 0x01, 0x17, 0x57, 0xf1, 0x47, 0xa2, 0x50, 0x30, 0x22, - 0xe6, 0x8f, 0xe1, 0x5c, 0x12, 0xaf, 0xd4, 0x27, 0xa4, 0xe7, 0x88, 0x93, 0x6b, 0x71, 0x79, 0x42, - 0x3f, 0x34, 0xd8, 0xc8, 0xaa, 0x44, 0x59, 0x51, 0xfe, 0xdf, 0x1a, 0x9c, 0xce, 0x3d, 0x41, 0x3e, - 0xcf, 0xe0, 0x65, 0xc1, 0x55, 0x9f, 0x45, 0x70, 0x2d, 0xbb, 0x28, 0x5d, 0x87, 0xf3, 0xe2, 0x58, - 0x0e, 0xdd, 0xa7, 0x64, 0xe8, 0x93, 0x60, 0x18, 0x12, 0x9b, 0x7a, 0x22, 0x45, 0xd7, 0x31, 0xe2, - 0x1f, 0x07, 0xee, 0x53, 0xb2, 0x4d, 0x82, 0x01, 0xff, 0x52, 0x56, 0xad, 0x35, 0xff, 0xa0, 0x01, - 0x52, 0xdf, 0x58, 0x66, 0x13, 0x57, 0xdf, 0x83, 0xf6, 0x6e, 0x2a, 0x34, 0x79, 0x3b, 0x79, 0xb9, - 0xfc, 0x6c, 0x52, 0xc7, 0xcf, 0xf2, 0x95, 0xae, 0x92, 0x03, 0xf3, 0x6a, 0x86, 0xc0, 0x30, 0x91, - 0x3b, 0x21, 0xf2, 0x1a, 0xce, 0xdb, 0xac, 0x8f, 0xdd, 0xce, 0xe5, 0x51, 0xcc, 0xdb, 0xac, 0xcf, - 0x8e, 0x65, 0x35, 0x31, 0x6f, 0xb3, 0xed, 0x3e, 0x11, 0x05, 0x7e, 0x6e, 0xb7, 0x26, 0x8e, 0x49, - 0xf3, 0x0d, 0x98, 0xcf, 0x17, 0x2b, 0xf7, 0xdc, 0xd1, 0x9e, 0x7c, 0xc3, 0xe4, 0x6d, 0x64, 0x40, - 0x65, 0x4c, 0x0f, 0x64, 0xa0, 0x60, 0x4d, 0xa6, 0x9b, 0x6a, 0x96, 0x67, 0xe3, 0xe2, 0xda, 0xb2, - 0xc4, 0x41, 0x6a, 0xc6, 0xda, 0x2c, 0xb4, 0xc6, 0xf7, 0x10, 0xa9, 0x5a, 0x42, 0x9b, 0x3f, 0x84, - 0x2b, 0xf7, 0xe8, 0x48, 0xa9, 0x01, 0xa4, 0xaf, 0x16, 0xb3, 0x59, 0x40, 0xf3, 0x27, 0x1a, 0xac, - 0x1e, 0x3e, 0xc4, 0x6c, 0x0e, 0xc2, 0xe3, 0x9e, 0x44, 0xc6, 0xcc, 0x96, 0xc4, 0xde, 0x0f, 0xa7, - 0x93, 0x0d, 0x12, 0x59, 0xe8, 0xab, 0xf1, 0xde, 0x2e, 0x3b, 0x01, 0x63, 0x64, 0x66, 0x8f, 0xaf, - 0x83, 0x61, 0xab, 0xfd, 0x03, 0xf2, 0x50, 0x8e, 0x53, 0xe8, 0x37, 0x7f, 0xa1, 0xc1, 0x79, 0xe5, - 0x35, 0x8f, 0x44, 0xb1, 0x44, 0x74, 0x0e, 0x6a, 0xa2, 0x24, 0x2b, 0x16, 0x51, 0x10, 0xcc, 0x73, - 0x1e, 0xd3, 0xe0, 0x0e, 0x5b, 0x5c, 0x79, 0x50, 0x48, 0x92, 0xdd, 0xbd, 0x1f, 0xd3, 0xe0, 0x1e, - 0x3d, 0x90, 0xfb, 0x56, 0x52, 0xe2, 0xe0, 0x9f, 0x70, 0x8e, 0xaa, 0xbc, 0x7a, 0x0b, 0x92, 0x71, - 0x84, 0xd3, 0x09, 0xe3, 0x10, 0x69, 0x94, 0xa4, 0xcc, 0xdf, 0x6a, 0xb0, 0x5a, 0xaa, 0x53, 0xc7, - 0xde, 0x9f, 0xd5, 0x2a, 0x9c, 0x83, 0x9a, 0x5a, 0xa1, 0x12, 0x44, 0xd9, 0xbe, 0x8b, 0xff, 0x6c, - 0xa8, 0x26, 0x7f, 0x36, 0x98, 0xff, 0xd0, 0xc0, 0x2c, 0xd5, 0x4f, 0x9c, 0x14, 0x33, 0x0a, 0x26, - 0x27, 0xd0, 0x10, 0xbd, 0x0d, 0x73, 0xf1, 0x4a, 0x73, 0xdb, 0xe6, 0xdf, 0xc5, 0x4b, 0xb5, 0xc7, - 0x09, 0xcf, 0xfa, 0x65, 0xa8, 0xcb, 0x17, 0x9d, 0x26, 0xd4, 0xee, 0x07, 0x6e, 0x44, 0x8c, 0x53, - 0x68, 0x0e, 0xaa, 0xdb, 0x56, 0x18, 0x1a, 0xda, 0xfa, 0x9a, 0xc8, 0x62, 0x94, 0x87, 0x1f, 0x80, - 0x7a, 0x37, 0x20, 0x16, 0xc7, 0x01, 0xd4, 0x45, 0xf5, 0xc9, 0xd0, 0xd6, 0x37, 0x60, 0x5e, 0x7d, - 0xef, 0x61, 0xe2, 0xb6, 0x86, 0x1d, 0xc7, 0x31, 0x4e, 0xa1, 0x79, 0x98, 0xdb, 0x1a, 0xc6, 0x40, - 0xc6, 0xb4, 0x35, 0xdc, 0x60, 0x6d, 0x1d, 0xb5, 0xa0, 0xb1, 0x35, 0xe4, 0x39, 0x93, 0x51, 0x11, - 0x04, 0x7f, 0x14, 0x32, 0xaa, 0xeb, 0x37, 0x61, 0x5e, 0xad, 0x6f, 0x32, 0x71, 0x9d, 0x7b, 0xfd, - 0xef, 0xde, 0x16, 0xe2, 0x7a, 0xb8, 0xd3, 0xdf, 0xec, 0x6f, 0xbe, 0x67, 0x68, 0x8c, 0x1a, 0xec, - 0x6c, 0x6d, 0x6f, 0x33, 0x4a, 0x5f, 0x7f, 0x13, 0x20, 0x3d, 0x76, 0xd9, 0x3c, 0x36, 0xb7, 0x36, - 0x19, 0x4f, 0x0b, 0x1a, 0xf7, 0x3b, 0xfd, 0x1d, 0xc1, 0xc2, 0x08, 0x2c, 0x08, 0x9d, 0x61, 0x7a, - 0x0c, 0x53, 0x59, 0x7f, 0x2d, 0x97, 0x88, 0xa2, 0x06, 0x54, 0x3a, 0xe3, 0xb1, 0x71, 0x0a, 0xd5, - 0x41, 0xef, 0xdd, 0x12, 0xaa, 0x6f, 0xd2, 0x60, 0x62, 0x8d, 0x0d, 0x7d, 0xfd, 0x29, 0x2c, 0x64, - 0x8f, 0x39, 0x2e, 0x96, 0x06, 0xfb, 0xae, 0x37, 0x12, 0x03, 0x0e, 0x22, 0x9e, 0xcf, 0x88, 0x01, - 0xc5, 0xf4, 0x1d, 0x43, 0x47, 0x06, 0xcc, 0xf7, 0x3d, 0x37, 0x72, 0xad, 0xb1, 0xfb, 0x94, 0x61, - 0x2b, 0xa8, 0x0d, 0xcd, 0xed, 0x80, 0xf8, 0x56, 0xc0, 0xc8, 0x2a, 0x5a, 0x00, 0xe0, 0x56, 0xc0, - 0xc4, 0x72, 0x9e, 0x18, 0x35, 0xc6, 0x70, 0xdf, 0x72, 0x23, 0xd7, 0x1b, 0x09, 0xe3, 0xd4, 0xd7, - 0xbf, 0x05, 0xed, 0x4c, 0x38, 0x40, 0x67, 0xa0, 0xfd, 0xfe, 0x66, 0x7f, 0xb3, 0xbf, 0xd3, 0xef, - 0xdc, 0xeb, 0x7f, 0x70, 0xbb, 0x27, 0xac, 0xb4, 0xd1, 0x1f, 0x6c, 0x74, 0x76, 0xba, 0x77, 0x0c, - 0x8d, 0x99, 0x4f, 0x34, 0xf5, 0x5b, 0x6f, 0xff, 0xe5, 0xb3, 0x15, 0xed, 0x93, 0xcf, 0x56, 0xb4, - 0x7f, 0x7e, 0xb6, 0xa2, 0xfd, 0xfc, 0xf3, 0x95, 0x53, 0x9f, 0x7c, 0xbe, 0x72, 0xea, 0xd3, 0xcf, - 0x57, 0x4e, 0x7d, 0xf0, 0xca, 0xc8, 0x8d, 0xf6, 0xa6, 0xbb, 0x57, 0x6d, 0x3a, 0xb9, 0xe6, 0xbb, - 0xde, 0xc8, 0xb6, 0xfc, 0x6b, 0x91, 0x6b, 0x3b, 0xf6, 0x35, 0xc5, 0xa3, 0x76, 0xeb, 0xfc, 0xcf, - 0xb1, 0xd7, 0xff, 0x1f, 0x00, 0x00, 0xff, 0xff, 0x8e, 0x4d, 0x8d, 0x99, 0x58, 0x26, 0x00, 0x00, + // 2875 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x3a, 0x4d, 0x8c, 0x1c, 0x57, + 0xd1, 0xee, 0x9e, 0xff, 0xda, 0x9d, 0x75, 0xfb, 0xd9, 0x5e, 0x6f, 0xec, 0xf5, 0x7a, 0xd3, 0x5f, + 0x3e, 0xb4, 0x6c, 0x82, 0x8d, 0x9d, 0x98, 0x40, 0x08, 0x09, 0xe3, 0x99, 0x4d, 0x3c, 0x5a, 0xef, + 0x8f, 0xde, 0x6c, 0x30, 0x84, 0xc3, 0xd0, 0xdb, 0xfd, 0x3c, 0xdb, 0xd9, 0x99, 0xee, 0x76, 0x77, + 0x8f, 0xd7, 0x6b, 0x29, 0x20, 0x14, 0x71, 0xe3, 0x40, 0x24, 0x90, 0xe0, 0xc0, 0x01, 0x21, 0x71, + 0x46, 0x42, 0x1c, 0xb9, 0x23, 0x71, 0xc9, 0x31, 0x37, 0x50, 0x72, 0x47, 0x11, 0x1c, 0xb8, 0xa2, + 0xf7, 0xd7, 0xfd, 0xba, 0xa7, 0xf7, 0xc7, 0xec, 0x28, 0xb7, 0x57, 0xaf, 0xab, 0xea, 0xd5, 0xab, + 0xaa, 0x57, 0x55, 0xaf, 0x5e, 0xc3, 0xb5, 0x3d, 0x62, 0x85, 0xf1, 0x2e, 0xb1, 0xe2, 0x60, 0xf7, + 0x56, 0x32, 0xbe, 0x19, 0x84, 0x7e, 0xec, 0xa3, 0x19, 0xe5, 0xa3, 0x79, 0x08, 0x8d, 0x1d, 0x6b, + 0x77, 0x48, 0x7a, 0x81, 0xe5, 0xa1, 0x05, 0xa8, 0x31, 0xa0, 0xdb, 0x59, 0xd0, 0x96, 0xb5, 0x95, + 0x12, 0x96, 0x20, 0xba, 0x0a, 0xf5, 0x5e, 0x6c, 0x85, 0xf1, 0x3a, 0x39, 0x5c, 0xd0, 0x97, 0xb5, + 0x95, 0x59, 0x9c, 0xc0, 0x68, 0x1e, 0xaa, 0x6b, 0x9e, 0x43, 0xbf, 0x94, 0xd8, 0x17, 0x01, 0xa1, + 0x25, 0x80, 0x75, 0x72, 0x18, 0x05, 0x96, 0x4d, 0x19, 0x96, 0x97, 0xb5, 0x95, 0x26, 0x56, 0x66, + 0xcc, 0xdf, 0x97, 0xc0, 0xb8, 0x4f, 0x45, 0xb9, 0x47, 0xac, 0x18, 0x93, 0xc7, 0x63, 0x12, 0xc5, + 0xe8, 0x3b, 0x30, 0x6b, 0xef, 0x59, 0xde, 0x80, 0x3c, 0x22, 0xc4, 0x11, 0x72, 0xcc, 0xdc, 0x79, + 0xe1, 0xa6, 0x22, 0xf3, 0xcd, 0xb6, 0x82, 0x80, 0x33, 0xe8, 0xe8, 0x35, 0x68, 0x1c, 0x58, 0x31, + 0x09, 0x47, 0x56, 0xb8, 0xcf, 0x04, 0x9d, 0xb9, 0x33, 0x9f, 0xa1, 0x7d, 0x28, 0xbf, 0xe2, 0x14, + 0x11, 0xbd, 0x09, 0xcd, 0x90, 0x38, 0x7e, 0xf2, 0x8d, 0x6d, 0xe4, 0x68, 0xca, 0x2c, 0x32, 0xfa, + 0x26, 0xd4, 0xa3, 0xd8, 0x8a, 0xc7, 0x11, 0x89, 0x16, 0xca, 0xcb, 0xa5, 0x95, 0x99, 0x3b, 0x8b, + 0x19, 0xc2, 0x44, 0xbf, 0x3d, 0x86, 0x85, 0x13, 0x6c, 0xb4, 0x02, 0xe7, 0x6d, 0x7f, 0x14, 0x90, + 0x21, 0x89, 0x09, 0xff, 0xb8, 0x50, 0x59, 0xd6, 0x56, 0xea, 0x38, 0x3f, 0x8d, 0x5e, 0x86, 0x12, + 0x09, 0xc3, 0x85, 0x6a, 0x81, 0x36, 0xf0, 0xd8, 0xf3, 0x5c, 0x6f, 0xb0, 0x16, 0x86, 0x7e, 0x88, + 0x29, 0x16, 0x5a, 0x07, 0x14, 0x1d, 0x7a, 0x76, 0x3f, 0xf0, 0x5d, 0x2f, 0xee, 0xdb, 0xbe, 0x17, + 0x87, 0xfe, 0x70, 0xa1, 0xc6, 0x68, 0xaf, 0x67, 0x68, 0x7b, 0x87, 0x9e, 0xbd, 0x4d, 0xb1, 0xda, + 0x1c, 0x09, 0x1b, 0x51, 0x6e, 0xc6, 0xfc, 0x99, 0x06, 0x8d, 0x74, 0xaf, 0x26, 0x35, 0x0f, 0xb1, + 0xf7, 0x19, 0xeb, 0x9d, 0x88, 0x99, 0xa7, 0x8c, 0x33, 0x73, 0xd4, 0xee, 0x21, 0x89, 0xfc, 0xe1, + 0x13, 0xe2, 0xec, 0x44, 0xcc, 0x08, 0x65, 0xac, 0xcc, 0x20, 0x03, 0x4a, 0x11, 0x79, 0xcc, 0x74, + 0x5c, 0xc6, 0x74, 0x48, 0xb9, 0x0e, 0xad, 0x28, 0xa6, 0xd2, 0x30, 0x9a, 0x32, 0xe7, 0xaa, 0xce, + 0x99, 0x1f, 0x82, 0xd1, 0x71, 0xa3, 0xc0, 0x8a, 0xed, 0x3d, 0x12, 0xb6, 0xec, 0xd8, 0xf5, 0x3d, + 0xf4, 0x32, 0x54, 0x2d, 0x36, 0x62, 0x72, 0xcc, 0xdd, 0xb9, 0x98, 0xd9, 0x1c, 0x47, 0xc2, 0x02, + 0x85, 0xba, 0x70, 0xdb, 0x1f, 0x8d, 0xdc, 0x38, 0x11, 0x2a, 0x81, 0xd1, 0x32, 0xcc, 0x74, 0xa3, + 0x44, 0x19, 0x4c, 0xb4, 0x3a, 0x56, 0xa7, 0xcc, 0x36, 0x94, 0x5a, 0xed, 0xf5, 0x0c, 0x13, 0xed, + 0x78, 0x26, 0xfa, 0x24, 0x13, 0x0c, 0xa8, 0x3b, 0xf0, 0xfc, 0x90, 0x38, 0xf7, 0x86, 0xbe, 0xbd, + 0x2f, 0x6c, 0x7b, 0x36, 0x9e, 0x1f, 0xe9, 0x70, 0xb9, 0xeb, 0x3d, 0x1a, 0x8e, 0x09, 0x55, 0x54, + 0xaa, 0xa2, 0x08, 0x7d, 0x17, 0x9a, 0xc9, 0x87, 0x9d, 0xc3, 0x80, 0x08, 0x25, 0x5d, 0xcd, 0x28, + 0x29, 0x83, 0x81, 0xb3, 0x04, 0xe8, 0x6d, 0x68, 0xa6, 0x0c, 0xbb, 0x1d, 0xaa, 0xb7, 0xd2, 0x84, + 0xff, 0xa9, 0x18, 0x38, 0x8b, 0xcf, 0xc2, 0x86, 0xbd, 0x47, 0x46, 0x56, 0xb7, 0xc3, 0x94, 0x5a, + 0xc2, 0x09, 0x8c, 0xd6, 0xe1, 0x22, 0x79, 0x6a, 0x0f, 0xc7, 0x0e, 0x51, 0x68, 0x1c, 0x66, 0xfb, + 0x63, 0x97, 0x28, 0xa2, 0x32, 0x7f, 0xad, 0xab, 0xee, 0x21, 0x14, 0xfb, 0x7d, 0xb8, 0xec, 0x16, + 0x69, 0x46, 0x04, 0x15, 0xb3, 0x58, 0x11, 0x2a, 0x26, 0x2e, 0x66, 0x80, 0xee, 0x26, 0x8e, 0xa7, + 0x17, 0x9c, 0xaa, 0xbc, 0x9f, 0x26, 0x2e, 0x68, 0x42, 0xc9, 0xb2, 0x65, 0x74, 0x31, 0xb2, 0xce, + 0xda, 0x5e, 0xc7, 0xf4, 0x23, 0xda, 0x02, 0xe4, 0x4e, 0xf8, 0x88, 0xd0, 0xca, 0x8d, 0xac, 0xc4, + 0x13, 0x68, 0xb8, 0x80, 0xd4, 0xfc, 0xb3, 0x06, 0x17, 0x94, 0x30, 0x1b, 0x05, 0xbe, 0x17, 0x91, + 0xb3, 0xc6, 0xd9, 0x0d, 0x40, 0x4e, 0x4e, 0xdd, 0x44, 0xba, 0xc7, 0x51, 0xca, 0x90, 0x32, 0x4e, + 0x12, 0x22, 0x04, 0xe5, 0x91, 0xef, 0x10, 0xe1, 0x23, 0x6c, 0x6c, 0x3e, 0x85, 0x8b, 0x6d, 0x25, + 0xac, 0x6c, 0x90, 0x28, 0xb2, 0x06, 0x67, 0x16, 0x3c, 0x1f, 0xc0, 0xf4, 0xc9, 0x00, 0x66, 0x0e, + 0xc1, 0xc8, 0x07, 0x46, 0x74, 0x09, 0x2a, 0x24, 0xf0, 0xed, 0x3d, 0x71, 0x42, 0x39, 0x80, 0x4c, + 0x68, 0x46, 0xfb, 0x6e, 0xd0, 0x8f, 0x68, 0x2e, 0xec, 0xc7, 0x92, 0xdd, 0x0c, 0x9d, 0x64, 0xf9, + 0x91, 0x85, 0x43, 0x06, 0xf6, 0x89, 0xe7, 0x50, 0x0c, 0x1e, 0xf6, 0x1a, 0x74, 0x6a, 0xcd, 0xa3, + 0x81, 0xed, 0x63, 0x0d, 0xae, 0xe4, 0x97, 0x9b, 0xd2, 0x66, 0x5f, 0x87, 0x9a, 0x8c, 0xfe, 0xfa, + 0x69, 0xa2, 0xbf, 0xc4, 0x36, 0x7f, 0xa9, 0xc1, 0x79, 0x4c, 0x1c, 0x7f, 0x83, 0xc4, 0xd6, 0x94, + 0x64, 0x39, 0x29, 0x2b, 0xe4, 0x0d, 0x53, 0x2a, 0x30, 0xcc, 0x8f, 0xe1, 0x3a, 0x95, 0x0a, 0x27, + 0x54, 0xdb, 0xa1, 0x3f, 0x08, 0x49, 0x14, 0x7d, 0x39, 0x32, 0x9a, 0x1f, 0xc2, 0x62, 0x76, 0xfd, + 0x77, 0xfc, 0xf0, 0xc0, 0x0a, 0x9d, 0x2f, 0x69, 0xf9, 0x7f, 0x6b, 0x6a, 0x90, 0x6b, 0xfb, 0xde, + 0x23, 0x77, 0x80, 0x56, 0xa1, 0x1c, 0x05, 0x96, 0x27, 0xd6, 0x9a, 0x2f, 0xae, 0x3c, 0x30, 0xc3, + 0xa1, 0xf5, 0x5d, 0xc4, 0xbd, 0x52, 0x70, 0x97, 0x20, 0x95, 0xdc, 0x51, 0x82, 0xac, 0x08, 0x51, + 0xc7, 0x44, 0xe1, 0x0c, 0x3a, 0x8d, 0xf3, 0x91, 0x8c, 0xf3, 0x65, 0x1e, 0xe7, 0x25, 0x9c, 0x9c, + 0xed, 0x4a, 0x7a, 0xb6, 0xd1, 0x2a, 0x18, 0xf4, 0x00, 0x74, 0x36, 0x1e, 0xb4, 0x22, 0x71, 0x4e, + 0x58, 0x6d, 0x53, 0xc7, 0x13, 0xf3, 0xe6, 0xaf, 0x74, 0x78, 0x81, 0x26, 0x0d, 0x67, 0x3c, 0x54, + 0x62, 0xfe, 0x94, 0xea, 0xc5, 0xbb, 0x50, 0xb5, 0x99, 0x1e, 0x4f, 0x08, 0xe4, 0x5c, 0xd9, 0x58, + 0x20, 0xa3, 0x36, 0xcc, 0x45, 0x42, 0x24, 0x1e, 0xe2, 0x99, 0xc2, 0xe6, 0xee, 0x5c, 0xcb, 0x9e, + 0xaf, 0x0c, 0x0a, 0xce, 0x91, 0x50, 0xd1, 0xfd, 0x80, 0x84, 0x56, 0xec, 0x87, 0x2c, 0x3d, 0x97, + 0x19, 0x8b, 0xac, 0xe8, 0x5b, 0x0a, 0x02, 0xce, 0xa0, 0x9b, 0xff, 0xd1, 0x60, 0x7e, 0x83, 0x84, + 0x83, 0xe9, 0x2b, 0xe5, 0x6d, 0x68, 0x3a, 0xcf, 0x99, 0xf6, 0x33, 0xf8, 0xa8, 0x0b, 0x68, 0x44, + 0x25, 0x73, 0x3a, 0xcf, 0xe5, 0x53, 0x05, 0x44, 0x89, 0xf7, 0x94, 0x95, 0xcc, 0xb0, 0x0d, 0x17, + 0x37, 0x2c, 0xd7, 0x8b, 0x2d, 0xd7, 0x23, 0xe1, 0x7d, 0xc9, 0x0d, 0x7d, 0x4b, 0xa9, 0xc3, 0xb5, + 0x82, 0x4c, 0x94, 0xd2, 0xe4, 0x0b, 0x71, 0xf3, 0x53, 0x0d, 0x9a, 0x9d, 0xd0, 0x72, 0x3d, 0x19, + 0x50, 0xd0, 0x4b, 0x30, 0x17, 0x5b, 0xe1, 0x80, 0xc4, 0x7d, 0xcf, 0x77, 0x48, 0xdf, 0x75, 0x98, + 0x12, 0x1b, 0x78, 0x96, 0xcf, 0x6e, 0xfa, 0x0e, 0xe9, 0x3a, 0xe8, 0x45, 0x10, 0x70, 0x9f, 0x27, + 0x07, 0x11, 0xfe, 0xf9, 0xdc, 0x1a, 0x4b, 0x11, 0xdf, 0x80, 0x2b, 0x02, 0x25, 0xd5, 0x51, 0xdf, + 0xf6, 0xc7, 0xa2, 0xcc, 0x6c, 0xe2, 0xcb, 0xfc, 0xb3, 0xea, 0x6b, 0x63, 0x2f, 0x46, 0xef, 0xc0, + 0xb2, 0xa0, 0xa3, 0x25, 0x88, 0x3b, 0xd8, 0x8b, 0xfb, 0x0e, 0x95, 0xb0, 0x3f, 0xf2, 0x9f, 0x10, + 0xc1, 0x80, 0xdf, 0xa9, 0x16, 0x39, 0x5e, 0x57, 0xa0, 0xb1, 0x7d, 0x6c, 0xf8, 0x4f, 0x08, 0xe3, + 0x63, 0x7e, 0x54, 0x02, 0x23, 0xbf, 0xf3, 0xb3, 0x3a, 0xc8, 0x75, 0x00, 0x3a, 0xa2, 0x69, 0x2f, + 0x26, 0x6c, 0xd3, 0x0d, 0xdc, 0xa0, 0x33, 0x94, 0x3d, 0x41, 0xb7, 0xa1, 0xc2, 0xbf, 0x14, 0x1d, + 0x8a, 0xb6, 0x3f, 0x0a, 0x7c, 0x8f, 0x78, 0x31, 0xc3, 0xc5, 0x1c, 0x13, 0xfd, 0x1f, 0x34, 0xd3, + 0x48, 0x4f, 0xd3, 0x64, 0xb9, 0xe0, 0x62, 0x21, 0x2e, 0x41, 0x95, 0x02, 0x6f, 0x9c, 0xbc, 0x04, + 0xfd, 0x3f, 0xcc, 0xed, 0xfa, 0x7e, 0x1c, 0xc5, 0xa1, 0x15, 0xf4, 0x1d, 0xdf, 0x23, 0x22, 0xc0, + 0x34, 0x93, 0xd9, 0x8e, 0xef, 0x91, 0x89, 0xab, 0x47, 0x6d, 0xf2, 0xea, 0x81, 0x5a, 0x30, 0xc7, + 0x55, 0x1f, 0x08, 0xef, 0x58, 0xa8, 0x33, 0x7d, 0x65, 0x2b, 0xe9, 0x8c, 0xff, 0xe0, 0xa6, 0xa3, + 0x82, 0xe6, 0x3f, 0x35, 0x68, 0x52, 0x9f, 0x49, 0xbd, 0xf5, 0x2e, 0xd4, 0x87, 0xee, 0x13, 0xe2, + 0x51, 0x76, 0x5a, 0xc1, 0xc9, 0xa7, 0xd8, 0x0f, 0x04, 0x02, 0x4e, 0x50, 0xa9, 0xea, 0x99, 0x43, + 0xaa, 0xfe, 0xd6, 0xa0, 0x33, 0xdc, 0xdb, 0x3a, 0x70, 0x43, 0x71, 0x33, 0x2e, 0x75, 0xce, 0x8f, + 0x4b, 0xcc, 0x5c, 0xd7, 0x52, 0x34, 0x26, 0xf8, 0x8e, 0xea, 0xd6, 0x2d, 0xb8, 0x7e, 0x14, 0x17, + 0xbe, 0x2e, 0xb7, 0xce, 0xd5, 0x42, 0x1e, 0x4c, 0x10, 0xf3, 0x03, 0x98, 0xef, 0x71, 0x7e, 0xc9, + 0x26, 0x44, 0x70, 0xba, 0x0d, 0x55, 0xce, 0xeb, 0xe4, 0x6d, 0x0b, 0xc4, 0x13, 0x36, 0x6d, 0x8e, + 0xe0, 0xca, 0xc4, 0x5a, 0xa2, 0xcc, 0x7d, 0x15, 0x6a, 0x56, 0x10, 0x0c, 0x5d, 0xe2, 0x9c, 0xbc, + 0x9a, 0xc4, 0x3c, 0x69, 0xb9, 0x0f, 0xe0, 0x46, 0x4f, 0x3d, 0xaf, 0xca, 0xde, 0xe5, 0x1e, 0xa7, + 0x15, 0x3d, 0xcc, 0xd7, 0xe1, 0x5a, 0xdb, 0xf7, 0x43, 0xc7, 0xf5, 0x68, 0xdc, 0xbf, 0x27, 0x5d, + 0x57, 0xae, 0xb3, 0x00, 0xb5, 0x27, 0x24, 0x8c, 0xe4, 0x0d, 0xb8, 0x84, 0x25, 0x68, 0xfe, 0x00, + 0x16, 0x8b, 0x09, 0x85, 0x62, 0xce, 0x10, 0x2c, 0xff, 0xa6, 0xc1, 0xa5, 0x96, 0xe3, 0xa4, 0x18, + 0x52, 0x9a, 0xaf, 0x82, 0x2e, 0x76, 0x7a, 0x6c, 0x2c, 0xd1, 0x5d, 0x07, 0xcd, 0x67, 0xf2, 0xee, + 0x6c, 0x92, 0x58, 0x27, 0xe2, 0x40, 0x41, 0x19, 0x88, 0x56, 0xe1, 0x82, 0x1b, 0xf5, 0x3d, 0x72, + 0xd0, 0x4f, 0xa3, 0x12, 0x73, 0xc9, 0x3a, 0x3e, 0xef, 0x46, 0x9b, 0xe4, 0x20, 0x5d, 0x0e, 0xdd, + 0x80, 0x99, 0x7d, 0xd1, 0x72, 0xa2, 0x66, 0xa8, 0xf0, 0x2e, 0x94, 0x9c, 0xea, 0x3a, 0xe6, 0x6f, + 0x34, 0xb8, 0x82, 0x09, 0x0d, 0xaa, 0x67, 0xda, 0xd0, 0x02, 0xd4, 0x6c, 0x2b, 0xb2, 0x2d, 0x87, + 0x88, 0x4b, 0xba, 0x04, 0xe9, 0x97, 0x90, 0xf1, 0x77, 0x44, 0x5f, 0x41, 0x82, 0x79, 0xd9, 0xca, + 0x13, 0xb2, 0x7d, 0x51, 0x82, 0xab, 0xa9, 0x54, 0x13, 0xd6, 0x3f, 0x63, 0x14, 0x3f, 0xca, 0x06, + 0x2f, 0x30, 0xd7, 0x08, 0x15, 0xf5, 0x27, 0x65, 0xa2, 0x0d, 0x2f, 0xc6, 0xb4, 0xa6, 0xec, 0xc7, + 0xa1, 0x3b, 0x18, 0x90, 0xb0, 0x4f, 0x9e, 0x10, 0x2f, 0x93, 0xd9, 0xdc, 0x53, 0xdc, 0xe0, 0xaf, + 0x33, 0x1e, 0x3b, 0x9c, 0xc5, 0x1a, 0xe5, 0xa0, 0xde, 0xe5, 0x8b, 0xcd, 0x5b, 0x29, 0x36, 0xaf, + 0x45, 0xb3, 0xa4, 0x2a, 0x50, 0x48, 0x1c, 0x3f, 0x27, 0x4f, 0xf5, 0x24, 0x79, 0x16, 0x55, 0x79, + 0x68, 0x81, 0x9f, 0x11, 0x27, 0x67, 0xa5, 0x5a, 0xde, 0x4a, 0x47, 0xb4, 0xdb, 0xea, 0xff, 0x5b, + 0xbb, 0xed, 0x0f, 0x25, 0xb8, 0x56, 0x68, 0xf2, 0xe9, 0xdc, 0xdb, 0xef, 0x42, 0x85, 0xde, 0x04, + 0x64, 0x49, 0x97, 0x6d, 0x28, 0x24, 0xab, 0xa5, 0xf7, 0x06, 0x8e, 0x2d, 0x33, 0x6f, 0xe9, 0x54, + 0xed, 0xc7, 0x53, 0xe5, 0xf2, 0x57, 0x00, 0x31, 0x53, 0x65, 0x31, 0x2b, 0x0c, 0xd3, 0xa0, 0x5f, + 0xd4, 0xbb, 0x3f, 0xea, 0x40, 0x43, 0xd6, 0xbe, 0xf4, 0xa2, 0x40, 0x45, 0xff, 0x4a, 0x61, 0xa9, + 0x3d, 0x51, 0x0b, 0xe3, 0x94, 0x70, 0xba, 0x7d, 0xd1, 0x3f, 0xe9, 0xb0, 0x94, 0x1a, 0x6a, 0xdb, + 0x8f, 0xe2, 0x69, 0x9f, 0xcf, 0x53, 0x1d, 0x36, 0xfd, 0x8c, 0x87, 0xed, 0x36, 0xd4, 0xf8, 0x4d, + 0x8d, 0x9e, 0x75, 0xaa, 0xd7, 0x2b, 0x13, 0x7a, 0x1d, 0x59, 0x5d, 0xef, 0x91, 0x8f, 0x25, 0x1e, + 0x7a, 0x03, 0x66, 0x99, 0xe9, 0x24, 0x5d, 0xf9, 0x78, 0xba, 0x19, 0x8a, 0xcc, 0xe1, 0xc8, 0xfc, + 0x97, 0x06, 0x37, 0x8e, 0xd4, 0xda, 0x74, 0x5c, 0xfc, 0x4b, 0x51, 0xdb, 0xf3, 0x1c, 0x08, 0xf3, + 0x29, 0x40, 0xaa, 0x8f, 0x4c, 0x4f, 0x54, 0xcb, 0xf5, 0x44, 0x97, 0x24, 0xe6, 0xa6, 0x35, 0x92, + 0x85, 0xb5, 0x32, 0x83, 0x6e, 0x42, 0x95, 0x9d, 0x4d, 0x69, 0xac, 0x82, 0xeb, 0x3e, 0xd3, 0xb9, + 0xc0, 0x32, 0xdb, 0xe2, 0x75, 0x87, 0x2d, 0x7c, 0xf4, 0xeb, 0xce, 0xa2, 0x40, 0x53, 0x56, 0x4d, + 0x27, 0xcc, 0xbf, 0xe8, 0x80, 0x26, 0x43, 0x03, 0x4d, 0x8e, 0x47, 0x18, 0x27, 0xa3, 0x48, 0x5d, + 0xbc, 0x1e, 0xc9, 0x2d, 0xeb, 0xb9, 0x2d, 0xcb, 0xfe, 0x45, 0xe9, 0x14, 0xfd, 0x8b, 0x77, 0xc0, + 0xb0, 0xe5, 0xf5, 0xa1, 0x1f, 0xa5, 0x9d, 0xd1, 0x13, 0xee, 0x18, 0xe7, 0x6d, 0x15, 0x1e, 0x47, + 0x93, 0x11, 0xaa, 0x52, 0x10, 0xa1, 0x5e, 0x85, 0x99, 0xdd, 0xa1, 0x6f, 0xef, 0x8b, 0x5b, 0x0e, + 0xcf, 0x22, 0x28, 0xeb, 0xe5, 0x8c, 0x3d, 0xec, 0xca, 0x6e, 0x2b, 0x49, 0xae, 0xab, 0x35, 0xe5, + 0xba, 0xfa, 0x18, 0xe6, 0x53, 0x97, 0x6f, 0x0f, 0xfd, 0x88, 0x4c, 0x29, 0x40, 0x28, 0x95, 0x85, + 0x9e, 0xa9, 0x2c, 0xcc, 0x10, 0xae, 0x4c, 0x2c, 0x39, 0x9d, 0xd3, 0xb5, 0x00, 0xb5, 0x68, 0x6c, + 0xdb, 0xf4, 0xd6, 0x22, 0xd6, 0x14, 0xa0, 0xf9, 0x73, 0x0d, 0x8c, 0xb4, 0x89, 0xce, 0x1d, 0x70, + 0x0a, 0x6f, 0x10, 0x57, 0xa1, 0x2e, 0xdc, 0x94, 0x27, 0xad, 0x12, 0x4e, 0xe0, 0xe3, 0x9e, 0x17, + 0xcc, 0x1f, 0x42, 0x85, 0xe1, 0x9d, 0xf0, 0xa8, 0x79, 0x94, 0x5b, 0x2e, 0x42, 0xa3, 0x17, 0x0c, + 0x5d, 0x16, 0x05, 0x44, 0xdd, 0x96, 0x4e, 0x98, 0x1e, 0xcc, 0x49, 0x4c, 0xae, 0xab, 0x63, 0x56, + 0x59, 0x86, 0x99, 0xad, 0xa1, 0x93, 0x5b, 0x48, 0x9d, 0xa2, 0x18, 0x9b, 0xe4, 0x20, 0xb7, 0x13, + 0x75, 0xca, 0xfc, 0x5d, 0x09, 0x2a, 0xdc, 0xc1, 0x16, 0xa1, 0xd1, 0x8d, 0x58, 0x7b, 0x5f, 0x5c, + 0x69, 0xea, 0x38, 0x9d, 0xa0, 0x52, 0xb0, 0x61, 0xda, 0xe0, 0x13, 0x20, 0x7a, 0x1b, 0x66, 0xf8, + 0x50, 0x86, 0x8f, 0xc9, 0xa4, 0x97, 0x37, 0x1e, 0x56, 0x29, 0xd0, 0x3a, 0x5c, 0xd8, 0x24, 0xc4, + 0xe9, 0x84, 0x7e, 0x10, 0x48, 0x0c, 0x51, 0xea, 0x9d, 0xc0, 0x66, 0x92, 0x0e, 0xbd, 0x09, 0xe7, + 0xe9, 0x64, 0xcb, 0x71, 0x12, 0x56, 0xfc, 0x56, 0x8f, 0x26, 0xcf, 0x3f, 0xce, 0xa3, 0xa2, 0x36, + 0xcc, 0xbd, 0x17, 0x38, 0x56, 0x4c, 0x84, 0x0a, 0x65, 0x49, 0x70, 0xad, 0x28, 0x05, 0x09, 0x03, + 0xe1, 0x1c, 0x49, 0xfe, 0x65, 0xad, 0x36, 0xf1, 0xb2, 0x86, 0xbe, 0xc6, 0xda, 0x18, 0x03, 0xc2, + 0x4a, 0xb9, 0xb9, 0x5c, 0x82, 0x93, 0x2f, 0x2c, 0x03, 0xde, 0xc2, 0x18, 0x10, 0xf3, 0x27, 0x70, + 0x29, 0x89, 0x57, 0xea, 0xf3, 0xde, 0x73, 0xc4, 0xc9, 0x15, 0xd9, 0x38, 0xd1, 0x8f, 0x0c, 0x36, + 0xa2, 0x5f, 0x52, 0xf4, 0x60, 0xf2, 0x85, 0x06, 0xe7, 0x73, 0x6f, 0xcd, 0xcf, 0xb3, 0x78, 0x51, + 0x70, 0xd5, 0xa7, 0x11, 0x5c, 0x8b, 0xae, 0x70, 0xb7, 0xe1, 0x32, 0x4f, 0xcb, 0x91, 0xfb, 0x8c, + 0xf4, 0x03, 0x12, 0xf6, 0x23, 0x62, 0xfb, 0x1e, 0xbf, 0x3c, 0xe8, 0x18, 0xb1, 0x8f, 0x3d, 0xf7, + 0x19, 0xd9, 0x26, 0x61, 0x8f, 0x7d, 0x29, 0xea, 0x23, 0x9b, 0x7f, 0xd4, 0x00, 0xa9, 0xef, 0x5f, + 0xd3, 0x89, 0xab, 0xef, 0x42, 0x73, 0x37, 0x65, 0x9a, 0xbc, 0x6b, 0xbd, 0x58, 0x9c, 0x9b, 0xd4, + 0xf5, 0xb3, 0x74, 0x85, 0x56, 0x72, 0x60, 0x56, 0xad, 0x10, 0x28, 0x4e, 0xec, 0x8e, 0x88, 0x68, + 0x10, 0xb0, 0x31, 0x9d, 0xf3, 0x7c, 0x47, 0xa6, 0x62, 0x36, 0xa6, 0x73, 0xb6, 0xe4, 0xd5, 0xc0, + 0x6c, 0x4c, 0x8f, 0xfb, 0x88, 0x3f, 0x3d, 0x30, 0xbd, 0x35, 0xb0, 0x04, 0xcd, 0xd7, 0x60, 0x36, + 0xdf, 0x46, 0xdd, 0x73, 0x07, 0xf2, 0xf5, 0x8a, 0x8d, 0x91, 0x01, 0xa5, 0xa1, 0x7f, 0x20, 0x02, + 0x05, 0x1d, 0x52, 0xd9, 0x54, 0xb5, 0x9c, 0x8e, 0x8a, 0x49, 0x4b, 0x0b, 0x07, 0x21, 0x19, 0x1d, + 0xd3, 0xd0, 0x2a, 0x6f, 0x48, 0x42, 0xb4, 0x04, 0x36, 0x7f, 0x04, 0x37, 0x1e, 0xf8, 0x03, 0xa5, + 0x3b, 0x91, 0xbe, 0xa7, 0x4c, 0xc7, 0x80, 0xe6, 0x4f, 0x35, 0x58, 0x3e, 0x7a, 0x89, 0xe9, 0x24, + 0xc2, 0x93, 0x1e, 0x6b, 0x86, 0x54, 0x97, 0xc4, 0xde, 0x8f, 0xc6, 0xa3, 0x0d, 0x12, 0x5b, 0xe8, + 0xeb, 0xf2, 0x6c, 0x17, 0x65, 0x40, 0x89, 0x99, 0x39, 0xe3, 0xab, 0x60, 0xd8, 0xea, 0x7c, 0x8f, + 0x3c, 0x16, 0xeb, 0x4c, 0xcc, 0x9b, 0x1f, 0x6b, 0x70, 0x59, 0x79, 0x69, 0x25, 0xb1, 0xe4, 0x88, + 0x2e, 0x41, 0x85, 0x37, 0x8b, 0xc5, 0xc3, 0x25, 0x03, 0xa8, 0xe7, 0x3c, 0xf5, 0xc3, 0xfb, 0xd4, + 0xb8, 0x22, 0x51, 0x08, 0x10, 0xcd, 0x43, 0xf5, 0xa9, 0x1f, 0x3e, 0xf0, 0x0f, 0xc4, 0xb9, 0x15, + 0x10, 0x4f, 0xfc, 0x23, 0x46, 0x51, 0x16, 0x4d, 0x01, 0x0e, 0x52, 0x8a, 0x68, 0x3c, 0xa2, 0x14, + 0xbc, 0x8c, 0x12, 0x90, 0xf9, 0x5b, 0x0d, 0x96, 0x0b, 0x65, 0x6a, 0xd9, 0xfb, 0xd3, 0xb2, 0x42, + 0xf2, 0x2c, 0xab, 0xab, 0xcf, 0xb2, 0x05, 0xe7, 0x4e, 0xfe, 0x75, 0x52, 0x4e, 0xfe, 0x3a, 0x31, + 0xff, 0xae, 0x81, 0x59, 0x28, 0x1f, 0xcf, 0x14, 0x53, 0x0a, 0x26, 0x67, 0x90, 0x10, 0xbd, 0x05, + 0x75, 0x69, 0x69, 0xa6, 0xdb, 0xfc, 0x3f, 0x0b, 0x85, 0xd2, 0xe3, 0x84, 0x66, 0xf5, 0x3a, 0x54, + 0xc5, 0x5b, 0x53, 0x03, 0x2a, 0x0f, 0x43, 0x37, 0x26, 0xc6, 0x39, 0x54, 0x87, 0xf2, 0xb6, 0x15, + 0x45, 0x86, 0xb6, 0xba, 0xc2, 0xab, 0x18, 0xe5, 0x49, 0x0a, 0xa0, 0xda, 0x0e, 0x89, 0xc5, 0xf0, + 0x00, 0xaa, 0xbc, 0x2f, 0x66, 0x68, 0xab, 0x1b, 0x30, 0xab, 0xbe, 0x44, 0x51, 0x76, 0x5b, 0xfd, + 0x96, 0xe3, 0x18, 0xe7, 0xd0, 0x2c, 0xd4, 0xb7, 0xfa, 0x12, 0x91, 0x12, 0x6d, 0xf5, 0x37, 0xe8, + 0x58, 0x47, 0x33, 0x50, 0xdb, 0xea, 0xb3, 0x9a, 0xc9, 0x28, 0x71, 0x80, 0x3d, 0x57, 0x19, 0xe5, + 0xd5, 0xbb, 0x30, 0xab, 0x76, 0x5e, 0x29, 0xbb, 0xd6, 0x83, 0xee, 0xf7, 0xd6, 0x38, 0xbb, 0x0e, + 0x6e, 0x75, 0x37, 0xbb, 0x9b, 0xef, 0x1a, 0x1a, 0x85, 0x7a, 0x3b, 0x5b, 0xdb, 0xdb, 0x14, 0xd2, + 0x57, 0xdf, 0x00, 0x48, 0xd3, 0x2e, 0xdd, 0xc7, 0xe6, 0xd6, 0x26, 0xa5, 0x99, 0x81, 0xda, 0xc3, + 0x56, 0x77, 0x87, 0x93, 0x50, 0x00, 0x73, 0x40, 0xa7, 0x38, 0x1d, 0x8a, 0x53, 0x5a, 0x7d, 0x25, + 0x57, 0x88, 0xa2, 0x1a, 0x94, 0x5a, 0xc3, 0xa1, 0x71, 0x0e, 0x55, 0x41, 0xef, 0xdc, 0xe3, 0xa2, + 0x6f, 0xfa, 0xe1, 0xc8, 0x1a, 0x1a, 0xfa, 0xea, 0x33, 0x98, 0xcb, 0xa6, 0x39, 0xc6, 0xd6, 0x0f, + 0xf7, 0x5d, 0x6f, 0xc0, 0x17, 0xec, 0xc5, 0xac, 0x9e, 0xe1, 0x0b, 0xf2, 0xed, 0x3b, 0x86, 0x8e, + 0x0c, 0x98, 0xed, 0x7a, 0x6e, 0xec, 0x5a, 0x43, 0xf7, 0x19, 0xc5, 0x2d, 0xa1, 0x26, 0x34, 0xb6, + 0x43, 0x12, 0x58, 0x21, 0x05, 0xcb, 0x68, 0x0e, 0x80, 0x69, 0x01, 0x13, 0xcb, 0x39, 0x34, 0x2a, + 0x94, 0xe0, 0xa1, 0xe5, 0xc6, 0xae, 0x37, 0xe0, 0xca, 0xa9, 0xae, 0x7e, 0x1b, 0x9a, 0x99, 0x70, + 0x80, 0x2e, 0x40, 0xf3, 0xbd, 0xcd, 0xee, 0x66, 0x77, 0xa7, 0xdb, 0x7a, 0xd0, 0x7d, 0x7f, 0xad, + 0xc3, 0xb5, 0xb4, 0xd1, 0xed, 0x6d, 0xb4, 0x76, 0xda, 0xf7, 0x0d, 0x8d, 0xaa, 0x8f, 0x0f, 0xf5, + 0x7b, 0x6f, 0xfd, 0xf5, 0xb3, 0x25, 0xed, 0x93, 0xcf, 0x96, 0xb4, 0x7f, 0x7c, 0xb6, 0xa4, 0xfd, + 0xe2, 0xf3, 0xa5, 0x73, 0x9f, 0x7c, 0xbe, 0x74, 0xee, 0xd3, 0xcf, 0x97, 0xce, 0xbd, 0xff, 0xd2, + 0xc0, 0x8d, 0xf7, 0xc6, 0xbb, 0x37, 0x6d, 0x7f, 0x74, 0x2b, 0x70, 0xbd, 0x81, 0x6d, 0x05, 0xb7, + 0x62, 0xd7, 0x76, 0xec, 0x5b, 0x8a, 0x47, 0xed, 0x56, 0xd9, 0x2f, 0x82, 0xaf, 0xfe, 0x37, 0x00, + 0x00, 0xff, 0xff, 0x2d, 0xa6, 0xae, 0xc7, 0x41, 0x28, 0x00, 0x00, } func (m *TableSpan) Marshal() (dAtA []byte, err error) { @@ -3966,6 +4111,18 @@ func (m *HeartBeatRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.SyncPointControl != nil { + { + size, err := m.SyncPointControl.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintHeartbeat(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } if m.Err != nil { { size, err := m.Err.MarshalToSizedBuffer(dAtA[:i]) @@ -4427,6 +4584,91 @@ func (m *CheckpointTsMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *SyncPointControl) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SyncPointControl) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SyncPointControl) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.SkipEndTs != 0 { + i = encodeVarintHeartbeat(dAtA, i, uint64(m.SkipEndTs)) + i-- + dAtA[i] = 0x18 + } + if m.SkipStartTs != 0 { + i = encodeVarintHeartbeat(dAtA, i, uint64(m.SkipStartTs)) + i-- + dAtA[i] = 0x10 + } + if m.Epoch != 0 { + i = encodeVarintHeartbeat(dAtA, i, uint64(m.Epoch)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *SyncPointControlMessage) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SyncPointControlMessage) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SyncPointControlMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Control != nil { + { + size, err := m.Control.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintHeartbeat(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.ChangefeedID != nil { + { + size, err := m.ChangefeedID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintHeartbeat(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *RedoMetaMessage) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -5275,11 +5517,23 @@ func (m *MaintainerBootstrapRequest) MarshalToSizedBuffer(dAtA []byte) (int, err _ = i var l int _ = l - if m.KeyspaceId != 0 { - i = encodeVarintHeartbeat(dAtA, i, uint64(m.KeyspaceId)) - i-- - dAtA[i] = 0x38 - } + if m.SyncPointControl != nil { + { + size, err := m.SyncPointControl.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintHeartbeat(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + if m.KeyspaceId != 0 { + i = encodeVarintHeartbeat(dAtA, i, uint64(m.KeyspaceId)) + i-- + dAtA[i] = 0x38 + } if m.TableTriggerRedoDispatcherId != nil { { size, err := m.TableTriggerRedoDispatcherId.MarshalToSizedBuffer(dAtA[:i]) @@ -5361,6 +5615,18 @@ func (m *MaintainerBootstrapResponse) MarshalToSizedBuffer(dAtA []byte) (int, er _ = i var l int _ = l + if m.SyncPointControl != nil { + { + size, err := m.SyncPointControl.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintHeartbeat(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } if len(m.Operators) > 0 { for iNdEx := len(m.Operators) - 1; iNdEx >= 0; iNdEx-- { { @@ -5839,21 +6105,21 @@ func (m *InfluencedTables) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x18 } if len(m.TableIDs) > 0 { - dAtA41 := make([]byte, len(m.TableIDs)*10) - var j40 int + dAtA46 := make([]byte, len(m.TableIDs)*10) + var j45 int for _, num1 := range m.TableIDs { num := uint64(num1) for num >= 1<<7 { - dAtA41[j40] = uint8(uint64(num)&0x7f | 0x80) + dAtA46[j45] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j40++ + j45++ } - dAtA41[j40] = uint8(num) - j40++ + dAtA46[j45] = uint8(num) + j45++ } - i -= j40 - copy(dAtA[i:], dAtA41[:j40]) - i = encodeVarintHeartbeat(dAtA, i, uint64(j40)) + i -= j45 + copy(dAtA[i:], dAtA46[:j45]) + i = encodeVarintHeartbeat(dAtA, i, uint64(j45)) i-- dAtA[i] = 0x12 } @@ -6677,6 +6943,10 @@ func (m *HeartBeatRequest) Size() (n int) { l = m.Err.Size() n += 1 + l + sovHeartbeat(uint64(l)) } + if m.SyncPointControl != nil { + l = m.SyncPointControl.Size() + n += 1 + l + sovHeartbeat(uint64(l)) + } return n } @@ -6837,6 +7107,41 @@ func (m *CheckpointTsMessage) Size() (n int) { return n } +func (m *SyncPointControl) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Epoch != 0 { + n += 1 + sovHeartbeat(uint64(m.Epoch)) + } + if m.SkipStartTs != 0 { + n += 1 + sovHeartbeat(uint64(m.SkipStartTs)) + } + if m.SkipEndTs != 0 { + n += 1 + sovHeartbeat(uint64(m.SkipEndTs)) + } + return n +} + +func (m *SyncPointControlMessage) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ChangefeedID != nil { + l = m.ChangefeedID.Size() + n += 1 + l + sovHeartbeat(uint64(l)) + } + if m.Control != nil { + l = m.Control.Size() + n += 1 + l + sovHeartbeat(uint64(l)) + } + return n +} + func (m *RedoMetaMessage) Size() (n int) { if m == nil { return 0 @@ -7216,6 +7521,10 @@ func (m *MaintainerBootstrapRequest) Size() (n int) { if m.KeyspaceId != 0 { n += 1 + sovHeartbeat(uint64(m.KeyspaceId)) } + if m.SyncPointControl != nil { + l = m.SyncPointControl.Size() + n += 1 + l + sovHeartbeat(uint64(l)) + } return n } @@ -7251,6 +7560,10 @@ func (m *MaintainerBootstrapResponse) Size() (n int) { n += 1 + l + sovHeartbeat(uint64(l)) } } + if m.SyncPointControl != nil { + l = m.SyncPointControl.Size() + n += 1 + l + sovHeartbeat(uint64(l)) + } return n } @@ -8141,6 +8454,42 @@ func (m *HeartBeatRequest) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SyncPointControl", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHeartbeat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthHeartbeat + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthHeartbeat + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SyncPointControl == nil { + m.SyncPointControl = &SyncPointControl{} + } + if err := m.SyncPointControl.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipHeartbeat(dAtA[iNdEx:]) @@ -9170,6 +9519,235 @@ func (m *CheckpointTsMessage) Unmarshal(dAtA []byte) error { } return nil } +func (m *SyncPointControl) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHeartbeat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SyncPointControl: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SyncPointControl: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType) + } + m.Epoch = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHeartbeat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Epoch |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SkipStartTs", wireType) + } + m.SkipStartTs = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHeartbeat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SkipStartTs |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SkipEndTs", wireType) + } + m.SkipEndTs = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHeartbeat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SkipEndTs |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipHeartbeat(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthHeartbeat + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SyncPointControlMessage) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHeartbeat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SyncPointControlMessage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SyncPointControlMessage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChangefeedID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHeartbeat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthHeartbeat + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthHeartbeat + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ChangefeedID == nil { + m.ChangefeedID = &ChangefeedID{} + } + if err := m.ChangefeedID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Control", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHeartbeat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthHeartbeat + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthHeartbeat + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Control == nil { + m.Control = &SyncPointControl{} + } + if err := m.Control.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipHeartbeat(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthHeartbeat + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *RedoMetaMessage) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -11647,6 +12225,42 @@ func (m *MaintainerBootstrapRequest) Unmarshal(dAtA []byte) error { break } } + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SyncPointControl", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHeartbeat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthHeartbeat + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthHeartbeat + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SyncPointControl == nil { + m.SyncPointControl = &SyncPointControl{} + } + if err := m.SyncPointControl.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipHeartbeat(dAtA[iNdEx:]) @@ -11875,6 +12489,42 @@ func (m *MaintainerBootstrapResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SyncPointControl", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHeartbeat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthHeartbeat + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthHeartbeat + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SyncPointControl == nil { + m.SyncPointControl = &SyncPointControl{} + } + if err := m.SyncPointControl.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipHeartbeat(dAtA[iNdEx:]) diff --git a/heartbeatpb/heartbeat.proto b/heartbeatpb/heartbeat.proto index 4c718f14fc..736180569b 100644 --- a/heartbeatpb/heartbeat.proto +++ b/heartbeatpb/heartbeat.proto @@ -17,6 +17,7 @@ message HeartBeatRequest { repeated TableSpanStatus statuses = 4; bool compeleteStatus = 5; // Whether includes all table spans in the changefeed? RunningError err = 6; + SyncPointControl sync_point_control = 7; } message Watermark { @@ -79,6 +80,17 @@ message CheckpointTsMessage { uint64 checkpointTs = 2; } +message SyncPointControl { + uint64 epoch = 1; + uint64 skip_start_ts = 2; + uint64 skip_end_ts = 3; +} + +message SyncPointControlMessage { + ChangefeedID changefeedID = 1; + SyncPointControl control = 2; +} + // RedoMetaMessage used to send unflushed ts to update redo meta // from maintainer to dispatcher manager message RedoMetaMessage { @@ -249,6 +261,7 @@ message MaintainerBootstrapRequest { bool is_new_changefeed = 5; // only true when the changefeed is new created or resumed with overwriteCheckpointTs DispatcherID table_trigger_redo_dispatcher_id = 6; // only for redo uint32 keyspace_id = 7; + SyncPointControl sync_point_control = 8; } message MaintainerBootstrapResponse { @@ -268,6 +281,7 @@ message MaintainerBootstrapResponse { // It will be used when redo enable. uint64 redo_checkpoint_ts = 5; repeated ScheduleDispatcherRequest operators = 6; + SyncPointControl sync_point_control = 7; } message MaintainerPostBootstrapRequest { diff --git a/maintainer/barrier.go b/maintainer/barrier.go index 0c92fdeb87..94c70d3439 100644 --- a/maintainer/barrier.go +++ b/maintainer/barrier.go @@ -42,6 +42,10 @@ type Barrier struct { spanController *span.Controller operatorController *operator.Controller splitTableEnabled bool + // shouldDirectPassSyncPoint decides whether syncpoint barriers should bypass the write + // path and directly enter pass mode based on maintainer-global lag. + shouldDirectPassSyncPoint func() bool + shouldSkipSyncPoint func(uint64) bool // mode identifies which replication pipeline this barrier belongs to // (common.DefaultMode or common.RedoMode). Barrier state, resend messages, // and logs must stay in the same mode. @@ -67,6 +71,14 @@ func NewBarrier(spanController *span.Controller, return &barrier } +func (b *Barrier) SetSyncPointDirectPassDecider(decider func() bool) { + b.shouldDirectPassSyncPoint = decider +} + +func (b *Barrier) SetSyncPointSkipDecider(decider func(uint64) bool) { + b.shouldSkipSyncPoint = decider +} + // HandleStatus handle the block status from dispatcher manager func (b *Barrier) HandleStatus(from node.ID, request *heartbeatpb.BlockStatusRequest, @@ -116,6 +128,43 @@ func (b *Barrier) HandleStatus(from node.ID, } } + if status.State != nil && + status.State.IsBlocked && + status.State.IsSyncPoint && + b.shouldSkipSyncPoint != nil && + b.shouldSkipSyncPoint(status.State.BlockTs) { + if task := b.spanController.GetTaskByID(dispatcherID); task != nil { + task.UpdateStatus(&heartbeatpb.TableSpanStatus{ + ID: status.ID, + CheckpointTs: status.State.BlockTs - 1, + ComponentStatus: heartbeatpb.ComponentState_Working, + Mode: status.Mode, + }) + task.UpdateBlockState(*status.State) + } + dispatcherStatus = append(dispatcherStatus, &heartbeatpb.DispatcherStatus{ + InfluencedDispatchers: &heartbeatpb.InfluencedDispatchers{ + InfluenceType: heartbeatpb.InfluenceType_Normal, + DispatcherIDs: []*heartbeatpb.DispatcherID{status.ID}, + }, + Ack: ackEvent(status.State.BlockTs, true), + }) + if status.State.Stage != heartbeatpb.BlockStage_DONE { + dispatcherStatus = append(dispatcherStatus, &heartbeatpb.DispatcherStatus{ + InfluencedDispatchers: &heartbeatpb.InfluencedDispatchers{ + InfluenceType: heartbeatpb.InfluenceType_Normal, + DispatcherIDs: []*heartbeatpb.DispatcherID{status.ID}, + }, + Action: &heartbeatpb.DispatcherAction{ + Action: heartbeatpb.Action_Pass, + CommitTs: status.State.BlockTs, + IsSyncPoint: true, + }, + }) + } + continue + } + // deal with block status, and check whether need to return action. // we need to deal with the block status in order, otherwise scheduler may have problem // e.g. TODO(truncate + create table) @@ -381,6 +430,10 @@ func (b *Barrier) handleBlockState(changefeedID common.ChangeFeedID, ) // check whether the event can be finished. b.checkEventFinish(event) + if event.writerDispatcherAdvanced { + action, targetID := event.passActionForDispatcher(dispatcherID) + return event, action, targetID, true + } return event, nil, "", true } @@ -412,7 +465,8 @@ func (b *Barrier) handleBlockState(changefeedID common.ChangeFeedID, // the block event, and check whether we need to send write action event.markDispatcherEventDone(dispatcherID) - status, targetID := event.checkEventAction(dispatcherID) + directPassSyncPoint := blockState.IsSyncPoint && b.shouldDirectPassSyncPoint != nil && b.shouldDirectPassSyncPoint() + status, targetID := event.checkEventAction(dispatcherID, directPassSyncPoint) if status != nil && event.needSchedule { // scheduling is only required for ddl that changes tables, enqueue the event b.pendingEvents.add(event) @@ -461,6 +515,15 @@ func (b *Barrier) getOrInsertNewEvent(changefeedID common.ChangeFeedID, dispatch // check whether the event is get all the done message from dispatchers // if so, remove the event from blockedTs, not need to resend message anymore func (b *Barrier) checkEventFinish(be *BarrierEvent) { + if be.isSyncPoint && be.selected.Load() && b.spanController.GetMaintainerCommittedCheckpointTs() > be.commitTs { + log.Info("syncpoint barrier finished by committed checkpoint", + zap.String("changefeed", be.cfID.Name()), + zap.Uint64("commitTs", be.commitTs), + zap.Uint64("committedCheckpointTs", b.spanController.GetMaintainerCommittedCheckpointTs()), + zap.Int64("mode", b.mode)) + b.blockedEvents.Delete(getEventKey(be.commitTs, be.isSyncPoint)) + return + } if !be.allDispatcherReported() { return } diff --git a/maintainer/barrier_event.go b/maintainer/barrier_event.go index cf81e05a5e..3b53c0b102 100644 --- a/maintainer/barrier_event.go +++ b/maintainer/barrier_event.go @@ -172,17 +172,17 @@ func (be *BarrierEvent) createRangeCheckerForTypeDB() { log.Info("create range checker for block event", zap.Any("influcenceType", be.blockedDispatchers.InfluenceType), zap.Any("commitTs", be.commitTs), zap.Int64("mode", be.mode)) } -func (be *BarrierEvent) checkEventAction(dispatcherID common.DispatcherID) (*heartbeatpb.DispatcherStatus, node.ID) { +func (be *BarrierEvent) checkEventAction(dispatcherID common.DispatcherID, directPassSyncPoint bool) (*heartbeatpb.DispatcherStatus, node.ID) { if !be.allDispatcherReported() { return nil, "" } - return be.onAllDispatcherReportedBlockEvent(dispatcherID) + return be.onAllDispatcherReportedBlockEvent(dispatcherID, directPassSyncPoint) } // onAllDispatcherReportedBlockEvent is called when all dispatcher reported the block event // it will select a dispatcher as the writer, reset the range checker ,and move the event to the selected state // returns the dispatcher status to the dispatcher manager -func (be *BarrierEvent) onAllDispatcherReportedBlockEvent(dispatcherID common.DispatcherID) (*heartbeatpb.DispatcherStatus, node.ID) { +func (be *BarrierEvent) onAllDispatcherReportedBlockEvent(dispatcherID common.DispatcherID, directPassSyncPoint bool) (*heartbeatpb.DispatcherStatus, node.ID) { var dispatcher common.DispatcherID switch be.blockedDispatchers.InfluenceType { case heartbeatpb.InfluenceType_DB, heartbeatpb.InfluenceType_All: @@ -212,6 +212,29 @@ func (be *BarrierEvent) onAllDispatcherReportedBlockEvent(dispatcherID common.Di be.rangeChecker.Reset() be.reportedDispatchers = make(map[common.DispatcherID]struct{}) + if be.isSyncPoint && directPassSyncPoint { + be.selected.Store(true) + be.writerDispatcher = dispatcher + be.writerDispatcherAdvanced = true + be.lastResendTime = time.Now().Add(-20 * time.Second) + log.Info("direct pass syncpoint due to lag after all dispatchers reported", + zap.String("changefeed", be.cfID.Name()), + zap.String("dispatcher", dispatcherID.String()), + zap.Uint64("commitTs", be.commitTs), + zap.Int64("mode", be.mode)) + stm := be.spanController.GetTaskByID(dispatcherID) + if stm == nil { + return nil, "" + } + return &heartbeatpb.DispatcherStatus{ + InfluencedDispatchers: &heartbeatpb.InfluencedDispatchers{ + InfluenceType: heartbeatpb.InfluenceType_Normal, + DispatcherIDs: []*heartbeatpb.DispatcherID{dispatcherID.ToPB()}, + }, + Action: be.action(heartbeatpb.Action_Pass), + }, stm.GetNodeID() + } + be.selected.Store(true) be.writerDispatcher = dispatcher be.lastResendTime = time.Now() @@ -231,6 +254,20 @@ func (be *BarrierEvent) onAllDispatcherReportedBlockEvent(dispatcherID common.Di }, stm.GetNodeID() } +func (be *BarrierEvent) passActionForDispatcher(dispatcherID common.DispatcherID) (*heartbeatpb.DispatcherStatus, node.ID) { + stm := be.spanController.GetTaskByID(dispatcherID) + if stm == nil || stm.GetNodeID() == "" { + return nil, "" + } + return &heartbeatpb.DispatcherStatus{ + InfluencedDispatchers: &heartbeatpb.InfluencedDispatchers{ + InfluenceType: heartbeatpb.InfluenceType_Normal, + DispatcherIDs: []*heartbeatpb.DispatcherID{dispatcherID.ToPB()}, + }, + Action: be.action(heartbeatpb.Action_Pass), + }, stm.GetNodeID() +} + func (be *BarrierEvent) scheduleBlockEvent() { log.Info("schedule block event", zap.Uint64("commitTs", be.commitTs), zap.Int64("mode", be.mode)) // dispatcher notify us to drop some tables, by dispatcher ID or schema ID diff --git a/maintainer/barrier_test.go b/maintainer/barrier_test.go index 5e982762a5..8542e0a236 100644 --- a/maintainer/barrier_test.go +++ b/maintainer/barrier_test.go @@ -165,6 +165,116 @@ func TestOneBlockEvent(t *testing.T) { require.Len(t, resp.DispatcherStatuses, 0) } +func TestBarrierDirectPassSyncPoint(t *testing.T) { + testutil.SetUpTestServices(t) + + tableTriggerEventDispatcherID := common.NewDispatcherID() + cfID := common.NewChangeFeedIDWithName("test", common.DefaultKeyspaceName) + ddlSpan := replica.NewWorkingSpanReplication(cfID, tableTriggerEventDispatcherID, + common.DDLSpanSchemaID, + common.KeyspaceDDLSpan(common.DefaultKeyspaceID), &heartbeatpb.TableSpanStatus{ + ID: tableTriggerEventDispatcherID.ToPB(), + ComponentStatus: heartbeatpb.ComponentState_Working, + CheckpointTs: 1, + }, "node1", false) + spanController := span.NewController(cfID, ddlSpan, nil, nil, nil, common.DefaultKeyspaceID, common.DefaultMode) + operatorController := operator.NewOperatorController(cfID, spanController, 1000, common.DefaultMode) + startTs := uint64(10) + spanController.AddNewTable(commonEvent.Table{SchemaID: 1, TableID: 1}, startTs) + stm := spanController.GetTasksByTableID(1)[0] + spanController.BindSpanToNode("", "node1", stm) + spanController.MarkSpanReplicating(stm) + + barrier := NewBarrier(spanController, operatorController, false, nil, common.DefaultMode) + barrier.SetSyncPointDirectPassDecider(func() bool { return true }) + + msgs := barrier.HandleStatus("node1", &heartbeatpb.BlockStatusRequest{ + ChangefeedID: cfID.ToPB(), + BlockStatuses: []*heartbeatpb.TableSpanBlockStatus{ + { + ID: stm.ID.ToPB(), + State: &heartbeatpb.State{ + IsBlocked: true, + BlockTs: 10, + BlockTables: &heartbeatpb.InfluencedTables{ + InfluenceType: heartbeatpb.InfluenceType_All, + }, + IsSyncPoint: true, + }, + }, + }, + }) + require.NotEmpty(t, msgs) + + event, ok := barrier.blockedEvents.Get(getEventKey(10, true)) + require.True(t, ok) + require.NotNil(t, event) + require.False(t, event.selected.Load()) + require.False(t, event.writerDispatcherAdvanced) + require.Nil(t, event.rangeChecker) + + resp := msgs[0].Message[0].(*heartbeatpb.HeartBeatResponse) + require.Len(t, resp.DispatcherStatuses, 1) + require.Equal(t, uint64(10), resp.DispatcherStatuses[0].Ack.CommitTs) + + msgs = barrier.HandleStatus("node1", &heartbeatpb.BlockStatusRequest{ + ChangefeedID: cfID.ToPB(), + BlockStatuses: []*heartbeatpb.TableSpanBlockStatus{ + { + ID: spanController.GetDDLDispatcherID().ToPB(), + State: &heartbeatpb.State{ + IsBlocked: true, + BlockTs: 10, + BlockTables: &heartbeatpb.InfluencedTables{ + InfluenceType: heartbeatpb.InfluenceType_All, + }, + IsSyncPoint: true, + }, + }, + }, + }) + require.NotEmpty(t, msgs) + + event, ok = barrier.blockedEvents.Get(getEventKey(10, true)) + require.True(t, ok) + require.NotNil(t, event) + require.True(t, event.selected.Load()) + require.True(t, event.writerDispatcherAdvanced) + + resp = msgs[0].Message[0].(*heartbeatpb.HeartBeatResponse) + require.Len(t, resp.DispatcherStatuses, 2) + require.Equal(t, heartbeatpb.Action_Pass, resp.DispatcherStatuses[1].Action.Action) + require.True(t, resp.DispatcherStatuses[1].Action.IsSyncPoint) + require.Equal(t, spanController.GetDDLDispatcherID(), common.NewDispatcherIDFromPB(resp.DispatcherStatuses[1].InfluencedDispatchers.DispatcherIDs[0])) + + msgs = barrier.HandleStatus("node1", &heartbeatpb.BlockStatusRequest{ + ChangefeedID: cfID.ToPB(), + BlockStatuses: []*heartbeatpb.TableSpanBlockStatus{ + { + ID: stm.ID.ToPB(), + State: &heartbeatpb.State{ + IsBlocked: true, + BlockTs: 10, + BlockTables: &heartbeatpb.InfluencedTables{ + InfluenceType: heartbeatpb.InfluenceType_All, + }, + IsSyncPoint: true, + }, + }, + }, + }) + require.NotEmpty(t, msgs) + resp = msgs[0].Message[0].(*heartbeatpb.HeartBeatResponse) + require.Len(t, resp.DispatcherStatuses, 2) + require.Equal(t, heartbeatpb.Action_Pass, resp.DispatcherStatuses[1].Action.Action) + require.True(t, resp.DispatcherStatuses[1].Action.IsSyncPoint) + require.Equal(t, stm.ID, common.NewDispatcherIDFromPB(resp.DispatcherStatuses[1].InfluencedDispatchers.DispatcherIDs[0])) + + spanController.AdvanceMaintainerCommittedCheckpointTs(11) + _ = barrier.Resend() + require.Equal(t, 0, barrier.blockedEvents.Len()) +} + func TestNormalBlock(t *testing.T) { testutil.SetUpTestServices(t) tableTriggerEventDispatcherID := common.NewDispatcherID() @@ -1096,6 +1206,79 @@ func TestHandleBlockBootstrapResponse(t *testing.T) { require.Nil(t, event) } +func TestBarrierSkipSyncPointWindow(t *testing.T) { + testutil.SetUpTestServices(t) + + tableTriggerEventDispatcherID := common.NewDispatcherID() + cfID := common.NewChangeFeedIDWithName("test", common.DefaultKeyspaceName) + ddlSpan := replica.NewWorkingSpanReplication(cfID, tableTriggerEventDispatcherID, + common.DDLSpanSchemaID, + common.KeyspaceDDLSpan(common.DefaultKeyspaceID), &heartbeatpb.TableSpanStatus{ + ID: tableTriggerEventDispatcherID.ToPB(), + ComponentStatus: heartbeatpb.ComponentState_Working, + CheckpointTs: 1, + }, "node1", false) + spanController := span.NewController(cfID, ddlSpan, nil, nil, nil, common.DefaultKeyspaceID, common.DefaultMode) + operatorController := operator.NewOperatorController(cfID, spanController, 1000, common.DefaultMode) + spanController.AddNewTable(commonEvent.Table{SchemaID: 1, TableID: 1}, 10) + stm := spanController.GetTasksByTableID(1)[0] + spanController.BindSpanToNode("", "node1", stm) + spanController.MarkSpanReplicating(stm) + + barrier := NewBarrier(spanController, operatorController, false, nil, common.DefaultMode) + barrier.SetSyncPointSkipDecider(func(commitTs uint64) bool { + return commitTs == 10 + }) + + msgs := barrier.HandleStatus("node1", &heartbeatpb.BlockStatusRequest{ + ChangefeedID: cfID.ToPB(), + BlockStatuses: []*heartbeatpb.TableSpanBlockStatus{ + { + ID: stm.ID.ToPB(), + State: &heartbeatpb.State{ + IsBlocked: true, + BlockTs: 10, + BlockTables: &heartbeatpb.InfluencedTables{ + InfluenceType: heartbeatpb.InfluenceType_All, + }, + IsSyncPoint: true, + }, + }, + }, + }) + require.Len(t, msgs, 1) + _, ok := barrier.blockedEvents.Get(getEventKey(10, true)) + require.False(t, ok) + + resp := msgs[0].Message[0].(*heartbeatpb.HeartBeatResponse) + require.Len(t, resp.DispatcherStatuses, 2) + require.NotNil(t, resp.DispatcherStatuses[0].Ack) + require.Equal(t, uint64(10), resp.DispatcherStatuses[0].Ack.CommitTs) + require.NotNil(t, resp.DispatcherStatuses[1].Action) + require.Equal(t, heartbeatpb.Action_Pass, resp.DispatcherStatuses[1].Action.Action) + require.True(t, resp.DispatcherStatuses[1].Action.IsSyncPoint) + + msgs = barrier.HandleStatus("node1", &heartbeatpb.BlockStatusRequest{ + ChangefeedID: cfID.ToPB(), + BlockStatuses: []*heartbeatpb.TableSpanBlockStatus{ + { + ID: stm.ID.ToPB(), + State: &heartbeatpb.State{ + IsBlocked: true, + BlockTs: 10, + IsSyncPoint: true, + Stage: heartbeatpb.BlockStage_DONE, + }, + }, + }, + }) + require.Len(t, msgs, 1) + resp = msgs[0].Message[0].(*heartbeatpb.HeartBeatResponse) + require.Len(t, resp.DispatcherStatuses, 1) + require.NotNil(t, resp.DispatcherStatuses[0].Ack) + require.Nil(t, resp.DispatcherStatuses[0].Action) +} + func TestSyncPointBlockPerf(t *testing.T) { testutil.SetUpTestServices(t) tableTriggerEventDispatcherID := common.NewDispatcherID() @@ -1544,6 +1727,7 @@ func TestDeferAllDBBlockEventFromDDLDispatcherWhilePendingSchedule(t *testing.T) spanController.MarkSpanReplicating(absents[0]) barrier := NewBarrier(spanController, operatorController, false, nil, common.DefaultMode) + barrier.SetSyncPointDirectPassDecider(func() bool { return true }) // Build a TRUNCATE TABLE-like block event, which requires scheduling and will be enqueued into pendingEvents // when the write action is issued. diff --git a/maintainer/maintainer.go b/maintainer/maintainer.go index 3e4e152312..bf46f9bb7c 100644 --- a/maintainer/maintainer.go +++ b/maintainer/maintainer.go @@ -49,6 +49,9 @@ import ( const ( periodEventInterval = time.Millisecond * 100 periodRedoInterval = time.Second * 1 + + defaultSyncPointDirectPassThreshold = 20 * time.Minute + defaultSyncPointDirectPassResume = 15 * time.Minute ) // Maintainer is response for handle changefeed replication tasks. Maintainer should: @@ -163,6 +166,15 @@ type Maintainer struct { redoScheduledTaskGauge prometheus.Gauge redoSpanCountGauge prometheus.Gauge redoTableCountGauge prometheus.Gauge + + syncPointDirectPassActive atomic.Bool + syncPointDirectPassThreshold time.Duration + syncPointDirectPassResume time.Duration + desiredSyncPointControl common.SyncPointControl + authoritativeSyncPointControl common.SyncPointControl + nodeAppliedSyncPointControl map[node.ID]common.SyncPointControl + syncPointControlEpoch uint64 + syncPointControlReady bool } // NewMaintainer create the maintainer for the changefeed @@ -230,8 +242,17 @@ func NewMaintainer(cfID common.ChangeFeedID, redoScheduledTaskGauge: metrics.ScheduleTaskGauge.WithLabelValues(keyspaceName, name, "redo"), redoSpanCountGauge: metrics.SpanCountGauge.WithLabelValues(keyspaceName, name, "redo"), redoTableCountGauge: metrics.TableCountGauge.WithLabelValues(keyspaceName, name, "redo"), + + syncPointDirectPassThreshold: defaultSyncPointDirectPassThreshold, + syncPointDirectPassResume: defaultSyncPointDirectPassResume, + desiredSyncPointControl: common.NewDisabledSyncPointControl(), + authoritativeSyncPointControl: common.NewDisabledSyncPointControl(), + nodeAppliedSyncPointControl: make(map[node.ID]common.SyncPointControl), + syncPointControlReady: false, } m.controller.SetSelfNodeID(selfNode.ID) + m.controller.SetSyncPointDirectPassDecider(m.shouldDirectPassSyncPoint) + m.controller.SetSyncPointSkipDecider(m.shouldSkipSyncPoint) m.nodeChanged.changed = false m.runningErrors.m = make(map[node.ID]*heartbeatpb.RunningError) @@ -587,6 +608,7 @@ func (m *Maintainer) onNodeChanged() { m.controller.RemoveNode(id) m.checkpointTsByCapture.Delete(id) m.redoTsByCapture.Delete(id) + delete(m.nodeAppliedSyncPointControl, id) } m.sendMessages(requests) @@ -831,6 +853,49 @@ func (m *Maintainer) updateMetrics() { m.resolvedTsLagGauge.Set(lag) } +func (m *Maintainer) shouldDirectPassSyncPoint() bool { + if m == nil || m.syncPointDirectPassThreshold <= 0 { + return false + } + + watermark := m.getWatermark() + if watermark.CheckpointTs == 0 || watermark.CheckpointTs == math.MaxUint64 { + return false + } + + pdPhysicalTime := oracle.GetPhysical(m.pdClock.CurrentTime()) + phyCheckpointTs := oracle.ExtractPhysical(watermark.CheckpointTs) + lag := time.Duration(0) + if pdPhysicalTime > phyCheckpointTs { + lag = time.Duration(pdPhysicalTime-phyCheckpointTs) * time.Millisecond + } + + if m.syncPointDirectPassActive.Load() { + if lag <= m.syncPointDirectPassResume { + if m.syncPointDirectPassActive.CompareAndSwap(true, false) { + log.Info("syncpoint direct pass disabled", + zap.Stringer("changefeedID", m.changefeedID), + zap.Duration("lag", lag), + zap.Duration("resumeThreshold", m.syncPointDirectPassResume)) + } + return false + } + return true + } + + if lag > m.syncPointDirectPassThreshold { + if m.syncPointDirectPassActive.CompareAndSwap(false, true) { + log.Info("syncpoint direct pass enabled", + zap.Stringer("changefeedID", m.changefeedID), + zap.Duration("lag", lag), + zap.Duration("suppressThreshold", m.syncPointDirectPassThreshold), + zap.Duration("resumeThreshold", m.syncPointDirectPassResume)) + } + return true + } + return false +} + // send message to other components func (m *Maintainer) sendMessages(msgs []*messaging.TargetMessage) { for _, msg := range msgs { @@ -880,6 +945,9 @@ func (m *Maintainer) onHeartbeatRequest(msg *messaging.TargetMessage) { m.redoTsByCapture.Set(msg.From, *req.RedoWatermark) } } + if req.SyncPointControl != nil { + m.nodeAppliedSyncPointControl[msg.From] = common.NewSyncPointControlFromPB(req.SyncPointControl) + } if req.Err != nil { log.Error("dispatcher report an error", zap.Stringer("changefeedID", m.changefeedID), @@ -996,6 +1064,7 @@ func (m *Maintainer) onBootstrapResponses(responses map[node.ID]*heartbeatpb.Mai if responses == nil || m.removing.Load() { return } + m.recoverSyncPointControlFromBootstrapResponses(responses) isMySQLSinkCompatible, err := isMysqlCompatible(m.info.SinkURI) if err != nil { m.handleError(err) @@ -1148,6 +1217,9 @@ func (m *Maintainer) createBootstrapMessageFactory() bootstrap.NewBootstrapReque IsNewChangefeed: false, KeyspaceId: m.info.KeyspaceID, } + if m.syncPointControlReady { + msg.SyncPointControl = m.desiredSyncPointControl.ToPB() + } // only send dispatcher targetNodeID to dispatcher manager on the same node if targetNodeID == m.selfNode.ID { @@ -1176,6 +1248,8 @@ func (m *Maintainer) createBootstrapMessageFactory() bootstrap.NewBootstrapReque } func (m *Maintainer) onPeriodTask() { + m.reconcileSyncPointControl() + m.broadcastSyncPointControl() // send scheduling messages m.handleResendMessage() m.collectMetrics() diff --git a/maintainer/maintainer_controller.go b/maintainer/maintainer_controller.go index 1b2e3eb67c..202372f76e 100644 --- a/maintainer/maintainer_controller.go +++ b/maintainer/maintainer_controller.go @@ -44,13 +44,15 @@ type Controller struct { bootstrapped bool startTs uint64 - schedulerController *pkgscheduler.Controller - operatorController *operator.Controller - redoOperatorController *operator.Controller - spanController *span.Controller - redoSpanController *span.Controller - barrier *Barrier - redoBarrier *Barrier + schedulerController *pkgscheduler.Controller + operatorController *operator.Controller + redoOperatorController *operator.Controller + spanController *span.Controller + redoSpanController *span.Controller + barrier *Barrier + redoBarrier *Barrier + syncPointDirectPassDecider func() bool + syncPointSkipDecider func(uint64) bool messageCenter messaging.MessageCenter nodeManager *watcher.NodeManager @@ -244,6 +246,26 @@ func (c *Controller) HandleStatus(from node.ID, statusList []*heartbeatpb.TableS } } +func (c *Controller) SetSyncPointDirectPassDecider(decider func() bool) { + c.syncPointDirectPassDecider = decider + if c.barrier != nil { + c.barrier.SetSyncPointDirectPassDecider(decider) + } + if c.redoBarrier != nil { + c.redoBarrier.SetSyncPointDirectPassDecider(decider) + } +} + +func (c *Controller) SetSyncPointSkipDecider(decider func(uint64) bool) { + c.syncPointSkipDecider = decider + if c.barrier != nil { + c.barrier.SetSyncPointSkipDecider(decider) + } + if c.redoBarrier != nil { + c.redoBarrier.SetSyncPointSkipDecider(decider) + } +} + func (c *Controller) GetMinCheckpointTs(minCheckpointTs uint64) uint64 { minCheckpointTsForOperator := c.operatorController.GetMinCheckpointTs(minCheckpointTs) minCheckpointTsForSpan := c.spanController.GetMinCheckpointTsForNonReplicatingSpans(minCheckpointTs) diff --git a/maintainer/maintainer_controller_bootstrap.go b/maintainer/maintainer_controller_bootstrap.go index 305d9e4616..e82ba06fa4 100644 --- a/maintainer/maintainer_controller_bootstrap.go +++ b/maintainer/maintainer_controller_bootstrap.go @@ -365,8 +365,12 @@ func (c *Controller) initializeComponents( // Initialize barrier if c.enableRedo { c.redoBarrier = NewBarrier(c.redoSpanController, c.redoOperatorController, util.GetOrZero(c.replicaConfig.Scheduler.EnableTableAcrossNodes), allNodesResp, common.RedoMode) + c.redoBarrier.SetSyncPointDirectPassDecider(c.syncPointDirectPassDecider) + c.redoBarrier.SetSyncPointSkipDecider(c.syncPointSkipDecider) } c.barrier = NewBarrier(c.spanController, c.operatorController, util.GetOrZero(c.replicaConfig.Scheduler.EnableTableAcrossNodes), allNodesResp, common.DefaultMode) + c.barrier.SetSyncPointDirectPassDecider(c.syncPointDirectPassDecider) + c.barrier.SetSyncPointSkipDecider(c.syncPointSkipDecider) // Start scheduler c.taskHandlesMu.Lock() diff --git a/maintainer/maintainer_test.go b/maintainer/maintainer_test.go index 1df5a11e28..a1798d5041 100644 --- a/maintainer/maintainer_test.go +++ b/maintainer/maintainer_test.go @@ -35,22 +35,25 @@ import ( "github.com/pingcap/ticdc/pkg/messaging" "github.com/pingcap/ticdc/pkg/node" "github.com/pingcap/ticdc/pkg/pdutil" + "github.com/pingcap/ticdc/pkg/util" "github.com/pingcap/ticdc/server/watcher" "github.com/pingcap/ticdc/utils/threadpool" "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/oracle" "go.uber.org/atomic" "go.uber.org/zap" ) type mockDispatcherManager struct { - mc messaging.MessageCenter - self node.ID - dispatchers []*heartbeatpb.TableSpanStatus - msgCh chan *messaging.TargetMessage - maintainerID node.ID - checkpointTs uint64 - changefeedID *heartbeatpb.ChangefeedID + mc messaging.MessageCenter + self node.ID + dispatchers []*heartbeatpb.TableSpanStatus + msgCh chan *messaging.TargetMessage + maintainerID node.ID + checkpointTs uint64 + changefeedID *heartbeatpb.ChangefeedID + syncPointControl *heartbeatpb.SyncPointControl bootstrapTables []*heartbeatpb.BootstrapTableSpan dispatchersMap map[heartbeatpb.DispatcherID]*heartbeatpb.TableSpanStatus @@ -98,6 +101,8 @@ func (m *mockDispatcherManager) handleMessage(msg *messaging.TargetMessage) { m.onDispatchRequest(msg) case messaging.TypeMaintainerCloseRequest: m.onMaintainerCloseRequest(msg) + case messaging.TypeSyncPointControlMessage: + m.onSyncPointControlMessage(msg) default: log.Panic("unknown msg type", zap.Any("msg", msg)) } @@ -121,7 +126,8 @@ func (m *mockDispatcherManager) recvMessages(ctx context.Context, msg *messaging case messaging.TypeScheduleDispatcherRequest, messaging.TypeMaintainerBootstrapRequest, messaging.TypeMaintainerPostBootstrapRequest, - messaging.TypeMaintainerCloseRequest: + messaging.TypeMaintainerCloseRequest, + messaging.TypeSyncPointControlMessage: select { case <-ctx.Done(): return ctx.Err() @@ -138,12 +144,14 @@ func (m *mockDispatcherManager) onBootstrapRequest(msg *messaging.TargetMessage) req := msg.Message[0].(*heartbeatpb.MaintainerBootstrapRequest) m.maintainerID = msg.From response := &heartbeatpb.MaintainerBootstrapResponse{ - ChangefeedID: req.ChangefeedID, - Spans: m.bootstrapTables, - CheckpointTs: req.StartTs, + ChangefeedID: req.ChangefeedID, + Spans: m.bootstrapTables, + CheckpointTs: req.StartTs, + SyncPointControl: m.syncPointControl, } m.changefeedID = req.ChangefeedID m.checkpointTs = req.StartTs + m.syncPointControl = req.SyncPointControl if req.TableTriggerEventDispatcherId != nil { m.dispatchersMap[*req.TableTriggerEventDispatcherId] = &heartbeatpb.TableSpanStatus{ ID: req.TableTriggerEventDispatcherId, @@ -245,6 +253,11 @@ func (m *mockDispatcherManager) onMaintainerCloseRequest(msg *messaging.TargetMe })) } +func (m *mockDispatcherManager) onSyncPointControlMessage(msg *messaging.TargetMessage) { + req := msg.Message[0].(*heartbeatpb.SyncPointControlMessage) + m.syncPointControl = req.Control +} + func (m *mockDispatcherManager) sendHeartbeat() { if m.maintainerID.String() != "" { response := &heartbeatpb.HeartBeatRequest{ @@ -253,7 +266,8 @@ func (m *mockDispatcherManager) sendHeartbeat() { CheckpointTs: m.checkpointTs, ResolvedTs: m.checkpointTs, }, - Statuses: m.dispatchers, + Statuses: m.dispatchers, + SyncPointControl: m.syncPointControl, } m.checkpointTs++ m.sendMessages(response) @@ -472,6 +486,66 @@ func TestMaintainerCalCheckpointTsSkipsInvalidGlobalCheckpoint(t *testing.T) { wg.Wait() } +func TestMaintainerShouldDirectPassSyncPoint(t *testing.T) { + m, _ := newMaintainerForCheckpointCalculationTest(t) + clock := m.pdClock.(*pdutil.Clock4Test) + m.syncPointDirectPassThreshold = 20 * time.Minute + m.syncPointDirectPassResume = 15 * time.Minute + + checkpointTs := oracle.GoTimeToTS(time.Unix(0, 0).Add(10 * time.Minute)) + m.watermark.Watermark = &heartbeatpb.Watermark{ + CheckpointTs: checkpointTs, + ResolvedTs: checkpointTs, + } + + clock.SetTS(oracle.GoTimeToTS(time.Unix(0, 0).Add(31 * time.Minute))) + require.True(t, m.shouldDirectPassSyncPoint()) + require.True(t, m.syncPointDirectPassActive.Load()) + + clock.SetTS(oracle.GoTimeToTS(time.Unix(0, 0).Add(26 * time.Minute))) + require.True(t, m.shouldDirectPassSyncPoint()) + require.True(t, m.syncPointDirectPassActive.Load()) + + clock.SetTS(oracle.GoTimeToTS(time.Unix(0, 0).Add(24 * time.Minute))) + require.False(t, m.shouldDirectPassSyncPoint()) + require.False(t, m.syncPointDirectPassActive.Load()) +} + +func TestMaintainerReconcileSyncPointControl(t *testing.T) { + m, selfNodeID := newMaintainerForCheckpointCalculationTest(t) + replicaConfig := config.GetDefaultReplicaConfig() + replicaConfig.EnableSyncPoint = util.AddressOf(true) + replicaConfig.SyncPointInterval = util.AddressOf(time.Minute) + m.info = &config.ChangeFeedInfo{Config: replicaConfig} + m.nodeAppliedSyncPointControl = make(map[node.ID]common.SyncPointControl) + m.syncPointControlReady = true + m.syncPointDirectPassThreshold = 20 * time.Minute + m.syncPointDirectPassResume = 15 * time.Minute + m.watermark.Watermark = &heartbeatpb.Watermark{ + CheckpointTs: oracle.GoTimeToTS(time.Unix(0, 0).Add(10 * time.Minute)), + ResolvedTs: oracle.GoTimeToTS(time.Unix(0, 0).Add(10 * time.Minute)), + } + + clock := m.pdClock.(*pdutil.Clock4Test) + clock.SetTS(oracle.GoTimeToTS(time.Unix(0, 0).Add(31 * time.Minute))) + m.reconcileSyncPointControl() + require.True(t, m.authoritativeSyncPointControl.IsOpenEnded()) + require.True(t, m.desiredSyncPointControl.Equal(m.authoritativeSyncPointControl)) + + m.watermark.Watermark = &heartbeatpb.Watermark{ + CheckpointTs: oracle.GoTimeToTS(time.Unix(0, 0).Add(40 * time.Minute)), + ResolvedTs: oracle.GoTimeToTS(time.Unix(0, 0).Add(40 * time.Minute)), + } + clock.SetTS(oracle.GoTimeToTS(time.Unix(0, 0).Add(54 * time.Minute))) + m.reconcileSyncPointControl() + require.True(t, m.authoritativeSyncPointControl.IsOpenEnded()) + require.False(t, m.desiredSyncPointControl.IsOpenEnded()) + + m.nodeAppliedSyncPointControl[selfNodeID] = m.desiredSyncPointControl + m.reconcileSyncPointControl() + require.True(t, m.authoritativeSyncPointControl.Equal(m.desiredSyncPointControl)) +} + func TestMaintainerHandleRedoMetaTsMessageUsesRedoCheckpointForRedoController(t *testing.T) { m, selfNodeID := newMaintainerForRedoCheckpointCalculationTest(t) m.initialized.Store(true) diff --git a/pkg/messaging/message.go b/pkg/messaging/message.go index 3e1cc0015d..8aac3b971b 100644 --- a/pkg/messaging/message.go +++ b/pkg/messaging/message.go @@ -109,6 +109,7 @@ const ( TypeSetNodeLivenessRequest IOType = 43 TypeSetNodeLivenessResponse IOType = 44 TypeSetDispatcherDrainTargetRequest IOType = 45 + TypeSyncPointControlMessage IOType = 46 ) func (t IOType) String() string { @@ -203,6 +204,8 @@ func (t IOType) String() string { return "SetNodeLivenessResponse" case TypeSetDispatcherDrainTargetRequest: return "SetDispatcherDrainTargetRequest" + case TypeSyncPointControlMessage: + return "SyncPointControlMessage" default: } return "Unknown" @@ -395,6 +398,8 @@ func decodeIOType(ioType IOType, value []byte) (IOTypeT, error) { m = &heartbeatpb.SetNodeLivenessResponse{} case TypeSetDispatcherDrainTargetRequest: m = &heartbeatpb.SetDispatcherDrainTargetRequest{} + case TypeSyncPointControlMessage: + m = &heartbeatpb.SyncPointControlMessage{} default: log.Debug("Unimplemented IOType, ignore the message", zap.Stringer("Type", ioType)) return nil, errors.ErrUnimplementedIOType.GenWithStackByArgs(int(ioType)) @@ -515,6 +520,8 @@ func NewSingleTargetMessage(To node.ID, Topic string, Message IOTypeT, Group ... ioType = TypeSetNodeLivenessResponse case *heartbeatpb.SetDispatcherDrainTargetRequest: ioType = TypeSetDispatcherDrainTargetRequest + case *heartbeatpb.SyncPointControlMessage: + ioType = TypeSyncPointControlMessage default: panic("unknown io type") } From 31021a0241ba42c0a2cb0c74e44360ad6f04a823 Mon Sep 17 00:00:00 2001 From: dongmen <414110582@qq.com> Date: Wed, 6 May 2026 14:18:59 +0800 Subject: [PATCH 2/2] *: skip syncpoint in maintainer Signed-off-by: dongmen <414110582@qq.com> --- maintainer/sync_point_control.go | 252 +++++++++++++++++++++++++++++++ pkg/common/sync_point_control.go | 57 +++++++ 2 files changed, 309 insertions(+) create mode 100644 maintainer/sync_point_control.go create mode 100644 pkg/common/sync_point_control.go diff --git a/maintainer/sync_point_control.go b/maintainer/sync_point_control.go new file mode 100644 index 0000000000..6cd34ccc81 --- /dev/null +++ b/maintainer/sync_point_control.go @@ -0,0 +1,252 @@ +package maintainer + +import ( + "math" + "time" + + "github.com/pingcap/log" + "github.com/pingcap/ticdc/downstreamadapter/syncpoint" + "github.com/pingcap/ticdc/heartbeatpb" + "github.com/pingcap/ticdc/pkg/common" + "github.com/pingcap/ticdc/pkg/messaging" + "github.com/pingcap/ticdc/pkg/node" + "github.com/pingcap/ticdc/pkg/util" + "github.com/tikv/client-go/v2/oracle" + "go.uber.org/zap" +) + +func (m *Maintainer) syncPointControlEnabled() bool { + if m == nil || m.info == nil || m.info.Config == nil { + return false + } + return util.GetOrZero(m.info.Config.EnableSyncPoint) && util.GetOrZero(m.info.Config.SyncPointInterval) > 0 +} + +func (m *Maintainer) nextSyncPointTsAfter(ts uint64) uint64 { + if !m.syncPointControlEnabled() { + return 0 + } + interval := util.GetOrZero(m.info.Config.SyncPointInterval) + nextTs := syncpoint.CalculateStartSyncPointTs(ts, interval, false) + if nextTs <= ts { + nextTime := oracle.GetTimeFromTS(nextTs).Add(interval) + nextTs = oracle.GoTimeToTS(nextTime) + } + return nextTs +} + +func (m *Maintainer) newSyncPointControl(skipStartTs, skipEndTs uint64) common.SyncPointControl { + m.syncPointControlEpoch++ + return common.SyncPointControl{ + Epoch: m.syncPointControlEpoch, + SkipStartTs: skipStartTs, + SkipEndTs: skipEndTs, + } +} + +func (m *Maintainer) recordSyncPointControlEpoch(control common.SyncPointControl) { + if control.Epoch > m.syncPointControlEpoch { + m.syncPointControlEpoch = control.Epoch + } +} + +func (m *Maintainer) setDesiredAndAuthoritativeSyncPointControl(control common.SyncPointControl) { + m.recordSyncPointControlEpoch(control) + m.desiredSyncPointControl = control.Clone() + m.authoritativeSyncPointControl = control.Clone() +} + +func (m *Maintainer) shouldSkipSyncPoint(commitTs uint64) bool { + return m.authoritativeSyncPointControl.Contains(commitTs) +} + +func (m *Maintainer) currentSyncPointLag() time.Duration { + if m == nil { + return 0 + } + watermark := m.getWatermark() + if watermark.CheckpointTs == 0 || watermark.CheckpointTs == math.MaxUint64 { + return 0 + } + pdPhysicalTime := oracle.GetPhysical(m.pdClock.CurrentTime()) + phyCheckpointTs := oracle.ExtractPhysical(watermark.CheckpointTs) + if pdPhysicalTime <= phyCheckpointTs { + return 0 + } + return time.Duration(pdPhysicalTime-phyCheckpointTs) * time.Millisecond +} + +func (m *Maintainer) allNodesAppliedDesiredSyncPointControl() bool { + for _, id := range m.bootstrapper.GetAllNodeIDs() { + applied, ok := m.nodeAppliedSyncPointControl[id] + if !ok || !applied.Equal(m.desiredSyncPointControl) { + return false + } + } + return true +} + +func (m *Maintainer) reconcileSyncPointControl() { + if !m.syncPointControlEnabled() || !m.syncPointControlReady { + return + } + + nowTs := m.pdClock.CurrentTS() + lag := m.currentSyncPointLag() + authoritative := m.authoritativeSyncPointControl + desired := m.desiredSyncPointControl + + if lag > m.syncPointDirectPassThreshold { + if !authoritative.IsOpenEnded() { + startTs := m.nextSyncPointTsAfter(nowTs) + if startTs == 0 { + return + } + control := m.newSyncPointControl(startTs, 0) + m.setDesiredAndAuthoritativeSyncPointControl(control) + log.Info("syncpoint skip window enabled", + zap.Stringer("changefeedID", m.changefeedID), + zap.Uint64("epoch", control.Epoch), + zap.Uint64("skipStartTs", control.SkipStartTs)) + } + return + } + + if !authoritative.IsOpenEnded() { + if !authoritative.Disabled() && authoritative.SkipEndTs != 0 && m.getWatermark().CheckpointTs >= authoritative.SkipEndTs { + control := m.newSyncPointControl(0, 0) + m.setDesiredAndAuthoritativeSyncPointControl(control) + log.Info("syncpoint skip window fully cleared", + zap.Stringer("changefeedID", m.changefeedID), + zap.Uint64("epoch", control.Epoch)) + } + return + } + + if lag > m.syncPointDirectPassResume { + return + } + + if desired.IsOpenEnded() { + endTs := m.nextSyncPointTsAfter(nowTs) + if endTs == 0 || endTs <= authoritative.SkipStartTs { + return + } + control := m.newSyncPointControl(authoritative.SkipStartTs, endTs) + m.desiredSyncPointControl = control + log.Info("syncpoint skip window starts resuming", + zap.Stringer("changefeedID", m.changefeedID), + zap.Uint64("epoch", control.Epoch), + zap.Uint64("skipStartTs", control.SkipStartTs), + zap.Uint64("skipEndTs", control.SkipEndTs)) + return + } + + if desired.SkipEndTs != 0 && desired.SkipEndTs <= nowTs && !m.allNodesAppliedDesiredSyncPointControl() { + endTs := m.nextSyncPointTsAfter(nowTs) + if endTs != 0 && endTs > desired.SkipStartTs { + control := m.newSyncPointControl(desired.SkipStartTs, endTs) + m.desiredSyncPointControl = control + log.Info("syncpoint resume boundary reproposed", + zap.Stringer("changefeedID", m.changefeedID), + zap.Uint64("epoch", control.Epoch), + zap.Uint64("skipStartTs", control.SkipStartTs), + zap.Uint64("skipEndTs", control.SkipEndTs)) + } + return + } + + if m.allNodesAppliedDesiredSyncPointControl() && !authoritative.Equal(desired) { + m.authoritativeSyncPointControl = desired.Clone() + log.Info("syncpoint authoritative window resumed", + zap.Stringer("changefeedID", m.changefeedID), + zap.Uint64("epoch", desired.Epoch), + zap.Uint64("skipStartTs", desired.SkipStartTs), + zap.Uint64("skipEndTs", desired.SkipEndTs)) + } +} + +func (m *Maintainer) broadcastSyncPointControl() { + if !m.syncPointControlEnabled() || !m.syncPointControlReady { + return + } + msgs := make([]*messaging.TargetMessage, 0, len(m.bootstrapper.GetAllNodeIDs())) + control := m.desiredSyncPointControl + for _, id := range m.bootstrapper.GetAllNodeIDs() { + msgs = append(msgs, messaging.NewSingleTargetMessage( + id, + messaging.HeartbeatCollectorTopic, + &heartbeatpb.SyncPointControlMessage{ + ChangefeedID: m.changefeedID.ToPB(), + Control: control.ToPB(), + }, + )) + } + m.sendMessages(msgs) +} + +func (m *Maintainer) recoverSyncPointControlFromBootstrapResponses(responses map[node.ID]*heartbeatpb.MaintainerBootstrapResponse) { + if len(responses) == 0 { + return + } + + var ( + hasControl bool + supported = true + openEnded bool + minStartTs uint64 + maxEndTs uint64 + maxEpoch uint64 + ) + + for id, resp := range responses { + if resp.SyncPointControl == nil { + supported = false + continue + } + control := common.NewSyncPointControlFromPB(resp.SyncPointControl) + m.nodeAppliedSyncPointControl[id] = control + if control.Epoch > maxEpoch { + maxEpoch = control.Epoch + } + if control.Disabled() { + continue + } + if !hasControl || control.SkipStartTs < minStartTs { + minStartTs = control.SkipStartTs + } + if control.IsOpenEnded() { + openEnded = true + } else if control.SkipEndTs > maxEndTs { + maxEndTs = control.SkipEndTs + } + hasControl = true + } + + if maxEpoch > m.syncPointControlEpoch { + m.syncPointControlEpoch = maxEpoch + } + if !supported { + m.syncPointControlReady = false + m.desiredSyncPointControl = common.NewDisabledSyncPointControl() + m.authoritativeSyncPointControl = common.NewDisabledSyncPointControl() + log.Warn("disable syncpoint skip window because some nodes do not support syncpoint control", + zap.Stringer("changefeedID", m.changefeedID)) + return + } + m.syncPointControlReady = true + if !hasControl { + return + } + + recovered := m.newSyncPointControl(minStartTs, maxEndTs) + if openEnded { + recovered.SkipEndTs = 0 + } + m.setDesiredAndAuthoritativeSyncPointControl(recovered) + log.Info("recover syncpoint control from bootstrap responses", + zap.Stringer("changefeedID", m.changefeedID), + zap.Uint64("epoch", recovered.Epoch), + zap.Uint64("skipStartTs", recovered.SkipStartTs), + zap.Uint64("skipEndTs", recovered.SkipEndTs)) +} diff --git a/pkg/common/sync_point_control.go b/pkg/common/sync_point_control.go new file mode 100644 index 0000000000..58c4aad001 --- /dev/null +++ b/pkg/common/sync_point_control.go @@ -0,0 +1,57 @@ +package common + +import "github.com/pingcap/ticdc/heartbeatpb" + +type SyncPointControl struct { + Epoch uint64 + SkipStartTs uint64 + SkipEndTs uint64 +} + +func NewDisabledSyncPointControl() SyncPointControl { + return SyncPointControl{} +} + +func NewSyncPointControlFromPB(control *heartbeatpb.SyncPointControl) SyncPointControl { + if control == nil { + return NewDisabledSyncPointControl() + } + return SyncPointControl{ + Epoch: control.Epoch, + SkipStartTs: control.SkipStartTs, + SkipEndTs: control.SkipEndTs, + } +} + +func (c SyncPointControl) ToPB() *heartbeatpb.SyncPointControl { + return &heartbeatpb.SyncPointControl{ + Epoch: c.Epoch, + SkipStartTs: c.SkipStartTs, + SkipEndTs: c.SkipEndTs, + } +} + +func (c SyncPointControl) Disabled() bool { + return c.SkipStartTs == 0 && c.SkipEndTs == 0 +} + +func (c SyncPointControl) IsOpenEnded() bool { + return c.SkipStartTs != 0 && c.SkipEndTs == 0 +} + +func (c SyncPointControl) Contains(ts uint64) bool { + if c.Disabled() || ts < c.SkipStartTs { + return false + } + return c.SkipEndTs == 0 || ts < c.SkipEndTs +} + +func (c SyncPointControl) Equal(other SyncPointControl) bool { + return c.Epoch == other.Epoch && + c.SkipStartTs == other.SkipStartTs && + c.SkipEndTs == other.SkipEndTs +} + +func (c SyncPointControl) Clone() SyncPointControl { + return c +}