github.com/matrixorigin/matrixone@v0.7.0/pkg/tests/service/dnservice.go (about) 1 // Copyright 2021 - 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 "path/filepath" 21 "sync" 22 "time" 23 24 "github.com/google/uuid" 25 26 "github.com/matrixorigin/matrixone/pkg/common/moerr" 27 "github.com/matrixorigin/matrixone/pkg/common/morpc" 28 "github.com/matrixorigin/matrixone/pkg/common/runtime" 29 "github.com/matrixorigin/matrixone/pkg/dnservice" 30 "github.com/matrixorigin/matrixone/pkg/fileservice" 31 "github.com/matrixorigin/matrixone/pkg/logservice" 32 "github.com/matrixorigin/matrixone/pkg/pb/metadata" 33 "github.com/matrixorigin/matrixone/pkg/taskservice" 34 "github.com/matrixorigin/matrixone/pkg/util/toml" 35 ) 36 37 // DNService describes expected behavior for dn service. 38 type DNService interface { 39 // Start sends heartbeat and start to handle command. 40 Start() error 41 // Close stops store 42 Close() error 43 // Status returns the status of service. 44 Status() ServiceStatus 45 46 // ID returns uuid of store 47 ID() string 48 49 // StartDNReplica start the DNShard replica 50 StartDNReplica(shard metadata.DNShard) error 51 // CloseDNReplica close the DNShard replica. 52 CloseDNReplica(shard metadata.DNShard) error 53 54 // GetTaskService returns the taskservice 55 GetTaskService() (taskservice.TaskService, bool) 56 } 57 58 // dnService wraps dnservice.Service. 59 // 60 // The main purpose of this structure is to maintain status. 61 type dnService struct { 62 sync.Mutex 63 status ServiceStatus 64 uuid string 65 svc dnservice.Service 66 } 67 68 func (ds *dnService) Start() error { 69 ds.Lock() 70 defer ds.Unlock() 71 72 if ds.status == ServiceInitialized { 73 err := ds.svc.Start() 74 if err != nil { 75 return err 76 } 77 ds.status = ServiceStarted 78 } 79 80 return nil 81 } 82 83 func (ds *dnService) Close() error { 84 ds.Lock() 85 defer ds.Unlock() 86 87 if ds.status == ServiceStarted { 88 err := ds.svc.Close() 89 if err != nil { 90 return err 91 } 92 ds.status = ServiceClosed 93 } 94 95 return nil 96 } 97 98 func (ds *dnService) Status() ServiceStatus { 99 ds.Lock() 100 defer ds.Unlock() 101 return ds.status 102 } 103 104 func (ds *dnService) ID() string { 105 ds.Lock() 106 defer ds.Unlock() 107 return ds.uuid 108 } 109 110 func (ds *dnService) StartDNReplica(shard metadata.DNShard) error { 111 ds.Lock() 112 defer ds.Unlock() 113 114 if ds.status != ServiceStarted { 115 return moerr.NewNoServiceNoCtx(ds.uuid) 116 } 117 118 return ds.svc.StartDNReplica(shard) 119 } 120 121 func (ds *dnService) CloseDNReplica(shard metadata.DNShard) error { 122 ds.Lock() 123 defer ds.Unlock() 124 125 if ds.status != ServiceStarted { 126 return moerr.NewNoServiceNoCtx(ds.uuid) 127 } 128 129 return ds.svc.CloseDNReplica(shard) 130 } 131 132 func (ds *dnService) GetTaskService() (taskservice.TaskService, bool) { 133 return ds.svc.GetTaskService() 134 } 135 136 // dnOptions is options for a dn service. 137 type dnOptions []dnservice.Option 138 139 // newDNService initializes an instance of `DNService`. 140 func newDNService( 141 cfg *dnservice.Config, 142 rt runtime.Runtime, 143 fs fileservice.FileService, 144 opts dnOptions, 145 ) (DNService, error) { 146 svc, err := dnservice.NewService(cfg, rt, fs, opts...) 147 if err != nil { 148 return nil, err 149 } 150 return &dnService{ 151 status: ServiceInitialized, 152 uuid: cfg.UUID, 153 svc: svc, 154 }, nil 155 } 156 157 // buildDNConfig builds configuration for a dn service. 158 func buildDNConfig( 159 index int, opt Options, address serviceAddresses, 160 ) *dnservice.Config { 161 cfg := &dnservice.Config{ 162 UUID: uuid.New().String(), 163 ListenAddress: address.getDnListenAddress(index), 164 } 165 cfg.LogtailServer.ListenAddress = address.getDnLogtailAddress(index) 166 cfg.DataDir = filepath.Join(opt.rootDataDir, cfg.UUID) 167 cfg.HAKeeper.ClientConfig.ServiceAddresses = address.listHAKeeperListenAddresses() 168 cfg.HAKeeper.HeatbeatInterval.Duration = opt.heartbeat.dn 169 cfg.Txn.Storage.Backend = opt.storage.dnStorage 170 cfg.Txn.Storage.LogBackend = "logservice" 171 172 // FIXME: disable tae flush 173 cfg.Ckp.MinCount = 2000000 174 cfg.Ckp.FlushInterval.Duration = time.Second * 100000 175 cfg.Ckp.ScanInterval.Duration = time.Second * 100000 176 cfg.Ckp.IncrementalInterval.Duration = time.Second * 100000 177 cfg.Ckp.GlobalMinCount = 10000 178 179 // logtail push service config for tae storage 180 cfg.LogtailServer.RpcMaxMessageSize = toml.ByteSize(opt.logtailPushServer.rpcMaxMessageSize) 181 cfg.LogtailServer.RpcPayloadCopyBufferSize = toml.ByteSize(opt.logtailPushServer.rpcPayloadCopyBufferSize) 182 cfg.LogtailServer.LogtailCollectInterval.Duration = opt.logtailPushServer.logtailCollectInterval 183 cfg.LogtailServer.LogtailResponseSendTimeout.Duration = opt.logtailPushServer.logtailResponseSendTimeout 184 cfg.LogtailServer.MaxLogtailFetchFailure = opt.logtailPushServer.maxLogtailFetchFailure 185 186 // We need the filled version of configuration. 187 // It's necessary when building dnservice.Option. 188 if err := cfg.Validate(); err != nil { 189 panic(fmt.Sprintf("fatal when building dnservice.Config: %s", err)) 190 } 191 192 return cfg 193 } 194 195 // buildDNOptions builds options for a dn service. 196 // 197 // NB: We need the filled version of dnservice.Config. 198 func buildDNOptions(cfg *dnservice.Config, filter FilterFunc) dnOptions { 199 // factory to construct client for hakeeper 200 hakeeperClientFactory := func() (logservice.DNHAKeeperClient, error) { 201 ctx, cancel := context.WithTimeout( 202 context.Background(), cfg.HAKeeper.DiscoveryTimeout.Duration, 203 ) 204 defer cancel() 205 206 // transfer morpc.BackendOption via context 207 ctx = logservice.SetBackendOptions(ctx, morpc.WithBackendFilter(filter)) 208 209 client, err := logservice.NewDNHAKeeperClient( 210 ctx, cfg.HAKeeper.ClientConfig, 211 ) 212 if err != nil { 213 return nil, err 214 } 215 return client, nil 216 } 217 218 // factory to construct client for log service 219 logServiceClientFactory := func(shard metadata.DNShard) (logservice.Client, error) { 220 ctx, cancel := context.WithTimeout( 221 context.Background(), cfg.LogService.ConnectTimeout.Duration, 222 ) 223 defer cancel() 224 225 // transfer morpc.BackendOption via context 226 ctx = logservice.SetBackendOptions(ctx, morpc.WithBackendFilter(filter)) 227 228 return logservice.NewClient(ctx, logservice.ClientConfig{ 229 Tag: "Test-DN", 230 ReadOnly: false, 231 LogShardID: shard.LogShardID, 232 DNReplicaID: shard.ReplicaID, 233 ServiceAddresses: cfg.HAKeeper.ClientConfig.ServiceAddresses, 234 }) 235 } 236 237 return []dnservice.Option{ 238 dnservice.WithHAKeeperClientFactory(hakeeperClientFactory), 239 dnservice.WithLogServiceClientFactory(logServiceClientFactory), 240 dnservice.WithBackendFilter(filter), 241 } 242 }