github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/gossip/keys.go (about) 1 // Copyright 2014 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package gossip 12 13 import ( 14 "regexp" 15 "strconv" 16 "strings" 17 18 "github.com/cockroachdb/cockroach/pkg/roachpb" 19 "github.com/cockroachdb/errors" 20 ) 21 22 // separator is used to separate the non-prefix components of a 23 // Gossip key, facilitating the automated generation of regular 24 // expressions for various prefixes. 25 // It must not be contained in any of the other keys defined here. 26 const separator = ":" 27 28 // Constants for gossip keys. 29 const ( 30 // KeyClusterID is the unique UUID for this Cockroach cluster. 31 // The value is a string UUID for the cluster. The cluster ID is 32 // gossiped by all nodes that contain a replica of the first range, 33 // and it serves as a check for basic gossip connectivity. The 34 // Gossip.Connected channel is closed when we see this key. 35 KeyClusterID = "cluster-id" 36 37 // KeyStorePrefix is the key prefix for gossiping stores in the network. 38 // The suffix is a store ID and the value is roachpb.StoreDescriptor. 39 KeyStorePrefix = "store" 40 41 // KeyNodeIDPrefix is the key prefix for gossiping node id 42 // addresses. The actual key is suffixed with the decimal 43 // representation of the node id and the value is the host:port 44 // string address of the node. E.g. node:1 => 127.0.0.1:24001 45 KeyNodeIDPrefix = "node" 46 47 // KeyHealthAlertPrefix is the key prefix for gossiping health alerts. The 48 // value is a proto of type HealthCheckResult. 49 KeyNodeHealthAlertPrefix = "health-alert" 50 51 // KeyNodeLivenessPrefix is the key prefix for gossiping node liveness info. 52 KeyNodeLivenessPrefix = "liveness" 53 54 // KeySentinel is a key for gossip which must not expire or 55 // else the node considers itself partitioned and will retry with 56 // bootstrap hosts. The sentinel is gossiped by the node that holds 57 // the range lease for the first range. 58 KeySentinel = "sentinel" 59 60 // KeyFirstRangeDescriptor is the descriptor for the "first" 61 // range. The "first" range contains the meta1 key range, the first 62 // level of the bi-level key addressing scheme. The value is a slice 63 // of storage.Replica structs. 64 KeyFirstRangeDescriptor = "first-range" 65 66 // KeySystemConfig is the gossip key for the system DB span. 67 // The value if a config.SystemConfig which holds all key/value 68 // pairs in the system DB span. 69 KeySystemConfig = "system-db" 70 71 // KeyDistSQLNodeVersionKeyPrefix is key prefix for each node's DistSQL 72 // version. 73 KeyDistSQLNodeVersionKeyPrefix = "distsql-version" 74 75 // KeyDistSQLDrainingPrefix is the key prefix for each node's DistSQL 76 // draining state. 77 KeyDistSQLDrainingPrefix = "distsql-draining" 78 79 // KeyTableStatAddedPrefix is the prefix for keys that indicate a new table 80 // statistic was computed. The statistics themselves are not stored in gossip; 81 // the keys are used to notify nodes to invalidate table statistic caches. 82 KeyTableStatAddedPrefix = "table-stat-added" 83 84 // KeyGossipClientsPrefix is the prefix for keys that indicate which gossip 85 // client connections a node has open. This is used by other nodes in the 86 // cluster to build a map of the gossip network. 87 KeyGossipClientsPrefix = "gossip-clients" 88 89 // KeyGossipStatementDiagnosticsRequest is the gossip key for new statement 90 // diagnostics requests. The values is the id of the request that generated 91 // the notification, as a little-endian-encoded uint64. 92 // stmtDiagnosticsRequestRegistry listens for notifications and responds by 93 // polling for new requests. 94 KeyGossipStatementDiagnosticsRequest = "stmt-diag-req" 95 ) 96 97 // MakeKey creates a canonical key under which to gossip a piece of 98 // information. The first argument will typically be one of the key constants 99 // defined in this package. 100 func MakeKey(components ...string) string { 101 return strings.Join(components, separator) 102 } 103 104 // MakePrefixPattern returns a regular expression pattern that 105 // matches precisely the Gossip keys created by invocations of 106 // MakeKey with multiple arguments for which the first argument 107 // is equal to the given prefix. 108 func MakePrefixPattern(prefix string) string { 109 return regexp.QuoteMeta(prefix+separator) + ".*" 110 } 111 112 // MakeNodeIDKey returns the gossip key for node ID info. 113 func MakeNodeIDKey(nodeID roachpb.NodeID) string { 114 return MakeKey(KeyNodeIDPrefix, nodeID.String()) 115 } 116 117 // IsNodeIDKey returns true iff the provided key is a valid node ID key. 118 func IsNodeIDKey(key string) bool { 119 return strings.HasPrefix(key, KeyNodeIDPrefix+separator) 120 } 121 122 // NodeIDFromKey attempts to extract a NodeID from the provided key after 123 // stripping the provided prefix. Returns an error if the key is not of the 124 // correct type or is not parsable. 125 func NodeIDFromKey(key string, prefix string) (roachpb.NodeID, error) { 126 trimmedKey, err := removePrefixFromKey(key, prefix) 127 if err != nil { 128 return 0, err 129 } 130 nodeID, err := strconv.ParseInt(trimmedKey, 10 /* base */, 64 /* bitSize */) 131 if err != nil { 132 return 0, errors.Wrapf(err, "failed parsing NodeID from key %q", key) 133 } 134 return roachpb.NodeID(nodeID), nil 135 } 136 137 // MakeGossipClientsKey returns the gossip client key for the given node. 138 func MakeGossipClientsKey(nodeID roachpb.NodeID) string { 139 return MakeKey(KeyGossipClientsPrefix, nodeID.String()) 140 } 141 142 // MakeNodeHealthAlertKey returns the gossip key under which the given node can 143 // gossip health alerts. 144 func MakeNodeHealthAlertKey(nodeID roachpb.NodeID) string { 145 return MakeKey(KeyNodeHealthAlertPrefix, strconv.Itoa(int(nodeID))) 146 } 147 148 // MakeNodeLivenessKey returns the gossip key for node liveness info. 149 func MakeNodeLivenessKey(nodeID roachpb.NodeID) string { 150 return MakeKey(KeyNodeLivenessPrefix, nodeID.String()) 151 } 152 153 // MakeStoreKey returns the gossip key for the given store. 154 func MakeStoreKey(storeID roachpb.StoreID) string { 155 return MakeKey(KeyStorePrefix, storeID.String()) 156 } 157 158 // StoreIDFromKey attempts to extract a StoreID from the provided key after 159 // stripping the provided prefix. Returns an error if the key is not of the 160 // correct type or is not parsable. 161 func StoreIDFromKey(storeKey string) (roachpb.StoreID, error) { 162 trimmedKey, err := removePrefixFromKey(storeKey, KeyStorePrefix) 163 if err != nil { 164 return 0, err 165 } 166 storeID, err := strconv.ParseInt(trimmedKey, 10 /* base */, 64 /* bitSize */) 167 if err != nil { 168 return 0, errors.Wrapf(err, "failed parsing StoreID from key %q", storeKey) 169 } 170 return roachpb.StoreID(storeID), nil 171 } 172 173 // MakeDistSQLNodeVersionKey returns the gossip key for the given store. 174 func MakeDistSQLNodeVersionKey(nodeID roachpb.NodeID) string { 175 return MakeKey(KeyDistSQLNodeVersionKeyPrefix, nodeID.String()) 176 } 177 178 // MakeDistSQLDrainingKey returns the gossip key for the given node's distsql 179 // draining state. 180 func MakeDistSQLDrainingKey(nodeID roachpb.NodeID) string { 181 return MakeKey(KeyDistSQLDrainingPrefix, nodeID.String()) 182 } 183 184 // MakeTableStatAddedKey returns the gossip key used to notify that a new 185 // statistic is available for the given table. 186 func MakeTableStatAddedKey(tableID uint32) string { 187 return MakeKey(KeyTableStatAddedPrefix, strconv.FormatUint(uint64(tableID), 10 /* base */)) 188 } 189 190 // TableIDFromTableStatAddedKey attempts to extract the table ID from the 191 // provided key. 192 // The key should have been constructed by MakeTableStatAddedKey. 193 // Returns an error if the key is not of the correct type or is not parsable. 194 func TableIDFromTableStatAddedKey(key string) (uint32, error) { 195 trimmedKey, err := removePrefixFromKey(key, KeyTableStatAddedPrefix) 196 if err != nil { 197 return 0, err 198 } 199 tableID, err := strconv.ParseUint(trimmedKey, 10 /* base */, 32 /* bitSize */) 200 if err != nil { 201 return 0, errors.Wrapf(err, "failed parsing table ID from key %q", key) 202 } 203 return uint32(tableID), nil 204 } 205 206 // removePrefixFromKey removes the key prefix and separator and returns what's 207 // left. Returns an error if the key doesn't have this prefix. 208 func removePrefixFromKey(key, prefix string) (string, error) { 209 trimmedKey := strings.TrimPrefix(key, prefix+separator) 210 if trimmedKey == key { 211 return "", errors.Errorf("%q does not have expected prefix %q%s", key, prefix, separator) 212 } 213 return trimmedKey, nil 214 }