From 4bf4554e4c2b511a3afeecc7a30ab570fb27c54c Mon Sep 17 00:00:00 2001 From: Guido Iaquinti Date: Thu, 22 Apr 2021 12:15:09 +0200 Subject: [PATCH 1/2] vttablet/tabletmanager: add isInSRVKeyspace/isShardServing Signed-off-by: Guido Iaquinti --- go/vt/vttablet/tabletmanager/tm_init.go | 4 + go/vt/vttablet/tabletmanager/tm_state.go | 19 +++ go/vt/vttablet/tabletmanager/tm_state_test.go | 153 ++++++++++++++++++ 3 files changed, 176 insertions(+) diff --git a/go/vt/vttablet/tabletmanager/tm_init.go b/go/vt/vttablet/tabletmanager/tm_init.go index 8a4f7dd34cf..7b0d33ea2d8 100644 --- a/go/vt/vttablet/tabletmanager/tm_init.go +++ b/go/vt/vttablet/tabletmanager/tm_init.go @@ -94,6 +94,9 @@ var ( // statsBackupIsRunning is set to 1 (true) if a backup is running. statsBackupIsRunning *stats.GaugesWithMultiLabels + // statsIsInSRVKeyspace is set to 1 (true), 0 (false) whether the tablet is in the serving keyspace + statsIsInSRVKeyspace *stats.Gauge + statsKeyspace = stats.NewString("TabletKeyspace") statsShard = stats.NewString("TabletShard") statsKeyRangeStart = stats.NewString("TabletKeyRangeStart") @@ -115,6 +118,7 @@ func init() { statsTabletType = stats.NewString("TabletType") statsTabletTypeCount = stats.NewCountersWithSingleLabel("TabletTypeCount", "Number of times the tablet changed to the labeled type", "type") statsBackupIsRunning = stats.NewGaugesWithMultiLabels("BackupIsRunning", "Whether a backup is running", []string{"mode"}) + statsIsInSRVKeyspace = stats.NewGauge("IsInSRVKeyspace", "Whether the vttablet is in the serving keyspace (1 = true / 0 = false)") } // TabletManager is the main class for the tablet manager. diff --git a/go/vt/vttablet/tabletmanager/tm_state.go b/go/vt/vttablet/tabletmanager/tm_state.go index f52ced1cfee..2af4eac0589 100644 --- a/go/vt/vttablet/tabletmanager/tm_state.go +++ b/go/vt/vttablet/tabletmanager/tm_state.go @@ -62,6 +62,8 @@ type tmState struct { mu sync.Mutex isOpen bool isResharding bool + isInSRVKeyspace bool + isShardServing map[topodatapb.TabletType]bool tabletControls map[topodatapb.TabletType]bool blacklistedTables map[topodatapb.TabletType][]string tablet *topodatapb.Tablet @@ -139,8 +141,17 @@ func (ts *tmState) RefreshFromTopoInfo(ctx context.Context, shardInfo *topo.Shar } if srvKeyspace != nil { + ts.isShardServing = make(map[topodatapb.TabletType]bool) ts.tabletControls = make(map[topodatapb.TabletType]bool) + for _, partition := range srvKeyspace.GetPartitions() { + + for _, shard := range partition.GetShardReferences() { + if key.KeyRangeEqual(shard.GetKeyRange(), ts.tablet.KeyRange) { + ts.isShardServing[partition.GetServedType()] = true + } + } + for _, tabletControl := range partition.GetShardTabletControls() { if key.KeyRangeEqual(tabletControl.GetKeyRange(), ts.KeyRange()) { if tabletControl.QueryServiceDisabled { @@ -252,6 +263,14 @@ func (ts *tmState) updateLocked(ctx context.Context) { } } + if ts.isShardServing[ts.tablet.Type] { + ts.isInSRVKeyspace = true + statsIsInSRVKeyspace.Set(1) + } else { + ts.isInSRVKeyspace = false + statsIsInSRVKeyspace.Set(0) + } + // Open TabletServer last so that it advertises serving after all other services are up. if reason == "" { if err := ts.tm.QueryServiceControl.SetServingType(ts.tablet.Type, terTime, true, ""); err != nil { diff --git a/go/vt/vttablet/tabletmanager/tm_state_test.go b/go/vt/vttablet/tabletmanager/tm_state_test.go index 81d5b50d3d6..ee9d44e4174 100644 --- a/go/vt/vttablet/tabletmanager/tm_state_test.go +++ b/go/vt/vttablet/tabletmanager/tm_state_test.go @@ -22,6 +22,7 @@ import ( "testing" "time" + "vitess.io/vitess/go/vt/key" "vitess.io/vitess/go/vt/servenv" "context" @@ -154,6 +155,158 @@ func TestStateTabletControls(t *testing.T) { assert.False(t, qsc.IsServing()) } +func TestStateIsShardServingisInSRVKeyspace(t *testing.T) { + ctx := context.Background() + ts := memorytopo.NewServer("cell1") + tm := newTestTM(t, ts, 1, "ks", "0") + defer tm.Stop() + + tm.tmState.mu.Lock() + tm.tmState.tablet.Type = topodatapb.TabletType_MASTER + tm.tmState.mu.Unlock() + + leftKeyRange, err := key.ParseShardingSpec("-80") + if err != nil || len(leftKeyRange) != 1 { + t.Fatalf("ParseShardingSpec failed. Expected non error and only one element. Got err: %v, len(%v)", err, len(leftKeyRange)) + } + + rightKeyRange, err := key.ParseShardingSpec("80-") + if err != nil || len(rightKeyRange) != 1 { + t.Fatalf("ParseShardingSpec failed. Expected non error and only one element. Got err: %v, len(%v)", err, len(rightKeyRange)) + } + + keyRange, err := key.ParseShardingSpec("0") + if err != nil || len(keyRange) != 1 { + t.Fatalf("ParseShardingSpec failed. Expected non error and only one element. Got err: %v, len(%v)", err, len(keyRange)) + } + + // Shard not in the SrvKeyspace, ServedType not in SrvKeyspace + ks := &topodatapb.SrvKeyspace{ + Partitions: []*topodatapb.SrvKeyspace_KeyspacePartition{ + { + ServedType: topodatapb.TabletType_DRAINED, + ShardReferences: []*topodatapb.ShardReference{ + { + Name: "-80", + KeyRange: leftKeyRange[0], + }, + { + Name: "80-", + KeyRange: rightKeyRange[0], + }, + }, + }, + }, + } + want := map[topodatapb.TabletType]bool{} + tm.tmState.RefreshFromTopoInfo(ctx, nil, ks) + + tm.tmState.mu.Lock() + assert.False(t, tm.tmState.isInSRVKeyspace) + assert.Equal(t, want, tm.tmState.isShardServing) + tm.tmState.mu.Unlock() + + assert.Equal(t, int64(0), statsIsInSRVKeyspace.Get()) + + // Shard not in the SrvKeyspace, ServedType in SrvKeyspace + ks = &topodatapb.SrvKeyspace{ + Partitions: []*topodatapb.SrvKeyspace_KeyspacePartition{ + { + ServedType: topodatapb.TabletType_MASTER, + ShardReferences: []*topodatapb.ShardReference{ + { + Name: "-80", + KeyRange: leftKeyRange[0], + }, + { + Name: "80-", + KeyRange: rightKeyRange[0], + }, + }, + }, + }, + } + want = map[topodatapb.TabletType]bool{} + tm.tmState.RefreshFromTopoInfo(ctx, nil, ks) + + tm.tmState.mu.Lock() + assert.False(t, tm.tmState.isInSRVKeyspace) + assert.Equal(t, want, tm.tmState.isShardServing) + tm.tmState.mu.Unlock() + + assert.Equal(t, int64(0), statsIsInSRVKeyspace.Get()) + + // Shard in the SrvKeyspace, ServedType in the SrvKeyspace + ks = &topodatapb.SrvKeyspace{ + Partitions: []*topodatapb.SrvKeyspace_KeyspacePartition{ + { + ServedType: topodatapb.TabletType_MASTER, + ShardReferences: []*topodatapb.ShardReference{ + { + Name: "0", + KeyRange: keyRange[0], + }, + }, + }, + }, + } + want = map[topodatapb.TabletType]bool{ + topodatapb.TabletType_MASTER: true, + } + tm.tmState.RefreshFromTopoInfo(ctx, nil, ks) + + tm.tmState.mu.Lock() + assert.True(t, tm.tmState.isInSRVKeyspace) + assert.Equal(t, want, tm.tmState.isShardServing) + tm.tmState.mu.Unlock() + + assert.Equal(t, int64(1), statsIsInSRVKeyspace.Get()) + + // Shard in the SrvKeyspace, ServedType not in the SrvKeyspace + ks = &topodatapb.SrvKeyspace{ + Partitions: []*topodatapb.SrvKeyspace_KeyspacePartition{ + { + ServedType: topodatapb.TabletType_RDONLY, + ShardReferences: []*topodatapb.ShardReference{ + { + Name: "0", + KeyRange: keyRange[0], + }, + }, + }, + }, + } + want = map[topodatapb.TabletType]bool{ + topodatapb.TabletType_RDONLY: true, + } + tm.tmState.RefreshFromTopoInfo(ctx, nil, ks) + + tm.tmState.mu.Lock() + assert.False(t, tm.tmState.isInSRVKeyspace) + assert.Equal(t, want, tm.tmState.isShardServing) + tm.tmState.mu.Unlock() + + assert.Equal(t, int64(0), statsIsInSRVKeyspace.Get()) + + // Test tablet type change - shard in the SrvKeyspace, ServedType in the SrvKeyspace + err = tm.tmState.ChangeTabletType(ctx, topodatapb.TabletType_RDONLY, DBActionNone) + require.NoError(t, err) + tm.tmState.mu.Lock() + assert.True(t, tm.tmState.isInSRVKeyspace) + tm.tmState.mu.Unlock() + + assert.Equal(t, int64(1), statsIsInSRVKeyspace.Get()) + + // Test tablet type change - shard in the SrvKeyspace, ServedType in the SrvKeyspace + err = tm.tmState.ChangeTabletType(ctx, topodatapb.TabletType_DRAINED, DBActionNone) + require.NoError(t, err) + tm.tmState.mu.Lock() + assert.False(t, tm.tmState.isInSRVKeyspace) + tm.tmState.mu.Unlock() + + assert.Equal(t, int64(0), statsIsInSRVKeyspace.Get()) +} + func TestStateNonServing(t *testing.T) { ctx := context.Background() ts := memorytopo.NewServer("cell1") From aefb97c09f81b17d868e19c8b83af13bc8b86b0d Mon Sep 17 00:00:00 2001 From: Guido Iaquinti Date: Mon, 26 Apr 2021 09:42:02 +0200 Subject: [PATCH 2/2] SRV -> Srv Signed-off-by: Guido Iaquinti --- go/vt/vttablet/tabletmanager/tm_init.go | 6 ++--- go/vt/vttablet/tabletmanager/tm_state.go | 10 +++---- go/vt/vttablet/tabletmanager/tm_state_test.go | 26 +++++++++---------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go/vt/vttablet/tabletmanager/tm_init.go b/go/vt/vttablet/tabletmanager/tm_init.go index 7b0d33ea2d8..db38b091ea2 100644 --- a/go/vt/vttablet/tabletmanager/tm_init.go +++ b/go/vt/vttablet/tabletmanager/tm_init.go @@ -94,8 +94,8 @@ var ( // statsBackupIsRunning is set to 1 (true) if a backup is running. statsBackupIsRunning *stats.GaugesWithMultiLabels - // statsIsInSRVKeyspace is set to 1 (true), 0 (false) whether the tablet is in the serving keyspace - statsIsInSRVKeyspace *stats.Gauge + // statsIsInSrvKeyspace is set to 1 (true), 0 (false) whether the tablet is in the serving keyspace + statsIsInSrvKeyspace *stats.Gauge statsKeyspace = stats.NewString("TabletKeyspace") statsShard = stats.NewString("TabletShard") @@ -118,7 +118,7 @@ func init() { statsTabletType = stats.NewString("TabletType") statsTabletTypeCount = stats.NewCountersWithSingleLabel("TabletTypeCount", "Number of times the tablet changed to the labeled type", "type") statsBackupIsRunning = stats.NewGaugesWithMultiLabels("BackupIsRunning", "Whether a backup is running", []string{"mode"}) - statsIsInSRVKeyspace = stats.NewGauge("IsInSRVKeyspace", "Whether the vttablet is in the serving keyspace (1 = true / 0 = false)") + statsIsInSrvKeyspace = stats.NewGauge("IsInSrvKeyspace", "Whether the vttablet is in the serving keyspace (1 = true / 0 = false)") } // TabletManager is the main class for the tablet manager. diff --git a/go/vt/vttablet/tabletmanager/tm_state.go b/go/vt/vttablet/tabletmanager/tm_state.go index 2af4eac0589..1eb27d99cda 100644 --- a/go/vt/vttablet/tabletmanager/tm_state.go +++ b/go/vt/vttablet/tabletmanager/tm_state.go @@ -62,7 +62,7 @@ type tmState struct { mu sync.Mutex isOpen bool isResharding bool - isInSRVKeyspace bool + isInSrvKeyspace bool isShardServing map[topodatapb.TabletType]bool tabletControls map[topodatapb.TabletType]bool blacklistedTables map[topodatapb.TabletType][]string @@ -264,11 +264,11 @@ func (ts *tmState) updateLocked(ctx context.Context) { } if ts.isShardServing[ts.tablet.Type] { - ts.isInSRVKeyspace = true - statsIsInSRVKeyspace.Set(1) + ts.isInSrvKeyspace = true + statsIsInSrvKeyspace.Set(1) } else { - ts.isInSRVKeyspace = false - statsIsInSRVKeyspace.Set(0) + ts.isInSrvKeyspace = false + statsIsInSrvKeyspace.Set(0) } // Open TabletServer last so that it advertises serving after all other services are up. diff --git a/go/vt/vttablet/tabletmanager/tm_state_test.go b/go/vt/vttablet/tabletmanager/tm_state_test.go index ee9d44e4174..d4e9eb7d025 100644 --- a/go/vt/vttablet/tabletmanager/tm_state_test.go +++ b/go/vt/vttablet/tabletmanager/tm_state_test.go @@ -155,7 +155,7 @@ func TestStateTabletControls(t *testing.T) { assert.False(t, qsc.IsServing()) } -func TestStateIsShardServingisInSRVKeyspace(t *testing.T) { +func TestStateIsShardServingisInSrvKeyspace(t *testing.T) { ctx := context.Background() ts := memorytopo.NewServer("cell1") tm := newTestTM(t, ts, 1, "ks", "0") @@ -202,11 +202,11 @@ func TestStateIsShardServingisInSRVKeyspace(t *testing.T) { tm.tmState.RefreshFromTopoInfo(ctx, nil, ks) tm.tmState.mu.Lock() - assert.False(t, tm.tmState.isInSRVKeyspace) + assert.False(t, tm.tmState.isInSrvKeyspace) assert.Equal(t, want, tm.tmState.isShardServing) tm.tmState.mu.Unlock() - assert.Equal(t, int64(0), statsIsInSRVKeyspace.Get()) + assert.Equal(t, int64(0), statsIsInSrvKeyspace.Get()) // Shard not in the SrvKeyspace, ServedType in SrvKeyspace ks = &topodatapb.SrvKeyspace{ @@ -230,11 +230,11 @@ func TestStateIsShardServingisInSRVKeyspace(t *testing.T) { tm.tmState.RefreshFromTopoInfo(ctx, nil, ks) tm.tmState.mu.Lock() - assert.False(t, tm.tmState.isInSRVKeyspace) + assert.False(t, tm.tmState.isInSrvKeyspace) assert.Equal(t, want, tm.tmState.isShardServing) tm.tmState.mu.Unlock() - assert.Equal(t, int64(0), statsIsInSRVKeyspace.Get()) + assert.Equal(t, int64(0), statsIsInSrvKeyspace.Get()) // Shard in the SrvKeyspace, ServedType in the SrvKeyspace ks = &topodatapb.SrvKeyspace{ @@ -256,11 +256,11 @@ func TestStateIsShardServingisInSRVKeyspace(t *testing.T) { tm.tmState.RefreshFromTopoInfo(ctx, nil, ks) tm.tmState.mu.Lock() - assert.True(t, tm.tmState.isInSRVKeyspace) + assert.True(t, tm.tmState.isInSrvKeyspace) assert.Equal(t, want, tm.tmState.isShardServing) tm.tmState.mu.Unlock() - assert.Equal(t, int64(1), statsIsInSRVKeyspace.Get()) + assert.Equal(t, int64(1), statsIsInSrvKeyspace.Get()) // Shard in the SrvKeyspace, ServedType not in the SrvKeyspace ks = &topodatapb.SrvKeyspace{ @@ -282,29 +282,29 @@ func TestStateIsShardServingisInSRVKeyspace(t *testing.T) { tm.tmState.RefreshFromTopoInfo(ctx, nil, ks) tm.tmState.mu.Lock() - assert.False(t, tm.tmState.isInSRVKeyspace) + assert.False(t, tm.tmState.isInSrvKeyspace) assert.Equal(t, want, tm.tmState.isShardServing) tm.tmState.mu.Unlock() - assert.Equal(t, int64(0), statsIsInSRVKeyspace.Get()) + assert.Equal(t, int64(0), statsIsInSrvKeyspace.Get()) // Test tablet type change - shard in the SrvKeyspace, ServedType in the SrvKeyspace err = tm.tmState.ChangeTabletType(ctx, topodatapb.TabletType_RDONLY, DBActionNone) require.NoError(t, err) tm.tmState.mu.Lock() - assert.True(t, tm.tmState.isInSRVKeyspace) + assert.True(t, tm.tmState.isInSrvKeyspace) tm.tmState.mu.Unlock() - assert.Equal(t, int64(1), statsIsInSRVKeyspace.Get()) + assert.Equal(t, int64(1), statsIsInSrvKeyspace.Get()) // Test tablet type change - shard in the SrvKeyspace, ServedType in the SrvKeyspace err = tm.tmState.ChangeTabletType(ctx, topodatapb.TabletType_DRAINED, DBActionNone) require.NoError(t, err) tm.tmState.mu.Lock() - assert.False(t, tm.tmState.isInSRVKeyspace) + assert.False(t, tm.tmState.isInSrvKeyspace) tm.tmState.mu.Unlock() - assert.Equal(t, int64(0), statsIsInSRVKeyspace.Get()) + assert.Equal(t, int64(0), statsIsInSrvKeyspace.Get()) } func TestStateNonServing(t *testing.T) {