github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/common/common.go (about) 1 // Copyright 2019 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package common 15 16 import ( 17 "encoding/hex" 18 "fmt" 19 "path" 20 "strings" 21 22 "github.com/pingcap/tiflow/dm/pkg/terror" 23 ) 24 25 var ( 26 useOfClosedErrMsg = "use of closed network connection" 27 // ClusterVersionKey is used to store the version of the cluster. 28 ClusterVersionKey = "/dm-cluster/version" 29 // ClusterIDKey is used to store the cluster id of the whole dm cluster. Cluster id is the unique identification of dm cluster 30 // After leader of dm master bootstraped, the leader will get the id from etcd or generate fresh one, and backfill to etcd. 31 ClusterIDKey = "/dm-cluster/id" 32 // ClusterTopologyKey is used to store the cluster topo info of the whole dm cluster, and this info is maintained by tiup. 33 ClusterTopologyKey = "/dm-cluster/topology" 34 // WorkerRegisterKeyAdapter is used to encode and decode register key. 35 // k/v: Encode(worker-name) -> the information of the DM-worker node. 36 WorkerRegisterKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-worker/r/") 37 // WorkerKeepAliveKeyAdapter is used to encode and decode keepalive key. 38 // k/v: Encode(worker-name) -> time. 39 WorkerKeepAliveKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-worker/a/") 40 // LoadTaskKeyAdapter is used to store the worker which in load stage for the source of the subtask. 41 // k/v: Encode(task, source-id) -> worker-name. 42 LoadTaskKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/load-task/") 43 // UpstreamConfigKeyAdapter stores all config of which MySQL-task has not stopped. 44 // k/v: Encode(source-id) -> config. 45 UpstreamConfigKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/v2/upstream/config/") 46 // UpstreamBoundWorkerKeyAdapter is used to store address of worker in which MySQL-tasks which are running. 47 // k/v: Encode(worker-name) -> the bound relationship. 48 UpstreamBoundWorkerKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/bound-worker/") 49 // UpstreamLastBoundWorkerKeyAdapter is used to store address of worker in which MySQL-tasks which are running. 50 // different with UpstreamBoundWorkerKeyAdapter, this kv should not be deleted when unbound, to provide a priority 51 // k/v: Encode(worker-name) -> the bound relationship. 52 UpstreamLastBoundWorkerKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/last-bound-worker/") 53 // UpstreamRelayWorkerKeyAdapter is used to store the upstream which this worker needs to pull relay log 54 // k/v: Encode(worker-name) -> source-id. 55 UpstreamRelayWorkerKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/relay-worker/") 56 // UpstreamSubTaskKeyAdapter is used to store SubTask which are subscribing data from MySQL source. 57 // k/v: Encode(source-id, task-name) -> SubTaskConfig. 58 UpstreamSubTaskKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/upstream/subtask/") 59 // StageRelayKeyAdapter is used to store the running stage of the relay. 60 // k/v: Encode(source-id) -> the running stage of the relay. 61 StageRelayKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/v2/stage/relay/") 62 // StageSubTaskKeyAdapter is used to store the running stage of the subtask. 63 // k/v: Encode(source-id, task-name) -> the running stage of the subtask. 64 StageSubTaskKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/stage/subtask/") 65 // StageValidatorKeyAdapter is used to store the running stage of the validator. 66 // k/v: Encode(source-id, task-name) -> the running stage of the validator. 67 StageValidatorKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/stage/validator/") 68 // LightningCoordinationKeyAdapter is used to store the coordination information of lightning. 69 // k/v: Encode(task-name, source-id) -> lightning status. 70 LightningCoordinationKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/lightning-coord/") 71 // ShardDDLPessimismInfoKeyAdapter is used to store shard DDL info in pessimistic model. 72 // k/v: Encode(task-name, source-id) -> shard DDL info. 73 ShardDDLPessimismInfoKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/shardddl-pessimism/info/") 74 // ShardDDLPessimismOperationKeyAdapter is used to store shard DDL operation in pessimistic model. 75 // k/v: Encode(task-name, source-id) -> shard DDL operation. 76 ShardDDLPessimismOperationKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/shardddl-pessimism/operation/") 77 78 // ShardDDLOptimismSourceTablesKeyAdapter is used to store INITIAL upstream schema & table names when starting the subtask. 79 // In other words, if any Info for this subtask exists, we should obey source tables in the Info. 80 // This is because the current upstream tables may not match the tables that the binlog stream has reached. 81 // k/v: Encode(task-name, source-id) -> upstream schema & table names. 82 ShardDDLOptimismSourceTablesKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/shardddl-optimism/source-tables/") 83 // ShardDDLOptimismInfoKeyAdapter is used to store shard DDL info in optimistic model. 84 // k/v: Encode(task-name, source-id, upstream-schema-name, upstream-table-name) -> shard DDL info. 85 ShardDDLOptimismInfoKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/shardddl-optimism/info/") 86 // ShardDDLOptimismOperationKeyAdapter is used to store shard DDL operation in optimistic model. 87 // k/v: Encode(task-name, source-id, upstream-schema-name, upstream-table-name) -> shard DDL operation. 88 ShardDDLOptimismOperationKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/shardddl-optimism/operation/") 89 // ShardDDLOptimismInitSchemaKeyAdapter is used to store the initial schema (before constructed the lock) of merged tables. 90 // k/v: Encode(task-name, downstream-schema-name, downstream-table-name) -> table schema. 91 // TODO: prune in etcd when upgrade 92 // ShardDDLOptimismInitSchemaKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/shardddl-optimism/init-schema/") 93 // ShardDDLOptimismDroppedColumnsKeyAdapter is used to store the columns that are not fully dropped 94 // k/v: Encode(lock-id, column-name, source-id, upstream-schema-name, upstream-table-name) -> int 95 // If we don't identify different upstream tables, we may report an error for tb2 in the following case. 96 // Time series: (+a/-a means add/drop column a) 97 // older ----------------> newer 98 // tb1: +a +b +c -c 99 // tb2: +a +b +c 100 // tb3: +a +b +c 101 ShardDDLOptimismDroppedColumnsKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/shardddl-optimism/dropped-columns/") 102 103 // OpenAPITaskTemplateKeyAdapter is used to store the openapi task-config-template (openapi.Task), now it's only used for WebUI. 104 // openapi.Task is a struct that can be converted to config.StubTaskConfig so if any field of openapi.Task updated 105 // user should use ha.PutOpenAPITaskTemplate(key, openapi.Task,overwrite) to force update the content in etcd. 106 // k/v: Encode(task-name) -> openapi.Task. 107 // task config template is used to generate task config before user create a real task by openapi. user can modify eg: 108 // import from running tasks/create/update/delete the template and those changes will not affect the running tasks. 109 OpenAPITaskTemplateKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/openapi-task-template/") 110 // TaskCliArgsKeyAdapter is used to store the command line arguments of task. They are different from the task 111 // config because the command line arguments may be expected to take effect only once when failover. 112 // kv: Encode(task-name, source-id) -> TaskCliArgs. 113 TaskCliArgsKeyAdapter KeyAdapter = keyHexEncoderDecoder("/dm-master/task-cli-args/") 114 ) 115 116 func keyAdapterKeysLen(s KeyAdapter) int { 117 switch s { 118 case WorkerRegisterKeyAdapter, UpstreamConfigKeyAdapter, UpstreamBoundWorkerKeyAdapter, 119 WorkerKeepAliveKeyAdapter, StageRelayKeyAdapter, 120 UpstreamLastBoundWorkerKeyAdapter, UpstreamRelayWorkerKeyAdapter, OpenAPITaskTemplateKeyAdapter: 121 return 1 122 case UpstreamSubTaskKeyAdapter, StageSubTaskKeyAdapter, StageValidatorKeyAdapter, 123 ShardDDLPessimismInfoKeyAdapter, ShardDDLPessimismOperationKeyAdapter, 124 ShardDDLOptimismSourceTablesKeyAdapter, LoadTaskKeyAdapter, TaskCliArgsKeyAdapter, 125 LightningCoordinationKeyAdapter: 126 return 2 127 case ShardDDLOptimismInfoKeyAdapter, ShardDDLOptimismOperationKeyAdapter: 128 return 4 129 case ShardDDLOptimismDroppedColumnsKeyAdapter: 130 return 5 131 // used in upgrading 132 case UpstreamConfigKeyAdapterV1, StageRelayKeyAdapterV1: 133 return 1 134 } 135 return -1 136 } 137 138 // IsErrNetClosing checks whether is an ErrNetClosing error. 139 func IsErrNetClosing(err error) bool { 140 if err == nil { 141 return false 142 } 143 return strings.Contains(err.Error(), useOfClosedErrMsg) 144 } 145 146 // KeyAdapter is used to construct etcd key. 147 type KeyAdapter interface { 148 // Encode returns a string encoded by given keys. 149 // If give all keys whose number is the same as specified in keyAdapterKeysLen, it returns a non `/` terminated 150 // string, and it should not be used with WithPrefix. 151 // If give not enough keys, it returns a `/` terminated string that could be used with WithPrefix. 152 Encode(keys ...string) string 153 Decode(key string) ([]string, error) 154 Path() string 155 } 156 157 type keyEncoderDecoder string 158 159 // always use keyHexEncoderDecoder to avoid `/` in keys. 160 type keyHexEncoderDecoder string 161 162 func (s keyEncoderDecoder) Encode(keys ...string) string { 163 t := []string{string(s)} 164 t = append(t, keys...) 165 return path.Join(t...) 166 } 167 168 func (s keyEncoderDecoder) Decode(key string) ([]string, error) { 169 v := strings.TrimPrefix(key, string(s)) 170 vals := strings.Split(v, "/") 171 if l := keyAdapterKeysLen(s); l != len(vals) { 172 return nil, terror.ErrDecodeEtcdKeyFail.Generate(fmt.Sprintf("decoder is %s, the key is %s", string(s), key)) 173 } 174 return vals, nil 175 } 176 177 func (s keyEncoderDecoder) Path() string { 178 return string(s) 179 } 180 181 func (s keyHexEncoderDecoder) Encode(keys ...string) string { 182 hexKeys := []string{string(s)} 183 for _, key := range keys { 184 hexKeys = append(hexKeys, hex.EncodeToString([]byte(key))) 185 } 186 ret := path.Join(hexKeys...) 187 if len(keys) < keyAdapterKeysLen(s) { 188 ret += "/" 189 } 190 return ret 191 } 192 193 func (s keyHexEncoderDecoder) Decode(key string) ([]string, error) { 194 if key[len(key)-1] == '/' { 195 key = key[:len(key)-1] 196 } 197 v := strings.Split(strings.TrimPrefix(key, string(s)), "/") 198 if l := keyAdapterKeysLen(s); l != len(v) { 199 return nil, terror.ErrDecodeEtcdKeyFail.Generate(fmt.Sprintf("decoder is %s, the key is %s", string(s), key)) 200 } 201 for i, k := range v { 202 dec, err := hex.DecodeString(k) 203 if err != nil { 204 return nil, terror.ErrDecodeEtcdKeyFail.Generate(err.Error()) 205 } 206 v[i] = string(dec) 207 } 208 return v, nil 209 } 210 211 func (s keyHexEncoderDecoder) Path() string { 212 return string(s) 213 } 214 215 // used in upgrade. 216 var ( 217 // UpstreamConfigKeyAdapterV1 stores all config of which MySQL-task has not stopped. 218 // k/v: Encode(source-id) -> config. 219 UpstreamConfigKeyAdapterV1 KeyAdapter = keyEncoderDecoder("/dm-master/upstream/config/") 220 // StageRelayKeyAdapterV1 is used to store the running stage of the relay. 221 // k/v: Encode(source-id) -> the running stage of the relay. 222 StageRelayKeyAdapterV1 KeyAdapter = keyEncoderDecoder("/dm-master/stage/relay/") 223 ) 224 225 // NoSubTaskMsg returns a formatted string for subtask not started. 226 func NoSubTaskMsg(name string) string { 227 return fmt.Sprintf("no sub task with name %s has started", name) 228 }