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  }