github.com/matrixorigin/matrixone@v1.2.0/pkg/hakeeper/operator/controller.go (about) 1 // Copyright 2020 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 // Portions of this file are additionally subject to the following 15 // copyright. 16 // 17 // Copyright (C) 2021 Matrix Origin. 18 // 19 // Modified the behavior of the operator controller. 20 21 package operator 22 23 import ( 24 "github.com/matrixorigin/matrixone/pkg/catalog" 25 pb "github.com/matrixorigin/matrixone/pkg/pb/logservice" 26 ) 27 28 // Controller is used to manage operators. 29 type Controller struct { 30 // operators is a map from shardID to its operators. 31 operators map[uint64][]*Operator 32 } 33 34 func NewController() *Controller { 35 return &Controller{ 36 operators: make(map[uint64][]*Operator), 37 } 38 } 39 40 // RemoveOperator removes an operator from the operators. 41 func (c *Controller) RemoveOperator(op *Operator) bool { 42 removed := c.removeOperator(op) 43 if removed { 44 _ = op.Cancel() 45 } 46 return removed 47 } 48 49 func (c *Controller) removeOperator(op *Operator) bool { 50 for i, curOp := range c.operators[op.shardID] { 51 if curOp == op { 52 c.operators[op.shardID] = append(c.operators[op.shardID][:i], c.operators[op.shardID][i+1:]...) 53 if len(c.operators[op.shardID]) == 0 { 54 delete(c.operators, op.shardID) 55 } 56 return true 57 } 58 } 59 return false 60 } 61 62 // GetOperators gets operators from the given shard. 63 func (c *Controller) GetOperators(shardID uint64) []*Operator { 64 return c.operators[shardID] 65 } 66 67 type ExecutingReplicas struct { 68 Adding map[uint64][]uint64 69 Removing map[uint64][]uint64 70 Starting map[uint64][]uint64 71 } 72 73 func (c *Controller) GetExecutingReplicas() ExecutingReplicas { 74 executing := ExecutingReplicas{ 75 Adding: make(map[uint64][]uint64), 76 Removing: make(map[uint64][]uint64), 77 Starting: make(map[uint64][]uint64), 78 } 79 for shardID, operators := range c.operators { 80 for _, op := range operators { 81 for _, step := range op.steps { 82 switch step := step.(type) { 83 case RemoveLogService: 84 executing.Removing[shardID] = append(executing.Removing[shardID], step.ReplicaID) 85 case AddLogService: 86 executing.Adding[shardID] = append(executing.Adding[shardID], step.ReplicaID) 87 case StartLogService: 88 executing.Starting[shardID] = append(executing.Starting[shardID], step.ReplicaID) 89 } 90 } 91 } 92 } 93 return executing 94 } 95 96 func (c *Controller) RemoveFinishedOperator( 97 logState pb.LogState, tnState pb.TNState, cnState pb.CNState, proxyState pb.ProxyState, 98 ) { 99 for _, ops := range c.operators { 100 for _, op := range ops { 101 op.Check(logState, tnState, cnState, proxyState) 102 switch op.Status() { 103 case SUCCESS, EXPIRED: 104 c.RemoveOperator(op) 105 } 106 } 107 } 108 } 109 110 func (c *Controller) Dispatch(ops []*Operator, logState pb.LogState, 111 tnState pb.TNState, cnState pb.CNState, proxyState pb.ProxyState) (commands []pb.ScheduleCommand) { 112 for _, op := range ops { 113 c.operators[op.shardID] = append(c.operators[op.shardID], op) 114 if step := op.Check(logState, tnState, cnState, proxyState); step != nil { 115 commands = append(commands, generateScheduleCommand(step)) 116 } 117 } 118 return 119 } 120 121 func generateScheduleCommand(step OpStep) pb.ScheduleCommand { 122 switch st := step.(type) { 123 case AddLogService: 124 return addLogService(st) 125 case RemoveLogService: 126 return removeLogService(st) 127 case StartLogService: 128 return startLogService(st) 129 case StopLogService: 130 return stopLogService(st) 131 case KillLogZombie: 132 return killLogZombie(st) 133 case AddTnReplica: 134 return addTnReplica(st) 135 case RemoveTnReplica: 136 return removeTnReplica(st) 137 case StopTnStore: 138 return stopTnStore(st) 139 case StopLogStore: 140 return stopLogStore(st) 141 case CreateTaskService: 142 return createTaskService(st) 143 case DeleteCNStore: 144 return deleteCNStore(st) 145 case JoinGossipCluster: 146 return joinGossipCluster(st) 147 case DeleteProxyStore: 148 return deleteProxyStore(st) 149 } 150 panic("invalid schedule command") 151 } 152 153 func addLogService(st AddLogService) pb.ScheduleCommand { 154 return pb.ScheduleCommand{ 155 UUID: st.Target, 156 ConfigChange: &pb.ConfigChange{ 157 Replica: pb.Replica{ 158 UUID: st.UUID, 159 ShardID: st.ShardID, 160 ReplicaID: st.ReplicaID, 161 Epoch: st.Epoch, 162 }, 163 ChangeType: pb.AddReplica, 164 }, 165 ServiceType: pb.LogService, 166 } 167 } 168 169 func removeLogService(st RemoveLogService) pb.ScheduleCommand { 170 return pb.ScheduleCommand{ 171 UUID: st.Target, 172 ConfigChange: &pb.ConfigChange{ 173 Replica: pb.Replica{ 174 UUID: st.UUID, 175 ShardID: st.ShardID, 176 ReplicaID: st.ReplicaID, 177 Epoch: st.Epoch, 178 }, 179 ChangeType: pb.RemoveReplica, 180 }, 181 ServiceType: pb.LogService, 182 } 183 } 184 185 func startLogService(st StartLogService) pb.ScheduleCommand { 186 return pb.ScheduleCommand{ 187 UUID: st.UUID, 188 ConfigChange: &pb.ConfigChange{ 189 Replica: pb.Replica{ 190 UUID: st.UUID, 191 ShardID: st.ShardID, 192 ReplicaID: st.ReplicaID, 193 }, 194 ChangeType: pb.StartReplica, 195 }, 196 ServiceType: pb.LogService, 197 } 198 } 199 200 func stopLogService(st StopLogService) pb.ScheduleCommand { 201 return pb.ScheduleCommand{ 202 UUID: st.UUID, 203 ConfigChange: &pb.ConfigChange{ 204 Replica: pb.Replica{ 205 UUID: st.UUID, 206 ShardID: st.ShardID, 207 Epoch: st.Epoch, 208 }, 209 ChangeType: pb.RemoveReplica, 210 }, 211 ServiceType: pb.LogService, 212 } 213 } 214 215 func killLogZombie(st KillLogZombie) pb.ScheduleCommand { 216 return pb.ScheduleCommand{ 217 UUID: st.UUID, 218 Bootstrapping: false, 219 ConfigChange: &pb.ConfigChange{ 220 Replica: pb.Replica{ 221 UUID: st.UUID, 222 ShardID: st.ShardID, 223 ReplicaID: st.ReplicaID, 224 }, 225 ChangeType: pb.KillZombie, 226 }, 227 ServiceType: pb.LogService, 228 } 229 } 230 231 func addTnReplica(st AddTnReplica) pb.ScheduleCommand { 232 return pb.ScheduleCommand{ 233 UUID: st.StoreID, 234 ConfigChange: &pb.ConfigChange{ 235 Replica: pb.Replica{ 236 UUID: st.StoreID, 237 ShardID: st.ShardID, 238 ReplicaID: st.ReplicaID, 239 LogShardID: st.LogShardID, 240 }, 241 ChangeType: pb.StartReplica, 242 }, 243 ServiceType: pb.TNService, 244 } 245 } 246 247 func removeTnReplica(st RemoveTnReplica) pb.ScheduleCommand { 248 return pb.ScheduleCommand{ 249 UUID: st.StoreID, 250 ConfigChange: &pb.ConfigChange{ 251 Replica: pb.Replica{ 252 UUID: st.StoreID, 253 ShardID: st.ShardID, 254 ReplicaID: st.ReplicaID, 255 LogShardID: st.LogShardID, 256 }, 257 ChangeType: pb.StopReplica, 258 }, 259 ServiceType: pb.TNService, 260 } 261 } 262 263 func stopTnStore(st StopTnStore) pb.ScheduleCommand { 264 return pb.ScheduleCommand{ 265 UUID: st.StoreID, 266 ShutdownStore: &pb.ShutdownStore{ 267 StoreID: st.StoreID, 268 }, 269 ServiceType: pb.TNService, 270 } 271 } 272 273 func stopLogStore(st StopLogStore) pb.ScheduleCommand { 274 return pb.ScheduleCommand{ 275 UUID: st.StoreID, 276 ShutdownStore: &pb.ShutdownStore{ 277 StoreID: st.StoreID, 278 }, 279 ServiceType: pb.LogService, 280 } 281 } 282 283 func createTaskService(st CreateTaskService) pb.ScheduleCommand { 284 return pb.ScheduleCommand{ 285 UUID: st.StoreID, 286 ServiceType: st.StoreType, 287 CreateTaskService: &pb.CreateTaskService{ 288 User: st.TaskUser, 289 TaskDatabase: catalog.MOTaskDB, 290 }, 291 } 292 } 293 294 func deleteCNStore(st DeleteCNStore) pb.ScheduleCommand { 295 return pb.ScheduleCommand{ 296 UUID: st.StoreID, 297 ServiceType: pb.CNService, 298 DeleteCNStore: &pb.DeleteCNStore{ 299 StoreID: st.StoreID, 300 }, 301 } 302 } 303 304 func joinGossipCluster(st JoinGossipCluster) pb.ScheduleCommand { 305 return pb.ScheduleCommand{ 306 UUID: st.StoreID, 307 ServiceType: pb.CNService, 308 JoinGossipCluster: &pb.JoinGossipCluster{ 309 Existing: st.Existing, 310 }, 311 } 312 } 313 314 func deleteProxyStore(st DeleteProxyStore) pb.ScheduleCommand { 315 return pb.ScheduleCommand{ 316 UUID: st.StoreID, 317 ServiceType: pb.ProxyService, 318 DeleteProxyStore: &pb.DeleteProxyStore{ 319 StoreID: st.StoreID, 320 }, 321 } 322 }