github.com/matrixorigin/matrixone@v1.2.0/pkg/tests/service/cnservice.go (about) 1 // Copyright 2022 Matrix Origin 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package service 16 17 import ( 18 "context" 19 "fmt" 20 "strconv" 21 "sync" 22 "time" 23 24 "github.com/google/uuid" 25 "github.com/matrixorigin/matrixone/pkg/bootstrap" 26 "github.com/matrixorigin/matrixone/pkg/cnservice" 27 "github.com/matrixorigin/matrixone/pkg/config" 28 "github.com/matrixorigin/matrixone/pkg/fileservice" 29 "github.com/matrixorigin/matrixone/pkg/taskservice" 30 "github.com/matrixorigin/matrixone/pkg/tests" 31 "github.com/matrixorigin/matrixone/pkg/util/executor" 32 ) 33 34 // CNService describes expected behavior for tn service. 35 type CNService interface { 36 // Start sends heartbeat and start to handle command. 37 Start() error 38 // Close stops store 39 Close() error 40 // Status returns the status of service. 41 Status() ServiceStatus 42 43 // ID returns uuid of store 44 ID() string 45 // SQLAddress returns the sql listen address 46 SQLAddress() string 47 //GetTaskRunner returns the taskRunner. 48 GetTaskRunner() taskservice.TaskRunner 49 // GetTaskService returns the taskservice 50 GetTaskService() (taskservice.TaskService, bool) 51 // GetSQLExecutor returns sql executor 52 GetSQLExecutor() executor.SQLExecutor 53 // GetBootstrapService returns bootstrap service 54 GetBootstrapService() bootstrap.Service 55 //SetCancel sets CancelFunc to stop GetClusterDetailsFromHAKeeper 56 SetCancel(context.CancelFunc) 57 } 58 59 // cnService wraps cnservice.Service. 60 // 61 // The main purpose of this structure is to maintain status. 62 type cnService struct { 63 sync.Mutex 64 status ServiceStatus 65 svc cnservice.Service 66 cfg *cnservice.Config 67 68 cancel context.CancelFunc 69 } 70 71 func (c *cnService) Start() error { 72 c.Lock() 73 defer c.Unlock() 74 75 if c.status == ServiceInitialized { 76 err := c.svc.Start() 77 if err != nil { 78 return err 79 } 80 c.status = ServiceStarted 81 } 82 83 return nil 84 } 85 86 func (c *cnService) Close() error { 87 c.Lock() 88 defer c.Unlock() 89 90 if c.status == ServiceStarted { 91 err := c.svc.Close() 92 c.cancel() 93 if err != nil { 94 return err 95 } 96 c.status = ServiceClosed 97 } 98 99 return nil 100 } 101 102 func (c *cnService) Status() ServiceStatus { 103 c.Lock() 104 defer c.Unlock() 105 106 return c.status 107 } 108 109 func (c *cnService) ID() string { 110 c.Lock() 111 defer c.Unlock() 112 113 return c.cfg.UUID 114 } 115 116 func (c *cnService) SQLAddress() string { 117 return fmt.Sprintf("127.0.0.1:%d", c.cfg.Frontend.Port) 118 } 119 120 func (c *cnService) GetTaskRunner() taskservice.TaskRunner { 121 return c.svc.GetTaskRunner() 122 } 123 124 func (c *cnService) GetTaskService() (taskservice.TaskService, bool) { 125 return c.svc.GetTaskService() 126 } 127 128 func (c *cnService) GetSQLExecutor() executor.SQLExecutor { 129 return c.svc.GetSQLExecutor() 130 } 131 132 func (c *cnService) GetBootstrapService() bootstrap.Service { 133 return c.svc.GetBootstrapService() 134 } 135 136 func (c *cnService) SetCancel(cancel context.CancelFunc) { 137 c.cancel = cancel 138 } 139 140 // cnOptions is options for a cn service. 141 type cnOptions []cnservice.Option 142 143 // newCNService initializes an instance of `CNService`. 144 func newCNService( 145 cfg *cnservice.Config, 146 ctx context.Context, 147 fileService fileservice.FileService, 148 options cnOptions, 149 ) (CNService, error) { 150 srv, err := cnservice.NewService(cfg, ctx, fileService, nil, options...) 151 if err != nil { 152 return nil, err 153 } 154 155 return &cnService{ 156 status: ServiceInitialized, 157 svc: srv, 158 cfg: cfg, 159 }, nil 160 } 161 162 func buildCNConfig(index int, opt Options, address *serviceAddresses) *cnservice.Config { 163 port, err := tests.GetAvailablePort("127.0.0.1") 164 if err != nil { 165 panic(err) 166 } 167 p, err := strconv.Atoi(port) 168 if err != nil { 169 panic(err) 170 } 171 uid, _ := uuid.NewV7() 172 cfg := &cnservice.Config{ 173 UUID: uid.String(), 174 ListenAddress: address.getCNListenAddress(index), 175 ServiceAddress: address.getCNListenAddress(index), 176 SQLAddress: fmt.Sprintf("127.0.0.1:%d", p), 177 Frontend: config.FrontendParameters{ 178 Port: int64(p), 179 }, 180 } 181 cfg.HAKeeper.ClientConfig.ServiceAddresses = address.listHAKeeperListenAddresses() 182 cfg.HAKeeper.HeatbeatInterval.Duration = opt.heartbeat.cn 183 cfg.Engine.Type = opt.storage.cnEngine 184 cfg.TaskRunner.Parallelism = 4 185 cfg.LockService.ListenAddress = address.getCNLockListenAddress(index) 186 cfg.LockService.ServiceAddress = cfg.LockService.ListenAddress 187 cfg.LockService.KeepBindTimeout.Duration = time.Second * 30 188 cfg.QueryServiceConfig.Address.ListenAddress = address.getCNQueryListenAddress(index) 189 cfg.QueryServiceConfig.Address.ServiceAddress = cfg.QueryServiceConfig.Address.ListenAddress 190 191 // We need the filled version of configuration. 192 // It's necessary when building cnservice.Option. 193 if err := cfg.Validate(); err != nil { 194 panic(fmt.Sprintf("fatal when building cnservice.Config: %s", err)) 195 } 196 197 return cfg 198 }