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