Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cherrypick-2.0: config/storage: per-replica constraints, improved locality handling #22906

Merged
merged 1 commit into from
Feb 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions pkg/ccl/cliccl/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,15 @@ func Example_cclzone() {
// gc:
// ttlseconds: 90000
// num_replicas: 1
// constraints: [us-east-1a, ssd]
// constraints: [+us-east-1a, +ssd]
// zone get db.t.p0
// db.t@primary
// range_min_bytes: 1048576
// range_max_bytes: 67108864
// gc:
// ttlseconds: 90000
// num_replicas: 1
// constraints: [us-east-1a, ssd]
// constraints: [+us-east-1a, +ssd]
// zone get db.t
// .default
// range_min_bytes: 1048576
Expand All @@ -149,23 +149,23 @@ func Example_cclzone() {
// gc:
// ttlseconds: 90000
// num_replicas: 3
// constraints: [us-east-1a, ssd]
// constraints: [+us-east-1a, +ssd]
// zone get db.t.p1
// db.t.p1
// range_min_bytes: 1048576
// range_max_bytes: 134217728
// gc:
// ttlseconds: 90000
// num_replicas: 3
// constraints: [us-east-1a, ssd]
// constraints: [+us-east-1a, +ssd]
// zone get db.t.p0
// db.t@primary
// range_min_bytes: 1048576
// range_max_bytes: 67108864
// gc:
// ttlseconds: 90000
// num_replicas: 1
// constraints: [us-east-1a, ssd]
// constraints: [+us-east-1a, +ssd]
// zone ls
// .default
// .liveness
Expand All @@ -190,7 +190,7 @@ func Example_cclzone() {
// gc:
// ttlseconds: 90000
// num_replicas: 3
// constraints: [us-east-1a, ssd]
// constraints: [+us-east-1a, +ssd]
// zone ls
// .default
// .liveness
Expand Down
14 changes: 5 additions & 9 deletions pkg/ccl/partitionccl/partition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/testutils/sqlutils"
"github.com/cockroachdb/cockroach/pkg/testutils/testcluster"
"github.com/pkg/errors"
yaml "gopkg.in/yaml.v2"

"github.com/cockroachdb/cockroach/pkg/base"
"github.com/cockroachdb/cockroach/pkg/util/hlc"
Expand Down Expand Up @@ -169,16 +170,11 @@ func (t *partitioningTest) parse() error {
}
}

for _, constraintStr := range strings.Split(constraints, `,`) {
if constraintStr == "" {
continue
}
var c config.Constraint
if err := c.FromString(constraintStr); err != nil {
return errors.Wrapf(err, "parsing constraint: %s", constraintStr)
}
subzone.Config.Constraints.Constraints = append(subzone.Config.Constraints.Constraints, c)
var parsedConstraints config.ConstraintsList
if err := yaml.UnmarshalStrict([]byte("["+constraints+"]"), &parsedConstraints); err != nil {
return errors.Wrapf(err, "parsing constraints: %s", constraints)
}
subzone.Config.Constraints = ([]config.Constraints)(parsedConstraints)

t.parsed.subzones = append(t.parsed.subzones, subzone)
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ func Example_zone() {
// gc:
// ttlseconds: 90000
// num_replicas: 1
// constraints: [us-east-1a, ssd]
// constraints: [+us-east-1a, +ssd]
// zone ls
// .default
// .liveness
Expand Down Expand Up @@ -505,7 +505,7 @@ func Example_zone() {
// gc:
// ttlseconds: 90000
// num_replicas: 1
// constraints: [us-east-1a, ssd]
// constraints: [+us-east-1a, +ssd]
// zone set system.descriptor --file=./testdata/zone_attrs.yaml
// pq: cannot set zone configs for system config tables; try setting your config on the entire "system" database instead
// zone set system.namespace --file=./testdata/zone_attrs.yaml
Expand All @@ -518,15 +518,15 @@ func Example_zone() {
// gc:
// ttlseconds: 90000
// num_replicas: 3
// constraints: [us-east-1a, ssd]
// constraints: [+us-east-1a, +ssd]
// zone get system
// system
// range_min_bytes: 1048576
// range_max_bytes: 134217728
// gc:
// ttlseconds: 90000
// num_replicas: 3
// constraints: [us-east-1a, ssd]
// constraints: [+us-east-1a, +ssd]
// zone rm system
// CONFIGURE ZONE 1
// zone ls
Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/testdata/zone_attrs.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
num_replicas: 1
constraints: [us-east-1a,ssd]
constraints: [+us-east-1a,+ssd]
75 changes: 43 additions & 32 deletions pkg/config/zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/pkg/errors"
yaml "gopkg.in/yaml.v2"
)

// Several ranges outside of the SQL keyspace are given special names so they
Expand Down Expand Up @@ -226,6 +225,9 @@ func (c Constraint) String() string {

// FromString populates the constraint from the constraint shorthand notation.
func (c *Constraint) FromString(short string) error {
if len(short) == 0 {
return fmt.Errorf("the empty string is not a valid constraint")
}
switch short[0] {
case '+':
c.Type = Constraint_REQUIRED
Expand All @@ -234,7 +236,7 @@ func (c *Constraint) FromString(short string) error {
c.Type = Constraint_PROHIBITED
short = short[1:]
default:
c.Type = Constraint_POSITIVE
c.Type = Constraint_DEPRECATED_POSITIVE
}
parts := strings.Split(short, "=")
if len(parts) == 1 {
Expand All @@ -248,34 +250,6 @@ func (c *Constraint) FromString(short string) error {
return nil
}

var _ yaml.Marshaler = Constraints{}
var _ yaml.Unmarshaler = &Constraints{}

// MarshalYAML implements yaml.Marshaler.
func (c Constraints) MarshalYAML() (interface{}, error) {
short := make([]string, len(c.Constraints))
for i, c := range c.Constraints {
short[i] = c.String()
}
return short, nil
}

// UnmarshalYAML implements yaml.Unmarshaler.
func (c *Constraints) UnmarshalYAML(unmarshal func(interface{}) error) error {
var shortConstraints []string
if err := unmarshal(&shortConstraints); err != nil {
return err
}
constraints := make([]Constraint, len(shortConstraints))
for i, short := range shortConstraints {
if err := constraints[i].FromString(short); err != nil {
return err
}
}
c.Constraints = constraints
return nil
}

// minRangeMaxBytes is the minimum value for range max bytes.
const minRangeMaxBytes = 64 << 10 // 64 KB

Expand Down Expand Up @@ -321,8 +295,8 @@ func TestingSetDefaultZoneConfig(cfg ZoneConfig) func() {
}
}

// Validate returns an error if the ZoneConfig specifies a known-dangerous
// configuration.
// Validate returns an error if the ZoneConfig specifies a known-dangerous or
// disallowed configuration.
func (z *ZoneConfig) Validate() error {
for _, s := range z.Subzones {
if err := s.Config.Validate(); err != nil {
Expand All @@ -348,6 +322,43 @@ func (z *ZoneConfig) Validate() error {
return fmt.Errorf("RangeMinBytes %d is greater than or equal to RangeMaxBytes %d",
z.RangeMinBytes, z.RangeMaxBytes)
}

for _, constraints := range z.Constraints {
for _, constraint := range constraints.Constraints {
if constraint.Type == Constraint_DEPRECATED_POSITIVE {
return fmt.Errorf("constraints must either be required (prefixed with a '+') or " +
"prohibited (prefixed with a '-')")
}
}
}

// We only need to further validate constraints if per-replica constraints
// are in use. The old style of constraints that apply to all replicas don't
// require validation.
if len(z.Constraints) > 1 || (len(z.Constraints) == 1 && z.Constraints[0].NumReplicas != 0) {
var numConstrainedRepls int64
for _, constraints := range z.Constraints {
if constraints.NumReplicas <= 0 {
return fmt.Errorf("constraints must apply to at least one replica")
}
numConstrainedRepls += int64(constraints.NumReplicas)
for _, constraint := range constraints.Constraints {
if constraint.Type != Constraint_REQUIRED && constraints.NumReplicas != z.NumReplicas {
return fmt.Errorf(
"only required constraints (prefixed with a '+') can be applied to a subset of replicas")
}
if strings.Contains(constraint.Key, ":") || strings.Contains(constraint.Value, ":") {
return fmt.Errorf("the ':' character is not allowed in constraint keys or values")
}
}
}
// TODO(a-robinson): Relax this constraint, as discussed on #22412.
if numConstrainedRepls != int64(z.NumReplicas) {
return fmt.Errorf(
"the number of replicas specified in constraints (%d) does not equal the number of replicas configured for the zone (%d)",
numConstrainedRepls, z.NumReplicas)
}
}
return nil
}

Expand Down
Loading