Repository: matrixorigin/matrixone
Pull request #3842 (2022-07-10 06:04:08)

hakeeper: added CN support
**What type of PR is this?**

- [ ] API-change
- [ ] BUG
- [ ] Improvement
- [ ] Documentation
- [x] Feature
- [ ] Test and CI
- [ ] Code Refactoring

**Which issue(s) this PR fixes:**

issue #

**What this PR does / why we need it:**

Added HAKeeper CN support. It currently only keeps heartbeats from CNs. API required to query available CN is not included in this PR. 

**Special notes for your reviewer:**

Not Available

**Additional documentation (e.g. design docs, usage docs, etc.):**

Not Available



Patch:
diff --git a/pkg/hakeeper/rsm.go b/pkg/hakeeper/rsm.go
index 03f9572d0..94b51ba20 100644
--- a/pkg/hakeeper/rsm.go
+++ b/pkg/hakeeper/rsm.go
@@ -118,6 +118,10 @@ func GetGetIDCmd(count uint64) []byte {
 	return cmd
 }
 
+func isCNHeartbeatCmd(cmd []byte) bool {
+	return isHeartbeatCmd(cmd, pb.CNHeartbeatUpdate)
+}
+
 func isDNHeartbeatCmd(cmd []byte) bool {
 	return isHeartbeatCmd(cmd, pb.DNHeartbeatUpdate)
 }
@@ -174,6 +178,10 @@ func GetLogStoreHeartbeatCmd(data []byte) []byte {
 	return getHeartbeatCmd(data, pb.LogHeartbeatUpdate)
 }
 
+func GetCNStoreHeartbeatCmd(data []byte) []byte {
+	return getHeartbeatCmd(data, pb.CNHeartbeatUpdate)
+}
+
 func GetDNStoreHeartbeatCmd(data []byte) []byte {
 	return getHeartbeatCmd(data, pb.DNHeartbeatUpdate)
 }
@@ -242,6 +250,16 @@ func (s *stateMachine) handleUpdateCommandsCmd(cmd []byte) sm.Result {
 	return sm.Result{}
 }
 
+func (s *stateMachine) handleCNHeartbeat(cmd []byte) sm.Result {
+	data := parseHeartbeatCmd(cmd)
+	var hb pb.CNStoreHeartbeat
+	if err := hb.Unmarshal(data); err != nil {
+		panic(err)
+	}
+	s.state.CNState.Update(hb, s.state.Tick)
+	return sm.Result{}
+}
+
 func (s *stateMachine) handleDNHeartbeat(cmd []byte) sm.Result {
 	data := parseHeartbeatCmd(cmd)
 	var hb pb.DNStoreHeartbeat
@@ -351,6 +369,8 @@ func (s *stateMachine) Update(e sm.Entry) (sm.Result, error) {
 	cmd := e.Cmd
 	if isDNHeartbeatCmd(cmd) {
 		return s.handleDNHeartbeat(cmd), nil
+	} else if isCNHeartbeatCmd(cmd) {
+		return s.handleCNHeartbeat(cmd), nil
 	} else if isLogHeartbeatCmd(cmd) {
 		return s.handleLogHeartbeat(cmd), nil
 	} else if isTickCmd(cmd) {
diff --git a/pkg/logservice/service.go b/pkg/logservice/service.go
index a7c7d9d66..55e3d1e7e 100644
--- a/pkg/logservice/service.go
+++ b/pkg/logservice/service.go
@@ -164,10 +164,12 @@ func (s *Service) handle(req pb.Request,
 		return s.handleConnectRO(req), pb.LogRecordResponse{}
 	case pb.LOG_HEARTBEAT:
 		return s.handleLogHeartbeat(req), pb.LogRecordResponse{}
+	case pb.CN_HEARTBEAT:
+		return s.handleCNHeartbeat(req), pb.LogRecordResponse{}
 	case pb.DN_HEARTBEAT:
 		return s.handleDNHeartbeat(req), pb.LogRecordResponse{}
 	default:
-		panic("unknown method type")
+		panic("unknown log service method type")
 	}
 }
 
@@ -284,6 +286,19 @@ func (s *Service) handleLogHeartbeat(req pb.Request) pb.Response {
 	return resp
 }
 
+func (s *Service) handleCNHeartbeat(req pb.Request) pb.Response {
+	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(req.Timeout))
+	defer cancel()
+	hb := req.CNHeartbeat
+	resp := getResponse(req)
+	if err := s.store.addCNStoreHeartbeat(ctx, hb); err != nil {
+		resp.ErrorCode, resp.ErrorMessage = toErrorCode(err)
+		return resp
+	}
+
+	return resp
+}
+
 func (s *Service) handleDNHeartbeat(req pb.Request) pb.Response {
 	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(req.Timeout))
 	defer cancel()
diff --git a/pkg/logservice/store.go b/pkg/logservice/store.go
index f0ee6ce39..3e67f32a4 100644
--- a/pkg/logservice/store.go
+++ b/pkg/logservice/store.go
@@ -345,6 +345,18 @@ func (l *store) addLogStoreHeartbeat(ctx context.Context,
 	return nil
 }
 
+func (l *store) addCNStoreHeartbeat(ctx context.Context,
+	hb pb.CNStoreHeartbeat) error {
+	data := MustMarshal(&hb)
+	cmd := hakeeper.GetCNStoreHeartbeatCmd(data)
+	session := l.nh.GetNoOPSession(hakeeper.DefaultHAKeeperShardID)
+	if _, err := l.propose(ctx, session, cmd); err != nil {
+		plog.Errorf("propose failed, %v", err)
+		return err
+	}
+	return nil
+}
+
 func (l *store) addDNStoreHeartbeat(ctx context.Context,
 	hb pb.DNStoreHeartbeat) error {
 	data := MustMarshal(&hb)
diff --git a/pkg/pb/logservice/logservice.go b/pkg/pb/logservice/logservice.go
index 24bc28275..da1cf98a5 100644
--- a/pkg/pb/logservice/logservice.go
+++ b/pkg/pb/logservice/logservice.go
@@ -41,6 +41,7 @@ func NewRSMState() HAKeeperRSMState {
 	return HAKeeperRSMState{
 		ScheduleCommands: make(map[string]CommandBatch),
 		LogShards:        make(map[string]uint64),
+		CNState:          NewCNState(),
 		DNState:          NewDNState(),
 		LogState:         NewLogState(),
 		ClusterInfo:      newClusterInfo(),
@@ -54,6 +55,24 @@ func newClusterInfo() ClusterInfo {
 	}
 }
 
+// NewCNState creates a new CNState.
+func NewCNState() CNState {
+	return CNState{
+		Stores: make(map[string]CNStoreInfo),
+	}
+}
+
+// Update applies the incoming CNStoreHeartbeat into HAKeeper. Tick is the
+// current tick of the HAKeeper which is used as the timestamp of the heartbeat.
+func (s *CNState) Update(hb CNStoreHeartbeat, tick uint64) {
+	storeInfo, ok := s.Stores[hb.UUID]
+	if !ok {
+		storeInfo = CNStoreInfo{}
+	}
+	storeInfo.Tick = tick
+	s.Stores[hb.UUID] = storeInfo
+}
+
 // NewDNState creates a new DNState.
 func NewDNState() DNState {
 	return DNState{
@@ -62,8 +81,7 @@ func NewDNState() DNState {
 }
 
 // Update applies the incoming DNStoreHeartbeat into HAKeeper. Tick is the
-// current tick of the HAKeeper which can be used as the timestamp of the
-// heartbeat.
+// current tick of the HAKeeper which is used as the timestamp of the heartbeat.
 func (s *DNState) Update(hb DNStoreHeartbeat, tick uint64) {
 	storeInfo, ok := s.Stores[hb.UUID]
 	if !ok {
diff --git a/pkg/pb/logservice/logservice.pb.go b/pkg/pb/logservice/logservice.pb.go
index ab1f421f9..e128dfe15 100644
--- a/pkg/pb/logservice/logservice.pb.go
+++ b/pkg/pb/logservice/logservice.pb.go
@@ -67,7 +67,8 @@ const (
 	CONNECT       MethodType = 5
 	CONNECT_RO    MethodType = 6
 	LOG_HEARTBEAT MethodType = 7
-	DN_HEARTBEAT  MethodType = 8
+	CN_HEARTBEAT  MethodType = 8
+	DN_HEARTBEAT  MethodType = 9
 )
 
 var MethodType_name = map[int32]string{
@@ -79,7 +80,8 @@ var MethodType_name = map[int32]string{
 	5: "CONNECT",
 	6: "CONNECT_RO",
 	7: "LOG_HEARTBEAT",
-	8: "DN_HEARTBEAT",
+	8: "CN_HEARTBEAT",
+	9: "DN_HEARTBEAT",
 }
 
 var MethodType_value = map[string]int32{
@@ -91,7 +93,8 @@ var MethodType_value = map[string]int32{
 	"CONNECT":       5,
 	"CONNECT_RO":    6,
 	"LOG_HEARTBEAT": 7,
-	"DN_HEARTBEAT":  8,
+	"CN_HEARTBEAT":  8,
+	"DN_HEARTBEAT":  9,
 }
 
 func (x MethodType) String() string {
@@ -198,32 +201,35 @@ type HAKeeperUpdateType int32
 
 const (
 	TickUpdate            HAKeeperUpdateType = 0
-	DNHeartbeatUpdate     HAKeeperUpdateType = 1
-	LogHeartbeatUpdate    HAKeeperUpdateType = 2
-	GetIDUpdate           HAKeeperUpdateType = 3
-	ScheduleCommandUpdate HAKeeperUpdateType = 4
-	SetStateUpdate        HAKeeperUpdateType = 5
-	InitialClusterUpdate  HAKeeperUpdateType = 6
+	CNHeartbeatUpdate     HAKeeperUpdateType = 1
+	DNHeartbeatUpdate     HAKeeperUpdateType = 2
+	LogHeartbeatUpdate    HAKeeperUpdateType = 3
+	GetIDUpdate           HAKeeperUpdateType = 4
+	ScheduleCommandUpdate HAKeeperUpdateType = 5
+	SetStateUpdate        HAKeeperUpdateType = 6
+	InitialClusterUpdate  HAKeeperUpdateType = 7
 )
 
 var HAKeeperUpdateType_name = map[int32]string{
 	0: "TickUpdate",
-	1: "DNHeartbeatUpdate",
-	2: "LogHeartbeatUpdate",
-	3: "GetIDUpdate",
-	4: "ScheduleCommandUpdate",
-	5: "SetStateUpdate",
-	6: "InitialClusterUpdate",
+	1: "CNHeartbeatUpdate",
+	2: "DNHeartbeatUpdate",
+	3: "LogHeartbeatUpdate",
+	4: "GetIDUpdate",
+	5: "ScheduleCommandUpdate",
+	6: "SetStateUpdate",
+	7: "InitialClusterUpdate",
 }
 
 var HAKeeperUpdateType_value = map[string]int32{
 	"TickUpdate":            0,
-	"DNHeartbeatUpdate":     1,
-	"LogHeartbeatUpdate":    2,
-	"GetIDUpdate":           3,
-	"ScheduleCommandUpdate": 4,
-	"SetStateUpdate":        5,
-	"InitialClusterUpdate":  6,
+	"CNHeartbeatUpdate":     1,
+	"DNHeartbeatUpdate":     2,
+	"LogHeartbeatUpdate":    3,
+	"GetIDUpdate":           4,
+	"ScheduleCommandUpdate": 5,
+	"SetStateUpdate":        6,
+	"InitialClusterUpdate":  7,
 }
 
 func (x HAKeeperUpdateType) String() string {
@@ -464,6 +470,54 @@ func (m *LogReplicaInfo) GetReplicaID() uint64 {
 	return 0
 }
 
+// CNStoreHeartbeat is the periodic message sent tp the HAKeeper by CN stores.
+type CNStoreHeartbeat struct {
+	UUID                 string   `protobuf:"bytes,1,opt,name=UUID,proto3" json:"UUID,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *CNStoreHeartbeat) Reset()         { *m = CNStoreHeartbeat{} }
+func (m *CNStoreHeartbeat) String() string { return proto.CompactTextString(m) }
+func (*CNStoreHeartbeat) ProtoMessage()    {}
+func (*CNStoreHeartbeat) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fd1040c5381ab5a7, []int{2}
+}
+func (m *CNStoreHeartbeat) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *CNStoreHeartbeat) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_CNStoreHeartbeat.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 *CNStoreHeartbeat) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_CNStoreHeartbeat.Merge(m, src)
+}
+func (m *CNStoreHeartbeat) XXX_Size() int {
+	return m.Size()
+}
+func (m *CNStoreHeartbeat) XXX_DiscardUnknown() {
+	xxx_messageInfo_CNStoreHeartbeat.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CNStoreHeartbeat proto.InternalMessageInfo
+
+func (m *CNStoreHeartbeat) GetUUID() string {
+	if m != nil {
+		return m.UUID
+	}
+	return ""
+}
+
 // LogStoreHeartbeat is the periodic message sent to the HAKeeper by Log Stores.
 type LogStoreHeartbeat struct {
 	// UUID is the uuid of the Log Store.
@@ -485,7 +539,7 @@ func (m *LogStoreHeartbeat) Reset()         { *m = LogStoreHeartbeat{} }
 func (m *LogStoreHeartbeat) String() string { return proto.CompactTextString(m) }
 func (*LogStoreHeartbeat) ProtoMessage()    {}
 func (*LogStoreHeartbeat) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{2}
+	return fileDescriptor_fd1040c5381ab5a7, []int{3}
 }
 func (m *LogStoreHeartbeat) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -567,7 +621,7 @@ func (m *DNShardInfo) Reset()         { *m = DNShardInfo{} }
 func (m *DNShardInfo) String() string { return proto.CompactTextString(m) }
 func (*DNShardInfo) ProtoMessage()    {}
 func (*DNShardInfo) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{3}
+	return fileDescriptor_fd1040c5381ab5a7, []int{4}
 }
 func (m *DNShardInfo) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -626,7 +680,7 @@ func (m *DNStoreHeartbeat) Reset()         { *m = DNStoreHeartbeat{} }
 func (m *DNStoreHeartbeat) String() string { return proto.CompactTextString(m) }
 func (*DNStoreHeartbeat) ProtoMessage()    {}
 func (*DNStoreHeartbeat) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{4}
+	return fileDescriptor_fd1040c5381ab5a7, []int{5}
 }
 func (m *DNStoreHeartbeat) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -684,7 +738,7 @@ func (m *RSMState) Reset()         { *m = RSMState{} }
 func (m *RSMState) String() string { return proto.CompactTextString(m) }
 func (*RSMState) ProtoMessage()    {}
 func (*RSMState) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{5}
+	return fileDescriptor_fd1040c5381ab5a7, []int{6}
 }
 func (m *RSMState) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -762,7 +816,7 @@ func (m *LogRecord) Reset()         { *m = LogRecord{} }
 func (m *LogRecord) String() string { return proto.CompactTextString(m) }
 func (*LogRecord) ProtoMessage()    {}
 func (*LogRecord) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{6}
+	return fileDescriptor_fd1040c5381ab5a7, []int{7}
 }
 func (m *LogRecord) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -828,7 +882,7 @@ func (m *LogRequest) Reset()         { *m = LogRequest{} }
 func (m *LogRequest) String() string { return proto.CompactTextString(m) }
 func (*LogRequest) ProtoMessage()    {}
 func (*LogRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{7}
+	return fileDescriptor_fd1040c5381ab5a7, []int{8}
 }
 func (m *LogRequest) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -910,7 +964,7 @@ func (m *TsoRequest) Reset()         { *m = TsoRequest{} }
 func (m *TsoRequest) String() string { return proto.CompactTextString(m) }
 func (*TsoRequest) ProtoMessage()    {}
 func (*TsoRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{8}
+	return fileDescriptor_fd1040c5381ab5a7, []int{9}
 }
 func (m *TsoRequest) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -952,8 +1006,9 @@ type Request struct {
 	Timeout              int64             `protobuf:"varint,3,opt,name=Timeout,proto3" json:"Timeout,omitempty"`
 	LogRequest           LogRequest        `protobuf:"bytes,4,opt,name=LogRequest,proto3" json:"LogRequest"`
 	LogHeartbeat         LogStoreHeartbeat `protobuf:"bytes,5,opt,name=LogHeartbeat,proto3" json:"LogHeartbeat"`
-	DNHeartbeat          DNStoreHeartbeat  `protobuf:"bytes,6,opt,name=DNHeartbeat,proto3" json:"DNHeartbeat"`
-	TsoRequest           TsoRequest        `protobuf:"bytes,7,opt,name=TsoRequest,proto3" json:"TsoRequest"`
+	CNHeartbeat          CNStoreHeartbeat  `protobuf:"bytes,6,opt,name=CNHeartbeat,proto3" json:"CNHeartbeat"`
+	DNHeartbeat          DNStoreHeartbeat  `protobuf:"bytes,7,opt,name=DNHeartbeat,proto3" json:"DNHeartbeat"`
+	TsoRequest           TsoRequest        `protobuf:"bytes,8,opt,name=TsoRequest,proto3" json:"TsoRequest"`
 	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
 	XXX_unrecognized     []byte            `json:"-"`
 	XXX_sizecache        int32             `json:"-"`
@@ -963,7 +1018,7 @@ func (m *Request) Reset()         { *m = Request{} }
 func (m *Request) String() string { return proto.CompactTextString(m) }
 func (*Request) ProtoMessage()    {}
 func (*Request) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{9}
+	return fileDescriptor_fd1040c5381ab5a7, []int{10}
 }
 func (m *Request) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1027,6 +1082,13 @@ func (m *Request) GetLogHeartbeat() LogStoreHeartbeat {
 	return LogStoreHeartbeat{}
 }
 
+func (m *Request) GetCNHeartbeat() CNStoreHeartbeat {
+	if m != nil {
+		return m.CNHeartbeat
+	}
+	return CNStoreHeartbeat{}
+}
+
 func (m *Request) GetDNHeartbeat() DNStoreHeartbeat {
 	if m != nil {
 		return m.DNHeartbeat
@@ -1054,7 +1116,7 @@ func (m *LogResponse) Reset()         { *m = LogResponse{} }
 func (m *LogResponse) String() string { return proto.CompactTextString(m) }
 func (*LogResponse) ProtoMessage()    {}
 func (*LogResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{10}
+	return fileDescriptor_fd1040c5381ab5a7, []int{11}
 }
 func (m *LogResponse) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1121,7 +1183,7 @@ func (m *Response) Reset()         { *m = Response{} }
 func (m *Response) String() string { return proto.CompactTextString(m) }
 func (*Response) ProtoMessage()    {}
 func (*Response) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{11}
+	return fileDescriptor_fd1040c5381ab5a7, []int{12}
 }
 func (m *Response) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1210,7 +1272,7 @@ func (m *LogRecordResponse) Reset()         { *m = LogRecordResponse{} }
 func (m *LogRecordResponse) String() string { return proto.CompactTextString(m) }
 func (*LogRecordResponse) ProtoMessage()    {}
 func (*LogRecordResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{12}
+	return fileDescriptor_fd1040c5381ab5a7, []int{13}
 }
 func (m *LogRecordResponse) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1257,7 +1319,7 @@ func (m *TsoResponse) Reset()         { *m = TsoResponse{} }
 func (m *TsoResponse) String() string { return proto.CompactTextString(m) }
 func (*TsoResponse) ProtoMessage()    {}
 func (*TsoResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{13}
+	return fileDescriptor_fd1040c5381ab5a7, []int{14}
 }
 func (m *TsoResponse) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1309,7 +1371,7 @@ func (m *Replica) Reset()         { *m = Replica{} }
 func (m *Replica) String() string { return proto.CompactTextString(m) }
 func (*Replica) ProtoMessage()    {}
 func (*Replica) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{14}
+	return fileDescriptor_fd1040c5381ab5a7, []int{15}
 }
 func (m *Replica) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1381,7 +1443,7 @@ func (m *ConfigChange) Reset()         { *m = ConfigChange{} }
 func (m *ConfigChange) String() string { return proto.CompactTextString(m) }
 func (*ConfigChange) ProtoMessage()    {}
 func (*ConfigChange) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{15}
+	return fileDescriptor_fd1040c5381ab5a7, []int{16}
 }
 func (m *ConfigChange) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1443,7 +1505,7 @@ func (m *ShutdownStore) Reset()         { *m = ShutdownStore{} }
 func (m *ShutdownStore) String() string { return proto.CompactTextString(m) }
 func (*ShutdownStore) ProtoMessage()    {}
 func (*ShutdownStore) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{16}
+	return fileDescriptor_fd1040c5381ab5a7, []int{17}
 }
 func (m *ShutdownStore) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1496,7 +1558,7 @@ func (m *ScheduleCommand) Reset()         { *m = ScheduleCommand{} }
 func (m *ScheduleCommand) String() string { return proto.CompactTextString(m) }
 func (*ScheduleCommand) ProtoMessage()    {}
 func (*ScheduleCommand) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{17}
+	return fileDescriptor_fd1040c5381ab5a7, []int{18}
 }
 func (m *ScheduleCommand) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1572,7 +1634,7 @@ func (m *CommandBatch) Reset()         { *m = CommandBatch{} }
 func (m *CommandBatch) String() string { return proto.CompactTextString(m) }
 func (*CommandBatch) ProtoMessage()    {}
 func (*CommandBatch) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{18}
+	return fileDescriptor_fd1040c5381ab5a7, []int{19}
 }
 func (m *CommandBatch) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1615,7 +1677,104 @@ func (m *CommandBatch) GetCommands() []ScheduleCommand {
 	return nil
 }
 
-// DNStoreInfo contins information on a list of shards.
+// CNStoreInfo contains infroamtion on a CN store.
+type CNStoreInfo struct {
+	Tick                 uint64   `protobuf:"varint,1,opt,name=Tick,proto3" json:"Tick,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *CNStoreInfo) Reset()         { *m = CNStoreInfo{} }
+func (m *CNStoreInfo) String() string { return proto.CompactTextString(m) }
+func (*CNStoreInfo) ProtoMessage()    {}
+func (*CNStoreInfo) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fd1040c5381ab5a7, []int{20}
+}
+func (m *CNStoreInfo) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *CNStoreInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_CNStoreInfo.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 *CNStoreInfo) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_CNStoreInfo.Merge(m, src)
+}
+func (m *CNStoreInfo) XXX_Size() int {
+	return m.Size()
+}
+func (m *CNStoreInfo) XXX_DiscardUnknown() {
+	xxx_messageInfo_CNStoreInfo.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CNStoreInfo proto.InternalMessageInfo
+
+func (m *CNStoreInfo) GetTick() uint64 {
+	if m != nil {
+		return m.Tick
+	}
+	return 0
+}
+
+// CNState contains all CN details known to the HAKeeper.
+type CNState struct {
+	// Stores is keyed by CN store UUID.
+	Stores               map[string]CNStoreInfo `protobuf:"bytes,1,rep,name=Stores,proto3" json:"Stores" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	XXX_NoUnkeyedLiteral struct{}               `json:"-"`
+	XXX_unrecognized     []byte                 `json:"-"`
+	XXX_sizecache        int32                  `json:"-"`
+}
+
+func (m *CNState) Reset()         { *m = CNState{} }
+func (m *CNState) String() string { return proto.CompactTextString(m) }
+func (*CNState) ProtoMessage()    {}
+func (*CNState) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fd1040c5381ab5a7, []int{21}
+}
+func (m *CNState) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *CNState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_CNState.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 *CNState) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_CNState.Merge(m, src)
+}
+func (m *CNState) XXX_Size() int {
+	return m.Size()
+}
+func (m *CNState) XXX_DiscardUnknown() {
+	xxx_messageInfo_CNState.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CNState proto.InternalMessageInfo
+
+func (m *CNState) GetStores() map[string]CNStoreInfo {
+	if m != nil {
+		return m.Stores
+	}
+	return nil
+}
+
+// DNStoreInfo contins information on a DN store.
 type DNStoreInfo struct {
 	Tick                 uint64        `protobuf:"varint,1,opt,name=Tick,proto3" json:"Tick,omitempty"`
 	Shards               []DNShardInfo `protobuf:"bytes,2,rep,name=Shards,proto3" json:"Shards"`
@@ -1628,7 +1787,7 @@ func (m *DNStoreInfo) Reset()         { *m = DNStoreInfo{} }
 func (m *DNStoreInfo) String() string { return proto.CompactTextString(m) }
 func (*DNStoreInfo) ProtoMessage()    {}
 func (*DNStoreInfo) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{19}
+	return fileDescriptor_fd1040c5381ab5a7, []int{22}
 }
 func (m *DNStoreInfo) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1673,8 +1832,7 @@ func (m *DNStoreInfo) GetShards() []DNShardInfo {
 
 // DNState contains all DN details known to the HAKeeper.
 type DNState struct {
-	// Stores is keyed by DN store UUID, it contains details found on each DN
-	// store. Each DNStoreInfo reflects what was last reported by each DN store.
+	// Stores is keyed by DN store UUID.
 	Stores               map[string]DNStoreInfo `protobuf:"bytes,1,rep,name=Stores,proto3" json:"Stores" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
 	XXX_NoUnkeyedLiteral struct{}               `json:"-"`
 	XXX_unrecognized     []byte                 `json:"-"`
@@ -1685,7 +1843,7 @@ func (m *DNState) Reset()         { *m = DNState{} }
 func (m *DNState) String() string { return proto.CompactTextString(m) }
 func (*DNState) ProtoMessage()    {}
 func (*DNState) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{20}
+	return fileDescriptor_fd1040c5381ab5a7, []int{23}
 }
 func (m *DNState) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1736,7 +1894,7 @@ func (m *ClusterInfo) Reset()         { *m = ClusterInfo{} }
 func (m *ClusterInfo) String() string { return proto.CompactTextString(m) }
 func (*ClusterInfo) ProtoMessage()    {}
 func (*ClusterInfo) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{21}
+	return fileDescriptor_fd1040c5381ab5a7, []int{24}
 }
 func (m *ClusterInfo) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1792,7 +1950,7 @@ func (m *InitialClusterRequest) Reset()         { *m = InitialClusterRequest{} }
 func (m *InitialClusterRequest) String() string { return proto.CompactTextString(m) }
 func (*InitialClusterRequest) ProtoMessage()    {}
 func (*InitialClusterRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{22}
+	return fileDescriptor_fd1040c5381ab5a7, []int{25}
 }
 func (m *InitialClusterRequest) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1858,7 +2016,7 @@ func (m *LogStoreInfo) Reset()         { *m = LogStoreInfo{} }
 func (m *LogStoreInfo) String() string { return proto.CompactTextString(m) }
 func (*LogStoreInfo) ProtoMessage()    {}
 func (*LogStoreInfo) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{23}
+	return fileDescriptor_fd1040c5381ab5a7, []int{26}
 }
 func (m *LogStoreInfo) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1941,7 +2099,7 @@ func (m *LogState) Reset()         { *m = LogState{} }
 func (m *LogState) String() string { return proto.CompactTextString(m) }
 func (*LogState) ProtoMessage()    {}
 func (*LogState) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{24}
+	return fileDescriptor_fd1040c5381ab5a7, []int{27}
 }
 func (m *LogState) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2001,7 +2159,7 @@ func (m *CheckerState) Reset()         { *m = CheckerState{} }
 func (m *CheckerState) String() string { return proto.CompactTextString(m) }
 func (*CheckerState) ProtoMessage()    {}
 func (*CheckerState) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{25}
+	return fileDescriptor_fd1040c5381ab5a7, []int{28}
 }
 func (m *CheckerState) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2073,9 +2231,10 @@ type HAKeeperRSMState struct {
 	State                HAKeeperState           `protobuf:"varint,4,opt,name=State,proto3,enum=logservice.HAKeeperState" json:"State,omitempty"`
 	ScheduleCommands     map[string]CommandBatch `protobuf:"bytes,5,rep,name=ScheduleCommands,proto3" json:"ScheduleCommands" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
 	LogShards            map[string]uint64       `protobuf:"bytes,6,rep,name=LogShards,proto3" json:"LogShards,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
-	DNState              DNState                 `protobuf:"bytes,7,opt,name=DNState,proto3" json:"DNState"`
-	LogState             LogState                `protobuf:"bytes,8,opt,name=LogState,proto3" json:"LogState"`
-	ClusterInfo          ClusterInfo             `protobuf:"bytes,9,opt,name=ClusterInfo,proto3" json:"ClusterInfo"`
+	CNState              CNState                 `protobuf:"bytes,7,opt,name=CNState,proto3" json:"CNState"`
+	DNState              DNState                 `protobuf:"bytes,8,opt,name=DNState,proto3" json:"DNState"`
+	LogState             LogState                `protobuf:"bytes,9,opt,name=LogState,proto3" json:"LogState"`
+	ClusterInfo          ClusterInfo             `protobuf:"bytes,10,opt,name=ClusterInfo,proto3" json:"ClusterInfo"`
 	XXX_NoUnkeyedLiteral struct{}                `json:"-"`
 	XXX_unrecognized     []byte                  `json:"-"`
 	XXX_sizecache        int32                   `json:"-"`
@@ -2085,7 +2244,7 @@ func (m *HAKeeperRSMState) Reset()         { *m = HAKeeperRSMState{} }
 func (m *HAKeeperRSMState) String() string { return proto.CompactTextString(m) }
 func (*HAKeeperRSMState) ProtoMessage()    {}
 func (*HAKeeperRSMState) Descriptor() ([]byte, []int) {
-	return fileDescriptor_fd1040c5381ab5a7, []int{26}
+	return fileDescriptor_fd1040c5381ab5a7, []int{29}
 }
 func (m *HAKeeperRSMState) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2156,6 +2315,13 @@ func (m *HAKeeperRSMState) GetLogShards() map[string]uint64 {
 	return nil
 }
 
+func (m *HAKeeperRSMState) GetCNState() CNState {
+	if m != nil {
+		return m.CNState
+	}
+	return CNState{}
+}
+
 func (m *HAKeeperRSMState) GetDNState() DNState {
 	if m != nil {
 		return m.DNState
@@ -2189,6 +2355,7 @@ func init() {
 	proto.RegisterType((*LogShardInfo)(nil), "logservice.LogShardInfo")
 	proto.RegisterMapType((map[uint64]string)(nil), "logservice.LogShardInfo.ReplicasEntry")
 	proto.RegisterType((*LogReplicaInfo)(nil), "logservice.LogReplicaInfo")
+	proto.RegisterType((*CNStoreHeartbeat)(nil), "logservice.CNStoreHeartbeat")
 	proto.RegisterType((*LogStoreHeartbeat)(nil), "logservice.LogStoreHeartbeat")
 	proto.RegisterType((*DNShardInfo)(nil), "logservice.DNShardInfo")
 	proto.RegisterType((*DNStoreHeartbeat)(nil), "logservice.DNStoreHeartbeat")
@@ -2208,6 +2375,9 @@ func init() {
 	proto.RegisterType((*ShutdownStore)(nil), "logservice.ShutdownStore")
 	proto.RegisterType((*ScheduleCommand)(nil), "logservice.ScheduleCommand")
 	proto.RegisterType((*CommandBatch)(nil), "logservice.CommandBatch")
+	proto.RegisterType((*CNStoreInfo)(nil), "logservice.CNStoreInfo")
+	proto.RegisterType((*CNState)(nil), "logservice.CNState")
+	proto.RegisterMapType((map[string]CNStoreInfo)(nil), "logservice.CNState.StoresEntry")
 	proto.RegisterType((*DNStoreInfo)(nil), "logservice.DNStoreInfo")
 	proto.RegisterType((*DNState)(nil), "logservice.DNState")
 	proto.RegisterMapType((map[string]DNStoreInfo)(nil), "logservice.DNState.StoresEntry")
@@ -2226,139 +2396,144 @@ func init() {
 func init() { proto.RegisterFile("logservice.proto", fileDescriptor_fd1040c5381ab5a7) }
 
 var fileDescriptor_fd1040c5381ab5a7 = []byte{
-	// 2111 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x59, 0x4f, 0x6f, 0x23, 0x49,
-	0x15, 0x4f, 0xdb, 0x8e, 0xff, 0x3c, 0x27, 0x99, 0x9e, 0xca, 0x64, 0xe2, 0xcd, 0x0e, 0x33, 0xa1,
-	0x59, 0x46, 0x83, 0xd9, 0x75, 0xa4, 0x44, 0x8b, 0x58, 0xc8, 0xee, 0xc8, 0xb1, 0xbd, 0x99, 0x2c,
-	0x89, 0x3d, 0x6a, 0x3b, 0x68, 0x85, 0x34, 0x1a, 0x75, 0xdc, 0x15, 0xbb, 0x89, 0xdd, 0x6d, 0xba,
-	0xcb, 0x61, 0xb2, 0x37, 0x0e, 0x20, 0x21, 0x71, 0x41, 0xe2, 0xb0, 0x42, 0x7c, 0x05, 0x6e, 0x7c,
-	0x88, 0x3d, 0xce, 0x85, 0xeb, 0x0a, 0xe6, 0xc4, 0x8d, 0x23, 0x17, 0x24, 0x50, 0xbd, 0xae, 0xea,
-	0xae, 0xb2, 0x9d, 0xcc, 0xcc, 0x8a, 0x0b, 0xb7, 0xae, 0x57, 0xef, 0xbd, 0x7a, 0x7f, 0x7e, 0xef,
-	0xd5, 0x2b, 0x1b, 0xcc, 0x51, 0x30, 0x88, 0x68, 0x78, 0xe9, 0xf5, 0x69, 0x6d, 0x12, 0x06, 0x2c,
-	0x20, 0x90, 0x52, 0xb6, 0x3e, 0x18, 0x78, 0x6c, 0x38, 0x3d, 0xab, 0xf5, 0x83, 0xf1, 0xce, 0x20,
-	0x18, 0x04, 0x3b, 0xc8, 0x72, 0x36, 0x3d, 0xc7, 0x15, 0x2e, 0xf0, 0x2b, 0x16, 0xdd, 0x5a, 0x1b,
-	0x53, 0xe6, 0xb8, 0x0e, 0x73, 0xe2, 0xb5, 0xf5, 0x4f, 0x03, 0x56, 0x8e, 0x83, 0x41, 0x77, 0xe8,
-	0x84, 0xee, 0x91, 0x7f, 0x1e, 0x90, 0x0a, 0x14, 0xe2, 0x45, 0xb3, 0x62, 0x6c, 0x1b, 0x8f, 0x72,
-	0xb6, 0x5c, 0x92, 0x03, 0x28, 0xda, 0x74, 0x32, 0xf2, 0xfa, 0x4e, 0x54, 0xc9, 0x6c, 0x67, 0x1f,
-	0x95, 0x77, 0x1f, 0xd6, 0x14, 0xd3, 0x54, 0x2d, 0x35, 0xc9, 0xd8, 0xf2, 0x59, 0x78, 0x65, 0x27,
-	0x72, 0xe4, 0x0e, 0x2c, 0xb7, 0x26, 0x41, 0x7f, 0x58, 0xc9, 0xa2, 0xee, 0x78, 0x41, 0xb6, 0xa0,
-	0x78, 0x4c, 0x1d, 0x97, 0x86, 0x47, 0xcd, 0x4a, 0x0e, 0x37, 0x92, 0x35, 0x21, 0x90, 0xeb, 0xd1,
-	0x70, 0x5c, 0x59, 0x46, 0x3a, 0x7e, 0x6f, 0xfd, 0x18, 0x56, 0xb5, 0x03, 0x88, 0x09, 0xd9, 0x0b,
-	0x7a, 0x25, 0x0c, 0xe6, 0x9f, 0xfc, 0xa0, 0x4b, 0x67, 0x34, 0xa5, 0x95, 0xcc, 0xb6, 0xf1, 0xa8,
-	0x64, 0xc7, 0x8b, 0x1f, 0x65, 0x7e, 0x68, 0x58, 0x97, 0xb0, 0x76, 0x1c, 0x0c, 0x84, 0x3c, 0xba,
-	0xfc, 0xa9, 0x1e, 0x02, 0x54, 0x53, 0xde, 0xad, 0x5c, 0xe7, 0xdc, 0x41, 0xf1, 0xab, 0xaf, 0x1f,
-	0x2c, 0xbd, 0xfc, 0xfa, 0x81, 0x61, 0xeb, 0xa1, 0xbb, 0x07, 0x25, 0xa9, 0xb6, 0x89, 0xe7, 0xe6,
-	0xec, 0x94, 0x60, 0xfd, 0xd5, 0x80, 0xdb, 0x9c, 0x9d, 0x05, 0x21, 0x7d, 0x42, 0x9d, 0x90, 0x9d,
-	0x51, 0x87, 0x71, 0xf7, 0x4e, 0x4f, 0x45, 0xac, 0x4b, 0x36, 0x7e, 0x93, 0x6d, 0x28, 0xdb, 0xce,
-	0x39, 0xab, 0xbb, 0x6e, 0x48, 0xa3, 0x48, 0x78, 0xa0, 0x92, 0xc8, 0x43, 0x58, 0xeb, 0xc6, 0x96,
-	0x49, 0xa6, 0x2c, 0x32, 0xcd, 0x50, 0xc9, 0x7b, 0xb0, 0x7a, 0x18, 0x44, 0x91, 0x37, 0x91, 0x6c,
-	0x39, 0x64, 0xd3, 0x89, 0x64, 0x5f, 0x49, 0xec, 0x32, 0x26, 0x76, 0x6b, 0xc6, 0x77, 0x25, 0x5a,
-	0x07, 0x39, 0xee, 0x7d, 0x9a, 0x52, 0xab, 0x05, 0xe5, 0x66, 0xfb, 0x4d, 0xf0, 0x73, 0x73, 0x78,
-	0x9e, 0x81, 0xd9, 0x6c, 0xbf, 0x41, 0x70, 0x3e, 0x84, 0x3c, 0x2a, 0x94, 0x18, 0xdc, 0x54, 0x4d,
-	0x55, 0x0c, 0x11, 0x76, 0x0a, 0x66, 0xeb, 0xb7, 0x19, 0x28, 0xda, 0xdd, 0x93, 0x2e, 0x73, 0x18,
-	0xe5, 0x70, 0xe9, 0x45, 0x81, 0x84, 0x4b, 0x2f, 0x0a, 0x38, 0x5c, 0x8e, 0x7c, 0x97, 0xbe, 0x10,
-	0x76, 0xc5, 0x0b, 0x1e, 0xbe, 0x63, 0xea, 0x44, 0xf4, 0x49, 0x30, 0x8a, 0xc1, 0x19, 0xa3, 0x56,
-	0x27, 0x12, 0x0b, 0x56, 0x7a, 0xe1, 0xd4, 0xef, 0x3b, 0x8c, 0xba, 0xc7, 0x91, 0x2f, 0x10, 0xac,
-	0xd1, 0xc8, 0x67, 0xb0, 0x12, 0x0b, 0x79, 0x11, 0x0b, 0xc2, 0x2b, 0x11, 0x66, 0xad, 0x7e, 0xa4,
-	0x75, 0x35, 0x95, 0x31, 0xae, 0x1f, 0x4d, 0x76, 0xeb, 0x31, 0xdc, 0x9e, 0x63, 0x79, 0x5d, 0x05,
-	0xe4, 0xd4, 0x0a, 0x78, 0x06, 0x25, 0xcc, 0x69, 0x3f, 0x08, 0x5d, 0x2e, 0xc8, 0x8d, 0x16, 0x82,
-	0xdc, 0xd6, 0x2a, 0xe4, 0x7a, 0x57, 0x93, 0x58, 0x6e, 0x6d, 0xf7, 0xae, 0x66, 0x23, 0xca, 0xf0,
-	0x5d, 0x1b, 0x79, 0x78, 0x86, 0x9a, 0x0e, 0x73, 0x30, 0x30, 0x2b, 0x36, 0x7e, 0x5b, 0x5f, 0x1a,
-	0x00, 0xa8, 0xff, 0x17, 0x53, 0x1a, 0x61, 0x12, 0xdb, 0xce, 0x98, 0xca, 0x24, 0xf2, 0x6f, 0x15,
-	0x24, 0x19, 0x1d, 0x24, 0xc2, 0x9c, 0x6c, 0x6a, 0x4e, 0x05, 0x0a, 0x27, 0xce, 0x8b, 0xae, 0xf7,
-	0x05, 0x15, 0x91, 0x95, 0x4b, 0x0e, 0x28, 0x99, 0xf0, 0xa6, 0xe8, 0x0f, 0x29, 0x01, 0x4d, 0x6b,
-	0x1f, 0x35, 0x2b, 0xf9, 0xb8, 0x71, 0xf0, 0x6f, 0xcb, 0x02, 0xe8, 0x45, 0x81, 0xb4, 0xec, 0x0e,
-	0x2c, 0x37, 0x82, 0xa9, 0xcf, 0x84, 0xf3, 0xf1, 0xc2, 0xfa, 0x77, 0x06, 0x0a, 0x92, 0x03, 0x21,
-	0x8b, 0x9f, 0x09, 0x9c, 0x53, 0x02, 0xa9, 0x41, 0xfe, 0x84, 0xb2, 0x61, 0xe0, 0x2e, 0x0a, 0x55,
-	0xbc, 0x83, 0xa1, 0x12, 0x5c, 0xdc, 0x93, 0x9e, 0x37, 0xa6, 0xc1, 0x94, 0xa1, 0x7f, 0x59, 0x5b,
-	0x2e, 0xc9, 0xbe, 0x1a, 0x31, 0x74, 0xb3, 0xac, 0x6b, 0x4b, 0x77, 0x05, 0xae, 0xd5, 0x08, 0x1f,
-	0x62, 0xff, 0x4a, 0xca, 0x06, 0x43, 0x51, 0xde, 0xfd, 0xd6, 0x6c, 0xff, 0xd2, 0x6a, 0x4b, 0xa8,
-	0xd1, 0x04, 0x49, 0x93, 0x97, 0x72, 0xaa, 0x27, 0x8f, 0x7a, 0xee, 0xcd, 0x14, 0xd8, 0x22, 0x35,
-	0xaa, 0x18, 0x77, 0x26, 0x0d, 0x72, 0xa5, 0x30, 0xef, 0x4c, 0xba, 0x2b, 0x9d, 0x49, 0x29, 0x56,
-	0x17, 0xca, 0xe8, 0x5a, 0x34, 0x09, 0xfc, 0x88, 0xde, 0xd0, 0x4e, 0x04, 0x52, 0x32, 0x1a, 0x52,
-	0x8e, 0x9d, 0x88, 0xa5, 0xf8, 0x91, 0x4b, 0xeb, 0x5f, 0xbc, 0xfa, 0xa5, 0xca, 0xff, 0x6d, 0x52,
-	0xf7, 0xa0, 0xd4, 0x0a, 0xc3, 0x20, 0x6c, 0x04, 0x2e, 0xc5, 0x63, 0xd7, 0x76, 0x37, 0x54, 0x91,
-	0x64, 0xd3, 0x4e, 0xf9, 0x78, 0xcb, 0xc0, 0xc5, 0x09, 0x8d, 0x22, 0x67, 0x40, 0x45, 0x5b, 0xd6,
-	0x68, 0xe4, 0xb1, 0x16, 0x08, 0x91, 0xd4, 0xcd, 0x39, 0x50, 0xc4, 0xdb, 0x32, 0x0f, 0x6a, 0xe8,
-	0x0e, 0x60, 0xa5, 0x11, 0x8c, 0xc7, 0x8e, 0xef, 0x1e, 0x38, 0xac, 0x3f, 0x14, 0xe9, 0xd4, 0xae,
-	0x35, 0x75, 0x5f, 0x22, 0x42, 0xa5, 0x71, 0x23, 0x30, 0x37, 0xc2, 0x88, 0xc2, 0xbc, 0x11, 0xca,
-	0xb6, 0x34, 0x42, 0x21, 0x59, 0x9f, 0xe1, 0xa5, 0x17, 0xf7, 0x8d, 0xc4, 0xb2, 0x0f, 0x79, 0x85,
-	0x71, 0x4a, 0x54, 0x31, 0xb0, 0x11, 0x6e, 0xcc, 0xb9, 0xc5, 0x77, 0x85, 0x3e, 0xc9, 0x6b, 0x7d,
-	0x47, 0x33, 0x86, 0x97, 0xef, 0x4f, 0xb1, 0xc1, 0x89, 0xf2, 0xc5, 0x85, 0x75, 0xc1, 0x75, 0xe3,
-	0xa5, 0xb2, 0xf0, 0xfa, 0xb8, 0xbe, 0xf3, 0x68, 0xd7, 0x53, 0x76, 0xe6, 0x7a, 0x4a, 0x07, 0x97,
-	0x9c, 0x32, 0xb8, 0x58, 0x7f, 0xcc, 0xf0, 0x18, 0xfb, 0xe7, 0xde, 0xa0, 0x31, 0x74, 0xfc, 0x01,
-	0x25, 0x7b, 0xc9, 0xe9, 0x62, 0x8a, 0x58, 0xd7, 0xdb, 0x27, 0x6e, 0xa5, 0x7e, 0xc5, 0x76, 0xee,
-	0x03, 0xc4, 0xe2, 0x4a, 0xdb, 0xbd, 0xa7, 0xa7, 0x29, 0x3d, 0x02, 0xc1, 0xa7, 0xf0, 0x93, 0x1e,
-	0xac, 0x1d, 0xf9, 0x1e, 0xf3, 0x9c, 0xd1, 0x09, 0x1d, 0x9f, 0xd1, 0x90, 0xcf, 0x02, 0x3c, 0xa6,
-	0xef, 0x5f, 0xa7, 0xa1, 0xa6, 0xb3, 0xc7, 0x57, 0xcc, 0x8c, 0x8e, 0xad, 0x3a, 0xac, 0x2f, 0x60,
-	0x7b, 0xab, 0x41, 0xeb, 0x7b, 0xb0, 0xda, 0x1d, 0x4e, 0x99, 0x1b, 0xfc, 0xd2, 0xc7, 0xa6, 0x81,
-	0xb1, 0xe7, 0x1f, 0x49, 0x4a, 0xe4, 0xd2, 0xfa, 0x75, 0x06, 0x6e, 0x75, 0xfb, 0x43, 0xea, 0x4e,
-	0x47, 0x54, 0xe0, 0x6f, 0x61, 0xf6, 0xde, 0x83, 0xd5, 0x83, 0x20, 0x60, 0x11, 0x0b, 0x9d, 0xc9,
-	0xc4, 0xf3, 0x07, 0x78, 0x68, 0xd1, 0xd6, 0x89, 0x64, 0x5f, 0x4f, 0x0a, 0x26, 0x73, 0x0e, 0xf8,
-	0xe9, 0xbe, 0xad, 0xa7, 0xf0, 0x23, 0x28, 0x8b, 0x29, 0x0a, 0xd3, 0x91, 0xc3, 0x74, 0x68, 0x90,
-	0x57, 0xb6, 0x6d, 0x95, 0x97, 0x3c, 0x9e, 0xf1, 0x58, 0x14, 0xed, 0x3b, 0x9a, 0xb0, 0xca, 0x60,
-	0xeb, 0xfc, 0x96, 0xa3, 0x97, 0x6c, 0x32, 0xfc, 0x1a, 0xe9, 0xf0, 0x4b, 0x3e, 0x86, 0xa2, 0xe0,
-	0x91, 0x23, 0xd0, 0xbb, 0x9a, 0x7e, 0x3d, 0x8c, 0x72, 0x5c, 0x93, 0x22, 0xd6, 0xe7, 0x38, 0xae,
-	0x61, 0xdc, 0xf9, 0xb8, 0xc6, 0x4f, 0xf0, 0xfa, 0x17, 0xc9, 0x09, 0x5e, 0xff, 0xe2, 0x9b, 0x8e,
-	0x58, 0x7f, 0x32, 0xa0, 0xc0, 0x55, 0xf3, 0x09, 0xeb, 0x63, 0xc8, 0xe3, 0x19, 0xb2, 0xc0, 0x1f,
-	0xcc, 0x5e, 0x22, 0x7c, 0xd0, 0x89, 0x39, 0x10, 0x58, 0x89, 0x2a, 0x24, 0x6d, 0xd9, 0x50, 0x56,
-	0x36, 0x55, 0xd4, 0x95, 0x62, 0xd4, 0x7d, 0xa0, 0xa2, 0x6e, 0xde, 0x42, 0xe9, 0x9e, 0x0a, 0xc7,
-	0xdf, 0x18, 0x50, 0x6e, 0x8c, 0xa6, 0x11, 0xa3, 0x21, 0x7a, 0xfe, 0x11, 0x14, 0x85, 0x2f, 0xd2,
-	0xc8, 0xcd, 0x5a, 0xf2, 0x38, 0x12, 0x3b, 0x5a, 0x1f, 0x4a, 0xd8, 0xc9, 0x3e, 0x0e, 0x50, 0x5a,
-	0x8c, 0x2a, 0xa9, 0xac, 0xdc, 0xd2, 0x84, 0x53, 0x01, 0xeb, 0xf7, 0x06, 0x6c, 0x88, 0xda, 0x12,
-	0xf6, 0xc8, 0x8b, 0xfc, 0x21, 0xac, 0xb5, 0xa7, 0xe3, 0xce, 0x79, 0xaa, 0x3c, 0x4e, 0xcb, 0x0c,
-	0x95, 0x97, 0x01, 0x52, 0x12, 0xfb, 0xe3, 0x56, 0xa6, 0x13, 0x49, 0x15, 0x4c, 0x29, 0x97, 0x8c,
-	0xf7, 0x71, 0x5f, 0x9b, 0xa3, 0x5b, 0x2f, 0xc5, 0x33, 0xf0, 0x46, 0x5c, 0xfc, 0x7f, 0xbd, 0x4b,
-	0xfe, 0x92, 0x81, 0x22, 0xba, 0xc4, 0xf1, 0xf8, 0x49, 0x02, 0xe9, 0x38, 0xd5, 0xdb, 0x73, 0xc3,
-	0x11, 0x02, 0x12, 0x59, 0x74, 0x40, 0xc6, 0xb1, 0xfc, 0x24, 0xc1, 0x73, 0xe6, 0x26, 0xf9, 0x6b,
-	0x01, 0xdd, 0x85, 0xb2, 0xa2, 0x7c, 0x41, 0x1b, 0xad, 0xe9, 0x80, 0xbe, 0xf6, 0xf1, 0xa9, 0x20,
-	0x1a, 0x95, 0xde, 0x58, 0x25, 0xaf, 0x53, 0xba, 0xa8, 0x4c, 0x7e, 0xc5, 0xaf, 0xb4, 0x21, 0xed,
-	0x5f, 0xd0, 0x30, 0x0e, 0xdd, 0x22, 0x24, 0x3c, 0xd6, 0x4a, 0x69, 0x51, 0x11, 0x2a, 0xdb, 0x72,
-	0x2c, 0x50, 0x8b, 0x6f, 0x2f, 0x69, 0x15, 0xa2, 0x3b, 0xaf, 0x2f, 0x68, 0x10, 0xf2, 0x9e, 0x94,
-	0x4d, 0xe5, 0x07, 0x69, 0x42, 0xc5, 0x8c, 0x7c, 0x67, 0x51, 0x1a, 0x24, 0x12, 0x92, 0xe4, 0xef,
-	0xc0, 0x72, 0x2c, 0xb4, 0x8c, 0xbd, 0x5c, 0x6b, 0xc7, 0x4f, 0xea, 0x3f, 0xa1, 0x74, 0x22, 0x7c,
-	0xb5, 0x63, 0x3e, 0xeb, 0x3f, 0x39, 0x30, 0xe5, 0x46, 0xf2, 0x68, 0x5c, 0x14, 0x87, 0xbb, 0x90,
-	0x6f, 0xd3, 0x17, 0x2c, 0x19, 0x26, 0xc4, 0x2a, 0xe9, 0xdb, 0x59, 0xa5, 0x6f, 0x27, 0x56, 0xe4,
-	0xde, 0xcc, 0x0a, 0xe2, 0x82, 0x39, 0xd3, 0xcc, 0x65, 0x19, 0xec, 0x2e, 0x92, 0x4d, 0xde, 0x8f,
-	0xb3, 0x42, 0x2a, 0x1e, 0xe7, 0x34, 0x92, 0x23, 0xb5, 0x97, 0xe5, 0x51, 0xfd, 0xf7, 0x6f, 0x54,
-	0x9f, 0x70, 0xc7, 0x83, 0x43, 0x2a, 0xad, 0x26, 0xb5, 0xf0, 0x8d, 0x92, 0x5a, 0x7c, 0x8b, 0xa4,
-	0xce, 0x40, 0xb0, 0xf4, 0xb6, 0x10, 0xdc, 0x7a, 0x06, 0x1b, 0x0b, 0x23, 0xf5, 0x96, 0x75, 0xa4,
-	0xde, 0xd7, 0x6a, 0x71, 0xee, 0xe3, 0xcf, 0x4c, 0xd7, 0x14, 0x7d, 0xe9, 0x35, 0x4f, 0xf4, 0xaa,
-	0x03, 0x70, 0x3a, 0x71, 0x1d, 0x16, 0xcf, 0x15, 0x9b, 0xb0, 0xae, 0xfd, 0xe4, 0x10, 0x6f, 0x99,
-	0x4b, 0xe4, 0x2e, 0x90, 0xf4, 0x67, 0x86, 0x6e, 0x5b, 0xd0, 0x0d, 0xb2, 0x0e, 0xb7, 0x4e, 0x23,
-	0x1a, 0xe2, 0xb9, 0x82, 0x98, 0x21, 0xab, 0x50, 0xea, 0x75, 0x3b, 0x62, 0x99, 0xad, 0xfe, 0xc1,
-	0x00, 0x48, 0xdf, 0x33, 0x64, 0x0d, 0xa0, 0xd7, 0xed, 0x3c, 0x3f, 0x7d, 0xda, 0xac, 0xf7, 0x5a,
-	0xe6, 0x12, 0x01, 0xc8, 0xd7, 0x9f, 0x3e, 0x6d, 0xb5, 0x9b, 0xa6, 0x41, 0x8a, 0x90, 0xb3, 0x5b,
-	0xf5, 0xa6, 0x99, 0x21, 0x2b, 0x50, 0xec, 0xd9, 0xa7, 0xed, 0x06, 0xe7, 0xc9, 0x12, 0x13, 0x56,
-	0x0e, 0x5b, 0xbd, 0xe7, 0x09, 0x25, 0x47, 0xca, 0x50, 0x68, 0x74, 0xda, 0xed, 0x56, 0xa3, 0x67,
-	0x2e, 0x73, 0x95, 0x62, 0xf1, 0xdc, 0xee, 0x98, 0x79, 0x72, 0x1b, 0x56, 0x8f, 0x3b, 0x87, 0xcf,
-	0x9f, 0xb4, 0xea, 0x76, 0xef, 0xa0, 0x55, 0xef, 0x99, 0x05, 0xae, 0xa1, 0xd9, 0x56, 0x28, 0xc5,
-	0x6a, 0x1b, 0x20, 0xfd, 0x95, 0x81, 0xab, 0xe0, 0x8e, 0xc4, 0x14, 0x73, 0x89, 0x9f, 0x7f, 0xe4,
-	0x33, 0x1a, 0xfa, 0xce, 0xc8, 0x34, 0xc8, 0x2d, 0x28, 0x63, 0x5c, 0x12, 0x17, 0x6f, 0x8b, 0x1f,
-	0x6c, 0x6c, 0xfa, 0x73, 0xda, 0x67, 0xd4, 0x35, 0xb3, 0xd5, 0xdf, 0x65, 0x94, 0x07, 0x1a, 0xb7,
-	0xaf, 0x1d, 0xe0, 0xd2, 0x5c, 0xe2, 0x0b, 0xf1, 0x00, 0x37, 0x0d, 0xae, 0xb9, 0xe1, 0xf8, 0x7d,
-	0x3a, 0xa2, 0xae, 0x99, 0xe1, 0x76, 0x1d, 0xf9, 0x97, 0xce, 0xc8, 0x73, 0x31, 0x83, 0x66, 0x96,
-	0x10, 0x3e, 0x66, 0x23, 0x45, 0xca, 0xe4, 0x14, 0xda, 0x53, 0xe7, 0x6a, 0x14, 0x38, 0xae, 0xb9,
-	0xcc, 0x53, 0xa2, 0xd3, 0xba, 0xde, 0x17, 0xd4, 0xcc, 0x73, 0xfd, 0x89, 0x55, 0x05, 0x6e, 0x28,
-	0x2a, 0x6e, 0x07, 0xcc, 0xa6, 0x8e, 0x7b, 0x65, 0x16, 0xf9, 0x91, 0xdd, 0xab, 0x88, 0xd1, 0x71,
-	0x63, 0x14, 0x44, 0xd4, 0x35, 0x4b, 0x98, 0xf6, 0xc8, 0xaf, 0x8f, 0x42, 0xce, 0x91, 0xe4, 0xd9,
-	0x74, 0x79, 0x54, 0x3a, 0x53, 0xd6, 0x39, 0xb7, 0xf9, 0xc0, 0x6a, 0xf2, 0xd6, 0xb4, 0xd6, 0x0e,
-	0x98, 0x02, 0x11, 0xf3, 0x9c, 0x6c, 0x80, 0xd9, 0x61, 0x43, 0x1a, 0xc6, 0x3a, 0x63, 0x97, 0xff,
-	0x51, 0xa8, 0xfe, 0xd9, 0x00, 0x22, 0x4b, 0x5a, 0x41, 0x18, 0xcf, 0xbe, 0xd7, 0xbf, 0x48, 0x80,
-	0xb5, 0x01, 0xb7, 0x95, 0x27, 0x7d, 0x82, 0xab, 0xbb, 0x40, 0xd4, 0x1f, 0x0c, 0x92, 0xb8, 0xdf,
-	0x82, 0xf2, 0x21, 0x65, 0x09, 0x30, 0xb3, 0xe4, 0x9d, 0xb9, 0xe2, 0x12, 0x5b, 0x18, 0xb4, 0x2e,
-	0x65, 0x58, 0xc4, 0x82, 0xb6, 0x4c, 0x2a, 0x70, 0x47, 0x9f, 0x88, 0xc4, 0x4e, 0xbe, 0xfa, 0xa5,
-	0x01, 0xab, 0x5a, 0x77, 0xe4, 0xd8, 0x96, 0x84, 0x46, 0x48, 0x31, 0x22, 0x4b, 0xfc, 0x3c, 0x49,
-	0xd4, 0xde, 0x02, 0xa6, 0x41, 0xbe, 0x0b, 0xdf, 0x9e, 0xdb, 0x92, 0x05, 0x6f, 0xd3, 0x3e, 0xf5,
-	0x2e, 0x31, 0xe3, 0xef, 0xc2, 0xe6, 0x1c, 0xdb, 0xa7, 0x8e, 0xc7, 0xe1, 0x90, 0x55, 0xcf, 0xb4,
-	0xa7, 0xbe, 0xcf, 0x15, 0xe7, 0xaa, 0x9f, 0x83, 0x39, 0xfb, 0x30, 0xe3, 0x71, 0xac, 0xbb, 0xae,
-	0x98, 0x41, 0xcc, 0x25, 0x9e, 0x67, 0x9b, 0x8e, 0x83, 0x4b, 0x2a, 0x49, 0x06, 0xe6, 0x99, 0x39,
-	0x21, 0x93, 0x14, 0x8c, 0x5e, 0x97, 0x05, 0x13, 0x49, 0xc8, 0x56, 0xdf, 0xd7, 0x9e, 0x20, 0x5c,
-	0x29, 0x6f, 0x25, 0x31, 0xc5, 0x5c, 0xe2, 0x85, 0xdc, 0xf4, 0xe5, 0xd2, 0x38, 0x68, 0xbd, 0xfc,
-	0xfb, 0xfd, 0xa5, 0xaf, 0x5e, 0xdd, 0x37, 0x5e, 0xbe, 0xba, 0x6f, 0xfc, 0xed, 0xd5, 0x7d, 0xe3,
-	0x67, 0x7b, 0xca, 0x7f, 0x02, 0x63, 0x87, 0x85, 0xde, 0x8b, 0x20, 0xf4, 0x06, 0x9e, 0x2f, 0x17,
-	0x3e, 0xdd, 0x99, 0x5c, 0x0c, 0x76, 0x26, 0x67, 0x3b, 0x69, 0x23, 0x3b, 0xcb, 0xe3, 0x1f, 0x02,
-	0x7b, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xf4, 0x35, 0x0a, 0x83, 0x6f, 0x18, 0x00, 0x00,
+	// 2181 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x59, 0xcd, 0x6f, 0x1b, 0xc7,
+	0x15, 0xd7, 0xf2, 0x9b, 0x8f, 0x92, 0xbc, 0x1a, 0x59, 0x36, 0xc3, 0xa4, 0xb6, 0xb2, 0x4d, 0x0d,
+	0x97, 0x4d, 0x28, 0x40, 0x42, 0x8a, 0xa6, 0x55, 0x62, 0x50, 0x5c, 0x46, 0x56, 0x2a, 0x91, 0xc6,
+	0x92, 0x2a, 0x82, 0x02, 0x86, 0xb1, 0xe2, 0x8e, 0xc8, 0xad, 0xc8, 0x5d, 0x76, 0x77, 0xa8, 0x5a,
+	0xb9, 0xf5, 0xd0, 0x02, 0x05, 0x7a, 0xe9, 0x2d, 0x28, 0x7a, 0xee, 0x5f, 0x90, 0xbf, 0xa0, 0xe8,
+	0x21, 0x47, 0x5f, 0x7a, 0x0d, 0x5a, 0x9f, 0x7a, 0xeb, 0xb1, 0xd7, 0x62, 0xbe, 0x76, 0x67, 0x48,
+	0x4a, 0xb6, 0x83, 0xf6, 0xd0, 0x1b, 0xe7, 0xcd, 0x7b, 0x6f, 0xde, 0xc7, 0xef, 0xbd, 0x79, 0xb3,
+	0x04, 0x73, 0x1c, 0x0e, 0x63, 0x1c, 0x5d, 0xfa, 0x03, 0xdc, 0x98, 0x46, 0x21, 0x09, 0x11, 0xa4,
+	0x94, 0xda, 0x07, 0x43, 0x9f, 0x8c, 0x66, 0x67, 0x8d, 0x41, 0x38, 0xd9, 0x19, 0x86, 0xc3, 0x70,
+	0x87, 0xb1, 0x9c, 0xcd, 0xce, 0xd9, 0x8a, 0x2d, 0xd8, 0x2f, 0x2e, 0x5a, 0x5b, 0x9f, 0x60, 0xe2,
+	0x7a, 0x2e, 0x71, 0xf9, 0xda, 0xfa, 0x97, 0x01, 0xab, 0xc7, 0xe1, 0xb0, 0x37, 0x72, 0x23, 0xef,
+	0x28, 0x38, 0x0f, 0x51, 0x15, 0x8a, 0x7c, 0x61, 0x57, 0x8d, 0x6d, 0xe3, 0x61, 0xce, 0x91, 0x4b,
+	0x74, 0x00, 0x25, 0x07, 0x4f, 0xc7, 0xfe, 0xc0, 0x8d, 0xab, 0x99, 0xed, 0xec, 0xc3, 0xca, 0xee,
+	0x83, 0x86, 0x62, 0x9a, 0xaa, 0xa5, 0x21, 0x19, 0xdb, 0x01, 0x89, 0xae, 0x9c, 0x44, 0x0e, 0xdd,
+	0x86, 0x7c, 0x7b, 0x1a, 0x0e, 0x46, 0xd5, 0x2c, 0xd3, 0xcd, 0x17, 0xa8, 0x06, 0xa5, 0x63, 0xec,
+	0x7a, 0x38, 0x3a, 0xb2, 0xab, 0x39, 0xb6, 0x91, 0xac, 0x11, 0x82, 0x5c, 0x1f, 0x47, 0x93, 0x6a,
+	0x9e, 0xd1, 0xd9, 0xef, 0xda, 0x4f, 0x60, 0x4d, 0x3b, 0x00, 0x99, 0x90, 0xbd, 0xc0, 0x57, 0xc2,
+	0x60, 0xfa, 0x93, 0x1e, 0x74, 0xe9, 0x8e, 0x67, 0xb8, 0x9a, 0xd9, 0x36, 0x1e, 0x96, 0x1d, 0xbe,
+	0xf8, 0x71, 0xe6, 0x47, 0x86, 0x75, 0x09, 0xeb, 0xc7, 0xe1, 0x50, 0xc8, 0x33, 0x97, 0x3f, 0xd5,
+	0x43, 0xc0, 0xd4, 0x54, 0x76, 0xab, 0xd7, 0x39, 0x77, 0x50, 0xfa, 0xfa, 0x9b, 0xfb, 0x2b, 0x2f,
+	0xbe, 0xb9, 0x6f, 0x38, 0x7a, 0xe8, 0xde, 0x81, 0xb2, 0x54, 0x6b, 0xb3, 0x73, 0x73, 0x4e, 0x4a,
+	0xb0, 0x1e, 0x80, 0xd9, 0xea, 0xf4, 0x48, 0x18, 0xe1, 0xc7, 0xd8, 0x8d, 0xc8, 0x19, 0x76, 0x09,
+	0x75, 0xee, 0xf4, 0x54, 0x44, 0xba, 0xec, 0xb0, 0xdf, 0xd6, 0xdf, 0x0c, 0xd8, 0xa0, 0x6a, 0x5f,
+	0xc9, 0x89, 0xb6, 0xa1, 0xe2, 0xb8, 0xe7, 0xa4, 0xe9, 0x79, 0x11, 0x8e, 0x63, 0xe1, 0xa9, 0x4a,
+	0x42, 0x0f, 0x60, 0xbd, 0xc7, 0x3d, 0x90, 0x4c, 0x59, 0xc6, 0x34, 0x47, 0x45, 0xef, 0xc1, 0xda,
+	0x61, 0x18, 0xc7, 0xfe, 0x54, 0xb2, 0xe5, 0x18, 0x9b, 0x4e, 0x44, 0xfb, 0x0a, 0x00, 0xf2, 0x0c,
+	0x00, 0xb5, 0xb9, 0x18, 0x29, 0x51, 0x3d, 0xc8, 0xd1, 0x28, 0xa5, 0xa9, 0xb7, 0xda, 0x50, 0xb1,
+	0x3b, 0xaf, 0x83, 0xb3, 0x9b, 0xc3, 0xf8, 0x14, 0x4c, 0xfb, 0x35, 0xc2, 0x88, 0x3e, 0x84, 0x02,
+	0x53, 0x28, 0xb1, 0x7a, 0x57, 0x35, 0x55, 0x31, 0x44, 0xd8, 0x29, 0x98, 0xad, 0xdf, 0x65, 0xa0,
+	0xe4, 0xf4, 0x4e, 0x7a, 0xc4, 0x25, 0x98, 0xc2, 0xaa, 0x1f, 0x87, 0x12, 0x56, 0xfd, 0x38, 0xa4,
+	0xb0, 0x3a, 0x0a, 0x3c, 0xfc, 0x5c, 0xd8, 0xc5, 0x17, 0x34, 0x7c, 0xc7, 0xd8, 0x8d, 0xf1, 0xe3,
+	0x70, 0xcc, 0x41, 0xcc, 0xd1, 0xad, 0x13, 0x91, 0x05, 0xab, 0xfd, 0x68, 0x16, 0x0c, 0x5c, 0x82,
+	0xbd, 0xe3, 0x38, 0x10, 0x48, 0xd7, 0x68, 0xe8, 0x33, 0x58, 0xe5, 0x42, 0x7e, 0x4c, 0xc2, 0xe8,
+	0x4a, 0x84, 0x59, 0xab, 0x33, 0x69, 0x5d, 0x43, 0x65, 0xe4, 0x75, 0xa6, 0xc9, 0xd6, 0x1e, 0xc1,
+	0xc6, 0x02, 0xcb, 0xab, 0x2a, 0x25, 0xa7, 0x56, 0xca, 0x53, 0x28, 0xb3, 0x9c, 0x0e, 0xc2, 0xc8,
+	0xa3, 0x82, 0xd4, 0x68, 0x21, 0x48, 0x6d, 0xad, 0x43, 0xae, 0x7f, 0x35, 0xe5, 0x72, 0xeb, 0xbb,
+	0x77, 0x34, 0x1b, 0x99, 0x0c, 0xdd, 0x75, 0x18, 0x0f, 0xcd, 0x90, 0xed, 0x12, 0x97, 0x05, 0x66,
+	0xd5, 0x61, 0xbf, 0xad, 0x2f, 0x0d, 0x00, 0xa6, 0xff, 0x97, 0x33, 0x1c, 0xb3, 0x24, 0x76, 0xdc,
+	0x09, 0x96, 0x49, 0xa4, 0xbf, 0x55, 0x90, 0x64, 0x74, 0x90, 0x08, 0x73, 0xb2, 0xa9, 0x39, 0x55,
+	0x28, 0x9e, 0xb8, 0xcf, 0x7b, 0xfe, 0x17, 0x58, 0x44, 0x56, 0x2e, 0x29, 0xa0, 0x64, 0xc2, 0x6d,
+	0xd1, 0x47, 0x52, 0x02, 0x33, 0xad, 0x73, 0x64, 0x57, 0x0b, 0xbc, 0xc1, 0xd0, 0xdf, 0x96, 0x05,
+	0xd0, 0x8f, 0x43, 0x69, 0xd9, 0x6d, 0xc8, 0xb7, 0xc2, 0x59, 0x40, 0x84, 0xf3, 0x7c, 0x61, 0xfd,
+	0x25, 0x0b, 0x45, 0xc9, 0xc1, 0x20, 0xcb, 0x7e, 0x26, 0x70, 0x4e, 0x09, 0xa8, 0x01, 0x85, 0x13,
+	0x4c, 0x46, 0xa1, 0xb7, 0x2c, 0x54, 0x7c, 0x87, 0x85, 0x4a, 0x70, 0x51, 0x4f, 0xfa, 0xfe, 0x04,
+	0x87, 0x33, 0xc2, 0xfc, 0xcb, 0x3a, 0x72, 0x89, 0xf6, 0xd5, 0x88, 0x31, 0x37, 0x2b, 0xba, 0xb6,
+	0x74, 0x57, 0xe0, 0x5a, 0x8d, 0xf0, 0x21, 0xeb, 0x73, 0x49, 0xd9, 0xb0, 0x50, 0x54, 0x76, 0xbf,
+	0x33, 0xdf, 0xe7, 0xb4, 0xda, 0x12, 0x6a, 0x34, 0x41, 0x64, 0x43, 0xa5, 0xd5, 0x49, 0xf5, 0x14,
+	0x98, 0x9e, 0x77, 0x54, 0x3d, 0xf3, 0x9d, 0x4e, 0xa8, 0x51, 0xc5, 0xa8, 0x16, 0x5b, 0xd1, 0x52,
+	0x5c, 0xd4, 0x62, 0x5f, 0xa3, 0x45, 0x11, 0xa3, 0x21, 0x49, 0x53, 0x55, 0x2d, 0x2d, 0x86, 0x24,
+	0xdd, 0x95, 0x21, 0x49, 0x29, 0x56, 0x0f, 0x2a, 0x2c, 0x40, 0xf1, 0x34, 0x0c, 0x62, 0x7c, 0x43,
+	0x53, 0x12, 0x78, 0xcb, 0x68, 0x78, 0x3b, 0x76, 0x63, 0x92, 0xa2, 0x50, 0x2e, 0xad, 0x7f, 0xd3,
+	0x1e, 0x22, 0x55, 0xfe, 0x77, 0xa1, 0xb1, 0x07, 0xe5, 0x76, 0x14, 0x85, 0x51, 0x2b, 0xf4, 0x30,
+	0x3b, 0x76, 0x7d, 0x77, 0x4b, 0x15, 0x49, 0x36, 0x9d, 0x94, 0x8f, 0x36, 0x1e, 0xb6, 0x38, 0xc1,
+	0x71, 0xec, 0x0e, 0xb1, 0x68, 0xee, 0x1a, 0x0d, 0x3d, 0xd2, 0x02, 0x21, 0xa0, 0x71, 0x77, 0x01,
+	0x5a, 0x7c, 0x5b, 0xe6, 0x41, 0x0d, 0xdd, 0x01, 0xac, 0xb6, 0xc2, 0xc9, 0xc4, 0x0d, 0xbc, 0x03,
+	0x97, 0x0c, 0x46, 0x02, 0x14, 0xda, 0x25, 0xaa, 0xee, 0x4b, 0x5c, 0xa9, 0x34, 0x6a, 0x04, 0xcb,
+	0x8d, 0x30, 0xa2, 0xb8, 0x68, 0x84, 0xb2, 0x2d, 0x8d, 0x50, 0x48, 0xd6, 0x67, 0xec, 0xea, 0xe4,
+	0xdd, 0x27, 0xb1, 0xec, 0x43, 0x5a, 0xa7, 0x94, 0x12, 0x57, 0x0d, 0xd6, 0x4e, 0xb7, 0x16, 0xdc,
+	0xa2, 0xbb, 0x42, 0x9f, 0xe4, 0xb5, 0xbe, 0xab, 0x19, 0x43, 0x9b, 0xc0, 0xcf, 0x58, 0x9b, 0x14,
+	0x4d, 0x80, 0x2d, 0xac, 0x0b, 0xaa, 0x9b, 0x5d, 0x4d, 0x4b, 0x2f, 0xa1, 0xeb, 0xfb, 0x97, 0x76,
+	0xc9, 0x65, 0xe7, 0x2e, 0xb9, 0x74, 0x4c, 0xca, 0x29, 0x63, 0x92, 0xf5, 0xc7, 0x0c, 0x8d, 0x71,
+	0x70, 0xee, 0x0f, 0x5b, 0x23, 0x37, 0x18, 0x62, 0xb4, 0x97, 0x9c, 0x2e, 0x66, 0x96, 0x4d, 0xbd,
+	0x09, 0xb3, 0xad, 0xd4, 0x2f, 0x6e, 0xe7, 0x3e, 0x00, 0x17, 0x57, 0x9a, 0xb7, 0x5e, 0xbb, 0xca,
+	0x11, 0x0c, 0x7c, 0x0a, 0x3f, 0xea, 0xc3, 0xfa, 0x51, 0xe0, 0x13, 0xdf, 0x1d, 0x9f, 0xe0, 0xc9,
+	0x19, 0x8e, 0xe8, 0x44, 0x41, 0x63, 0xfa, 0xfe, 0x75, 0x1a, 0x1a, 0x3a, 0x3b, 0xbf, 0xa8, 0xe6,
+	0x74, 0xd4, 0x9a, 0xb0, 0xb9, 0x84, 0xed, 0x8d, 0xc6, 0xba, 0xef, 0xc3, 0x5a, 0x6f, 0x34, 0x23,
+	0x5e, 0xf8, 0xab, 0x80, 0x35, 0x0d, 0x16, 0x7b, 0xfa, 0x23, 0x49, 0x89, 0x5c, 0x5a, 0xbf, 0xc9,
+	0xc0, 0xad, 0xde, 0x60, 0x84, 0xbd, 0xd9, 0x18, 0x0b, 0xfc, 0x2d, 0xcd, 0xde, 0x7b, 0xb0, 0x76,
+	0x10, 0x86, 0x24, 0x26, 0x91, 0x3b, 0x9d, 0xfa, 0xc1, 0x90, 0x1d, 0x5a, 0x72, 0x74, 0x22, 0xda,
+	0xd7, 0x93, 0xc2, 0x92, 0xb9, 0x00, 0xfc, 0x74, 0xdf, 0xd1, 0x53, 0xf8, 0x11, 0x54, 0xc4, 0x2c,
+	0xc6, 0xd2, 0x91, 0x63, 0xe9, 0xd0, 0x20, 0xaf, 0x6c, 0x3b, 0x2a, 0x2f, 0x7a, 0x34, 0xe7, 0xb1,
+	0x28, 0xda, 0xb7, 0x34, 0x61, 0x95, 0xc1, 0xd1, 0xf9, 0x2d, 0x57, 0x2f, 0xd9, 0x64, 0xd4, 0x36,
+	0xd2, 0x51, 0x1b, 0x7d, 0x0c, 0x25, 0xc1, 0x23, 0x07, 0xa9, 0xb7, 0x35, 0xfd, 0x7a, 0x18, 0xe5,
+	0xd0, 0x27, 0x45, 0xac, 0x77, 0xe9, 0x4d, 0xc1, 0xe3, 0x4e, 0x87, 0x3e, 0x7a, 0x82, 0x3f, 0xb8,
+	0x48, 0x4e, 0xf0, 0x07, 0x17, 0xd6, 0x9f, 0x0c, 0x28, 0x52, 0x1e, 0x3a, 0x70, 0x7d, 0x0c, 0x05,
+	0xc6, 0x2c, 0x2b, 0xf5, 0xfe, 0xfc, 0x9d, 0x42, 0xe7, 0x1e, 0xce, 0xc1, 0x10, 0x92, 0x0c, 0x6f,
+	0x8c, 0x54, 0x73, 0xa0, 0xa2, 0x6c, 0xaa, 0xf0, 0x29, 0x73, 0xf8, 0x7c, 0xa0, 0xc2, 0x67, 0xae,
+	0xb5, 0x28, 0x76, 0xaa, 0xb8, 0xfa, 0x9c, 0x8d, 0xad, 0x37, 0x79, 0xf0, 0x6d, 0x47, 0x4d, 0xea,
+	0xb8, 0xfd, 0x3a, 0x8e, 0xdb, 0xff, 0x5b, 0xc7, 0xed, 0xe5, 0x8e, 0xff, 0xd6, 0x80, 0x4a, 0x6b,
+	0x3c, 0x8b, 0x09, 0x8e, 0x98, 0xe7, 0x1f, 0x41, 0x49, 0xf8, 0x22, 0x8d, 0xbc, 0xdb, 0x48, 0x1e,
+	0x93, 0x62, 0x47, 0xeb, 0xa4, 0x09, 0x3b, 0xda, 0x67, 0x83, 0xa4, 0x16, 0xa3, 0x6a, 0x2a, 0x2b,
+	0xb7, 0x34, 0xe1, 0x54, 0xc0, 0xfa, 0x83, 0x01, 0x5b, 0xa2, 0x3b, 0x08, 0x7b, 0xe4, 0x40, 0xf3,
+	0x00, 0xd6, 0x3b, 0xb3, 0x49, 0xf7, 0x3c, 0x55, 0xce, 0xd3, 0x32, 0x47, 0xa5, 0x85, 0xcc, 0x28,
+	0x89, 0xfd, 0xbc, 0x19, 0xeb, 0x44, 0x54, 0x07, 0x53, 0xca, 0x25, 0xcf, 0x1c, 0xde, 0x99, 0x17,
+	0xe8, 0xd6, 0x0b, 0xf1, 0x6c, 0xbe, 0x11, 0x17, 0xff, 0x5f, 0xef, 0xb3, 0xaf, 0x32, 0x50, 0x62,
+	0x2e, 0x51, 0x3c, 0x7e, 0x92, 0x40, 0x9a, 0xa7, 0x7a, 0x7b, 0x61, 0x48, 0x64, 0x80, 0x64, 0x2c,
+	0x3a, 0x20, 0x79, 0x2c, 0x3f, 0x49, 0xf0, 0x9c, 0xb9, 0x49, 0xfe, 0x5a, 0x40, 0xf7, 0xa0, 0xa2,
+	0x28, 0x5f, 0x72, 0x11, 0x34, 0x74, 0x40, 0x5f, 0xfb, 0x58, 0x57, 0x10, 0xcd, 0x94, 0xde, 0x58,
+	0x25, 0xaf, 0x52, 0xba, 0xac, 0x4c, 0x7e, 0x4d, 0x2f, 0xe5, 0x11, 0x1e, 0x5c, 0xe0, 0x88, 0x87,
+	0x6e, 0x19, 0x12, 0x1e, 0x69, 0xa5, 0xb4, 0xb4, 0xfb, 0xa4, 0xdb, 0xc9, 0xac, 0xac, 0x14, 0xdf,
+	0x5e, 0xd2, 0x2a, 0xc4, 0xfd, 0xb2, 0xb9, 0xa4, 0x41, 0xc8, 0x9b, 0x5e, 0x36, 0x95, 0x1f, 0xa6,
+	0x09, 0x15, 0x6f, 0x85, 0xdb, 0xcb, 0xd2, 0x20, 0x91, 0x90, 0x24, 0x7f, 0x07, 0xf2, 0x5c, 0x28,
+	0xcf, 0x6e, 0x23, 0xed, 0x42, 0x79, 0xdc, 0xfc, 0x29, 0xc6, 0x53, 0xe1, 0xab, 0xc3, 0xf9, 0xac,
+	0xaf, 0xf2, 0x60, 0xca, 0x8d, 0xe4, 0xf1, 0xbc, 0x2c, 0x0e, 0x77, 0xa0, 0xd0, 0xc1, 0xcf, 0x49,
+	0x32, 0x0e, 0x89, 0x55, 0x72, 0xf3, 0x64, 0x95, 0x9b, 0x27, 0xb1, 0x22, 0xf7, 0x7a, 0x56, 0x20,
+	0x0f, 0xcc, 0xb9, 0xeb, 0x48, 0x96, 0xc1, 0xee, 0x32, 0xd9, 0xe4, 0x1d, 0x3d, 0x2f, 0xa4, 0xe2,
+	0x71, 0x41, 0x23, 0x3a, 0x52, 0x7b, 0x59, 0x81, 0xa9, 0xff, 0xc1, 0x8d, 0xea, 0x13, 0x6e, 0x3e,
+	0xfa, 0xa4, 0xd2, 0x34, 0xa9, 0xe2, 0x4e, 0x13, 0xa3, 0xee, 0xe6, 0x92, 0xeb, 0x4e, 0x26, 0x55,
+	0x5e, 0x91, 0x0a, 0x12, 0x4a, 0xdf, 0x0a, 0x09, 0xe5, 0x37, 0x40, 0xc2, 0x1c, 0x6e, 0xe1, 0x4d,
+	0x71, 0x5b, 0x7b, 0x0a, 0x5b, 0x4b, 0xc3, 0xfb, 0x86, 0xc5, 0xa7, 0x8e, 0x29, 0x6a, 0x45, 0xef,
+	0xb3, 0x6f, 0x79, 0xd7, 0x74, 0x8a, 0xf2, 0x2b, 0xbe, 0x6f, 0xd4, 0x5d, 0x80, 0xd3, 0xa9, 0xe7,
+	0x12, 0x3e, 0x4e, 0xdd, 0x85, 0x4d, 0xed, 0x7b, 0x0d, 0xdf, 0x32, 0x57, 0xd0, 0x1d, 0x40, 0xe9,
+	0x37, 0x9a, 0x5e, 0x47, 0xd0, 0x0d, 0xb4, 0x09, 0xb7, 0x4e, 0x63, 0x1c, 0xb1, 0x73, 0x05, 0x31,
+	0x83, 0xd6, 0xa0, 0xdc, 0xef, 0x75, 0xc5, 0x32, 0x5b, 0xff, 0xb3, 0x01, 0x90, 0x3e, 0xe3, 0xd0,
+	0x3a, 0x40, 0xbf, 0xd7, 0x7d, 0x76, 0xfa, 0xc4, 0x6e, 0xf6, 0xdb, 0xe6, 0x0a, 0x02, 0x28, 0x34,
+	0x9f, 0x3c, 0x69, 0x77, 0x6c, 0xd3, 0x40, 0x25, 0xc8, 0x39, 0xed, 0xa6, 0x6d, 0x66, 0xd0, 0x2a,
+	0x94, 0xfa, 0xce, 0x69, 0xa7, 0x45, 0x79, 0xb2, 0xc8, 0x84, 0xd5, 0xc3, 0x76, 0xff, 0x59, 0x42,
+	0xc9, 0xa1, 0x0a, 0x14, 0x5b, 0xdd, 0x4e, 0xa7, 0xdd, 0xea, 0x9b, 0x79, 0xaa, 0x52, 0x2c, 0x9e,
+	0x39, 0x5d, 0xb3, 0x80, 0x36, 0x60, 0xed, 0xb8, 0x7b, 0xf8, 0xec, 0x71, 0xbb, 0xe9, 0xf4, 0x0f,
+	0xda, 0xcd, 0xbe, 0x59, 0xa4, 0x1a, 0x5a, 0x1d, 0x85, 0x52, 0xa2, 0x14, 0x5b, 0xa5, 0x94, 0xeb,
+	0x1d, 0x80, 0xf4, 0xa3, 0x0d, 0x55, 0x4a, 0x5d, 0xe3, 0x14, 0x73, 0x85, 0x5a, 0x74, 0x14, 0x10,
+	0x1c, 0x05, 0xee, 0xd8, 0x34, 0xd0, 0x2d, 0xa8, 0xb0, 0x48, 0x25, 0x4e, 0x6f, 0x88, 0xef, 0x5f,
+	0x0e, 0xfe, 0x05, 0x1e, 0x10, 0xec, 0x99, 0xd9, 0xfa, 0xef, 0x33, 0xca, 0x4b, 0x95, 0x5a, 0xdc,
+	0x09, 0xd9, 0xd2, 0x5c, 0xa1, 0x0b, 0xf1, 0x3d, 0xc3, 0x34, 0xa8, 0xe6, 0x96, 0x1b, 0x0c, 0xf0,
+	0x18, 0x7b, 0x66, 0x86, 0xda, 0x75, 0x14, 0x5c, 0xba, 0x63, 0xdf, 0x63, 0x39, 0x35, 0xb3, 0x08,
+	0xd1, 0xf7, 0x06, 0xa3, 0x48, 0x99, 0x9c, 0x42, 0x7b, 0xe2, 0x5e, 0x8d, 0x43, 0xd7, 0x33, 0xf3,
+	0x34, 0x49, 0x3a, 0xad, 0xe7, 0x7f, 0x81, 0xcd, 0x02, 0xd5, 0x9f, 0x58, 0x55, 0xa4, 0x86, 0x32,
+	0xc5, 0x9d, 0x90, 0x38, 0xd8, 0xf5, 0xae, 0x78, 0x28, 0x7a, 0x57, 0x31, 0xc1, 0x93, 0xd6, 0x38,
+	0x8c, 0xb1, 0x67, 0x96, 0x19, 0x10, 0xe2, 0xa0, 0x39, 0x8e, 0x28, 0x47, 0x92, 0x79, 0xd3, 0xa3,
+	0x51, 0xe9, 0xce, 0x48, 0xf7, 0xdc, 0xa1, 0x93, 0xbb, 0x49, 0x3b, 0xdc, 0x7a, 0x27, 0x24, 0x0a,
+	0x68, 0xcc, 0x73, 0xb4, 0x05, 0x66, 0x97, 0x8c, 0x70, 0xc4, 0x75, 0x72, 0x97, 0xff, 0x59, 0xac,
+	0xff, 0xd5, 0x00, 0x24, 0x3b, 0x83, 0x82, 0x39, 0x8a, 0x07, 0x7f, 0x70, 0x91, 0x40, 0x6d, 0x0b,
+	0x36, 0x94, 0x2f, 0x24, 0x09, 0xd2, 0xb6, 0x60, 0xc3, 0x5e, 0x20, 0x67, 0xa8, 0xcf, 0xea, 0x67,
+	0x19, 0x09, 0x3a, 0x9a, 0x9f, 0x43, 0x4c, 0x12, 0x04, 0xe7, 0xd0, 0x5b, 0x0b, 0x55, 0x28, 0xb6,
+	0xf2, 0xd4, 0x87, 0x1e, 0x26, 0xac, 0xda, 0x05, 0xad, 0x80, 0xaa, 0x70, 0x5b, 0x9f, 0xb7, 0xc4,
+	0x4e, 0xb1, 0xfe, 0xa5, 0x01, 0x6b, 0x5a, 0xef, 0xa5, 0x45, 0x20, 0x09, 0xad, 0x08, 0xb3, 0x40,
+	0xad, 0xd0, 0xf3, 0x24, 0x51, 0x7b, 0x2b, 0x99, 0x06, 0xfa, 0x1e, 0xbc, 0xbb, 0xb0, 0x25, 0x3b,
+	0x83, 0x83, 0x07, 0xd8, 0xbf, 0x64, 0x40, 0x78, 0x1b, 0xee, 0x2e, 0xb0, 0x7d, 0xea, 0xfa, 0x14,
+	0x25, 0x59, 0xf5, 0x4c, 0x67, 0x16, 0x04, 0x54, 0x71, 0xae, 0xfe, 0x39, 0x98, 0xf3, 0x0f, 0x57,
+	0x1a, 0xde, 0xa6, 0xe7, 0x89, 0x09, 0xc7, 0x5c, 0xa1, 0xe9, 0x77, 0xf0, 0x24, 0xbc, 0xc4, 0x92,
+	0x64, 0xb0, 0xf4, 0x13, 0x37, 0x22, 0x92, 0x92, 0xa1, 0xd1, 0xeb, 0x91, 0x70, 0x2a, 0x09, 0xd9,
+	0xfa, 0xfb, 0xda, 0x13, 0x8d, 0x2a, 0xa5, 0x3d, 0x87, 0x53, 0xcc, 0x15, 0x5a, 0xf1, 0x76, 0x20,
+	0x97, 0xc6, 0x41, 0xfb, 0xc5, 0x3f, 0xee, 0xad, 0x7c, 0xfd, 0xf2, 0x9e, 0xf1, 0xe2, 0xe5, 0x3d,
+	0xe3, 0xef, 0x2f, 0xef, 0x19, 0x3f, 0xdf, 0x53, 0xfe, 0xa1, 0x99, 0xb8, 0x24, 0xf2, 0x9f, 0x87,
+	0x91, 0x3f, 0xf4, 0x03, 0xb9, 0x08, 0xf0, 0xce, 0xf4, 0x62, 0xb8, 0x33, 0x3d, 0xdb, 0x49, 0x3b,
+	0xde, 0x59, 0x81, 0xfd, 0x3d, 0xb3, 0xf7, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5f, 0x32, 0x2a,
+	0x8b, 0xfd, 0x19, 0x00, 0x00,
 }
 
 func (m *LogShardInfo) Marshal() (dAtA []byte, err error) {
@@ -2467,6 +2642,40 @@ func (m *LogReplicaInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	return len(dAtA) - i, nil
 }
 
+func (m *CNStoreHeartbeat) 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 *CNStoreHeartbeat) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *CNStoreHeartbeat) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.UUID) > 0 {
+		i -= len(m.UUID)
+		copy(dAtA[i:], m.UUID)
+		i = encodeVarintLogservice(dAtA, i, uint64(len(m.UUID)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
 func (m *LogStoreHeartbeat) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
@@ -2851,7 +3060,7 @@ func (m *Request) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 		i = encodeVarintLogservice(dAtA, i, uint64(size))
 	}
 	i--
-	dAtA[i] = 0x3a
+	dAtA[i] = 0x42
 	{
 		size, err := m.DNHeartbeat.MarshalToSizedBuffer(dAtA[:i])
 		if err != nil {
@@ -2861,6 +3070,16 @@ func (m *Request) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 		i = encodeVarintLogservice(dAtA, i, uint64(size))
 	}
 	i--
+	dAtA[i] = 0x3a
+	{
+		size, err := m.CNHeartbeat.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintLogservice(dAtA, i, uint64(size))
+	}
+	i--
 	dAtA[i] = 0x32
 	{
 		size, err := m.LogHeartbeat.MarshalToSizedBuffer(dAtA[:i])
@@ -3355,7 +3574,7 @@ func (m *CommandBatch) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	return len(dAtA) - i, nil
 }
 
-func (m *DNStoreInfo) Marshal() (dAtA []byte, err error) {
+func (m *CNStoreInfo) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
 	n, err := m.MarshalToSizedBuffer(dAtA[:size])
@@ -3365,12 +3584,12 @@ func (m *DNStoreInfo) Marshal() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *DNStoreInfo) MarshalTo(dAtA []byte) (int, error) {
+func (m *CNStoreInfo) MarshalTo(dAtA []byte) (int, error) {
 	size := m.Size()
 	return m.MarshalToSizedBuffer(dAtA[:size])
 }
 
-func (m *DNStoreInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+func (m *CNStoreInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	i := len(dAtA)
 	_ = i
 	var l int
@@ -3379,20 +3598,6 @@ func (m *DNStoreInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 		i -= len(m.XXX_unrecognized)
 		copy(dAtA[i:], m.XXX_unrecognized)
 	}
-	if len(m.Shards) > 0 {
-		for iNdEx := len(m.Shards) - 1; iNdEx >= 0; iNdEx-- {
-			{
-				size, err := m.Shards[iNdEx].MarshalToSizedBuffer(dAtA[:i])
-				if err != nil {
-					return 0, err
-				}
-				i -= size
-				i = encodeVarintLogservice(dAtA, i, uint64(size))
-			}
-			i--
-			dAtA[i] = 0x12
-		}
-	}
 	if m.Tick != 0 {
 		i = encodeVarintLogservice(dAtA, i, uint64(m.Tick))
 		i--
@@ -3401,7 +3606,7 @@ func (m *DNStoreInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	return len(dAtA) - i, nil
 }
 
-func (m *DNState) Marshal() (dAtA []byte, err error) {
+func (m *CNState) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
 	n, err := m.MarshalToSizedBuffer(dAtA[:size])
@@ -3411,12 +3616,12 @@ func (m *DNState) Marshal() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *DNState) MarshalTo(dAtA []byte) (int, error) {
+func (m *CNState) MarshalTo(dAtA []byte) (int, error) {
 	size := m.Size()
 	return m.MarshalToSizedBuffer(dAtA[:size])
 }
 
-func (m *DNState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+func (m *CNState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	i := len(dAtA)
 	_ = i
 	var l int
@@ -3452,7 +3657,7 @@ func (m *DNState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	return len(dAtA) - i, nil
 }
 
-func (m *ClusterInfo) Marshal() (dAtA []byte, err error) {
+func (m *DNStoreInfo) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
 	n, err := m.MarshalToSizedBuffer(dAtA[:size])
@@ -3462,12 +3667,12 @@ func (m *ClusterInfo) Marshal() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *ClusterInfo) MarshalTo(dAtA []byte) (int, error) {
+func (m *DNStoreInfo) MarshalTo(dAtA []byte) (int, error) {
 	size := m.Size()
 	return m.MarshalToSizedBuffer(dAtA[:size])
 }
 
-func (m *ClusterInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+func (m *DNStoreInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	i := len(dAtA)
 	_ = i
 	var l int
@@ -3476,10 +3681,10 @@ func (m *ClusterInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 		i -= len(m.XXX_unrecognized)
 		copy(dAtA[i:], m.XXX_unrecognized)
 	}
-	if len(m.LogShards) > 0 {
-		for iNdEx := len(m.LogShards) - 1; iNdEx >= 0; iNdEx-- {
+	if len(m.Shards) > 0 {
+		for iNdEx := len(m.Shards) - 1; iNdEx >= 0; iNdEx-- {
 			{
-				size, err := m.LogShards[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				size, err := m.Shards[iNdEx].MarshalToSizedBuffer(dAtA[:i])
 				if err != nil {
 					return 0, err
 				}
@@ -3490,24 +3695,15 @@ func (m *ClusterInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 			dAtA[i] = 0x12
 		}
 	}
-	if len(m.DNShards) > 0 {
-		for iNdEx := len(m.DNShards) - 1; iNdEx >= 0; iNdEx-- {
-			{
-				size, err := m.DNShards[iNdEx].MarshalToSizedBuffer(dAtA[:i])
-				if err != nil {
-					return 0, err
-				}
-				i -= size
-				i = encodeVarintLogservice(dAtA, i, uint64(size))
-			}
-			i--
-			dAtA[i] = 0xa
-		}
+	if m.Tick != 0 {
+		i = encodeVarintLogservice(dAtA, i, uint64(m.Tick))
+		i--
+		dAtA[i] = 0x8
 	}
 	return len(dAtA) - i, nil
 }
 
-func (m *InitialClusterRequest) Marshal() (dAtA []byte, err error) {
+func (m *DNState) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
 	n, err := m.MarshalToSizedBuffer(dAtA[:size])
@@ -3517,12 +3713,12 @@ func (m *InitialClusterRequest) Marshal() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *InitialClusterRequest) MarshalTo(dAtA []byte) (int, error) {
+func (m *DNState) MarshalTo(dAtA []byte) (int, error) {
 	size := m.Size()
 	return m.MarshalToSizedBuffer(dAtA[:size])
 }
 
-func (m *InitialClusterRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+func (m *DNState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 	i := len(dAtA)
 	_ = i
 	var l int
@@ -3531,16 +3727,122 @@ func (m *InitialClusterRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 		i -= len(m.XXX_unrecognized)
 		copy(dAtA[i:], m.XXX_unrecognized)
 	}
-	if m.NumOfLogReplicas != 0 {
-		i = encodeVarintLogservice(dAtA, i, uint64(m.NumOfLogReplicas))
-		i--
-		dAtA[i] = 0x18
-	}
-	if m.NumOfDNShards != 0 {
-		i = encodeVarintLogservice(dAtA, i, uint64(m.NumOfDNShards))
-		i--
-		dAtA[i] = 0x10
-	}
+	if len(m.Stores) > 0 {
+		for k := range m.Stores {
+			v := m.Stores[k]
+			baseI := i
+			{
+				size, err := (&v).MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintLogservice(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+			i -= len(k)
+			copy(dAtA[i:], k)
+			i = encodeVarintLogservice(dAtA, i, uint64(len(k)))
+			i--
+			dAtA[i] = 0xa
+			i = encodeVarintLogservice(dAtA, i, uint64(baseI-i))
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *ClusterInfo) 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 *ClusterInfo) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ClusterInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.LogShards) > 0 {
+		for iNdEx := len(m.LogShards) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.LogShards[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintLogservice(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	if len(m.DNShards) > 0 {
+		for iNdEx := len(m.DNShards) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.DNShards[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintLogservice(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0xa
+		}
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *InitialClusterRequest) 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 *InitialClusterRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *InitialClusterRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.NumOfLogReplicas != 0 {
+		i = encodeVarintLogservice(dAtA, i, uint64(m.NumOfLogReplicas))
+		i--
+		dAtA[i] = 0x18
+	}
+	if m.NumOfDNShards != 0 {
+		i = encodeVarintLogservice(dAtA, i, uint64(m.NumOfDNShards))
+		i--
+		dAtA[i] = 0x10
+	}
 	if m.NumOfLogShards != 0 {
 		i = encodeVarintLogservice(dAtA, i, uint64(m.NumOfLogShards))
 		i--
@@ -3789,7 +4091,7 @@ func (m *HAKeeperRSMState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 		i = encodeVarintLogservice(dAtA, i, uint64(size))
 	}
 	i--
-	dAtA[i] = 0x4a
+	dAtA[i] = 0x52
 	{
 		size, err := m.LogState.MarshalToSizedBuffer(dAtA[:i])
 		if err != nil {
@@ -3799,7 +4101,7 @@ func (m *HAKeeperRSMState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 		i = encodeVarintLogservice(dAtA, i, uint64(size))
 	}
 	i--
-	dAtA[i] = 0x42
+	dAtA[i] = 0x4a
 	{
 		size, err := m.DNState.MarshalToSizedBuffer(dAtA[:i])
 		if err != nil {
@@ -3809,6 +4111,16 @@ func (m *HAKeeperRSMState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
 		i = encodeVarintLogservice(dAtA, i, uint64(size))
 	}
 	i--
+	dAtA[i] = 0x42
+	{
+		size, err := m.CNState.MarshalToSizedBuffer(dAtA[:i])
+		if err != nil {
+			return 0, err
+		}
+		i -= size
+		i = encodeVarintLogservice(dAtA, i, uint64(size))
+	}
+	i--
 	dAtA[i] = 0x3a
 	if len(m.LogShards) > 0 {
 		for k := range m.LogShards {
@@ -3934,6 +4246,22 @@ func (m *LogReplicaInfo) Size() (n int) {
 	return n
 }
 
+func (m *CNStoreHeartbeat) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.UUID)
+	if l > 0 {
+		n += 1 + l + sovLogservice(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
 func (m *LogStoreHeartbeat) Size() (n int) {
 	if m == nil {
 		return 0
@@ -4127,6 +4455,8 @@ func (m *Request) Size() (n int) {
 	n += 1 + l + sovLogservice(uint64(l))
 	l = m.LogHeartbeat.Size()
 	n += 1 + l + sovLogservice(uint64(l))
+	l = m.CNHeartbeat.Size()
+	n += 1 + l + sovLogservice(uint64(l))
 	l = m.DNHeartbeat.Size()
 	n += 1 + l + sovLogservice(uint64(l))
 	l = m.TsoRequest.Size()
@@ -4339,6 +4669,42 @@ func (m *CommandBatch) Size() (n int) {
 	return n
 }
 
+func (m *CNStoreInfo) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Tick != 0 {
+		n += 1 + sovLogservice(uint64(m.Tick))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *CNState) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.Stores) > 0 {
+		for k, v := range m.Stores {
+			_ = k
+			_ = v
+			l = v.Size()
+			mapEntrySize := 1 + len(k) + sovLogservice(uint64(len(k))) + 1 + l + sovLogservice(uint64(l))
+			n += mapEntrySize + 1 + sovLogservice(uint64(mapEntrySize))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
 func (m *DNStoreInfo) Size() (n int) {
 	if m == nil {
 		return 0
@@ -4548,6 +4914,8 @@ func (m *HAKeeperRSMState) Size() (n int) {
 			n += mapEntrySize + 1 + sovLogservice(uint64(mapEntrySize))
 		}
 	}
+	l = m.CNState.Size()
+	n += 1 + l + sovLogservice(uint64(l))
 	l = m.DNState.Size()
 	n += 1 + l + sovLogservice(uint64(l))
 	l = m.LogState.Size()
@@ -4909,6 +5277,89 @@ func (m *LogReplicaInfo) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
+func (m *CNStoreHeartbeat) 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 ErrIntOverflowLogservice
+			}
+			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: CNStoreHeartbeat: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: CNStoreHeartbeat: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field UUID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowLogservice
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthLogservice
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthLogservice
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.UUID = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipLogservice(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthLogservice
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *LogStoreHeartbeat) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
@@ -6078,6 +6529,39 @@ func (m *Request) Unmarshal(dAtA []byte) error {
 			}
 			iNdEx = postIndex
 		case 6:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CNHeartbeat", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowLogservice
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthLogservice
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthLogservice
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.CNHeartbeat.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 7:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field DNHeartbeat", wireType)
 			}
@@ -6110,7 +6594,7 @@ func (m *Request) Unmarshal(dAtA []byte) error {
 				return err
 			}
 			iNdEx = postIndex
-		case 7:
+		case 8:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field TsoRequest", wireType)
 			}
@@ -7213,21 +7697,127 @@ func (m *ScheduleCommand) Unmarshal(dAtA []byte) error {
 			if postIndex < 0 {
 				return ErrInvalidLengthLogservice
 			}
-			if postIndex > l {
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.ConfigChange == nil {
+				m.ConfigChange = &ConfigChange{}
+			}
+			if err := m.ConfigChange.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ServiceType", wireType)
+			}
+			m.ServiceType = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowLogservice
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.ServiceType |= ServiceType(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ShutdownStore", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowLogservice
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthLogservice
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthLogservice
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.ShutdownStore == nil {
+				m.ShutdownStore = &ShutdownStore{}
+			}
+			if err := m.ShutdownStore.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipLogservice(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthLogservice
+			}
+			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
-			if m.ConfigChange == nil {
-				m.ConfigChange = &ConfigChange{}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *CommandBatch) 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 ErrIntOverflowLogservice
 			}
-			if err := m.ConfigChange.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
-				return err
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
 			}
-			iNdEx = postIndex
-		case 4:
+			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: CommandBatch: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: CommandBatch: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
 			if wireType != 0 {
-				return fmt.Errorf("proto: wrong wireType = %d for field ServiceType", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field Term", wireType)
 			}
-			m.ServiceType = 0
+			m.Term = 0
 			for shift := uint(0); ; shift += 7 {
 				if shift >= 64 {
 					return ErrIntOverflowLogservice
@@ -7237,14 +7827,14 @@ func (m *ScheduleCommand) Unmarshal(dAtA []byte) error {
 				}
 				b := dAtA[iNdEx]
 				iNdEx++
-				m.ServiceType |= ServiceType(b&0x7F) << shift
+				m.Term |= uint64(b&0x7F) << shift
 				if b < 0x80 {
 					break
 				}
 			}
-		case 5:
+		case 2:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field ShutdownStore", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field Commands", wireType)
 			}
 			var msglen int
 			for shift := uint(0); ; shift += 7 {
@@ -7271,10 +7861,8 @@ func (m *ScheduleCommand) Unmarshal(dAtA []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			if m.ShutdownStore == nil {
-				m.ShutdownStore = &ShutdownStore{}
-			}
-			if err := m.ShutdownStore.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+			m.Commands = append(m.Commands, ScheduleCommand{})
+			if err := m.Commands[len(m.Commands)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 				return err
 			}
 			iNdEx = postIndex
@@ -7300,7 +7888,7 @@ func (m *ScheduleCommand) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
-func (m *CommandBatch) Unmarshal(dAtA []byte) error {
+func (m *CNStoreInfo) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
 	for iNdEx < l {
@@ -7323,17 +7911,17 @@ func (m *CommandBatch) Unmarshal(dAtA []byte) error {
 		fieldNum := int32(wire >> 3)
 		wireType := int(wire & 0x7)
 		if wireType == 4 {
-			return fmt.Errorf("proto: CommandBatch: wiretype end group for non-group")
+			return fmt.Errorf("proto: CNStoreInfo: wiretype end group for non-group")
 		}
 		if fieldNum <= 0 {
-			return fmt.Errorf("proto: CommandBatch: illegal tag %d (wire type %d)", fieldNum, wire)
+			return fmt.Errorf("proto: CNStoreInfo: illegal tag %d (wire type %d)", fieldNum, wire)
 		}
 		switch fieldNum {
 		case 1:
 			if wireType != 0 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Term", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field Tick", wireType)
 			}
-			m.Term = 0
+			m.Tick = 0
 			for shift := uint(0); ; shift += 7 {
 				if shift >= 64 {
 					return ErrIntOverflowLogservice
@@ -7343,14 +7931,65 @@ func (m *CommandBatch) Unmarshal(dAtA []byte) error {
 				}
 				b := dAtA[iNdEx]
 				iNdEx++
-				m.Term |= uint64(b&0x7F) << shift
+				m.Tick |= uint64(b&0x7F) << shift
 				if b < 0x80 {
 					break
 				}
 			}
-		case 2:
+		default:
+			iNdEx = preIndex
+			skippy, err := skipLogservice(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if (skippy < 0) || (iNdEx+skippy) < 0 {
+				return ErrInvalidLengthLogservice
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *CNState) 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 ErrIntOverflowLogservice
+			}
+			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: CNState: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: CNState: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Commands", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field Stores", wireType)
 			}
 			var msglen int
 			for shift := uint(0); ; shift += 7 {
@@ -7377,10 +8016,105 @@ func (m *CommandBatch) Unmarshal(dAtA []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			m.Commands = append(m.Commands, ScheduleCommand{})
-			if err := m.Commands[len(m.Commands)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
-				return err
+			if m.Stores == nil {
+				m.Stores = make(map[string]CNStoreInfo)
 			}
+			var mapkey string
+			mapvalue := &CNStoreInfo{}
+			for iNdEx < postIndex {
+				entryPreIndex := iNdEx
+				var wire uint64
+				for shift := uint(0); ; shift += 7 {
+					if shift >= 64 {
+						return ErrIntOverflowLogservice
+					}
+					if iNdEx >= l {
+						return io.ErrUnexpectedEOF
+					}
+					b := dAtA[iNdEx]
+					iNdEx++
+					wire |= uint64(b&0x7F) << shift
+					if b < 0x80 {
+						break
+					}
+				}
+				fieldNum := int32(wire >> 3)
+				if fieldNum == 1 {
+					var stringLenmapkey uint64
+					for shift := uint(0); ; shift += 7 {
+						if shift >= 64 {
+							return ErrIntOverflowLogservice
+						}
+						if iNdEx >= l {
+							return io.ErrUnexpectedEOF
+						}
+						b := dAtA[iNdEx]
+						iNdEx++
+						stringLenmapkey |= uint64(b&0x7F) << shift
+						if b < 0x80 {
+							break
+						}
+					}
+					intStringLenmapkey := int(stringLenmapkey)
+					if intStringLenmapkey < 0 {
+						return ErrInvalidLengthLogservice
+					}
+					postStringIndexmapkey := iNdEx + intStringLenmapkey
+					if postStringIndexmapkey < 0 {
+						return ErrInvalidLengthLogservice
+					}
+					if postStringIndexmapkey > l {
+						return io.ErrUnexpectedEOF
+					}
+					mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
+					iNdEx = postStringIndexmapkey
+				} else if fieldNum == 2 {
+					var mapmsglen int
+					for shift := uint(0); ; shift += 7 {
+						if shift >= 64 {
+							return ErrIntOverflowLogservice
+						}
+						if iNdEx >= l {
+							return io.ErrUnexpectedEOF
+						}
+						b := dAtA[iNdEx]
+						iNdEx++
+						mapmsglen |= int(b&0x7F) << shift
+						if b < 0x80 {
+							break
+						}
+					}
+					if mapmsglen < 0 {
+						return ErrInvalidLengthLogservice
+					}
+					postmsgIndex := iNdEx + mapmsglen
+					if postmsgIndex < 0 {
+						return ErrInvalidLengthLogservice
+					}
+					if postmsgIndex > l {
+						return io.ErrUnexpectedEOF
+					}
+					mapvalue = &CNStoreInfo{}
+					if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil {
+						return err
+					}
+					iNdEx = postmsgIndex
+				} else {
+					iNdEx = entryPreIndex
+					skippy, err := skipLogservice(dAtA[iNdEx:])
+					if err != nil {
+						return err
+					}
+					if (skippy < 0) || (iNdEx+skippy) < 0 {
+						return ErrInvalidLengthLogservice
+					}
+					if (iNdEx + skippy) > postIndex {
+						return io.ErrUnexpectedEOF
+					}
+					iNdEx += skippy
+				}
+			}
+			m.Stores[mapkey] = *mapvalue
 			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
@@ -8946,6 +9680,39 @@ func (m *HAKeeperRSMState) Unmarshal(dAtA []byte) error {
 			m.LogShards[mapkey] = mapvalue
 			iNdEx = postIndex
 		case 7:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CNState", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowLogservice
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthLogservice
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthLogservice
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.CNState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 8:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field DNState", wireType)
 			}
@@ -8978,7 +9745,7 @@ func (m *HAKeeperRSMState) Unmarshal(dAtA []byte) error {
 				return err
 			}
 			iNdEx = postIndex
-		case 8:
+		case 9:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field LogState", wireType)
 			}
@@ -9011,7 +9778,7 @@ func (m *HAKeeperRSMState) Unmarshal(dAtA []byte) error {
 				return err
 			}
 			iNdEx = postIndex
-		case 9:
+		case 10:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field ClusterInfo", wireType)
 			}
diff --git a/proto/logservice.proto b/proto/logservice.proto
index 341573b9a..69d525413 100644
--- a/proto/logservice.proto
+++ b/proto/logservice.proto
@@ -53,6 +53,11 @@ message LogReplicaInfo {
   uint64 ReplicaID = 2;
 }
 
+// CNStoreHeartbeat is the periodic message sent tp the HAKeeper by CN stores.
+message CNStoreHeartbeat {
+  string UUID = 1;
+}
+
 // LogStoreHeartbeat is the periodic message sent to the HAKeeper by Log Stores.
 message LogStoreHeartbeat {
   // UUID is the uuid of the Log Store.
@@ -108,7 +113,8 @@ enum MethodType {
   CONNECT       = 5;
   CONNECT_RO    = 6;
   LOG_HEARTBEAT = 7;
-  DN_HEARTBEAT  = 8;
+  CN_HEARTBEAT  = 8;
+  DN_HEARTBEAT  = 9;
 };
 
 enum RecordType {
@@ -144,8 +150,9 @@ message Request {
   int64 Timeout                  = 3;
   LogRequest LogRequest          = 4 [(gogoproto.nullable) = false];
   LogStoreHeartbeat LogHeartbeat = 5 [(gogoproto.nullable) = false];
-  DNStoreHeartbeat DNHeartbeat   = 6 [(gogoproto.nullable) = false];
-  TsoRequest TsoRequest          = 7 [(gogoproto.nullable) = false];
+  CNStoreHeartbeat CNHeartbeat   = 6 [(gogoproto.nullable) = false];
+  DNStoreHeartbeat DNHeartbeat   = 7 [(gogoproto.nullable) = false];
+  TsoRequest TsoRequest          = 8 [(gogoproto.nullable) = false];
 };
 
 enum ErrorCode {
@@ -197,12 +204,13 @@ message TsoResponse {
 
 enum HAKeeperUpdateType {
   TickUpdate            = 0;
-  DNHeartbeatUpdate     = 1;
-  LogHeartbeatUpdate    = 2;
-  GetIDUpdate           = 3;
-  ScheduleCommandUpdate = 4;
-  SetStateUpdate        = 5;
-  InitialClusterUpdate  = 6;
+  CNHeartbeatUpdate     = 1;
+  DNHeartbeatUpdate     = 2;
+  LogHeartbeatUpdate    = 3;
+  GetIDUpdate           = 4;
+  ScheduleCommandUpdate = 5;
+  SetStateUpdate        = 6;
+  InitialClusterUpdate  = 7;
 }
 
 enum HAKeeperState {
@@ -267,7 +275,19 @@ message CommandBatch {
   repeated ScheduleCommand Commands = 2 [(gogoproto.nullable) = false];
 }
 
-// DNStoreInfo contins information on a list of shards.
+// CNStoreInfo contains infroamtion on a CN store.
+message CNStoreInfo {
+  uint64 Tick                 = 1;
+}
+
+// CNState contains all CN details known to the HAKeeper.
+message CNState {
+  // Stores is keyed by CN store UUID. 
+  map<string, CNStoreInfo> Stores = 1 [(gogoproto.nullable) = false];
+}
+
+
+// DNStoreInfo contins information on a DN store.
 message DNStoreInfo {
   uint64 Tick                 = 1;
   repeated DNShardInfo Shards = 2 [(gogoproto.nullable) = false];
@@ -275,8 +295,7 @@ message DNStoreInfo {
 
 // DNState contains all DN details known to the HAKeeper.
 message DNState {
-  // Stores is keyed by DN store UUID, it contains details found on each DN
-  // store. Each DNStoreInfo reflects what was last reported by each DN store.
+  // Stores is keyed by DN store UUID.
   map<string, DNStoreInfo> Stores = 1 [(gogoproto.nullable) = false];
 }
 
@@ -333,7 +352,8 @@ message HAKeeperRSMState {
   HAKeeperState State                        = 4;
   map<string, CommandBatch> ScheduleCommands = 5 [(gogoproto.nullable) = false];
   map<string, uint64> LogShards = 6;
-  DNState DNState               = 7 [(gogoproto.nullable) = false];
-  LogState LogState             = 8 [(gogoproto.nullable) = false];
-  ClusterInfo ClusterInfo       = 9 [(gogoproto.nullable) = false];
+  CNState CNState               = 7  [(gogoproto.nullable) = false];
+  DNState DNState               = 8  [(gogoproto.nullable) = false];
+  LogState LogState             = 9  [(gogoproto.nullable) = false];
+  ClusterInfo ClusterInfo       = 10 [(gogoproto.nullable) = false];
 }


Test patch:
diff --git a/pkg/hakeeper/rsm_test.go b/pkg/hakeeper/rsm_test.go
index e04814b26..1d925f184 100644
--- a/pkg/hakeeper/rsm_test.go
+++ b/pkg/hakeeper/rsm_test.go
@@ -166,6 +166,31 @@ func TestHandleDNHeartbeat(t *testing.T) {
 	assert.Equal(t, hb.Shards, dninfo.Shards)
 }
 
+func TestHandleCNHeartbeat(t *testing.T) {
+	tsm1 := NewStateMachine(0, 1).(*stateMachine)
+	cmd := GetTickCmd()
+	_, err := tsm1.Update(sm.Entry{Cmd: cmd})
+	assert.NoError(t, err)
+	_, err = tsm1.Update(sm.Entry{Cmd: cmd})
+	assert.NoError(t, err)
+	_, err = tsm1.Update(sm.Entry{Cmd: cmd})
+	assert.NoError(t, err)
+
+	hb := pb.CNStoreHeartbeat{
+		UUID: "uuid1",
+	}
+	data, err := hb.Marshal()
+	require.NoError(t, err)
+	cmd = GetCNStoreHeartbeatCmd(data)
+	_, err = tsm1.Update(sm.Entry{Cmd: cmd})
+	assert.NoError(t, err)
+	s := tsm1.state.CNState
+	assert.Equal(t, 1, len(s.Stores))
+	cninfo, ok := s.Stores[hb.UUID]
+	assert.True(t, ok)
+	assert.Equal(t, uint64(3), cninfo.Tick)
+}
+
 func TestGetIDCmd(t *testing.T) {
 	tsm1 := NewStateMachine(0, 1).(*stateMachine)
 	cmd := GetGetIDCmd(100)
diff --git a/pkg/logservice/service_test.go b/pkg/logservice/service_test.go
index b0826e3e0..13a07cc93 100644
--- a/pkg/logservice/service_test.go
+++ b/pkg/logservice/service_test.go
@@ -178,6 +178,22 @@ func TestServiceHandleLogHeartbeat(t *testing.T) {
 	runServiceTest(t, true, true, fn)
 }
 
+func TestServiceHandleCNHeartbeat(t *testing.T) {
+	fn := func(t *testing.T, s *Service) {
+		req := pb.Request{
+			Method:  pb.CN_HEARTBEAT,
+			Timeout: int64(time.Second),
+			CNHeartbeat: pb.CNStoreHeartbeat{
+				UUID: "uuid1",
+			},
+		}
+		resp := s.handleCNHeartbeat(req)
+		assert.Equal(t, 0, len(resp.CommandBatch.Commands))
+		assert.Equal(t, pb.ErrorCode(0), resp.ErrorCode)
+	}
+	runServiceTest(t, true, true, fn)
+}
+
 func TestServiceHandleDNHeartbeat(t *testing.T) {
 	fn := func(t *testing.T, s *Service) {
 		req := pb.Request{
diff --git a/pkg/logservice/store_test.go b/pkg/logservice/store_test.go
index dc4221f9b..f9cf5c5ea 100644
--- a/pkg/logservice/store_test.go
+++ b/pkg/logservice/store_test.go
@@ -353,6 +353,11 @@ func TestAddHeartbeat(t *testing.T) {
 		defer cancel()
 		assert.NoError(t, store.addLogStoreHeartbeat(ctx, m))
 
+		cnMsg := pb.CNStoreHeartbeat{
+			UUID: store.id(),
+		}
+		assert.NoError(t, store.addCNStoreHeartbeat(ctx, cnMsg))
+
 		dnMsg := pb.DNStoreHeartbeat{
 			UUID:   store.id(),
 			Shards: make([]pb.DNShardInfo, 0),