diff --git a/go.mod b/go.mod index dc18e95444a..0ec813f0d71 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/golang/mock v1.3.1 github.com/golang/protobuf v1.3.2 github.com/golang/snappy v0.0.0-20170215233205-553a64147049 + github.com/google/btree v1.0.0 // indirect github.com/gorilla/websocket v0.0.0-20160912153041-2d1e4548da23 github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 diff --git a/go/vt/proto/topodata/topodata.pb.go b/go/vt/proto/topodata/topodata.pb.go index 2132bd1faf5..bdc3fa43c16 100644 --- a/go/vt/proto/topodata/topodata.pb.go +++ b/go/vt/proto/topodata/topodata.pb.go @@ -8,6 +8,7 @@ import ( math "math" proto "github.com/golang/protobuf/proto" + logutil "vitess.io/vitess/go/vt/proto/logutil" ) // Reference imports to suppress errors if they are not otherwise used. @@ -369,12 +370,27 @@ func (m *Tablet) GetMysqlPort() int32 { // A Shard contains data about a subset of the data whithin a keyspace. type Shard struct { + // master_alias is the tablet alias of the master for the shard. + // If it is unset, then there is no master in this shard yet. // No lock is necessary to update this field, when for instance // TabletExternallyReparented updates this. However, we lock the // shard for reparenting operations (InitShardMaster, // PlannedReparentShard,EmergencyReparentShard), to guarantee // exclusive operation. MasterAlias *TabletAlias `protobuf:"bytes,1,opt,name=master_alias,json=masterAlias,proto3" json:"master_alias,omitempty"` + // master_term_start_time is the time (in UTC) at which the current term of + // the master specified in master_alias began. + // + // A new master term begins any time an authoritative decision is communicated + // about which tablet should be the master, such as via Vitess + // replication-management commands like PlannedReparentShard, + // EmergencyReparentShard, and TabletExternallyReparented. + // + // The master_alias should only ever be changed if the new master's term began + // at a later time than this. Note that a new term can start for the tablet + // that is already the master. In that case, the master_term_start_time would + // be increased without changing the master_alias. + MasterTermStartTime *logutil.Time `protobuf:"bytes,8,opt,name=master_term_start_time,json=masterTermStartTime,proto3" json:"master_term_start_time,omitempty"` // key_range is the KeyRange for this shard. It can be unset if: // - we are not using range-based sharding in this shard. // - the shard covers the entire keyrange. @@ -433,6 +449,13 @@ func (m *Shard) GetMasterAlias() *TabletAlias { return nil } +func (m *Shard) GetMasterTermStartTime() *logutil.Time { + if m != nil { + return m.MasterTermStartTime + } + return nil +} + func (m *Shard) GetKeyRange() *KeyRange { if m != nil { return m.KeyRange @@ -1274,82 +1297,84 @@ func init() { func init() { proto.RegisterFile("topodata.proto", fileDescriptor_52c350cb619f972e) } var fileDescriptor_52c350cb619f972e = []byte{ - // 1218 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0xe1, 0x6e, 0x1b, 0x45, - 0x10, 0xe6, 0xec, 0xb3, 0x63, 0x8f, 0x1d, 0xe7, 0xba, 0xa4, 0xd5, 0xe9, 0xa0, 0x22, 0xb2, 0x54, - 0x11, 0x15, 0xe1, 0xa0, 0xb4, 0x85, 0xa8, 0x12, 0x52, 0x5d, 0xc7, 0xa5, 0x69, 0x1a, 0xc7, 0x5a, - 0x3b, 0x82, 0xf2, 0xe7, 0x74, 0xf1, 0x6d, 0xd2, 0x53, 0xce, 0xb7, 0xee, 0xee, 0x26, 0x92, 0x79, - 0x05, 0x7e, 0x00, 0x7f, 0x79, 0x03, 0x1e, 0x81, 0x27, 0xe0, 0x39, 0xe0, 0x49, 0xd0, 0xce, 0xde, - 0xd9, 0x67, 0xbb, 0x2d, 0x29, 0xca, 0xbf, 0x99, 0xdd, 0x99, 0xb9, 0x99, 0x6f, 0xe6, 0x9b, 0xb5, - 0xa1, 0xa1, 0xf8, 0x84, 0x87, 0x81, 0x0a, 0x5a, 0x13, 0xc1, 0x15, 0x27, 0x95, 0x4c, 0x6f, 0xee, - 0x42, 0xe5, 0x90, 0x4d, 0x69, 0x90, 0x9c, 0x33, 0xb2, 0x09, 0x25, 0xa9, 0x02, 0xa1, 0x5c, 0x6b, - 0xcb, 0xda, 0xae, 0x53, 0xa3, 0x10, 0x07, 0x8a, 0x2c, 0x09, 0xdd, 0x02, 0x9e, 0x69, 0xb1, 0xf9, - 0x00, 0x6a, 0xc3, 0xe0, 0x34, 0x66, 0xaa, 0x1d, 0x47, 0x81, 0x24, 0x04, 0xec, 0x11, 0x8b, 0x63, - 0xf4, 0xaa, 0x52, 0x94, 0xb5, 0xd3, 0x65, 0x64, 0x9c, 0xd6, 0xa9, 0x16, 0x9b, 0x7f, 0xda, 0x50, - 0x36, 0x5e, 0xe4, 0x0b, 0x28, 0x05, 0xda, 0x13, 0x3d, 0x6a, 0xbb, 0xb7, 0x5b, 0xb3, 0xec, 0x72, - 0x61, 0xa9, 0xb1, 0x21, 0x1e, 0x54, 0x5e, 0x73, 0xa9, 0x92, 0x60, 0xcc, 0x30, 0x5c, 0x95, 0xce, - 0x74, 0xb2, 0x07, 0x95, 0x09, 0x17, 0xca, 0x1f, 0x07, 0x13, 0xd7, 0xde, 0x2a, 0x6e, 0xd7, 0x76, - 0xef, 0x2e, 0xc7, 0x6a, 0xf5, 0xb9, 0x50, 0x47, 0xc1, 0xa4, 0x9b, 0x28, 0x31, 0xa5, 0x6b, 0x13, - 0xa3, 0xe9, 0xa8, 0x17, 0x6c, 0x2a, 0x27, 0xc1, 0x88, 0xb9, 0x25, 0x13, 0x35, 0xd3, 0x11, 0x86, - 0xd7, 0x81, 0x08, 0xdd, 0x32, 0x5e, 0x18, 0x85, 0xec, 0x40, 0xf5, 0x82, 0x4d, 0x7d, 0xa1, 0x91, - 0x72, 0xd7, 0x30, 0x71, 0x32, 0xff, 0x58, 0x86, 0x21, 0x86, 0x31, 0x68, 0x6e, 0x83, 0xad, 0xa6, - 0x13, 0xe6, 0x56, 0xb6, 0xac, 0xed, 0xc6, 0xee, 0xe6, 0x72, 0x62, 0xc3, 0xe9, 0x84, 0x51, 0xb4, - 0x20, 0xdb, 0xe0, 0x84, 0xa7, 0xbe, 0xae, 0xc8, 0xe7, 0x57, 0x4c, 0x88, 0x28, 0x64, 0x6e, 0x15, - 0xbf, 0xdd, 0x08, 0x4f, 0x7b, 0xc1, 0x98, 0x1d, 0xa7, 0xa7, 0xa4, 0x05, 0xb6, 0x0a, 0xce, 0xa5, - 0x0b, 0x58, 0xac, 0xb7, 0x52, 0xec, 0x30, 0x38, 0x97, 0xa6, 0x52, 0xb4, 0x23, 0xf7, 0xa0, 0x31, - 0x9e, 0xca, 0x37, 0xb1, 0x3f, 0x83, 0xb0, 0x8e, 0x71, 0xd7, 0xf1, 0xf4, 0x79, 0x86, 0xe3, 0x5d, - 0x00, 0x63, 0xa6, 0xe1, 0x71, 0xd7, 0xb7, 0xac, 0xed, 0x12, 0xad, 0xe2, 0x89, 0x46, 0xcf, 0x7b, - 0x0c, 0xf5, 0x3c, 0x8a, 0xba, 0xb9, 0x17, 0x6c, 0x9a, 0xf6, 0x5b, 0x8b, 0x1a, 0xb2, 0xab, 0x20, - 0xbe, 0x34, 0x1d, 0x2a, 0x51, 0xa3, 0x3c, 0x2e, 0xec, 0x59, 0xde, 0x37, 0x50, 0x9d, 0x25, 0xf5, - 0x5f, 0x8e, 0xd5, 0x9c, 0xe3, 0x0b, 0xbb, 0x52, 0x74, 0xec, 0x17, 0x76, 0xa5, 0xe6, 0xd4, 0x9b, - 0xbf, 0x95, 0xa1, 0x34, 0xc0, 0x2e, 0xec, 0x41, 0x7d, 0x1c, 0x48, 0xc5, 0x84, 0x7f, 0x8d, 0x09, - 0xaa, 0x19, 0x53, 0x33, 0xa5, 0x0b, 0xfd, 0x2b, 0x5c, 0xa3, 0x7f, 0xdf, 0x42, 0x5d, 0x32, 0x71, - 0xc5, 0x42, 0x5f, 0x37, 0x49, 0xba, 0xc5, 0x65, 0xcc, 0x31, 0xa3, 0xd6, 0x00, 0x6d, 0xb0, 0x9b, - 0x35, 0x39, 0x93, 0x25, 0x79, 0x02, 0xeb, 0x92, 0x5f, 0x8a, 0x11, 0xf3, 0x71, 0x7e, 0x64, 0x3a, - 0xa0, 0x9f, 0xac, 0xf8, 0xa3, 0x11, 0xca, 0xb4, 0x2e, 0xe7, 0x8a, 0x24, 0xcf, 0x60, 0x43, 0x61, - 0x35, 0xfe, 0x88, 0x27, 0x4a, 0xf0, 0x58, 0xba, 0xe5, 0xe5, 0x21, 0x37, 0x31, 0x4c, 0xd1, 0x1d, - 0x63, 0x45, 0x1b, 0x2a, 0xaf, 0x4a, 0x72, 0x1f, 0x6e, 0x45, 0xd2, 0x4f, 0x61, 0xd3, 0x29, 0x46, - 0xc9, 0x39, 0x4e, 0x70, 0x85, 0x6e, 0x44, 0xf2, 0x08, 0xcf, 0x07, 0xe6, 0xd8, 0x7b, 0x05, 0x30, - 0x2f, 0x88, 0x3c, 0x82, 0x5a, 0x9a, 0x01, 0x4e, 0xb2, 0xf5, 0x9e, 0x49, 0x06, 0x35, 0x93, 0x75, - 0x53, 0xf5, 0x12, 0x90, 0x6e, 0x61, 0xab, 0xa8, 0x9b, 0x8a, 0x8a, 0xf7, 0xbb, 0x05, 0xb5, 0x5c, - 0xb1, 0xd9, 0x8a, 0xb0, 0x66, 0x2b, 0x62, 0x81, 0x94, 0x85, 0x77, 0x91, 0xb2, 0xf8, 0x4e, 0x52, - 0xda, 0xd7, 0x68, 0xea, 0x1d, 0x28, 0x63, 0xa2, 0xd2, 0x2d, 0x61, 0x6e, 0xa9, 0xe6, 0xfd, 0x61, - 0xc1, 0xfa, 0x02, 0x8a, 0x37, 0x5a, 0x3b, 0xf9, 0x12, 0xc8, 0x69, 0x1c, 0x8c, 0x2e, 0xe2, 0x48, - 0x2a, 0x3d, 0x50, 0x26, 0x05, 0x1b, 0x4d, 0x6e, 0xe5, 0x6e, 0x30, 0xa8, 0xd4, 0x59, 0x9e, 0x09, - 0xfe, 0x13, 0x4b, 0x70, 0x37, 0x55, 0x68, 0xaa, 0xcd, 0x38, 0x51, 0x72, 0xca, 0xcd, 0xbf, 0x0a, - 0xb8, 0xb9, 0x0d, 0x3a, 0x5f, 0xc1, 0x26, 0x02, 0x12, 0x25, 0xe7, 0xfe, 0x88, 0xc7, 0x97, 0xe3, - 0x04, 0xd7, 0x49, 0xca, 0x34, 0x92, 0xdd, 0x75, 0xf0, 0x4a, 0x6f, 0x14, 0xf2, 0x62, 0xd5, 0x03, - 0xeb, 0x2c, 0x60, 0x9d, 0xee, 0x02, 0x88, 0xf8, 0x8d, 0x03, 0x33, 0xe3, 0x4b, 0xb1, 0xb0, 0xe6, - 0x27, 0x33, 0xa6, 0x9c, 0x09, 0x3e, 0x96, 0xab, 0xab, 0x38, 0x8b, 0x91, 0x92, 0xe5, 0x99, 0xe0, - 0xe3, 0x8c, 0x2c, 0x5a, 0x96, 0xde, 0x65, 0x36, 0x76, 0x5a, 0xbd, 0x59, 0xe8, 0xf3, 0x43, 0x55, - 0x5c, 0x1c, 0x2a, 0x83, 0x67, 0xf3, 0x67, 0x0b, 0x1c, 0xc3, 0x3f, 0x36, 0x89, 0xa3, 0x51, 0xa0, - 0x22, 0x9e, 0x90, 0x47, 0x50, 0x4a, 0x78, 0xc8, 0xf4, 0x86, 0xd1, 0xc5, 0x7c, 0xb6, 0x44, 0xb9, - 0x9c, 0x69, 0xab, 0xc7, 0x43, 0x46, 0x8d, 0xb5, 0xf7, 0x04, 0x6c, 0xad, 0xea, 0x3d, 0x95, 0x96, - 0x70, 0x9d, 0x3d, 0xa5, 0xe6, 0x4a, 0xf3, 0x04, 0x1a, 0xe9, 0x17, 0xce, 0x98, 0x60, 0xc9, 0x88, - 0xe9, 0xf7, 0x35, 0xd7, 0x4c, 0x94, 0x3f, 0x78, 0x9b, 0x35, 0x7f, 0xb1, 0x80, 0x60, 0xdc, 0xc5, - 0x29, 0xbf, 0x89, 0xd8, 0xe4, 0x21, 0xdc, 0x79, 0x73, 0xc9, 0xc4, 0xd4, 0x2c, 0x97, 0x11, 0xf3, - 0xc3, 0x48, 0xea, 0xaf, 0x18, 0xb2, 0x56, 0xe8, 0x26, 0xde, 0x0e, 0xcc, 0xe5, 0x7e, 0x7a, 0xd7, - 0xfc, 0xc7, 0x86, 0xda, 0x40, 0x5c, 0xcd, 0x66, 0xf8, 0x3b, 0x80, 0x49, 0x20, 0x54, 0xa4, 0x31, - 0xcd, 0x60, 0xff, 0x3c, 0x07, 0xfb, 0xdc, 0x74, 0x36, 0x4f, 0xfd, 0xcc, 0x9e, 0xe6, 0x5c, 0xdf, - 0x49, 0x86, 0xc2, 0x07, 0x93, 0xa1, 0xf8, 0x3f, 0xc8, 0xd0, 0x86, 0x5a, 0x8e, 0x0c, 0x29, 0x17, - 0xb6, 0xde, 0x5e, 0x47, 0x8e, 0x0e, 0x30, 0xa7, 0x83, 0xf7, 0xb7, 0x05, 0xb7, 0x56, 0x4a, 0xd4, - 0xac, 0xc8, 0xbd, 0x47, 0xef, 0x67, 0xc5, 0xfc, 0x21, 0x22, 0x1d, 0x70, 0x30, 0x4b, 0x5f, 0x64, - 0x03, 0x65, 0x08, 0x52, 0xcb, 0xd7, 0xb5, 0x38, 0x71, 0x74, 0x43, 0x2e, 0xe8, 0x92, 0xf4, 0xe1, - 0xb6, 0x09, 0xb2, 0xfc, 0x20, 0x99, 0x47, 0xf1, 0xd3, 0xa5, 0x48, 0x8b, 0xef, 0xd1, 0xc7, 0x72, - 0xe5, 0x4c, 0x7a, 0xfe, 0x4d, 0x30, 0xfe, 0x3d, 0x0f, 0x46, 0xba, 0x25, 0x0f, 0xa1, 0xd2, 0x61, - 0x71, 0x7c, 0x90, 0x9c, 0x71, 0xfd, 0x63, 0x08, 0x71, 0x11, 0x7e, 0x10, 0x86, 0x82, 0x49, 0x99, - 0x4e, 0xfd, 0xba, 0x39, 0x6d, 0x9b, 0x43, 0x4d, 0x09, 0xc1, 0xb9, 0x4a, 0x03, 0xa2, 0x9c, 0x2e, - 0x8a, 0x26, 0x80, 0x0e, 0x26, 0xcd, 0x0f, 0x8a, 0xb7, 0xae, 0x9b, 0xfb, 0xbb, 0xd0, 0x58, 0x1c, - 0x12, 0x52, 0x85, 0xd2, 0x49, 0x6f, 0xd0, 0x1d, 0x3a, 0x1f, 0x11, 0x80, 0xf2, 0xc9, 0x41, 0x6f, - 0xf8, 0xf5, 0x43, 0xc7, 0xd2, 0xc7, 0x4f, 0x5f, 0x0d, 0xbb, 0x03, 0xa7, 0x70, 0xff, 0x57, 0x0b, - 0x60, 0x5e, 0x21, 0xa9, 0xc1, 0xda, 0x49, 0xef, 0xb0, 0x77, 0xfc, 0x7d, 0xcf, 0xb8, 0x1c, 0xb5, - 0x07, 0xc3, 0x2e, 0x75, 0x2c, 0x7d, 0x41, 0xbb, 0xfd, 0x97, 0x07, 0x9d, 0xb6, 0x53, 0xd0, 0x17, - 0x74, 0xff, 0xb8, 0xf7, 0xf2, 0x95, 0x53, 0xc4, 0x58, 0xed, 0x61, 0xe7, 0xb9, 0x11, 0x07, 0xfd, - 0x36, 0xed, 0x3a, 0x36, 0x71, 0xa0, 0xde, 0xfd, 0xa1, 0xdf, 0xa5, 0x07, 0x47, 0xdd, 0xde, 0xb0, - 0xfd, 0xd2, 0x29, 0x69, 0x9f, 0xa7, 0xed, 0xce, 0xe1, 0x49, 0xdf, 0x29, 0x9b, 0x60, 0x83, 0xe1, - 0x31, 0xed, 0x3a, 0x6b, 0x5a, 0xd9, 0xa7, 0xed, 0x83, 0x5e, 0x77, 0xdf, 0xa9, 0x78, 0x05, 0xc7, - 0x7a, 0xba, 0x07, 0x1b, 0x11, 0x6f, 0x5d, 0x45, 0x8a, 0x49, 0x69, 0xfe, 0x33, 0xfc, 0x78, 0x2f, - 0xd5, 0x22, 0xbe, 0x63, 0xa4, 0x9d, 0x73, 0xbe, 0x73, 0xa5, 0x76, 0xf0, 0x76, 0x27, 0x6b, 0xd5, - 0x69, 0x19, 0xf5, 0x07, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x89, 0xf4, 0xf5, 0x28, 0x73, 0x0c, - 0x00, 0x00, + // 1264 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0xe1, 0x6e, 0x1a, 0xc7, + 0x13, 0xff, 0x1f, 0x1c, 0x18, 0xe6, 0x00, 0x5f, 0x36, 0x4e, 0x74, 0xba, 0x7f, 0xa3, 0x5a, 0x48, + 0x51, 0xad, 0x54, 0xc5, 0x95, 0x93, 0xb4, 0x56, 0xa4, 0x4a, 0xc1, 0x98, 0x34, 0x8e, 0x63, 0x8c, + 0x16, 0xac, 0x36, 0xfd, 0x72, 0x3a, 0xc3, 0x9a, 0x9c, 0x7c, 0xdc, 0x91, 0xdd, 0xc5, 0x12, 0x7d, + 0x85, 0x7e, 0x68, 0x3f, 0xf7, 0x0d, 0xfa, 0x08, 0x7d, 0x82, 0x3e, 0x41, 0x1f, 0xa0, 0x7d, 0x92, + 0x6a, 0x67, 0xef, 0xe0, 0x80, 0xc4, 0x75, 0x2a, 0x7f, 0x9b, 0xd9, 0x9d, 0x99, 0xdb, 0xf9, 0xed, + 0xef, 0x37, 0x0b, 0x50, 0x93, 0xf1, 0x24, 0x1e, 0xfa, 0xd2, 0x6f, 0x4c, 0x78, 0x2c, 0x63, 0x52, + 0x4a, 0x7d, 0xb7, 0x1a, 0xc6, 0xa3, 0xa9, 0x0c, 0x42, 0xbd, 0x51, 0xdf, 0x83, 0xd2, 0x31, 0x9b, + 0x51, 0x3f, 0x1a, 0x31, 0xb2, 0x05, 0x05, 0x21, 0x7d, 0x2e, 0x1d, 0x63, 0xdb, 0xd8, 0xa9, 0x50, + 0xed, 0x10, 0x1b, 0xf2, 0x2c, 0x1a, 0x3a, 0x39, 0x5c, 0x53, 0x66, 0xfd, 0x31, 0x58, 0x7d, 0xff, + 0x3c, 0x64, 0xb2, 0x19, 0x06, 0xbe, 0x20, 0x04, 0xcc, 0x01, 0x0b, 0x43, 0xcc, 0x2a, 0x53, 0xb4, + 0x55, 0xd2, 0x34, 0xd0, 0x49, 0x55, 0xaa, 0xcc, 0xfa, 0xef, 0x26, 0x14, 0x75, 0x16, 0xf9, 0x1c, + 0x0a, 0xbe, 0xca, 0xc4, 0x0c, 0x6b, 0xef, 0x5e, 0x63, 0x7e, 0xd8, 0x4c, 0x59, 0xaa, 0x63, 0x88, + 0x0b, 0xa5, 0xb7, 0xb1, 0x90, 0x91, 0x3f, 0x66, 0x58, 0xae, 0x4c, 0xe7, 0x3e, 0xd9, 0x87, 0xd2, + 0x24, 0xe6, 0xd2, 0x1b, 0xfb, 0x13, 0xc7, 0xdc, 0xce, 0xef, 0x58, 0x7b, 0x0f, 0x56, 0x6b, 0x35, + 0xba, 0x31, 0x97, 0x27, 0xfe, 0xa4, 0x1d, 0x49, 0x3e, 0xa3, 0x1b, 0x13, 0xed, 0xa9, 0xaa, 0x97, + 0x6c, 0x26, 0x26, 0xfe, 0x80, 0x39, 0x05, 0x5d, 0x35, 0xf5, 0x11, 0x86, 0xb7, 0x3e, 0x1f, 0x3a, + 0x45, 0xdc, 0xd0, 0x0e, 0xd9, 0x85, 0xf2, 0x25, 0x9b, 0x79, 0x5c, 0x21, 0xe5, 0x6c, 0xe0, 0xc1, + 0xc9, 0xe2, 0x63, 0x29, 0x86, 0x58, 0x46, 0xa3, 0xb9, 0x03, 0xa6, 0x9c, 0x4d, 0x98, 0x53, 0xda, + 0x36, 0x76, 0x6a, 0x7b, 0x5b, 0xab, 0x07, 0xeb, 0xcf, 0x26, 0x8c, 0x62, 0x04, 0xd9, 0x01, 0x7b, + 0x78, 0xee, 0xa9, 0x8e, 0xbc, 0xf8, 0x8a, 0x71, 0x1e, 0x0c, 0x99, 0x53, 0xc6, 0x6f, 0xd7, 0x86, + 0xe7, 0x1d, 0x7f, 0xcc, 0x4e, 0x93, 0x55, 0xd2, 0x00, 0x53, 0xfa, 0x23, 0xe1, 0x00, 0x36, 0xeb, + 0xae, 0x35, 0xdb, 0xf7, 0x47, 0x42, 0x77, 0x8a, 0x71, 0xe4, 0x21, 0xd4, 0xc6, 0x33, 0xf1, 0x2e, + 0xf4, 0xe6, 0x10, 0x56, 0xb0, 0x6e, 0x15, 0x57, 0x5f, 0xa6, 0x38, 0x3e, 0x00, 0xd0, 0x61, 0x0a, + 0x1e, 0xa7, 0xba, 0x6d, 0xec, 0x14, 0x68, 0x19, 0x57, 0x14, 0x7a, 0xee, 0x33, 0xa8, 0x64, 0x51, + 0x54, 0x97, 0x7b, 0xc9, 0x66, 0xc9, 0x7d, 0x2b, 0x53, 0x41, 0x76, 0xe5, 0x87, 0x53, 0x7d, 0x43, + 0x05, 0xaa, 0x9d, 0x67, 0xb9, 0x7d, 0xc3, 0xfd, 0x1a, 0xca, 0xf3, 0x43, 0xfd, 0x5b, 0x62, 0x39, + 0x93, 0xf8, 0xca, 0x2c, 0xe5, 0x6d, 0xf3, 0x95, 0x59, 0xb2, 0xec, 0x4a, 0xfd, 0xcf, 0x22, 0x14, + 0x7a, 0x78, 0x0b, 0xfb, 0x50, 0x19, 0xfb, 0x42, 0x32, 0xee, 0xdd, 0x80, 0x41, 0x96, 0x0e, 0xd5, + 0x2c, 0x3d, 0x80, 0xfb, 0x49, 0xa6, 0x64, 0x7c, 0xec, 0x21, 0xb7, 0x3d, 0x19, 0x8c, 0xf5, 0x05, + 0x59, 0x7b, 0xd5, 0x46, 0x2a, 0x8c, 0x7e, 0x30, 0x66, 0xf4, 0xae, 0x0e, 0xee, 0x33, 0x3e, 0xee, + 0xa9, 0x50, 0xb5, 0xb8, 0xcc, 0x81, 0xdc, 0x0d, 0x38, 0xf0, 0x0d, 0x54, 0x04, 0xe3, 0x57, 0x6c, + 0xe8, 0xa9, 0x8b, 0x16, 0x4e, 0x7e, 0xf5, 0xde, 0xb0, 0xab, 0x46, 0x0f, 0x63, 0x90, 0x11, 0x96, + 0x98, 0xdb, 0x82, 0x3c, 0x87, 0xaa, 0x88, 0xa7, 0x7c, 0xc0, 0x3c, 0xe4, 0xa0, 0x48, 0x48, 0xfe, + 0xff, 0xb5, 0x7c, 0x0c, 0x42, 0x9b, 0x56, 0xc4, 0xc2, 0x11, 0xe4, 0x05, 0x6c, 0x4a, 0x44, 0xc4, + 0x1b, 0xc4, 0x91, 0xe4, 0x71, 0x28, 0x9c, 0xe2, 0xaa, 0x50, 0x74, 0x0d, 0x0d, 0x5c, 0x4b, 0x47, + 0xd1, 0x9a, 0xcc, 0xba, 0x82, 0x3c, 0x82, 0x3b, 0x81, 0xf0, 0x12, 0x00, 0xd5, 0x11, 0x83, 0x68, + 0x84, 0x2a, 0x28, 0xd1, 0xcd, 0x40, 0x9c, 0xe0, 0x7a, 0x4f, 0x2f, 0xbb, 0x6f, 0x00, 0x16, 0x0d, + 0x91, 0xa7, 0x60, 0x25, 0x27, 0x40, 0x35, 0x18, 0xd7, 0xa8, 0x01, 0xe4, 0xdc, 0x56, 0xc4, 0x50, + 0x83, 0x44, 0x38, 0xb9, 0xed, 0xbc, 0x22, 0x06, 0x3a, 0xee, 0xaf, 0x06, 0x58, 0x99, 0x66, 0xd3, + 0x31, 0x63, 0xcc, 0xc7, 0xcc, 0x92, 0xb0, 0x73, 0x1f, 0x12, 0x76, 0xfe, 0x83, 0xc2, 0x36, 0x6f, + 0x70, 0xa9, 0xf7, 0xa1, 0x88, 0x07, 0x15, 0x4e, 0x01, 0xcf, 0x96, 0x78, 0xee, 0x6f, 0x06, 0x54, + 0x97, 0x50, 0xbc, 0xd5, 0xde, 0xc9, 0x17, 0x40, 0xce, 0x43, 0x7f, 0x70, 0x19, 0x06, 0x42, 0x2a, + 0x42, 0xe9, 0x23, 0x98, 0x18, 0x72, 0x27, 0xb3, 0x83, 0x45, 0x85, 0x3a, 0xe5, 0x05, 0x8f, 0x7f, + 0x64, 0x11, 0xce, 0xb7, 0x12, 0x4d, 0xbc, 0xb9, 0xae, 0x0a, 0x76, 0xb1, 0xfe, 0x47, 0x0e, 0xa7, + 0xbf, 0x46, 0xe7, 0x4b, 0xd8, 0x42, 0x40, 0x82, 0x68, 0xe4, 0x0d, 0xe2, 0x70, 0x3a, 0x8e, 0x70, + 0x24, 0x25, 0x6a, 0x25, 0xe9, 0x5e, 0x0b, 0xb7, 0xd4, 0x54, 0x22, 0xaf, 0xd6, 0x33, 0xb0, 0xcf, + 0x1c, 0xf6, 0xe9, 0x2c, 0x81, 0x88, 0xdf, 0x38, 0xd2, 0x1c, 0x5f, 0xa9, 0x85, 0x3d, 0x3f, 0x9f, + 0x2b, 0xe5, 0x82, 0xc7, 0x63, 0xb1, 0x3e, 0xce, 0xd3, 0x1a, 0x89, 0x58, 0x5e, 0xf0, 0x78, 0x9c, + 0x8a, 0x45, 0xd9, 0xc2, 0x9d, 0xa6, 0xb4, 0x53, 0xee, 0xed, 0x42, 0x9f, 0x25, 0x55, 0x7e, 0x99, + 0x54, 0x1a, 0xcf, 0xfa, 0x4f, 0x06, 0xd8, 0x5a, 0x7f, 0x6c, 0x12, 0x06, 0x03, 0x5f, 0x06, 0x71, + 0x44, 0x9e, 0x42, 0x21, 0x8a, 0x87, 0x4c, 0x4d, 0x29, 0xd5, 0xcc, 0xa7, 0x2b, 0x92, 0xcb, 0x84, + 0x36, 0x3a, 0xf1, 0x90, 0x51, 0x1d, 0xed, 0x3e, 0x07, 0x53, 0xb9, 0x6a, 0xd6, 0x25, 0x2d, 0xdc, + 0x64, 0xd6, 0xc9, 0x85, 0x53, 0x3f, 0x83, 0x5a, 0xf2, 0x85, 0x0b, 0xc6, 0x59, 0x34, 0x60, 0xea, + 0x8d, 0xce, 0x5c, 0x26, 0xda, 0x1f, 0x3d, 0xcd, 0xea, 0x3f, 0x1b, 0x40, 0xb0, 0xee, 0x32, 0xcb, + 0x6f, 0xa3, 0x36, 0x79, 0x02, 0xf7, 0xdf, 0x4d, 0x19, 0x9f, 0xe9, 0xe1, 0x32, 0x60, 0xde, 0x30, + 0x10, 0xea, 0x2b, 0x5a, 0xac, 0x25, 0xba, 0x85, 0xbb, 0x3d, 0xbd, 0x79, 0x98, 0xec, 0xd5, 0xff, + 0x36, 0xc1, 0xea, 0xf1, 0xab, 0x39, 0x87, 0xbf, 0x05, 0x98, 0xf8, 0x5c, 0x06, 0x0a, 0xd3, 0x14, + 0xf6, 0xcf, 0x32, 0xb0, 0x2f, 0x42, 0xe7, 0x7c, 0xea, 0xa6, 0xf1, 0x34, 0x93, 0xfa, 0x41, 0x31, + 0xe4, 0x3e, 0x5a, 0x0c, 0xf9, 0xff, 0x20, 0x86, 0x26, 0x58, 0x19, 0x31, 0x24, 0x5a, 0xd8, 0x7e, + 0x7f, 0x1f, 0x19, 0x39, 0xc0, 0x42, 0x0e, 0xee, 0x5f, 0x06, 0xdc, 0x59, 0x6b, 0x51, 0xa9, 0x22, + 0xf3, 0x1e, 0x5d, 0xaf, 0x8a, 0xc5, 0x43, 0x44, 0x5a, 0x60, 0xe3, 0x29, 0x3d, 0x9e, 0x12, 0x4a, + 0x0b, 0xc4, 0xca, 0xf6, 0xb5, 0xcc, 0x38, 0xba, 0x29, 0x96, 0x7c, 0x41, 0xba, 0x70, 0x4f, 0x17, + 0x59, 0x7d, 0x90, 0xf4, 0xa3, 0xf8, 0xc9, 0x4a, 0xa5, 0xe5, 0xf7, 0xe8, 0xae, 0x58, 0x5b, 0x13, + 0xae, 0x77, 0x1b, 0x8a, 0xbf, 0xe6, 0xc1, 0x48, 0xa6, 0xe4, 0x31, 0x94, 0x5a, 0x2c, 0x0c, 0x8f, + 0xa2, 0x8b, 0x58, 0xfd, 0xa0, 0x42, 0x5c, 0xb8, 0xe7, 0x0f, 0x87, 0x9c, 0x09, 0x91, 0xb0, 0xbe, + 0xaa, 0x57, 0x9b, 0x7a, 0x51, 0x49, 0x82, 0xc7, 0xb1, 0x4c, 0x0a, 0xa2, 0x9d, 0x0c, 0x8a, 0x3a, + 0x80, 0x2a, 0x26, 0xf4, 0x8f, 0x92, 0xf7, 0x8e, 0x9b, 0x47, 0x7b, 0x50, 0x5b, 0x26, 0x09, 0x29, + 0x43, 0xe1, 0xac, 0xd3, 0x6b, 0xf7, 0xed, 0xff, 0x11, 0x80, 0xe2, 0xd9, 0x51, 0xa7, 0xff, 0xd5, + 0x13, 0xdb, 0x50, 0xcb, 0x07, 0x6f, 0xfa, 0xed, 0x9e, 0x9d, 0x7b, 0xf4, 0x8b, 0x01, 0xb0, 0xe8, + 0x90, 0x58, 0xb0, 0x71, 0xd6, 0x39, 0xee, 0x9c, 0x7e, 0xd7, 0xd1, 0x29, 0x27, 0xcd, 0x5e, 0xbf, + 0x4d, 0x6d, 0x43, 0x6d, 0xd0, 0x76, 0xf7, 0xf5, 0x51, 0xab, 0x69, 0xe7, 0xd4, 0x06, 0x3d, 0x3c, + 0xed, 0xbc, 0x7e, 0x63, 0xe7, 0xb1, 0x56, 0xb3, 0xdf, 0x7a, 0xa9, 0xcd, 0x5e, 0xb7, 0x49, 0xdb, + 0xb6, 0x49, 0x6c, 0xa8, 0xb4, 0xbf, 0xef, 0xb6, 0xe9, 0xd1, 0x49, 0xbb, 0xd3, 0x6f, 0xbe, 0xb6, + 0x0b, 0x2a, 0xe7, 0xa0, 0xd9, 0x3a, 0x3e, 0xeb, 0xda, 0x45, 0x5d, 0xac, 0xd7, 0x3f, 0xa5, 0x6d, + 0x7b, 0x43, 0x39, 0x87, 0xb4, 0x79, 0xd4, 0x69, 0x1f, 0xda, 0x25, 0x37, 0x67, 0x1b, 0x07, 0xfb, + 0xb0, 0x19, 0xc4, 0x8d, 0xab, 0x40, 0x32, 0x21, 0xf4, 0xbf, 0x8d, 0x1f, 0x1e, 0x26, 0x5e, 0x10, + 0xef, 0x6a, 0x6b, 0x77, 0x14, 0xef, 0x5e, 0xc9, 0x5d, 0xdc, 0xdd, 0x4d, 0xaf, 0xea, 0xbc, 0x88, + 0xfe, 0xe3, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xac, 0x6b, 0x4a, 0xcd, 0xc6, 0x0c, 0x00, 0x00, } diff --git a/go/vt/vttablet/tabletmanager/action_agent.go b/go/vt/vttablet/tabletmanager/action_agent.go index 7fe05a7b5b3..a1c3f9ad1b0 100644 --- a/go/vt/vttablet/tabletmanager/action_agent.go +++ b/go/vt/vttablet/tabletmanager/action_agent.go @@ -165,6 +165,16 @@ type ActionAgent struct { // It's only set once in NewActionAgent() and never modified after that. orc *orcClient + // shardSyncChan is a channel for informing the shard sync goroutine that + // it should wake up and recheck the tablet state, to make sure it and the + // shard record are in sync. + // + // Call agent.notifyShardSync() instead of sending directly to this channel. + shardSyncChan chan struct{} + + // shardSyncCancel is the function to stop the background shard sync goroutine. + shardSyncCancel context.CancelFunc + // mutex protects all the following fields (that start with '_'), // only hold the mutex to update the fields, nothing else. mutex sync.Mutex @@ -199,8 +209,8 @@ type ActionAgent struct { // replication delay the last time we got it _replicationDelay time.Duration - // last time we ran TabletExternallyReparented - _tabletExternallyReparentedTime time.Time + // _masterTermStartTime is the time at which our term as master began. + _masterTermStartTime time.Time // _ignoreHealthErrorExpr can be set by RPC to selectively disable certain // healthcheck errors. It should only be accessed while holding actionMutex. @@ -438,6 +448,9 @@ func (agent *ActionAgent) setTablet(tablet *topodatapb.Tablet) { agent.mutex.Lock() agent._tablet = proto.Clone(tablet).(*topodatapb.Tablet) agent.mutex.Unlock() + + // Notify the shard sync loop that the tablet state changed. + agent.notifyShardSync() } // Tablet reads the stored Tablet from the agent, protected by mutex. @@ -672,6 +685,10 @@ func (agent *ActionAgent) Start(ctx context.Context, mysqlHost string, mysqlPort startingTablet.Type = topodatapb.TabletType_UNKNOWN agent.setTablet(startingTablet) + // Start a background goroutine to watch and update the shard record, + // to make sure it and our tablet record are in sync. + agent.startShardSync() + return nil } @@ -699,6 +716,7 @@ func (agent *ActionAgent) Close() { // while taking lameduck into account. However, this may be useful for tests, // when you want to clean up an agent immediately. func (agent *ActionAgent) Stop() { + agent.stopShardSync() if agent.UpdateStream != nil { agent.UpdateStream.Disable() } diff --git a/go/vt/vttablet/tabletmanager/init_tablet.go b/go/vt/vttablet/tabletmanager/init_tablet.go index 47e5c00917f..316cc4f5fdf 100644 --- a/go/vt/vttablet/tabletmanager/init_tablet.go +++ b/go/vt/vttablet/tabletmanager/init_tablet.go @@ -108,17 +108,17 @@ func (agent *ActionAgent) InitTablet(port, gRPCPort int32) error { // There's no existing tablet record, so we can assume // no one has left us a message to step down. tabletType = topodatapb.TabletType_MASTER - // Update the TER timestamp (current value is 0) because we + // Update the master term start time (current value is 0) because we // assume that we are actually the MASTER and in case of a tiebreak, // vtgate should prefer us. - agent.setExternallyReparentedTime(time.Now()) + agent.setMasterTermStartTime(time.Now()) case err == nil: if oldTablet.Type == topodatapb.TabletType_MASTER { // We're marked as master in the shard record, // and our existing tablet record agrees. tabletType = topodatapb.TabletType_MASTER // Same comment as above. Update tiebreaking timestamp to now. - agent.setExternallyReparentedTime(time.Now()) + agent.setMasterTermStartTime(time.Now()) } default: return vterrors.Wrap(err, "InitTablet failed to read existing tablet record") diff --git a/go/vt/vttablet/tabletmanager/init_tablet_test.go b/go/vt/vttablet/tabletmanager/init_tablet_test.go index b19db6af3a1..f674571d5bd 100644 --- a/go/vt/vttablet/tabletmanager/init_tablet_test.go +++ b/go/vt/vttablet/tabletmanager/init_tablet_test.go @@ -262,8 +262,8 @@ func TestInitTablet(t *testing.T) { if string(ti.KeyRange.Start) != "" || string(ti.KeyRange.End) != "\xc0" { t.Errorf("wrong KeyRange for tablet: %v", ti.KeyRange) } - if got := agent._tabletExternallyReparentedTime; !got.IsZero() { - t.Fatalf("REPLICA tablet should not have an ExternallyReparentedTimestamp set: %v", got) + if got := agent._masterTermStartTime; !got.IsZero() { + t.Fatalf("REPLICA tablet should not have a MasterTermStartTime set: %v", got) } // 2. Update shard's master to our alias, then try to init again. @@ -288,7 +288,7 @@ func TestInitTablet(t *testing.T) { if ti.Type != topodatapb.TabletType_REPLICA { t.Errorf("wrong tablet type: %v", ti.Type) } - if got := agent._tabletExternallyReparentedTime; !got.IsZero() { + if got := agent._masterTermStartTime; !got.IsZero() { t.Fatalf("REPLICA tablet should not have an ExternallyReparentedTimestamp set: %v", got) } @@ -308,7 +308,7 @@ func TestInitTablet(t *testing.T) { if ti.Type != topodatapb.TabletType_MASTER { t.Errorf("wrong tablet type: %v", ti.Type) } - ter1 := agent._tabletExternallyReparentedTime + ter1 := agent._masterTermStartTime if ter1.IsZero() { t.Fatalf("MASTER tablet should have an ExternallyReparentedTimestamp set") } @@ -330,7 +330,7 @@ func TestInitTablet(t *testing.T) { if ti.Type != topodatapb.TabletType_MASTER { t.Errorf("wrong tablet type: %v", ti.Type) } - ter2 := agent._tabletExternallyReparentedTime + ter2 := agent._masterTermStartTime if ter2.IsZero() || !ter2.After(ter1) { t.Fatalf("After a restart, ExternallyReparentedTimestamp must be set to the current time. Previous timestamp: %v current timestamp: %v", ter1, ter2) } @@ -355,7 +355,7 @@ func TestInitTablet(t *testing.T) { if len(ti.Tags) != 1 || ti.Tags["aaa"] != "bbb" { t.Errorf("wrong tablet tags: %v", ti.Tags) } - ter3 := agent._tabletExternallyReparentedTime + ter3 := agent._masterTermStartTime if ter3.IsZero() || !ter3.After(ter2) { t.Fatalf("After a restart, ExternallyReparentedTimestamp must be set to the current time. Previous timestamp: %v current timestamp: %v", ter2, ter3) } diff --git a/go/vt/vttablet/tabletmanager/rpc_external_reparent.go b/go/vt/vttablet/tabletmanager/rpc_external_reparent.go index 5efaccb0d19..ecd9d4b7361 100644 --- a/go/vt/vttablet/tabletmanager/rpc_external_reparent.go +++ b/go/vt/vttablet/tabletmanager/rpc_external_reparent.go @@ -77,9 +77,9 @@ func (agent *ActionAgent) TabletExternallyReparented(ctx context.Context, extern return err } - // The external failover tool told us that we are still the MASTER. Update the - // timestamp to the current time. - agent.setExternallyReparentedTime(startTime) + // The external failover tool told us that we are still the MASTER. + // Update the timestamp to the current time (start a new term). + agent.setMasterTermStartTime(startTime) // Create a reusable Reparent event with available info. ev := &events.Reparent{ @@ -301,15 +301,3 @@ func (agent *ActionAgent) finalizeTabletExternallyReparented(ctx context.Context event.DispatchUpdate(ev, "finished") return nil } - -// setExternallyReparentedTime remembers the last time when we were told we're -// the master. -// If another tablet claims to be master and offers a more recent time, -// that tablet will be trusted over us. -func (agent *ActionAgent) setExternallyReparentedTime(t time.Time) { - agent.mutex.Lock() - defer agent.mutex.Unlock() - - agent._tabletExternallyReparentedTime = t - agent._replicationDelay = 0 -} diff --git a/go/vt/vttablet/tabletmanager/rpc_external_reparent_test.go b/go/vt/vttablet/tabletmanager/rpc_external_reparent_test.go index 05cf42110b6..b407cccd5af 100644 --- a/go/vt/vttablet/tabletmanager/rpc_external_reparent_test.go +++ b/go/vt/vttablet/tabletmanager/rpc_external_reparent_test.go @@ -29,17 +29,17 @@ func TestTabletExternallyReparentedAlwaysUpdatesTimestamp(t *testing.T) { if err := agent.TabletExternallyReparented(ctx, "unused_id"); err != nil { t.Fatal(err) } - if agent._tabletExternallyReparentedTime.IsZero() { - t.Fatalf("externally_reparented_time should have been updated") + if agent._masterTermStartTime.IsZero() { + t.Fatalf("master_term_start_time should have been updated") } // Run RPC again and verify that the timestamp was updated. - ter1 := agent._tabletExternallyReparentedTime + ter1 := agent._masterTermStartTime if err := agent.TabletExternallyReparented(ctx, "unused_id"); err != nil { t.Fatal(err) } - ter2 := agent._tabletExternallyReparentedTime + ter2 := agent._masterTermStartTime if ter1 == ter2 { - t.Fatalf("subsequent TER call did not update the timestamp: %v = %v", ter1, ter2) + t.Fatalf("subsequent TER call did not update the master_term_start_time: %v = %v", ter1, ter2) } } diff --git a/go/vt/vttablet/tabletmanager/rpc_replication.go b/go/vt/vttablet/tabletmanager/rpc_replication.go index 5fc30737cf4..6be2f0e14fe 100644 --- a/go/vt/vttablet/tabletmanager/rpc_replication.go +++ b/go/vt/vttablet/tabletmanager/rpc_replication.go @@ -216,7 +216,7 @@ func (agent *ActionAgent) InitMaster(ctx context.Context) (string, error) { if err := agent.MysqlDaemon.SetReadOnly(false); err != nil { return "", err } - agent.setExternallyReparentedTime(startTime) + agent.setMasterTermStartTime(startTime) // Change our type to master if not already if _, err := agent.TopoServer.UpdateTabletFields(ctx, agent.TabletAlias, func(tablet *topodatapb.Tablet) error { @@ -450,7 +450,7 @@ func (agent *ActionAgent) PromoteSlaveWhenCaughtUp(ctx context.Context, position if err := agent.MysqlDaemon.SetReadOnly(false); err != nil { return "", err } - agent.setExternallyReparentedTime(startTime) + agent.setMasterTermStartTime(startTime) if _, err := topotools.ChangeType(ctx, agent.TopoServer, agent.TabletAlias, topodatapb.TabletType_MASTER); err != nil { return "", err @@ -671,7 +671,7 @@ func (agent *ActionAgent) PromoteSlave(ctx context.Context) (string, error) { if err := agent.MysqlDaemon.SetReadOnly(false); err != nil { return "", err } - agent.setExternallyReparentedTime(startTime) + agent.setMasterTermStartTime(startTime) if _, err := topotools.ChangeType(ctx, agent.TopoServer, agent.TabletAlias, topodatapb.TabletType_MASTER); err != nil { return "", err diff --git a/go/vt/vttablet/tabletmanager/shard_sync.go b/go/vt/vttablet/tabletmanager/shard_sync.go new file mode 100644 index 00000000000..c612117b3ce --- /dev/null +++ b/go/vt/vttablet/tabletmanager/shard_sync.go @@ -0,0 +1,264 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tabletmanager + +import ( + "flag" + "time" + + "golang.org/x/net/context" + + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/logutil" + "vitess.io/vitess/go/vt/mysqlctl" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/topo/topoproto" +) + +var ( + shardSyncRetryDelay = flag.Duration("shard_sync_retry_delay", 30*time.Second, "delay between retries of updates to keep the tablet and its shard record in sync") +) + +// shardSyncLoop is a loop that tries to keep the tablet state and the +// shard record in sync. +// +// It is launched as a background goroutine in the tablet because it may need to +// initiate a tablet state change in response to an incoming watch event for the +// shard record, and it may need to continually retry updating the shard record +// if it's out of sync with the tablet state. At steady state, when the tablet +// and shard record are in sync, this goroutine goes to sleep waiting for +// something to change in either the tablet state or in the shard record. +// +// This goroutine gets woken up for shard record changes by maintaining a +// topo watch on the shard record. It gets woken up for tablet state changes by +// a notification signal from setTablet(). +func (agent *ActionAgent) shardSyncLoop(ctx context.Context) { + // Make a copy of the channel so we don't race when stopShardSync() clears it. + notifyChan := agent.shardSyncChan + + // retryChan is how we wake up after going to sleep between retries. + // If no retry is pending, this channel will be nil, which means it's fine + // to always select on it -- a nil channel is never ready. + var retryChan <-chan time.Time + + // shardWatch is how we get notified when the shard record is updated. + // We only watch the shard record while we are master. + shardWatch := &shardWatcher{} + defer shardWatch.stop() + + // This loop sleeps until it's notified that something may have changed. + // Then it wakes up to check if anything needs to be synchronized. + for { + select { + case <-notifyChan: + // Something may have changed in the tablet state. + case <-retryChan: + // It's time to retry a previous failed sync attempt. + case event := <-shardWatch.watchChan: + // Something may have changed in the shard record. + // We don't use the watch event except to know that we should + // re-read the shard record, and to know if the watch dies. + if event.Err != nil { + // The watch failed. Stop it so we start a new one if needed. + log.Errorf("Shard watch failed: %v", event.Err) + shardWatch.stop() + } + case <-ctx.Done(): + // Our context was cancelled. Terminate the loop. + return + } + + // Disconnect any pending retry timer since we're already retrying for + // another reason. + retryChan = nil + + // Get the latest internal tablet value, representing what we think we are. + tablet := agent.Tablet() + + switch tablet.Type { + case topodatapb.TabletType_MASTER: + // If we think we're master, check if we need to update the shard record. + masterAlias, err := syncShardMaster(ctx, agent.TopoServer, tablet, agent.masterTermStartTime()) + if err != nil { + log.Errorf("Failed to sync shard record: %v", err) + // Start retry timer and go back to sleep. + retryChan = time.After(*shardSyncRetryDelay) + continue + } + if !topoproto.TabletAliasEqual(masterAlias, tablet.Alias) { + // Another master has taken over while we still think we're master. + if err := agent.abortMasterTerm(ctx, masterAlias); err != nil { + // Start retry timer and go back to sleep. + retryChan = time.After(*shardSyncRetryDelay) + continue + } + // We're not master anymore, so stop watching the shard record. + shardWatch.stop() + continue + } + + // As long as we're master, watch the shard record so we'll be + // notified if another master takes over. + if shardWatch.active() { + // We already have an active watch. Nothing to do. + continue + } + if err := shardWatch.start(ctx, agent.TopoServer, tablet.Keyspace, tablet.Shard); err != nil { + log.Errorf("Failed to start shard watch: %v", err) + // Start retry timer and go back to sleep. + retryChan = time.After(*shardSyncRetryDelay) + continue + } + default: + // If we're not master, stop watching the shard record, + // so only masters contribute to global topo watch load. + shardWatch.stop() + } + } +} + +// syncShardMaster is called when we think we're master. +// It checks that the shard record agrees, and updates it if possible. +// +// If the returned error is nil, the returned masterAlias indicates the current +// master tablet according to the shard record. +// +// If the shard record indicates a new master has taken over, this returns +// success (we successfully synchronized), but the returned masterAlias will be +// different from the input tablet.Alias. +func syncShardMaster(ctx context.Context, ts *topo.Server, tablet *topodatapb.Tablet, masterTermStartTime time.Time) (masterAlias *topodatapb.TabletAlias, err error) { + ctx, cancel := context.WithTimeout(ctx, *topo.RemoteOperationTimeout) + defer cancel() + + var shardInfo *topo.ShardInfo + _, err = ts.UpdateShardFields(ctx, tablet.Keyspace, tablet.Shard, func(si *topo.ShardInfo) error { + lastTerm := logutil.ProtoToTime(si.MasterTermStartTime) + + // Save the ShardInfo so we can check it afterward. + // We can't use the return value of UpdateShardFields because it might be nil. + shardInfo = si + + // Only attempt an update if our term is more recent. + if !masterTermStartTime.After(lastTerm) { + return topo.NewError(topo.NoUpdateNeeded, si.ShardName()) + } + + aliasStr := topoproto.TabletAliasString(tablet.Alias) + log.Infof("Updating shard record: master_alias=%v, master_term_start_time=%v", aliasStr, masterTermStartTime) + si.MasterAlias = tablet.Alias + si.MasterTermStartTime = logutil.TimeToProto(masterTermStartTime) + return nil + }) + if err != nil { + return nil, err + } + + return shardInfo.MasterAlias, nil +} + +// abortMasterTerm is called when we unexpectedly lost mastership. +// +// Under normal circumstances, we should be gracefully demoted before a new +// master appears. This function is only reached when that graceful demotion +// failed or was skipped, so we only found out we're no longer master after the +// new master started advertising itself. +// +// If active reparents are enabled, we demote our own MySQL to a replica and +// update our tablet type to REPLICA. +// +// If active reparents are disabled, we don't touch our MySQL. +// We just directly update our tablet type to REPLICA. +func (agent *ActionAgent) abortMasterTerm(ctx context.Context, masterAlias *topodatapb.TabletAlias) error { + ctx, cancel := context.WithTimeout(ctx, *topo.RemoteOperationTimeout) + defer cancel() + + masterAliasStr := topoproto.TabletAliasString(masterAlias) + log.Warningf("Another tablet (%v) has won master election. Stepping down to REPLICA.", masterAliasStr) + + if *mysqlctl.DisableActiveReparents { + // Don't touch anything at the MySQL level. Just update tablet state. + log.Infof("Active reparents are disabled; updating tablet state only.") + return agent.SlaveWasRestarted(ctx, masterAlias) + } + + // Do a full demotion to convert MySQL into a replica. + log.Infof("Active reparents are enabled; converting MySQL to replica.") + if _, err := agent.DemoteMaster(ctx); err != nil { + return err + } + log.Infof("Attempting to reparent self to new master %v.", masterAliasStr) + return agent.SetMaster(ctx, masterAlias, 0, true) +} + +func (agent *ActionAgent) startShardSync() { + // Use a buffer size of 1 so we can remember we need to check the state + // even if the receiver is busy. We can drop any additional send attempts + // if the buffer is full because all we care about is that the receiver will + // be told it needs to recheck the state. + agent.shardSyncChan = make(chan struct{}, 1) + ctx, cancel := context.WithCancel(context.Background()) + agent.shardSyncCancel = cancel + + // Queue up a pending notification to force the loop to run once at startup. + agent.notifyShardSync() + + // Start the sync loop in the background. + go agent.shardSyncLoop(ctx) +} + +func (agent *ActionAgent) stopShardSync() { + if agent.shardSyncCancel != nil { + agent.shardSyncCancel() + agent.shardSyncCancel = nil + agent.shardSyncChan = nil + } +} + +func (agent *ActionAgent) notifyShardSync() { + // If this is called before the shard sync is started, do nothing. + if agent.shardSyncChan == nil { + return + } + + // Try to send. If the channel buffer is full, it means a notification is + // already pending, so we don't need to do anything. + select { + case agent.shardSyncChan <- struct{}{}: + default: + } +} + +// setMasterTermStartTime remembers the time when our term as master began. +// +// If another tablet claims to be master and offers a more recent time, +// that tablet will be trusted over us. +func (agent *ActionAgent) setMasterTermStartTime(t time.Time) { + agent.mutex.Lock() + agent._masterTermStartTime = t + agent._replicationDelay = 0 + agent.mutex.Unlock() + + // Notify the shard sync loop that the tablet state changed. + agent.notifyShardSync() +} + +func (agent *ActionAgent) masterTermStartTime() time.Time { + agent.mutex.Lock() + defer agent.mutex.Unlock() + return agent._masterTermStartTime +} diff --git a/go/vt/vttablet/tabletmanager/shard_watcher.go b/go/vt/vttablet/tabletmanager/shard_watcher.go new file mode 100644 index 00000000000..1688c1a27f2 --- /dev/null +++ b/go/vt/vttablet/tabletmanager/shard_watcher.go @@ -0,0 +1,65 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tabletmanager + +import ( + "golang.org/x/net/context" + + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/topo" +) + +type shardWatcher struct { + watchChan <-chan *topo.WatchShardData + watchCancel topo.CancelFunc +} + +func (sw *shardWatcher) active() bool { + return sw.watchChan != nil +} + +func (sw *shardWatcher) start(ctx context.Context, ts *topo.Server, keyspace, shard string) error { + ctx, cancel := context.WithTimeout(ctx, *topo.RemoteOperationTimeout) + defer cancel() + + log.Infof("Starting shard watch of %v/%v", keyspace, shard) + + event, c, watchCancel := ts.WatchShard(ctx, keyspace, shard) + if event.Err != nil { + return event.Err + } + + sw.watchChan = c + sw.watchCancel = watchCancel + return nil +} + +func (sw *shardWatcher) stop() { + if !sw.active() { + return + } + + sw.watchCancel() + + // Drain all remaining watch events. + log.Infof("Stopping shard watch...") + for range sw.watchChan { + } + + sw.watchChan = nil + sw.watchCancel = nil +} diff --git a/go/vt/vttablet/tabletmanager/state_change.go b/go/vt/vttablet/tabletmanager/state_change.go index 3d08d3a7f22..fdae444672e 100644 --- a/go/vt/vttablet/tabletmanager/state_change.go +++ b/go/vt/vttablet/tabletmanager/state_change.go @@ -101,7 +101,7 @@ func (agent *ActionAgent) broadcastHealth() { agent.mutex.Lock() replicationDelay := agent._replicationDelay healthError := agent._healthy - terTime := agent._tabletExternallyReparentedTime + terTime := agent._masterTermStartTime healthyTime := agent._healthyTime agent.mutex.Unlock() diff --git a/proto/topodata.proto b/proto/topodata.proto index 87758a1f930..7e52cff66f5 100644 --- a/proto/topodata.proto +++ b/proto/topodata.proto @@ -26,6 +26,8 @@ option java_package="io.vitess.proto"; package topodata; +import "logutil.proto"; + // KeyRange describes a range of sharding keys, when range-based // sharding is used. message KeyRange { @@ -157,7 +159,6 @@ message Tablet { message Shard { // master_alias is the tablet alias of the master for the shard. // If it is unset, then there is no master in this shard yet. - // No lock is necessary to update this field, when for instance // TabletExternallyReparented updates this. However, we lock the // shard for reparenting operations (InitShardMaster, @@ -165,6 +166,20 @@ message Shard { // exclusive operation. TabletAlias master_alias = 1; + // master_term_start_time is the time (in UTC) at which the current term of + // the master specified in master_alias began. + // + // A new master term begins any time an authoritative decision is communicated + // about which tablet should be the master, such as via Vitess + // replication-management commands like PlannedReparentShard, + // EmergencyReparentShard, and TabletExternallyReparented. + // + // The master_alias should only ever be changed if the new master's term began + // at a later time than this. Note that a new term can start for the tablet + // that is already the master. In that case, the master_term_start_time would + // be increased without changing the master_alias. + logutil.Time master_term_start_time = 8; + // key_range is the KeyRange for this shard. It can be unset if: // - we are not using range-based sharding in this shard. // - the shard covers the entire keyrange. diff --git a/py/vtproto/topodata_pb2.py b/py/vtproto/topodata_pb2.py index 66ac9fea9b0..386a998398c 100644 --- a/py/vtproto/topodata_pb2.py +++ b/py/vtproto/topodata_pb2.py @@ -13,6 +13,7 @@ _sym_db = _symbol_database.Default() +import logutil_pb2 as logutil__pb2 DESCRIPTOR = _descriptor.FileDescriptor( @@ -20,8 +21,9 @@ package='topodata', syntax='proto3', serialized_options=_b('\n\017io.vitess.protoZ%vitess.io/vitess/go/vt/proto/topodata'), - serialized_pb=_b('\n\x0etopodata.proto\x12\x08topodata\"&\n\x08KeyRange\x12\r\n\x05start\x18\x01 \x01(\x0c\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x0c\"(\n\x0bTabletAlias\x12\x0c\n\x04\x63\x65ll\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\r\"\xb6\x03\n\x06Tablet\x12$\n\x05\x61lias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\x12\x10\n\x08hostname\x18\x02 \x01(\t\x12/\n\x08port_map\x18\x04 \x03(\x0b\x32\x1d.topodata.Tablet.PortMapEntry\x12\x10\n\x08keyspace\x18\x05 \x01(\t\x12\r\n\x05shard\x18\x06 \x01(\t\x12%\n\tkey_range\x18\x07 \x01(\x0b\x32\x12.topodata.KeyRange\x12\"\n\x04type\x18\x08 \x01(\x0e\x32\x14.topodata.TabletType\x12\x18\n\x10\x64\x62_name_override\x18\t \x01(\t\x12(\n\x04tags\x18\n \x03(\x0b\x32\x1a.topodata.Tablet.TagsEntry\x12\x16\n\x0emysql_hostname\x18\x0c \x01(\t\x12\x12\n\nmysql_port\x18\r \x01(\x05\x1a.\n\x0cPortMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01J\x04\x08\x03\x10\x04J\x04\x08\x0b\x10\x0c\"\xd3\x04\n\x05Shard\x12+\n\x0cmaster_alias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x30\n\x0cserved_types\x18\x03 \x03(\x0b\x32\x1a.topodata.Shard.ServedType\x12\x32\n\rsource_shards\x18\x04 \x03(\x0b\x32\x1b.topodata.Shard.SourceShard\x12\x36\n\x0ftablet_controls\x18\x06 \x03(\x0b\x32\x1d.topodata.Shard.TabletControl\x12\x19\n\x11is_master_serving\x18\x07 \x01(\x08\x1a\x46\n\nServedType\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x1ar\n\x0bSourceShard\x12\x0b\n\x03uid\x18\x01 \x01(\r\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\r\n\x05shard\x18\x03 \x01(\t\x12%\n\tkey_range\x18\x04 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x0e\n\x06tables\x18\x05 \x03(\t\x1a{\n\rTabletControl\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x12\x1a\n\x12\x62lacklisted_tables\x18\x04 \x03(\t\x12\x0e\n\x06\x66rozen\x18\x05 \x01(\x08J\x04\x08\x03\x10\x04J\x04\x08\x05\x10\x06\"\xf5\x01\n\x08Keyspace\x12\x1c\n\x14sharding_column_name\x18\x01 \x01(\t\x12\x36\n\x14sharding_column_type\x18\x02 \x01(\x0e\x32\x18.topodata.KeyspaceIdType\x12\x33\n\x0cserved_froms\x18\x04 \x03(\x0b\x32\x1d.topodata.Keyspace.ServedFrom\x1aX\n\nServedFrom\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x12\x10\n\x08keyspace\x18\x03 \x01(\tJ\x04\x08\x03\x10\x04\"w\n\x10ShardReplication\x12.\n\x05nodes\x18\x01 \x03(\x0b\x32\x1f.topodata.ShardReplication.Node\x1a\x33\n\x04Node\x12+\n\x0ctablet_alias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\"E\n\x0eShardReference\x12\x0c\n\x04name\x18\x01 \x01(\t\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\"i\n\x12ShardTabletControl\x12\x0c\n\x04name\x18\x01 \x01(\t\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x1e\n\x16query_service_disabled\x18\x03 \x01(\x08\"\xda\x03\n\x0bSrvKeyspace\x12;\n\npartitions\x18\x01 \x03(\x0b\x32\'.topodata.SrvKeyspace.KeyspacePartition\x12\x1c\n\x14sharding_column_name\x18\x02 \x01(\t\x12\x36\n\x14sharding_column_type\x18\x03 \x01(\x0e\x32\x18.topodata.KeyspaceIdType\x12\x35\n\x0bserved_from\x18\x04 \x03(\x0b\x32 .topodata.SrvKeyspace.ServedFrom\x1a\xaf\x01\n\x11KeyspacePartition\x12)\n\x0bserved_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\x32\n\x10shard_references\x18\x02 \x03(\x0b\x32\x18.topodata.ShardReference\x12;\n\x15shard_tablet_controls\x18\x03 \x03(\x0b\x32\x1c.topodata.ShardTabletControl\x1aI\n\nServedFrom\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\x10\n\x08keyspace\x18\x02 \x01(\tJ\x04\x08\x05\x10\x06\"6\n\x08\x43\x65llInfo\x12\x16\n\x0eserver_address\x18\x01 \x01(\t\x12\x0c\n\x04root\x18\x02 \x01(\tJ\x04\x08\x03\x10\x04\"\x1b\n\nCellsAlias\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t*2\n\x0eKeyspaceIdType\x12\t\n\x05UNSET\x10\x00\x12\n\n\x06UINT64\x10\x01\x12\t\n\x05\x42YTES\x10\x02*\x90\x01\n\nTabletType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06MASTER\x10\x01\x12\x0b\n\x07REPLICA\x10\x02\x12\n\n\x06RDONLY\x10\x03\x12\t\n\x05\x42\x41TCH\x10\x03\x12\t\n\x05SPARE\x10\x04\x12\x10\n\x0c\x45XPERIMENTAL\x10\x05\x12\n\n\x06\x42\x41\x43KUP\x10\x06\x12\x0b\n\x07RESTORE\x10\x07\x12\x0b\n\x07\x44RAINED\x10\x08\x1a\x02\x10\x01\x42\x38\n\x0fio.vitess.protoZ%vitess.io/vitess/go/vt/proto/topodatab\x06proto3') -) + serialized_pb=_b('\n\x0etopodata.proto\x12\x08topodata\x1a\rlogutil.proto\"&\n\x08KeyRange\x12\r\n\x05start\x18\x01 \x01(\x0c\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x0c\"(\n\x0bTabletAlias\x12\x0c\n\x04\x63\x65ll\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\r\"\xb6\x03\n\x06Tablet\x12$\n\x05\x61lias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\x12\x10\n\x08hostname\x18\x02 \x01(\t\x12/\n\x08port_map\x18\x04 \x03(\x0b\x32\x1d.topodata.Tablet.PortMapEntry\x12\x10\n\x08keyspace\x18\x05 \x01(\t\x12\r\n\x05shard\x18\x06 \x01(\t\x12%\n\tkey_range\x18\x07 \x01(\x0b\x32\x12.topodata.KeyRange\x12\"\n\x04type\x18\x08 \x01(\x0e\x32\x14.topodata.TabletType\x12\x18\n\x10\x64\x62_name_override\x18\t \x01(\t\x12(\n\x04tags\x18\n \x03(\x0b\x32\x1a.topodata.Tablet.TagsEntry\x12\x16\n\x0emysql_hostname\x18\x0c \x01(\t\x12\x12\n\nmysql_port\x18\r \x01(\x05\x1a.\n\x0cPortMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01J\x04\x08\x03\x10\x04J\x04\x08\x0b\x10\x0c\"\x82\x05\n\x05Shard\x12+\n\x0cmaster_alias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\x12-\n\x16master_term_start_time\x18\x08 \x01(\x0b\x32\r.logutil.Time\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x30\n\x0cserved_types\x18\x03 \x03(\x0b\x32\x1a.topodata.Shard.ServedType\x12\x32\n\rsource_shards\x18\x04 \x03(\x0b\x32\x1b.topodata.Shard.SourceShard\x12\x36\n\x0ftablet_controls\x18\x06 \x03(\x0b\x32\x1d.topodata.Shard.TabletControl\x12\x19\n\x11is_master_serving\x18\x07 \x01(\x08\x1a\x46\n\nServedType\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x1ar\n\x0bSourceShard\x12\x0b\n\x03uid\x18\x01 \x01(\r\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\r\n\x05shard\x18\x03 \x01(\t\x12%\n\tkey_range\x18\x04 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x0e\n\x06tables\x18\x05 \x03(\t\x1a{\n\rTabletControl\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x12\x1a\n\x12\x62lacklisted_tables\x18\x04 \x03(\t\x12\x0e\n\x06\x66rozen\x18\x05 \x01(\x08J\x04\x08\x03\x10\x04J\x04\x08\x05\x10\x06\"\xf5\x01\n\x08Keyspace\x12\x1c\n\x14sharding_column_name\x18\x01 \x01(\t\x12\x36\n\x14sharding_column_type\x18\x02 \x01(\x0e\x32\x18.topodata.KeyspaceIdType\x12\x33\n\x0cserved_froms\x18\x04 \x03(\x0b\x32\x1d.topodata.Keyspace.ServedFrom\x1aX\n\nServedFrom\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x12\x10\n\x08keyspace\x18\x03 \x01(\tJ\x04\x08\x03\x10\x04\"w\n\x10ShardReplication\x12.\n\x05nodes\x18\x01 \x03(\x0b\x32\x1f.topodata.ShardReplication.Node\x1a\x33\n\x04Node\x12+\n\x0ctablet_alias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\"E\n\x0eShardReference\x12\x0c\n\x04name\x18\x01 \x01(\t\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\"i\n\x12ShardTabletControl\x12\x0c\n\x04name\x18\x01 \x01(\t\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x1e\n\x16query_service_disabled\x18\x03 \x01(\x08\"\xda\x03\n\x0bSrvKeyspace\x12;\n\npartitions\x18\x01 \x03(\x0b\x32\'.topodata.SrvKeyspace.KeyspacePartition\x12\x1c\n\x14sharding_column_name\x18\x02 \x01(\t\x12\x36\n\x14sharding_column_type\x18\x03 \x01(\x0e\x32\x18.topodata.KeyspaceIdType\x12\x35\n\x0bserved_from\x18\x04 \x03(\x0b\x32 .topodata.SrvKeyspace.ServedFrom\x1a\xaf\x01\n\x11KeyspacePartition\x12)\n\x0bserved_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\x32\n\x10shard_references\x18\x02 \x03(\x0b\x32\x18.topodata.ShardReference\x12;\n\x15shard_tablet_controls\x18\x03 \x03(\x0b\x32\x1c.topodata.ShardTabletControl\x1aI\n\nServedFrom\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\x10\n\x08keyspace\x18\x02 \x01(\tJ\x04\x08\x05\x10\x06\"6\n\x08\x43\x65llInfo\x12\x16\n\x0eserver_address\x18\x01 \x01(\t\x12\x0c\n\x04root\x18\x02 \x01(\tJ\x04\x08\x03\x10\x04\"\x1b\n\nCellsAlias\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t*2\n\x0eKeyspaceIdType\x12\t\n\x05UNSET\x10\x00\x12\n\n\x06UINT64\x10\x01\x12\t\n\x05\x42YTES\x10\x02*\x90\x01\n\nTabletType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06MASTER\x10\x01\x12\x0b\n\x07REPLICA\x10\x02\x12\n\n\x06RDONLY\x10\x03\x12\t\n\x05\x42\x41TCH\x10\x03\x12\t\n\x05SPARE\x10\x04\x12\x10\n\x0c\x45XPERIMENTAL\x10\x05\x12\n\n\x06\x42\x41\x43KUP\x10\x06\x12\x0b\n\x07RESTORE\x10\x07\x12\x0b\n\x07\x44RAINED\x10\x08\x1a\x02\x10\x01\x42\x38\n\x0fio.vitess.protoZ%vitess.io/vitess/go/vt/proto/topodatab\x06proto3') + , + dependencies=[logutil__pb2.DESCRIPTOR,]) _KEYSPACEIDTYPE = _descriptor.EnumDescriptor( name='KeyspaceIdType', @@ -44,8 +46,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=2258, - serialized_end=2308, + serialized_start=2320, + serialized_end=2370, ) _sym_db.RegisterEnumDescriptor(_KEYSPACEIDTYPE) @@ -99,8 +101,8 @@ ], containing_type=None, serialized_options=_b('\020\001'), - serialized_start=2311, - serialized_end=2455, + serialized_start=2373, + serialized_end=2517, ) _sym_db.RegisterEnumDescriptor(_TABLETTYPE) @@ -154,8 +156,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=28, - serialized_end=66, + serialized_start=43, + serialized_end=81, ) @@ -192,8 +194,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=68, - serialized_end=108, + serialized_start=83, + serialized_end=123, ) @@ -230,8 +232,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=446, - serialized_end=492, + serialized_start=461, + serialized_end=507, ) _TABLET_TAGSENTRY = _descriptor.Descriptor( @@ -267,8 +269,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=494, - serialized_end=537, + serialized_start=509, + serialized_end=552, ) _TABLET = _descriptor.Descriptor( @@ -367,8 +369,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=111, - serialized_end=549, + serialized_start=126, + serialized_end=564, ) @@ -405,8 +407,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=830, - serialized_end=900, + serialized_start=892, + serialized_end=962, ) _SHARD_SOURCESHARD = _descriptor.Descriptor( @@ -463,8 +465,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=902, - serialized_end=1016, + serialized_start=964, + serialized_end=1078, ) _SHARD_TABLETCONTROL = _descriptor.Descriptor( @@ -514,8 +516,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1018, - serialized_end=1141, + serialized_start=1080, + serialized_end=1203, ) _SHARD = _descriptor.Descriptor( @@ -533,35 +535,42 @@ is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='key_range', full_name='topodata.Shard.key_range', index=1, + name='master_term_start_time', full_name='topodata.Shard.master_term_start_time', index=1, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='key_range', full_name='topodata.Shard.key_range', index=2, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='served_types', full_name='topodata.Shard.served_types', index=2, + name='served_types', full_name='topodata.Shard.served_types', index=3, number=3, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='source_shards', full_name='topodata.Shard.source_shards', index=3, + name='source_shards', full_name='topodata.Shard.source_shards', index=4, number=4, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='tablet_controls', full_name='topodata.Shard.tablet_controls', index=4, + name='tablet_controls', full_name='topodata.Shard.tablet_controls', index=5, number=6, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='is_master_serving', full_name='topodata.Shard.is_master_serving', index=5, + name='is_master_serving', full_name='topodata.Shard.is_master_serving', index=6, number=7, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, @@ -579,8 +588,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=552, - serialized_end=1147, + serialized_start=567, + serialized_end=1209, ) @@ -624,8 +633,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1301, - serialized_end=1389, + serialized_start=1363, + serialized_end=1451, ) _KEYSPACE = _descriptor.Descriptor( @@ -668,8 +677,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1150, - serialized_end=1395, + serialized_start=1212, + serialized_end=1457, ) @@ -699,8 +708,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1465, - serialized_end=1516, + serialized_start=1527, + serialized_end=1578, ) _SHARDREPLICATION = _descriptor.Descriptor( @@ -729,8 +738,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1397, - serialized_end=1516, + serialized_start=1459, + serialized_end=1578, ) @@ -767,8 +776,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1518, - serialized_end=1587, + serialized_start=1580, + serialized_end=1649, ) @@ -812,8 +821,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1589, - serialized_end=1694, + serialized_start=1651, + serialized_end=1756, ) @@ -857,8 +866,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1915, - serialized_end=2090, + serialized_start=1977, + serialized_end=2152, ) _SRVKEYSPACE_SERVEDFROM = _descriptor.Descriptor( @@ -894,8 +903,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2092, - serialized_end=2165, + serialized_start=2154, + serialized_end=2227, ) _SRVKEYSPACE = _descriptor.Descriptor( @@ -945,8 +954,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1697, - serialized_end=2171, + serialized_start=1759, + serialized_end=2233, ) @@ -983,8 +992,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2173, - serialized_end=2227, + serialized_start=2235, + serialized_end=2289, ) @@ -1014,8 +1023,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2229, - serialized_end=2256, + serialized_start=2291, + serialized_end=2318, ) _TABLET_PORTMAPENTRY.containing_type = _TABLET @@ -1032,6 +1041,7 @@ _SHARD_TABLETCONTROL.fields_by_name['tablet_type'].enum_type = _TABLETTYPE _SHARD_TABLETCONTROL.containing_type = _SHARD _SHARD.fields_by_name['master_alias'].message_type = _TABLETALIAS +_SHARD.fields_by_name['master_term_start_time'].message_type = logutil__pb2._TIME _SHARD.fields_by_name['key_range'].message_type = _KEYRANGE _SHARD.fields_by_name['served_types'].message_type = _SHARD_SERVEDTYPE _SHARD.fields_by_name['source_shards'].message_type = _SHARD_SOURCESHARD