-
Notifications
You must be signed in to change notification settings - Fork 3.8k
/
Copy pathkeys.go
199 lines (169 loc) · 7.59 KB
/
keys.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
192
193
194
195
196
197
198
199
// Copyright 2014 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
package gossip
import (
"regexp"
"strconv"
"strings"
"github.com/cockroachdb/cockroach/pkg/base"
"github.com/cockroachdb/cockroach/pkg/roachpb"
"github.com/cockroachdb/errors"
)
// separator is used to separate the non-prefix components of a
// Gossip key, facilitating the automated generation of regular
// expressions for various prefixes.
// It must not be contained in any of the other keys defined here.
const separator = ":"
// Constants for gossip keys.
const (
// KeyClusterID is the unique UUID for this Cockroach cluster.
// The value is a string UUID for the cluster. The cluster ID is
// gossiped by all nodes that contain a replica of the first range,
// and it serves as a check for basic gossip connectivity. The
// Gossip.Connected channel is closed when we see this key.
KeyClusterID = "cluster-id"
// KeyStorePrefix is the key prefix for gossiping stores in the network.
// The suffix is a store ID and the value is a roachpb.StoreDescriptor.
KeyStorePrefix = "store"
// KeyNodeIDPrefix is the key prefix for gossiping node id addresses.
// The actual key is suffixed with the decimal representation of the
// node id (e.g. 'node:1') and the value is a roachpb.NodeDescriptor.
KeyNodeIDPrefix = "node"
// KeyHealthAlertPrefix is the key prefix for gossiping health alerts.
// The value is a proto of type HealthCheckResult.
KeyNodeHealthAlertPrefix = "health-alert"
// KeyNodeLivenessPrefix is the key prefix for gossiping node liveness
// info.
KeyNodeLivenessPrefix = "liveness"
// KeySentinel is a key for gossip which must not expire or
// else the node considers itself partitioned and will retry with
// bootstrap hosts. The sentinel is gossiped by the node that holds
// the range lease for the first range.
KeySentinel = "sentinel"
// KeyFirstRangeDescriptor is the descriptor for the "first" range. The
// "first" range contains the meta1 key range, the first level of the
// bi-level key addressing scheme. The value is a roachpb.RangeDescriptor.
KeyFirstRangeDescriptor = "first-range"
// KeyDeprecatedSystemConfig is the gossip key for the system DB span.
// The value if a config.SystemConfig which holds all key/value
// pairs in the system DB span.
//
// This key is used in the 21.2<->22.1 mixed version state. It is not used
// in 22.1.
//
// TODO(ajwerner): Delete in 22.2.
KeyDeprecatedSystemConfig = "system-db"
// KeyDistSQLNodeVersionKeyPrefix is key prefix for each node's DistSQL
// version.
KeyDistSQLNodeVersionKeyPrefix = "distsql-version"
// KeyDistSQLDrainingPrefix is the key prefix for each node's DistSQL
// draining state.
KeyDistSQLDrainingPrefix = "distsql-draining"
// KeyGossipClientsPrefix is the prefix for keys that indicate which gossip
// client connections a node has open. This is used by other nodes in the
// cluster to build a map of the gossip network.
KeyGossipClientsPrefix = "gossip-clients"
// KeyGossipStatementDiagnosticsRequest is the gossip key for new statement
// diagnostics requests. The values is the id of the request that generated
// the notification, as a little-endian-encoded uint64.
// stmtDiagnosticsRequestRegistry listens for notifications and responds by
// polling for new requests.
KeyGossipStatementDiagnosticsRequest = "stmt-diag-req"
// KeyGossipStatementDiagnosticsRequestCancellation is the gossip key for
// canceling an existing diagnostics request. The values is the id of the
// request that needs to be canceled, as a little-endian-encoded uint64.
// stmtDiagnosticsRequestRegistry listens for notifications and responds by
// polling for new requests.
KeyGossipStatementDiagnosticsRequestCancellation = "stmt-diag-cancel-req"
)
// MakeKey creates a canonical key under which to gossip a piece of
// information. The first argument will typically be one of the key constants
// defined in this package.
func MakeKey(components ...string) string {
return strings.Join(components, separator)
}
// MakePrefixPattern returns a regular expression pattern that
// matches precisely the Gossip keys created by invocations of
// MakeKey with multiple arguments for which the first argument
// is equal to the given prefix.
func MakePrefixPattern(prefix string) string {
return regexp.QuoteMeta(prefix+separator) + ".*"
}
// MakeNodeIDKey returns the gossip key for node ID info.
func MakeNodeIDKey(nodeID roachpb.NodeID) string {
return MakeKey(KeyNodeIDPrefix, nodeID.String())
}
// IsNodeIDKey returns true iff the provided key is a valid node ID key.
func IsNodeIDKey(key string) bool {
return strings.HasPrefix(key, KeyNodeIDPrefix+separator)
}
// NodeIDFromKey attempts to extract a NodeID from the provided key after
// stripping the provided prefix. Returns an error if the key is not of the
// correct type or is not parsable.
func NodeIDFromKey(key string, prefix string) (roachpb.NodeID, error) {
trimmedKey, err := removePrefixFromKey(key, prefix)
if err != nil {
return 0, err
}
nodeID, err := strconv.ParseInt(trimmedKey, 10 /* base */, 64 /* bitSize */)
if err != nil {
return 0, errors.Wrapf(err, "failed parsing NodeID from key %q", key)
}
return roachpb.NodeID(nodeID), nil
}
// MakeGossipClientsKey returns the gossip client key for the given node.
func MakeGossipClientsKey(nodeID roachpb.NodeID) string {
return MakeKey(KeyGossipClientsPrefix, nodeID.String())
}
// MakeNodeHealthAlertKey returns the gossip key under which the given node can
// gossip health alerts.
func MakeNodeHealthAlertKey(nodeID roachpb.NodeID) string {
return MakeKey(KeyNodeHealthAlertPrefix, strconv.Itoa(int(nodeID)))
}
// MakeNodeLivenessKey returns the gossip key for node liveness info.
func MakeNodeLivenessKey(nodeID roachpb.NodeID) string {
return MakeKey(KeyNodeLivenessPrefix, nodeID.String())
}
// MakeStoreKey returns the gossip key for the given store.
func MakeStoreKey(storeID roachpb.StoreID) string {
return MakeKey(KeyStorePrefix, storeID.String())
}
// StoreIDFromKey attempts to extract a StoreID from the provided key after
// stripping the provided prefix. Returns an error if the key is not of the
// correct type or is not parsable.
func StoreIDFromKey(storeKey string) (roachpb.StoreID, error) {
trimmedKey, err := removePrefixFromKey(storeKey, KeyStorePrefix)
if err != nil {
return 0, err
}
storeID, err := strconv.ParseInt(trimmedKey, 10 /* base */, 64 /* bitSize */)
if err != nil {
return 0, errors.Wrapf(err, "failed parsing StoreID from key %q", storeKey)
}
return roachpb.StoreID(storeID), nil
}
// MakeDistSQLNodeVersionKey returns the gossip key for the given store.
func MakeDistSQLNodeVersionKey(instanceID base.SQLInstanceID) string {
return MakeKey(KeyDistSQLNodeVersionKeyPrefix, instanceID.String())
}
// MakeDistSQLDrainingKey returns the gossip key for the given node's distsql
// draining state.
func MakeDistSQLDrainingKey(instanceID base.SQLInstanceID) string {
return MakeKey(KeyDistSQLDrainingPrefix, instanceID.String())
}
// removePrefixFromKey removes the key prefix and separator and returns what's
// left. Returns an error if the key doesn't have this prefix.
func removePrefixFromKey(key, prefix string) (string, error) {
trimmedKey := strings.TrimPrefix(key, prefix+separator)
if trimmedKey == key {
return "", errors.Errorf("%q does not have expected prefix %q%s", key, prefix, separator)
}
return trimmedKey, nil
}