-
Notifications
You must be signed in to change notification settings - Fork 0
/
metadata.go
191 lines (168 loc) · 6.28 KB
/
metadata.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// Copyright 2015 The Cockroach Authors.
//
// 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,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package sqlbase
import (
"fmt"
"sort"
"golang.org/x/net/context"
"github.com/cockroachdb/cockroach/pkg/keys"
"github.com/cockroachdb/cockroach/pkg/roachpb"
"github.com/cockroachdb/cockroach/pkg/util/log"
"github.com/gogo/protobuf/proto"
)
var _ DescriptorProto = &DatabaseDescriptor{}
var _ DescriptorProto = &TableDescriptor{}
// DescriptorKey is the interface implemented by both
// databaseKey and tableKey. It is used to easily get the
// descriptor key and plain name.
type DescriptorKey interface {
Key() roachpb.Key
Name() string
}
// DescriptorProto is the interface implemented by both DatabaseDescriptor
// and TableDescriptor.
// TODO(marc): this is getting rather large.
type DescriptorProto interface {
proto.Message
GetPrivileges() *PrivilegeDescriptor
GetID() ID
SetID(ID)
TypeName() string
GetName() string
SetName(string)
}
// WrapDescriptor fills in a Descriptor.
func WrapDescriptor(descriptor DescriptorProto) *Descriptor {
desc := &Descriptor{}
switch t := descriptor.(type) {
case *TableDescriptor:
desc.Union = &Descriptor_Table{Table: t}
case *DatabaseDescriptor:
desc.Union = &Descriptor_Database{Database: t}
default:
panic(fmt.Sprintf("unknown descriptor type: %s", descriptor.TypeName()))
}
return desc
}
// MetadataSchema is used to construct the initial sql schema for a new
// CockroachDB cluster being bootstrapped. Tables and databases must be
// installed on the underlying persistent storage before a cockroach store can
// start running correctly, thus requiring this special initialization.
type MetadataSchema struct {
descs []metadataDescriptor
configs int
otherKV []roachpb.KeyValue
}
type metadataDescriptor struct {
parentID ID
desc DescriptorProto
}
// MakeMetadataSchema constructs a new MetadataSchema value which constructs
// the "system" database.
func MakeMetadataSchema() MetadataSchema {
ms := MetadataSchema{}
addSystemDatabaseToSchema(&ms)
return ms
}
// AddDescriptor adds a new non-config descriptor to the system schema.
func (ms *MetadataSchema) AddDescriptor(parentID ID, desc DescriptorProto) {
if id := desc.GetID(); id > keys.MaxReservedDescID {
panic(fmt.Sprintf("invalid reserved table ID: %d > %d", id, keys.MaxReservedDescID))
}
for _, d := range ms.descs {
if d.desc.GetID() == desc.GetID() {
log.Errorf(context.TODO(), "adding descriptor with duplicate ID: %v", desc)
return
}
}
ms.descs = append(ms.descs, metadataDescriptor{parentID, desc})
}
// AddConfigDescriptor adds a new descriptor to the system schema. Used only for
// SystemConfig tables and databases.
func (ms *MetadataSchema) AddConfigDescriptor(parentID ID, desc DescriptorProto) {
ms.AddDescriptor(parentID, desc)
ms.configs++
}
// SystemDescriptorCount returns the number of descriptors that will be created by
// this schema. This value is needed to automate certain tests.
func (ms MetadataSchema) SystemDescriptorCount() int {
return len(ms.descs)
}
// SystemConfigDescriptorCount returns the number of config descriptors that
// will be created by this schema. This value is needed to automate certain
// tests.
func (ms MetadataSchema) SystemConfigDescriptorCount() int {
return ms.configs
}
// GetInitialValues returns the set of initial K/V values which should be added to
// a bootstrapping CockroachDB cluster in order to create the tables contained
// in the schema.
func (ms MetadataSchema) GetInitialValues() []roachpb.KeyValue {
var ret []roachpb.KeyValue
// Save the ID generator value, which will generate descriptor IDs for user
// objects.
value := roachpb.Value{}
value.SetInt(int64(keys.MaxReservedDescID + 1))
ret = append(ret, roachpb.KeyValue{
Key: keys.DescIDGenerator,
Value: value,
})
// addDescriptor generates the needed KeyValue objects to install a
// descriptor on a new cluster.
addDescriptor := func(parentID ID, desc DescriptorProto) {
// Create name metadata key.
value := roachpb.Value{}
value.SetInt(int64(desc.GetID()))
ret = append(ret, roachpb.KeyValue{
Key: MakeNameMetadataKey(parentID, desc.GetName()),
Value: value,
})
// Create descriptor metadata key.
value = roachpb.Value{}
wrappedDesc := WrapDescriptor(desc)
if err := value.SetProto(wrappedDesc); err != nil {
log.Fatalf(context.TODO(), "could not marshal %v", desc)
}
ret = append(ret, roachpb.KeyValue{
Key: MakeDescMetadataKey(desc.GetID()),
Value: value,
})
}
// Generate initial values for system databases and tables, which have
// static descriptors that were generated elsewhere.
for _, sysObj := range ms.descs {
addDescriptor(sysObj.parentID, sysObj.desc)
}
// Other key/value generation that doesn't fit into databases and
// tables. This can be used to add initial entries to a table.
ret = append(ret, ms.otherKV...)
// Sort returned key values; this is valuable because it matches the way the
// objects would be sorted if read from the engine.
sort.Sort(roachpb.KeyValueByKey(ret))
return ret
}
// InitialRangeCount returns the number of ranges that would be installed if
// this metadata schema were installed on a fresh cluster and nothing else. Most
// clusters will have additional ranges installed by migrations, so this
// function should be used when only a lower bound, and not an exact count, is
// needed. See server.ExpectedInitialRangeCount() for a count that includes
// migrations.
func (ms MetadataSchema) InitialRangeCount() int {
// The number of fixed ranges is determined by the pre-defined split points
// in SystemConfig.ComputeSplitKey. The early keyspace is split up in order
// to support separate zone configs for different parts of the system ranges.
// When there are `n` StaticSplit points, there will be `n+1` ranges.
const fixedRanges = 7
return len(ms.descs) - ms.configs + fixedRanges
}