Skip to content

Commit

Permalink
[prototype] *: s/config.SystemConfig/spanconfig.Store
Browse files Browse the repository at this point in the history
In KV server, we abstract away system config dependency through the
spanconfig.StoreReader interface (also implemented by
spanconfigstore.Store). The commit also:

- Fixes span generations for pseudo table IDs
- Introduce builtins to pretty print spans

Within KV we now store previous references zonepb.ZoneConfig as
roachpb.SpanConfig. This is done both on the config stored on the
Replica itself, and as a front-end to accessing config.SystemConfig; we
now talk to it through the StoreReader interface.

We gate the usage of the new infrastructure through a cluster setting.
When toggled, we switch over the ConfReader source to point to the
embedded spanconfigstore.Store instead.

Release note: None
  • Loading branch information
irfansharif committed Aug 17, 2021
1 parent dd55805 commit 7ba4ff2
Show file tree
Hide file tree
Showing 101 changed files with 2,806 additions and 2,114 deletions.
2 changes: 2 additions & 0 deletions docs/generated/sql/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2771,6 +2771,8 @@ SELECT * FROM crdb_internal.check_consistency(true, ‘\x02’, ‘\x04’)</p>
</span></td></tr>
<tr><td><a name="crdb_internal.pretty_key"></a><code>crdb_internal.pretty_key(raw_key: <a href="bytes.html">bytes</a>, skip_fields: <a href="int.html">int</a>) &rarr; <a href="string.html">string</a></code></td><td><span class="funcdesc"><p>This function is used only by CockroachDB’s developers for testing purposes.</p>
</span></td></tr>
<tr><td><a name="crdb_internal.pretty_span"></a><code>crdb_internal.pretty_span(raw_key_start: <a href="bytes.html">bytes</a>, raw_key_end: <a href="bytes.html">bytes</a>, skip_fields: <a href="int.html">int</a>) &rarr; <a href="string.html">string</a></code></td><td><span class="funcdesc"><p>This function is used only by CockroachDB’s developers for testing purposes.</p>
</span></td></tr>
<tr><td><a name="crdb_internal.range_stats"></a><code>crdb_internal.range_stats(key: <a href="bytes.html">bytes</a>) &rarr; jsonb</code></td><td><span class="funcdesc"><p>This function is used to retrieve range statistics information as a JSON object.</p>
</span></td></tr>
<tr><td><a name="crdb_internal.reset_sql_stats"></a><code>crdb_internal.reset_sql_stats() &rarr; <a href="bool.html">bool</a></code></td><td><span class="funcdesc"><p>This function is used to clear the collected SQL statistics.</p>
Expand Down
5 changes: 5 additions & 0 deletions pkg/ccl/backupccl/restore_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,11 @@ func createImportingDescriptors(
if err := sql.CreateTenantRecord(ctx, p.ExecCfg(), txn, &tenant); err != nil {
return err
}
if err := sql.CreateTenantSpanConfig(ctx, p.ExecCfg(), txn, &tenant,
p.ExtendedEvalContext().ExecCfg.DefaultZoneConfig.AsSpanConfig(),
); err != nil {
return err
}
}

details.PrepareCompleted = true
Expand Down
3 changes: 3 additions & 0 deletions pkg/ccl/kvccl/kvtenantccl/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ func (c *Connector) updateSystemConfig(ctx context.Context, key string, content
}

// GetSystemConfig implements the config.SystemConfigProvider interface.
//
// TODO(zcfgs-pod): We want to remove the remaining uses of this in SQL.
// GC job, listening in on TTL changes for SQL objects, and the opt catalog.
func (c *Connector) GetSystemConfig() *config.SystemConfig {
// TODO(nvanbenschoten): we need to wait in `(*Connector).Start()` until the
// system config is populated. As is, there's a small chance that we return
Expand Down
13 changes: 6 additions & 7 deletions pkg/cli/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
"github.com/cockroachdb/cockroach/pkg/base"
"github.com/cockroachdb/cockroach/pkg/cli/syncbench"
"github.com/cockroachdb/cockroach/pkg/config"
"github.com/cockroachdb/cockroach/pkg/config/zonepb"
"github.com/cockroachdb/cockroach/pkg/gossip"
"github.com/cockroachdb/cockroach/pkg/keys"
"github.com/cockroachdb/cockroach/pkg/kv/kvserver"
Expand Down Expand Up @@ -669,7 +668,7 @@ func runDebugGCCmd(cmd *cobra.Command, args []string) error {
defer stopper.Stop(context.Background())

var rangeID roachpb.RangeID
gcTTLInSeconds := int64((24 * time.Hour).Seconds())
gcTTL := 24 * time.Hour
intentAgeThreshold := gc.IntentAgeThreshold.Default()

if len(args) > 3 {
Expand All @@ -679,10 +678,11 @@ func runDebugGCCmd(cmd *cobra.Command, args []string) error {
}
}
if len(args) > 2 {
var err error
if gcTTLInSeconds, err = parsePositiveInt(args[2]); err != nil {
gcTTLInSeconds, err := parsePositiveInt(args[2])
if err != nil {
return errors.Wrapf(err, "unable to parse %v as TTL", args[2])
}
gcTTL = time.Duration(gcTTLInSeconds) * time.Second
}
if len(args) > 1 {
var err error
Expand Down Expand Up @@ -732,13 +732,12 @@ func runDebugGCCmd(cmd *cobra.Command, args []string) error {
for _, desc := range descs {
snap := db.NewSnapshot()
defer snap.Close()
policy := zonepb.GCPolicy{TTLSeconds: int32(gcTTLInSeconds)}
now := hlc.Timestamp{WallTime: timeutil.Now().UnixNano()}
thresh := gc.CalculateThreshold(now, policy)
thresh := gc.CalculateThreshold(now, gcTTL)
info, err := gc.Run(
context.Background(),
&desc, snap,
now, thresh, intentAgeThreshold, policy,
now, thresh, intentAgeThreshold, gcTTL,
gc.NoopGCer{},
func(_ context.Context, _ []roachpb.Intent) error { return nil },
func(_ context.Context, _ *roachpb.Transaction) error { return nil },
Expand Down
9 changes: 9 additions & 0 deletions pkg/config/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,15 @@ func (s *SystemConfig) GetZoneConfigForKey(key roachpb.RKey) (*zonepb.ZoneConfig
return s.getZoneConfigForKey(DecodeKeyIntoZoneIDAndSuffix(key))
}

// GetSpanConfigForKey looks of the span config for the given key.
func (s *SystemConfig) GetSpanConfigForKey(ctx context.Context, key roachpb.RKey) (roachpb.SpanConfig, error) {
zone, err := s.GetZoneConfigForKey(key)
if err != nil {
return roachpb.SpanConfig{}, err
}
return zone.AsSpanConfig(), nil
}

// DecodeKeyIntoZoneIDAndSuffix figures out the zone that the key belongs to.
func DecodeKeyIntoZoneIDAndSuffix(key roachpb.RKey) (id SystemTenantObjectID, keySuffix []byte) {
objectID, keySuffix, ok := DecodeSystemTenantObjectID(key)
Expand Down
7 changes: 4 additions & 3 deletions pkg/config/system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ func TestComputeSplitKeyTenantBoundaries(t *testing.T) {
func TestGetZoneConfigForKey(t *testing.T) {
defer leaktest.AfterTest(t)()

ctx := context.Background()
testCases := []struct {
key roachpb.RKey
expectedID config.SystemTenantObjectID
Expand Down Expand Up @@ -612,11 +613,11 @@ func TestGetZoneConfigForKey(t *testing.T) {
_ *config.SystemConfig, id config.SystemTenantObjectID,
) (*zonepb.ZoneConfig, *zonepb.ZoneConfig, bool, error) {
objectID = id
return &zonepb.ZoneConfig{}, nil, false, nil
return cfg.DefaultZoneConfig, nil, false, nil
}
_, err := cfg.GetZoneConfigForKey(tc.key)
_, err := cfg.GetSpanConfigForKey(ctx, tc.key)
if err != nil {
t.Errorf("#%d: GetZoneConfigForKey(%v) got error: %v", tcNum, tc.key, err)
t.Errorf("#%d: GetSpanConfigForKey(%v) got error: %v", tcNum, tc.key, err)
}
if objectID != tc.expectedID {
t.Errorf("#%d: GetZoneConfigForKey(%v) got %d; want %d", tcNum, tc.key, objectID, tc.expectedID)
Expand Down
1 change: 1 addition & 0 deletions pkg/config/zonepb/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ go_library(
"//pkg/roachpb",
"//pkg/sql/opt/cat",
"//pkg/sql/sem/tree",
"//pkg/util/log",
"@com_github_cockroachdb_errors//:errors",
"@com_github_gogo_protobuf//proto",
"@in_gopkg_yaml_v2//:yaml_v2",
Expand Down
74 changes: 14 additions & 60 deletions pkg/config/zonepb/zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ package zonepb

import (
"bytes"
"context"
"fmt"
"strings"
"time"

"github.com/cockroachdb/cockroach/pkg/base"
"github.com/cockroachdb/cockroach/pkg/keys"
"github.com/cockroachdb/cockroach/pkg/roachpb"
"github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/cockroachdb/cockroach/pkg/util/log"
"github.com/cockroachdb/errors"
"github.com/gogo/protobuf/proto"
)
Expand Down Expand Up @@ -204,20 +205,6 @@ func NewZoneConfig() *ZoneConfig {
}
}

// EmptyCompleteZoneConfig is the zone configuration where
// all fields are set but set to their respective zero values.
func EmptyCompleteZoneConfig() *ZoneConfig {
return &ZoneConfig{
NumReplicas: proto.Int32(0),
NumVoters: proto.Int32(0),
RangeMinBytes: proto.Int64(0),
RangeMaxBytes: proto.Int64(0),
GC: &GCPolicy{TTLSeconds: 0},
InheritedConstraints: true,
InheritedLeasePreferences: true,
}
}

// DefaultZoneConfig is the default zone configuration used when no custom
// config has been specified.
func DefaultZoneConfig() ZoneConfig {
Expand Down Expand Up @@ -975,37 +962,6 @@ func (z ZoneConfig) GetSubzoneForKeySuffix(keySuffix []byte) (*Subzone, int32) {
return nil, -1
}

// GetNumVoters returns the number of voting replicas for the given zone config.
//
// This method will panic if called on a ZoneConfig with an uninitialized
// NumReplicas attribute.
func (z *ZoneConfig) GetNumVoters() int32 {
if z.NumReplicas == nil {
panic("NumReplicas must not be nil")
}
if z.NumVoters != nil && *z.NumVoters != 0 {
return *z.NumVoters
}
return *z.NumReplicas
}

// GetNumNonVoters returns the number of non-voting replicas as defined in the
// zone config.
//
// This method will panic if called on a ZoneConfig with an uninitialized
// NumReplicas attribute.
func (z *ZoneConfig) GetNumNonVoters() int32 {
if z.NumReplicas == nil {
panic("NumReplicas must not be nil")
}
if z.NumVoters != nil && *z.NumVoters != 0 {
return *z.NumReplicas - *z.NumVoters
}
// `num_voters` hasn't been explicitly configured. Every replica should be a
// voting replica.
return 0
}

// SetSubzone installs subzone into the ZoneConfig, overwriting any existing
// subzone with the same IndexID and PartitionName.
func (z *ZoneConfig) SetSubzone(subzone Subzone) {
Expand Down Expand Up @@ -1114,11 +1070,18 @@ func (z *ZoneConfig) EnsureFullyHydrated() error {
return nil
}

// ToSpanConfig converts a fully hydrated zone configuration to an equivalent
// SpanConfig. It returns assertion errors if the zone config hasn't been fully
// hydrated (fields have been filled in via parent zone config following
// inheritance semantics).
func (z ZoneConfig) ToSpanConfig() (roachpb.SpanConfig, error) {
// AsSpanConfig converts a fully hydrated zone configuration to an equivalent
// SpanConfig. It fatals if the zone config hasn't been fully hydrated (fields are
// expected to have been cascaded through parent zone configs).
func (z *ZoneConfig) AsSpanConfig() roachpb.SpanConfig {
spanConfig, err := z.toSpanConfig()
if err != nil {
log.Fatalf(context.Background(), "%v", err)
}
return spanConfig
}

func (z *ZoneConfig) toSpanConfig() (roachpb.SpanConfig, error) {
var sc roachpb.SpanConfig
var err error

Expand All @@ -1132,14 +1095,10 @@ func (z ZoneConfig) ToSpanConfig() (roachpb.SpanConfig, error) {
sc.GCTTL = z.GC.TTLSeconds

// GlobalReads is false by default.
sc.GlobalReads = false
if z.GlobalReads != nil {
sc.GlobalReads = *z.GlobalReads
}
sc.NumReplicas = *z.NumReplicas

// NumVoters = NumReplicas if NumVoters is unset.
sc.NumVoters = *z.NumReplicas
if z.NumVoters != nil {
sc.NumVoters = *z.NumVoters
}
Expand Down Expand Up @@ -1246,8 +1205,3 @@ func (c *Constraint) GetKey() string {
func (c *Constraint) GetValue() string {
return c.Value
}

// TTL returns the implies TTL as a time.Duration.
func (m *GCPolicy) TTL() time.Duration {
return time.Duration(m.TTLSeconds) * time.Second
}
16 changes: 8 additions & 8 deletions pkg/config/zonepb/zone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ func TestDefaultRangeSizesAreSane(t *testing.T) {
}

// TestZoneConfigToSpanConfigConversion tests zone configurations are correctly
// translated to span configurations using `ToSpanConfig`.
// translated to span configurations using `toSpanConfig`.
func TestZoneConfigToSpanConfigConversion(t *testing.T) {
testCases := []struct {
zoneConfig ZoneConfig
Expand Down Expand Up @@ -1183,7 +1183,7 @@ func TestZoneConfigToSpanConfigConversion(t *testing.T) {
RangeMaxBytes: 200000,
GCTTL: 2400,
GlobalReads: false,
NumVoters: 3,
NumVoters: 0,
NumReplicas: 3,
Constraints: []roachpb.ConstraintsConjunction{},
VoterConstraints: []roachpb.ConstraintsConjunction{},
Expand All @@ -1206,7 +1206,7 @@ func TestZoneConfigToSpanConfigConversion(t *testing.T) {
RangeMaxBytes: 200000,
GCTTL: 2400,
GlobalReads: true,
NumVoters: 3,
NumVoters: 0,
NumReplicas: 3,
Constraints: []roachpb.ConstraintsConjunction{},
VoterConstraints: []roachpb.ConstraintsConjunction{},
Expand All @@ -1229,7 +1229,7 @@ func TestZoneConfigToSpanConfigConversion(t *testing.T) {
RangeMaxBytes: 200000,
GCTTL: 2400,
GlobalReads: false,
NumVoters: 3,
NumVoters: 0,
NumReplicas: 3,
Constraints: []roachpb.ConstraintsConjunction{},
VoterConstraints: []roachpb.ConstraintsConjunction{},
Expand Down Expand Up @@ -1285,7 +1285,7 @@ func TestZoneConfigToSpanConfigConversion(t *testing.T) {
RangeMaxBytes: 200000,
GCTTL: 2400,
GlobalReads: false,
NumVoters: 3,
NumVoters: 0,
NumReplicas: 3,
Constraints: []roachpb.ConstraintsConjunction{
{
Expand Down Expand Up @@ -1331,7 +1331,7 @@ func TestZoneConfigToSpanConfigConversion(t *testing.T) {
RangeMaxBytes: 200000,
GCTTL: 2400,
GlobalReads: false,
NumVoters: 3,
NumVoters: 0,
NumReplicas: 3,
Constraints: []roachpb.ConstraintsConjunction{},
VoterConstraints: []roachpb.ConstraintsConjunction{
Expand Down Expand Up @@ -1381,7 +1381,7 @@ func TestZoneConfigToSpanConfigConversion(t *testing.T) {
RangeMaxBytes: 200000,
GCTTL: 2400,
GlobalReads: false,
NumVoters: 3,
NumVoters: 0,
NumReplicas: 3,
Constraints: []roachpb.ConstraintsConjunction{},
VoterConstraints: []roachpb.ConstraintsConjunction{},
Expand All @@ -1406,7 +1406,7 @@ func TestZoneConfigToSpanConfigConversion(t *testing.T) {
},
}
for _, tc := range testCases {
spanConfig, err := tc.zoneConfig.ToSpanConfig()
spanConfig, err := tc.zoneConfig.toSpanConfig()
if tc.errorStr != "" {
require.Error(t, err, tc.errorStr)
testutils.IsError(err, tc.errorStr)
Expand Down
2 changes: 1 addition & 1 deletion pkg/keys/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ var (
//
// TableDataMin is the start of the range of table data keys.
TableDataMin = SystemSQLCodec.TablePrefix(0)
// TableDataMin is the end of the range of table data keys.
// TableDataMax is the end of the range of table data keys.
TableDataMax = SystemSQLCodec.TablePrefix(math.MaxUint32).PrefixEnd()
//
// SystemConfigSplitKey is the key to split at immediately prior to the
Expand Down
9 changes: 9 additions & 0 deletions pkg/keys/spans.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ var (
// NodeLivenessSpan holds the liveness records for nodes in the cluster.
NodeLivenessSpan = roachpb.Span{Key: NodeLivenessPrefix, EndKey: NodeLivenessKeyMax}

// TimeseriesSpan holds all the timeseries data in the cluster.
TimeseriesSpan = roachpb.Span{Key: TimeseriesPrefix, EndKey: TimeseriesKeyMax}

// SystemSpan holds all the global, system data in the cluster.
SystemSpan = roachpb.Span{Key: SystemPrefix, EndKey: SystemMax}

// SystemConfigSpan is the range of system objects which will be gossiped.
SystemConfigSpan = roachpb.Span{Key: SystemConfigSplitKey, EndKey: SystemConfigTableDataMax}

Expand All @@ -39,5 +45,8 @@ var (
// Meta2MaxSpan: between meta and system ranges.
// NodeLivenessSpan: liveness information on nodes in the cluster.
// SystemConfigSpan: system objects which will be gossiped.
//
// TODO(zcfgs-pod): Once we've stopped special casing the system config span,
// we can split it like regular ranges.
NoSplitSpans = []roachpb.Span{Meta1Span, Meta2MaxSpan, NodeLivenessSpan, SystemConfigSpan}
)
1 change: 0 additions & 1 deletion pkg/kv/kvclient/kvcoord/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ go_test(
"@com_github_cockroachdb_errors//:errors",
"@com_github_cockroachdb_errors//errutil",
"@com_github_cockroachdb_redact//:redact",
"@com_github_gogo_protobuf//proto",
"@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require",
"@org_golang_google_grpc//:go_default_library",
Expand Down
7 changes: 3 additions & 4 deletions pkg/kv/kvclient/kvcoord/split_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (
"github.com/cockroachdb/cockroach/pkg/util/log"
"github.com/cockroachdb/cockroach/pkg/util/randutil"
"github.com/cockroachdb/errors"
"github.com/gogo/protobuf/proto"
)

// startTestWriter creates a writer which initiates a sequence of
Expand Down Expand Up @@ -177,14 +176,14 @@ func TestRangeSplitsWithWritePressure(t *testing.T) {
defer leaktest.AfterTest(t)()
defer log.Scope(t).Close(t)
// Override default zone config.
cfg := zonepb.DefaultZoneConfigRef()
cfg.RangeMaxBytes = proto.Int64(1 << 18)
cfg := zonepb.DefaultZoneConfigRef().AsSpanConfig()
cfg.RangeMaxBytes = 1 << 18

// Manually create the local test cluster so that the split queue
// is not disabled (LocalTestCluster disables it by default).
s := &localtestcluster.LocalTestCluster{
Cfg: kvserver.StoreConfig{
DefaultZoneConfig: cfg,
DefaultSpanConfig: cfg,
},
StoreTestingKnobs: &kvserver.StoreTestingKnobs{
DisableScanner: true,
Expand Down
1 change: 1 addition & 0 deletions pkg/kv/kvserver/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ go_test(
"//pkg/server/serverpb",
"//pkg/server/telemetry",
"//pkg/settings/cluster",
"//pkg/spanconfig",
"//pkg/sql",
"//pkg/sql/catalog/bootstrap",
"//pkg/sql/catalog/catalogkeys",
Expand Down
Loading

0 comments on commit 7ba4ff2

Please sign in to comment.