Skip to content

Commit

Permalink
Merge branch 'master' into compare-ts
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreMouche authored May 17, 2021
2 parents cb68bd8 + e92df20 commit b220230
Show file tree
Hide file tree
Showing 34 changed files with 576 additions and 173 deletions.
2 changes: 1 addition & 1 deletion cmd/ddltest/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func (s *TestDDLSuite) SetUpSuite(c *C) {
s.procs = make([]*server, *serverNum)

// Set server restart retry count.
s.retryCount = 5
s.retryCount = 20

createLogFiles(c, *serverNum)
err = s.startServers()
Expand Down
14 changes: 7 additions & 7 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5895,8 +5895,8 @@ func buildPlacementSpecReplicasAndConstraint(replicas uint64, cnstr string) ([]*
}

rules = append(rules, &placement.Rule{
Count: int(replicas),
LabelConstraints: labelConstraints,
Count: int(replicas),
Constraints: labelConstraints,
})

return rules, nil
Expand Down Expand Up @@ -5925,8 +5925,8 @@ func buildPlacementSpecReplicasAndConstraint(replicas uint64, cnstr string) ([]*
}

rules = append(rules, &placement.Rule{
Count: cnt,
LabelConstraints: labelConstraints,
Count: cnt,
Constraints: labelConstraints,
})
}

Expand Down Expand Up @@ -6051,14 +6051,14 @@ func (d *ddl) AlterTableAlterPartition(ctx sessionctx.Context, ident ast.Ident,
newRules := bundle.Rules[:0]
for i, rule := range bundle.Rules {
// merge all empty constraints
if len(rule.LabelConstraints) == 0 {
if len(rule.Constraints) == 0 {
extraCnt[rule.Role] += rule.Count
continue
}
// refer to tidb#22065.
// add -engine=tiflash to every rule to avoid schedules to tiflash instances.
// placement rules in SQL is not compatible with `set tiflash replica` yet
if err := rule.LabelConstraints.Add(placement.Constraint{
if err := rule.Constraints.Add(placement.Constraint{
Op: placement.NotIn,
Key: placement.EngineLabelKey,
Values: []string{placement.EngineLabelTiFlash},
Expand All @@ -6083,7 +6083,7 @@ func (d *ddl) AlterTableAlterPartition(ctx sessionctx.Context, ident ast.Ident,
Count: cnt,
StartKeyHex: startKey,
EndKeyHex: endKey,
LabelConstraints: []placement.Constraint{{
Constraints: []placement.Constraint{{
Op: placement.NotIn,
Key: placement.EngineLabelKey,
Values: []string{placement.EngineLabelTiFlash},
Expand Down
6 changes: 6 additions & 0 deletions ddl/placement/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,10 @@ var (
ErrUnsupportedConstraint = errors.New("unsupported label constraint")
// ErrConflictingConstraints is from constraints.go.
ErrConflictingConstraints = errors.New("conflicting label constraints")
// ErrInvalidConstraintsMapcnt is from rule.go.
ErrInvalidConstraintsMapcnt = errors.New("label constraints in map syntax have invalid replicas")
// ErrInvalidConstraintsFormat is from rule.go.
ErrInvalidConstraintsFormat = errors.New("invalid label constraints format")
// ErrInvalidConstraintsRelicas is from rule.go.
ErrInvalidConstraintsRelicas = errors.New("label constraints with invalid REPLICAS")
)
132 changes: 132 additions & 0 deletions ddl/placement/rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright 2021 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package placement

import (
"fmt"
"strings"

"github.com/go-yaml/yaml"
)

// PeerRoleType is the expected peer type of the placement rule.
type PeerRoleType string

const (
// Voter can either match a leader peer or follower peer.
Voter PeerRoleType = "voter"
// Leader matches a leader.
Leader PeerRoleType = "leader"
// Follower matches a follower.
Follower PeerRoleType = "follower"
// Learner matches a learner.
Learner PeerRoleType = "learner"
)

// Rule is the core placement rule struct. Check https://github.com/tikv/pd/blob/master/server/schedule/placement/rule.go.
type Rule struct {
GroupID string `json:"group_id"`
ID string `json:"id"`
Index int `json:"index,omitempty"`
Override bool `json:"override,omitempty"`
StartKeyHex string `json:"start_key"`
EndKeyHex string `json:"end_key"`
Role PeerRoleType `json:"role"`
Count int `json:"count"`
Constraints Constraints `json:"label_constraints,omitempty"`
LocationLabels []string `json:"location_labels,omitempty"`
IsolationLevel string `json:"isolation_level,omitempty"`
}

// NewRules constructs []*Rule from a yaml-compatible representation of
// array or map of constraints. It converts 'CONSTRAINTS' field in RFC
// https://github.com/pingcap/tidb/blob/master/docs/design/2020-06-24-placement-rules-in-sql.md to structs.
func NewRules(replicas uint64, cnstr string) ([]*Rule, error) {
rules := []*Rule{}

cnstbytes := []byte(cnstr)

constraints1 := []string{}
err1 := yaml.UnmarshalStrict(cnstbytes, &constraints1)
if err1 == nil {
// can not emit REPLICAS with an array or empty label
if replicas == 0 {
return rules, fmt.Errorf("%w: should be positive", ErrInvalidConstraintsRelicas)
}

labelConstraints, err := NewConstraints(constraints1)
if err != nil {
return rules, err
}

rules = append(rules, &Rule{
Count: int(replicas),
Constraints: labelConstraints,
})

return rules, nil
}

constraints2 := map[string]int{}
err2 := yaml.UnmarshalStrict(cnstbytes, &constraints2)
if err2 == nil {
ruleCnt := 0
for labels, cnt := range constraints2 {
if cnt <= 0 {
return rules, fmt.Errorf("%w: count of labels '%s' should be positive, but got %d", ErrInvalidConstraintsMapcnt, labels, cnt)
}
ruleCnt += cnt
}

if replicas == 0 {
replicas = uint64(ruleCnt)
}

if int(replicas) < ruleCnt {
return rules, fmt.Errorf("%w: should be larger or equal to the number of total replicas, but REPLICAS=%d < total=%d", ErrInvalidConstraintsRelicas, replicas, ruleCnt)
}

for labels, cnt := range constraints2 {
labelConstraints, err := NewConstraints(strings.Split(labels, ","))
if err != nil {
return rules, err
}

rules = append(rules, &Rule{
Count: cnt,
Constraints: labelConstraints,
})
}

remain := int(replicas) - ruleCnt
if remain > 0 {
rules = append(rules, &Rule{
Count: remain,
})
}

return rules, nil
}

return nil, fmt.Errorf("%w: should be [constraint1, ...] (error %s), {constraint1: cnt1, ...} (error %s), or any yaml compatible representation", ErrInvalidConstraintsFormat, err1, err2)
}

// Clone is used to duplicate a RuleOp for safe modification.
// Note that it is a shallow copy: LocationLabels and Constraints
// is not cloned.
func (r *Rule) Clone() *Rule {
n := &Rule{}
*n = *r
return n
}
Loading

0 comments on commit b220230

Please sign in to comment.