Print MasterTermStartTime in ListAllTablets, ListTablets,

ListShardTablets. In case of an old master, we replace the timestamp
displayed with "defunct".
Also show MasterTermStartTime in output of "show vitess_tablets" from
vtgate.

Signed-off-by: deepthi <deepthi@planetscale.com>
This commit is contained in:
deepthi 2020-04-30 13:29:07 -07:00
Родитель 3b64e30cbc
Коммит 5389714d53
7 изменённых файлов: 76 добавлений и 12 удалений

1
go.mod
Просмотреть файл

@ -86,6 +86,7 @@ require (
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
gopkg.in/ini.v1 v1.51.0 // indirect
gopkg.in/ldap.v2 v2.5.0
gotest.tools v2.2.0+incompatible
honnef.co/go/tools v0.0.1-2019.2.3
k8s.io/apiextensions-apiserver v0.17.3
k8s.io/apimachinery v0.17.3

1
go.sum
Просмотреть файл

@ -754,6 +754,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

Просмотреть файл

@ -19,6 +19,9 @@ package discovery
import (
"sort"
"sync"
"time"
"vitess.io/vitess/go/vt/logutil"
"vitess.io/vitess/go/vt/topo"
"vitess.io/vitess/go/vt/topo/topoproto"
@ -179,6 +182,8 @@ func (fhc *FakeHealthCheck) AddFakeTablet(cell, host string, port int32, keyspac
t.Shard = shard
t.Type = tabletType
t.PortMap["vt"] = port
// reparentTS only has precision to seconds
t.MasterTermStartTime = logutil.TimeToProto(time.Unix(reparentTS, 0))
key := TabletToMapKey(t)
fhc.mu.Lock()

Просмотреть файл

@ -514,15 +514,41 @@ func fmtTabletAwkable(ti *topo.TabletInfo) string {
if shard == "" {
shard = "<null>"
}
return fmt.Sprintf("%v %v %v %v %v %v %v", topoproto.TabletAliasString(ti.Alias), keyspace, shard, topoproto.TabletTypeLString(ti.Type), ti.Addr(), ti.MysqlAddr(), fmtMapAwkable(ti.Tags))
mtst := ""
// special case for old master that hasn't updated topo yet
if ti.MasterTermStartTime != nil {
if ti.MasterTermStartTime.Seconds == -1 {
mtst = "defunct"
}
if ti.MasterTermStartTime.Seconds > 0 {
mtst = logutil.ProtoToTime(ti.MasterTermStartTime).Format(time.RFC3339)
}
}
return fmt.Sprintf("%v %v %v %v %v %v %v %v", topoproto.TabletAliasString(ti.Alias), keyspace, shard, topoproto.TabletTypeLString(ti.Type), ti.Addr(), ti.MysqlAddr(), fmtMapAwkable(ti.Tags), mtst)
}
func listTabletsByShard(ctx context.Context, wr *wrangler.Wrangler, keyspace, shard string) error {
tabletAliases, err := wr.TopoServer().FindAllTabletAliasesInShard(ctx, keyspace, shard)
tabletMap, err := wr.TopoServer().GetTabletMapForShard(ctx, keyspace, shard)
if err != nil {
return err
}
return dumpTablets(ctx, wr, tabletAliases)
var trueMasterTimestamp time.Time
for _, ti := range tabletMap {
if ti.Type == topodatapb.TabletType_MASTER {
masterTimestamp := logutil.ProtoToTime(ti.MasterTermStartTime)
if masterTimestamp.After(trueMasterTimestamp) {
trueMasterTimestamp = masterTimestamp
}
}
}
for _, ti := range tabletMap {
masterTimestamp := logutil.ProtoToTime(ti.MasterTermStartTime)
if ti.Type == topodatapb.TabletType_MASTER && masterTimestamp.Before(trueMasterTimestamp) {
ti.MasterTermStartTime.Seconds = -1
}
wr.Logger().Printf("%v\n", fmtTabletAwkable(ti))
}
return nil
}
func dumpAllTablets(ctx context.Context, wr *wrangler.Wrangler, cell string) error {
@ -530,12 +556,35 @@ func dumpAllTablets(ctx context.Context, wr *wrangler.Wrangler, cell string) err
if err != nil {
return err
}
// It is possible that an old master has not yet updated it's type in the topo
// In that case, replace timestamp with `defunct`
trueMasterTimestamps := findTrueMasterTimestamps(tablets)
for _, ti := range tablets {
key := ti.Keyspace + "." + ti.Shard
masterTimestamp := logutil.ProtoToTime(ti.MasterTermStartTime)
if ti.Type == topodatapb.TabletType_MASTER && masterTimestamp.Before(trueMasterTimestamps[key]) {
ti.MasterTermStartTime.Seconds = -1
}
wr.Logger().Printf("%v\n", fmtTabletAwkable(ti))
}
return nil
}
func findTrueMasterTimestamps(tablets []*topo.TabletInfo) map[string]time.Time {
result := make(map[string]time.Time)
for _, ti := range tablets {
key := ti.Keyspace + "." + ti.Shard
if v, ok := result[key]; !ok {
result[key] = logutil.ProtoToTime(ti.MasterTermStartTime)
} else {
if logutil.ProtoToTime(ti.MasterTermStartTime).After(v) {
result[key] = logutil.ProtoToTime(ti.MasterTermStartTime)
}
}
}
return result
}
func dumpTablets(ctx context.Context, wr *wrangler.Wrangler, tabletAliases []*topodatapb.TabletAlias) error {
tabletMap, err := wr.TopoServer().GetTabletMap(ctx, tabletAliases)
if err != nil {

Просмотреть файл

@ -68,10 +68,10 @@ func TestSuite(t *testing.T, ts *topo.Server, client vtctlclient.VtctlClient) {
PortMap: map[string]int32{
"vt": 3333,
},
Tags: map[string]string{"tag": "value"},
Keyspace: "test_keyspace",
Type: topodatapb.TabletType_MASTER,
MasterTermStartTime: logutil.TimeToProto(time.Date(1970, 1, 1, 1, 1, 1, 1, time.UTC)),
Tags: map[string]string{"tag": "value"},
Keyspace: "test_keyspace",
Type: topodatapb.TabletType_MASTER,
}
topoproto.SetMysqlPort(tablet, 3334)
if err := ts.CreateTablet(ctx, tablet); err != nil {
@ -88,7 +88,7 @@ func TestSuite(t *testing.T, ts *topo.Server, client vtctlclient.VtctlClient) {
if err != nil {
t.Fatalf("failed to get first line: %v", err)
}
expected := "cell1-0000000001 test_keyspace <null> master localhost:3333 localhost:3334 [tag: \"value\"]\n"
expected := "cell1-0000000001 test_keyspace <null> master localhost:3333 localhost:3334 [tag: \"value\"] 1970-01-01T01:01:01Z\n"
if logutil.EventString(got) != expected {
t.Errorf("Got unexpected log line '%v' expected '%v'", got.String(), expected)
}

Просмотреть файл

@ -29,6 +29,8 @@ import (
"sync"
"time"
"vitess.io/vitess/go/vt/logutil"
"vitess.io/vitess/go/vt/log"
vtgatepb "vitess.io/vitess/go/vt/proto/vtgate"
@ -828,6 +830,11 @@ func (e *Executor) handleShow(ctx context.Context, safeSession *SafeSession, sql
if !ts.Serving {
state = "NOT_SERVING"
}
mtst := ts.Tablet.MasterTermStartTime
mtstStr := ""
if mtst != nil && mtst.Seconds > 0 {
mtstStr = logutil.ProtoToTime(ts.Tablet.MasterTermStartTime).Format(time.RFC3339)
}
rows = append(rows, buildVarCharRow(
s.Cell,
s.Target.Keyspace,
@ -836,11 +843,12 @@ func (e *Executor) handleShow(ctx context.Context, safeSession *SafeSession, sql
state,
topoproto.TabletAliasString(ts.Tablet.Alias),
ts.Tablet.Hostname,
mtstStr,
))
}
}
return &sqltypes.Result{
Fields: buildVarCharFields("Cell", "Keyspace", "Shard", "TabletType", "State", "Alias", "Hostname"),
Fields: buildVarCharFields("Cell", "Keyspace", "Shard", "TabletType", "State", "Alias", "Hostname", "MasterTermStartTime"),
Rows: rows,
RowsAffected: uint64(len(rows)),
}, nil

Просмотреть файл

@ -797,10 +797,10 @@ func TestExecutorShow(t *testing.T) {
// Just test for first & last.
qr.Rows = [][]sqltypes.Value{qr.Rows[0], qr.Rows[len(qr.Rows)-1]}
wantqr = &sqltypes.Result{
Fields: buildVarCharFields("Cell", "Keyspace", "Shard", "TabletType", "State", "Alias", "Hostname"),
Fields: buildVarCharFields("Cell", "Keyspace", "Shard", "TabletType", "State", "Alias", "Hostname", "MasterTermStartTime"),
Rows: [][]sqltypes.Value{
buildVarCharRow("FakeCell", "TestExecutor", "-20", "MASTER", "SERVING", "aa-0000000000", "-20"),
buildVarCharRow("FakeCell", "TestUnsharded", "0", "MASTER", "SERVING", "aa-0000000000", "0"),
buildVarCharRow("FakeCell", "TestExecutor", "-20", "MASTER", "SERVING", "aa-0000000000", "-20", "1970-01-01T00:00:01Z"),
buildVarCharRow("FakeCell", "TestUnsharded", "0", "MASTER", "SERVING", "aa-0000000000", "0", "1970-01-01T00:00:01Z"),
},
RowsAffected: 9,
}