func SwitchMode(ctx context.Context, tls *common.TLS, tikvAddr string, mode import_sstpb.SwitchMode) error {
	task := log.With(zap.Stringer("mode", mode), zap.String("tikv", tikvAddr)).Begin(zap.DebugLevel, "switch mode")
	err := withTiKVConnection(ctx, tls, tikvAddr, func(client import_sstpb.ImportSSTClient) error {
		_, err := client.SwitchMode(ctx, &import_sstpb.SwitchModeRequest{
			Mode: mode,
		})
		return ignoreUnimplementedError(err, task.Logger)
	})
	task.End(zap.InfoLevel, err)
	return err
}
SwitchMode changes the TiKV node at the given address to a particular mode.
package backend
import (
	"context"
	"regexp"
	"github.com/pingcap/errors"
	"github.com/pingcap/kvproto/pkg/debugpb"
	"github.com/pingcap/kvproto/pkg/import_sstpb"
	"go.uber.org/zap"
	"golang.org/x/sync/errgroup"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"github.com/pingcap/tidb-lightning/lightning/common"
	"github.com/pingcap/tidb-lightning/lightning/log"
)
type StoreState int
const (
	StoreStateUp StoreState = -iota
	StoreStateOffline
	StoreStateDisconnected
	StoreStateDown
	StoreStateTombstone
)
var jsonToStoreState = map[string]StoreState{
	`"Up"`:           StoreStateUp,
	`"Offline"`:      StoreStateOffline,
	`"Disconnected"`: StoreStateDisconnected,
	`"Down"`:         StoreStateDown,
	`"Tombstone"`:    StoreStateTombstone,
}
func (ss *StoreState) UnmarshalJSON(content []byte) error {
	if state, ok := jsonToStoreState[string(content)]; ok {
		*ss = state
		return nil
	}
	return errors.New("Unknown store state")
}
type Store struct {
	Address string
	Version string
	State   StoreState `json:"state_name"`
}
func withTiKVConnection(ctx context.Context, tls *common.TLS, tikvAddr string, action func(import_sstpb.ImportSSTClient) error) error {
	conn, err := grpc.DialContext(ctx, tikvAddr, tls.ToGRPCDialOption())
	if err != nil {
		return errors.Trace(err)
	}
	defer conn.Close()
	client := import_sstpb.NewImportSSTClient(conn)
	return action(client)
}
func ForAllStores(
	ctx context.Context,
	tls *common.TLS,
	minState StoreState,
	action func(c context.Context, store *Store) error,
) error {
	var stores struct {
		Stores []struct {
			Store Store
		}
	}
	err := tls.GetJSON(ctx, "/pd/api/v1/stores", &stores)
	if err != nil {
		return err
	}
	eg, c := errgroup.WithContext(ctx)
	for _, store := range stores.Stores {
		if store.Store.State >= minState {
			s := store.Store
			eg.Go(func() error { return action(c, &s) })
		}
	}
	return eg.Wait()
}
func ignoreUnimplementedError(err error, logger log.Logger) error {
	if status.Code(err) == codes.Unimplemented {
		logger.Debug("skipping potentially TiFlash store")
		return nil
	}
	return errors.Trace(err)
}