diff --git a/client/client.go b/client/client.go index 415b6512e1f..cdd0795ed35 100644 --- a/client/client.go +++ b/client/client.go @@ -52,6 +52,7 @@ const ( // defaultKeySpaceGroupID is the default key space group id. // We also reserved 0 for the keyspace group for the same purpose. defaultKeySpaceGroupID = uint32(0) + defaultKeyspaceName = "DEFAULT" ) // Region contains information of a region's meta and its peers. @@ -335,6 +336,7 @@ func NewClientWithContext( } // NewClientWithKeyspace creates a client with context and the specified keyspace id. +// And now, it's only for test purpose. func NewClientWithKeyspace( ctx context.Context, keyspaceID uint32, svrAddrs []string, security SecurityOption, opts ...ClientOption, @@ -388,19 +390,87 @@ func createClientWithKeyspace( return c, nil } -// NewClientWithKeyspaceName creates a client with context and the specified keyspace name. -func NewClientWithKeyspaceName( +// APIVersion is the API version the server and the client is using. +// See more details in https://github.com/tikv/rfcs/blob/master/text/0069-api-v2.md#kvproto +type APIVersion int + +// The API versions the client supports. +// As for V1TTL, client won't use it and we just remove it. +const ( + V1 APIVersion = iota + _ + V2 +) + +// APIContext is the context for API version. +type APIContext interface { + GetAPIVersion() (apiVersion APIVersion) + GetKeyspaceName() (keyspaceName string) +} + +type apiContextV1 struct{} + +// NewAPIContextV1 creates a API context for V1. +func NewAPIContextV1() APIContext { + return &apiContextV1{} +} + +// GetAPIVersion returns the API version. +func (apiCtx *apiContextV1) GetAPIVersion() (version APIVersion) { + return V1 +} + +// GetKeyspaceName returns the keyspace name. +func (apiCtx *apiContextV1) GetKeyspaceName() (keyspaceName string) { + return "" +} + +type apiContextV2 struct { + keyspaceName string +} + +// NewAPIContextV2 creates a API context with the specified keyspace name for V2. +func NewAPIContextV2(keyspaceName string) APIContext { + if len(keyspaceName) == 0 { + keyspaceName = defaultKeyspaceName + } + return &apiContextV2{keyspaceName: keyspaceName} +} + +// GetAPIVersion returns the API version. +func (apiCtx *apiContextV2) GetAPIVersion() (version APIVersion) { + return V2 +} + +// GetKeyspaceName returns the keyspace name. +func (apiCtx *apiContextV2) GetKeyspaceName() (keyspaceName string) { + return apiCtx.keyspaceName +} + +// NewClientWithAPIContext creates a client according to the API context. +func NewClientWithAPIContext( + ctx context.Context, apiCtx APIContext, svrAddrs []string, + security SecurityOption, opts ...ClientOption, +) (Client, error) { + apiVersion, keyspaceName := apiCtx.GetAPIVersion(), apiCtx.GetKeyspaceName() + switch apiVersion { + case V1: + return NewClientWithContext(ctx, svrAddrs, security, opts...) + case V2: + return newClientWithKeyspaceName(ctx, keyspaceName, svrAddrs, security, opts...) + default: + return nil, errors.Errorf("[pd] invalid API version %d", apiVersion) + } +} + +// newClientWithKeyspaceName creates a client with context and the specified keyspace name. +func newClientWithKeyspaceName( ctx context.Context, keyspaceName string, svrAddrs []string, security SecurityOption, opts ...ClientOption, ) (Client, error) { log.Info("[pd] create pd client with endpoints and keyspace", zap.Strings("pd-address", svrAddrs), zap.String("keyspace-name", keyspaceName)) - // if keyspace name is empty, fall back to the legacy API - if len(keyspaceName) == 0 { - return NewClientWithContext(ctx, svrAddrs, security, opts...) - } - tlsCfg := &tlsutil.TLSConfig{ CAPath: security.CAPath, CertPath: security.CertPath, diff --git a/tests/integrations/mcs/testutil.go b/tests/integrations/mcs/testutil.go index e66c6520fea..dee5cba29dc 100644 --- a/tests/integrations/mcs/testutil.go +++ b/tests/integrations/mcs/testutil.go @@ -48,11 +48,11 @@ func InitLogger(cfg *tso.Config) (err error) { return err } -// SetupClientWithDefaultKeyspaceName creates a TSO client with default keyspace name for test. -func SetupClientWithDefaultKeyspaceName( - ctx context.Context, re *require.Assertions, endpoints []string, opts ...pd.ClientOption, +// SetupClientWithAPIContext creates a TSO client with api context name for test. +func SetupClientWithAPIContext( + ctx context.Context, re *require.Assertions, apiCtx pd.APIContext, endpoints []string, opts ...pd.ClientOption, ) pd.Client { - cli, err := pd.NewClientWithKeyspaceName(ctx, "", endpoints, pd.SecurityOption{}, opts...) + cli, err := pd.NewClientWithAPIContext(ctx, apiCtx, endpoints, pd.SecurityOption{}, opts...) re.NoError(err) return cli } diff --git a/tests/integrations/mcs/tso/server_test.go b/tests/integrations/mcs/tso/server_test.go index ce2efaa67ae..94e76d3ea03 100644 --- a/tests/integrations/mcs/tso/server_test.go +++ b/tests/integrations/mcs/tso/server_test.go @@ -189,7 +189,7 @@ func checkTSOPath(re *require.Assertions, isAPIServiceMode bool) { _, cleanup := mcs.StartSingleTSOTestServer(ctx, re, backendEndpoints, tempurl.Alloc()) defer cleanup() - cli := mcs.SetupClientWithDefaultKeyspaceName(ctx, re, []string{backendEndpoints}) + cli := mcs.SetupClientWithAPIContext(ctx, re, pd.NewAPIContextV2(""), []string{backendEndpoints}) physical, logical, err := cli.GetTS(ctx) re.NoError(err) ts := tsoutil.ComposeTS(physical, logical) diff --git a/tests/integrations/tso/client_test.go b/tests/integrations/tso/client_test.go index ba985228c18..be6ff9d77bd 100644 --- a/tests/integrations/tso/client_test.go +++ b/tests/integrations/tso/client_test.go @@ -456,7 +456,7 @@ func checkTSO(ctx context.Context, re *require.Assertions, wg *sync.WaitGroup, b for i := 0; i < tsoRequestConcurrencyNumber; i++ { go func() { defer wg.Done() - cli := mcs.SetupClientWithDefaultKeyspaceName(ctx, re, strings.Split(backendEndpoints, ",")) + cli := mcs.SetupClientWithAPIContext(ctx, re, pd.NewAPIContextV1(), strings.Split(backendEndpoints, ",")) var ts, lastTS uint64 for { select {