84 lines
2.2 KiB
Go
84 lines
2.2 KiB
Go
// Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0.
|
|
|
|
package pdutil
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"crypto/tls"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/pingcap/errors"
|
|
berrors "github.com/pingcap/tidb/br/pkg/errors"
|
|
"github.com/pingcap/tidb/br/pkg/httputil"
|
|
"github.com/pingcap/tidb/pkg/store/pdtypes"
|
|
"github.com/pingcap/tidb/pkg/tablecodec"
|
|
"github.com/pingcap/tidb/pkg/util/codec"
|
|
pd "github.com/tikv/pd/client/http"
|
|
)
|
|
|
|
// UndoFunc is a 'undo' operation of some undoable command.
|
|
// (e.g. RemoveSchedulers).
|
|
type UndoFunc func(context.Context) error
|
|
|
|
// Nop is the 'zero value' of undo func.
|
|
var Nop UndoFunc = func(context.Context) error { return nil }
|
|
|
|
// GetPlacementRules return the current placement rules.
|
|
func GetPlacementRules(ctx context.Context, pdAddr string, tlsConf *tls.Config) ([]pdtypes.Rule, error) {
|
|
cli := httputil.NewClient(tlsConf)
|
|
prefix := "http://"
|
|
if tlsConf != nil {
|
|
prefix = "https://"
|
|
}
|
|
reqURL := fmt.Sprintf("%s%s%s", prefix, pdAddr, pd.PlacementRules)
|
|
req, err := http.NewRequestWithContext(ctx, "GET", reqURL, nil)
|
|
if err != nil {
|
|
return nil, errors.Trace(err)
|
|
}
|
|
resp, err := cli.Do(req)
|
|
if err != nil {
|
|
return nil, errors.Trace(err)
|
|
}
|
|
defer resp.Body.Close()
|
|
buf := new(bytes.Buffer)
|
|
_, err = buf.ReadFrom(resp.Body)
|
|
if err != nil {
|
|
return nil, errors.Trace(err)
|
|
}
|
|
if resp.StatusCode == http.StatusPreconditionFailed {
|
|
return []pdtypes.Rule{}, nil
|
|
}
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, errors.Annotatef(berrors.ErrPDInvalidResponse,
|
|
"get placement rules failed: resp=%v, err=%v, code=%d", buf.String(), err, resp.StatusCode)
|
|
}
|
|
var rules []pdtypes.Rule
|
|
err = json.Unmarshal(buf.Bytes(), &rules)
|
|
if err != nil {
|
|
return nil, errors.Trace(err)
|
|
}
|
|
return rules, nil
|
|
}
|
|
|
|
// SearchPlacementRule returns the placement rule matched to the table or nil.
|
|
func SearchPlacementRule(tableID int64, placementRules []pdtypes.Rule, role pdtypes.PeerRoleType) *pdtypes.Rule {
|
|
for _, rule := range placementRules {
|
|
key, err := hex.DecodeString(rule.StartKeyHex)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
_, decoded, err := codec.DecodeBytes(key, nil)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if rule.Role == role && tableID == tablecodec.DecodeTableID(decoded) {
|
|
return &rule
|
|
}
|
|
}
|
|
return nil
|
|
}
|