github.com/matrixorigin/matrixone@v1.2.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/fileservice"
    30  	"github.com/matrixorigin/matrixone/pkg/logservice"
    31  	"github.com/matrixorigin/matrixone/pkg/pb/metadata"
    32  	"github.com/matrixorigin/matrixone/pkg/taskservice"
    33  	"github.com/matrixorigin/matrixone/pkg/tnservice"
    34  	"github.com/matrixorigin/matrixone/pkg/util/toml"
    35  )
    36  
    37  // TNService describes expected behavior for tn service.
    38  type TNService 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  	// StartTNReplica start the TNShard replica
    50  	StartTNReplica(shard metadata.TNShard) error
    51  	// CloseTNReplica close the TNShard replica.
    52  	CloseTNReplica(shard metadata.TNShard) error
    53  
    54  	// GetTaskService returns the taskservice
    55  	GetTaskService() (taskservice.TaskService, bool)
    56  }
    57  
    58  // tnService wraps tnservice.Service.
    59  //
    60  // The main purpose of this structure is to maintain status.
    61  type tnService struct {
    62  	sync.Mutex
    63  	status ServiceStatus
    64  	uuid   string
    65  	svc    tnservice.Service
    66  }
    67  
    68  func (ds *tnService) 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 *tnService) 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 *tnService) Status() ServiceStatus {
    99  	ds.Lock()
   100  	defer ds.Unlock()
   101  	return ds.status
   102  }
   103  
   104  func (ds *tnService) ID() string {
   105  	ds.Lock()
   106  	defer ds.Unlock()
   107  	return ds.uuid
   108  }
   109  
   110  func (ds *tnService) StartTNReplica(shard metadata.TNShard) 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.StartTNReplica(shard)
   119  }
   120  
   121  func (ds *tnService) CloseTNReplica(shard metadata.TNShard) 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.CloseTNReplica(shard)
   130  }
   131  
   132  func (ds *tnService) GetTaskService() (taskservice.TaskService, bool) {
   133  	return ds.svc.GetTaskService()
   134  }
   135  
   136  // tnOptions is options for a tn service.
   137  type tnOptions []tnservice.Option
   138  
   139  // newTNService initializes an instance of `TNService`.
   140  func newTNService(
   141  	cfg *tnservice.Config,
   142  	rt runtime.Runtime,
   143  	fs fileservice.FileService,
   144  	opts tnOptions,
   145  ) (TNService, error) {
   146  	svc, err := tnservice.NewService(cfg, rt, fs, nil, opts...)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	return &tnService{
   151  		status: ServiceInitialized,
   152  		uuid:   cfg.UUID,
   153  		svc:    svc,
   154  	}, nil
   155  }
   156  
   157  // buildTNConfig builds configuration for a tn service.
   158  func buildTNConfig(
   159  	index int, opt Options, address *serviceAddresses,
   160  ) *tnservice.Config {
   161  	uid, _ := uuid.NewV7()
   162  	cfg := &tnservice.Config{
   163  		UUID:          uid.String(),
   164  		ListenAddress: address.getTnListenAddress(index),
   165  	}
   166  	cfg.ServiceAddress = cfg.ListenAddress
   167  	cfg.LogtailServer.ListenAddress = address.getTnLogtailAddress(index)
   168  	cfg.LogtailServer.ServiceAddress = cfg.LogtailServer.ListenAddress
   169  	cfg.LockService.ListenAddress = address.getTNLockListenAddress(index)
   170  	cfg.LockService.ServiceAddress = cfg.LockService.ListenAddress
   171  	cfg.LockService.KeepBindTimeout.Duration = time.Second * 30
   172  	cfg.DataDir = filepath.Join(opt.rootDataDir, cfg.UUID)
   173  	cfg.HAKeeper.ClientConfig.ServiceAddresses = address.listHAKeeperListenAddresses()
   174  	cfg.HAKeeper.HeatbeatInterval.Duration = opt.heartbeat.tn
   175  	cfg.Txn.Storage.Backend = opt.storage.tnStorage
   176  
   177  	// FIXME: disable tae flush
   178  	cfg.Ckp.MinCount = 2000000
   179  	cfg.Ckp.FlushInterval.Duration = time.Second * 100000
   180  	cfg.Ckp.ScanInterval.Duration = time.Second * 100000
   181  	cfg.Ckp.IncrementalInterval.Duration = time.Second * 100000
   182  	cfg.Ckp.GlobalMinCount = 10000
   183  
   184  	// logtail push service config for tae storage
   185  	cfg.LogtailServer.RpcMaxMessageSize = toml.ByteSize(opt.logtailPushServer.rpcMaxMessageSize)
   186  	cfg.LogtailServer.LogtailCollectInterval.Duration = opt.logtailPushServer.logtailCollectInterval
   187  	cfg.LogtailServer.LogtailRPCStreamPoisonTime.Duration = opt.logtailPushServer.logtailRPCStreamPoisonTIme
   188  	cfg.LogtailServer.LogtailResponseSendTimeout.Duration = opt.logtailPushServer.logtailResponseSendTimeout
   189  
   190  	// We need the filled version of configuration.
   191  	// It's necessary when building tnservice.Option.
   192  	if err := cfg.Validate(); err != nil {
   193  		panic(fmt.Sprintf("fatal when building tnservice.Config: %s", err))
   194  	}
   195  
   196  	return cfg
   197  }
   198  
   199  // buildTNOptions builds options for a tn service.
   200  //
   201  // NB: We need the filled version of tnservice.Config.
   202  func buildTNOptions(cfg *tnservice.Config, filter FilterFunc) tnOptions {
   203  	// factory to construct client for hakeeper
   204  	hakeeperClientFactory := func() (logservice.TNHAKeeperClient, error) {
   205  		ctx, cancel := context.WithTimeout(
   206  			context.Background(), cfg.HAKeeper.DiscoveryTimeout.Duration,
   207  		)
   208  		defer cancel()
   209  
   210  		// transfer morpc.BackendOption via context
   211  		ctx = logservice.SetBackendOptions(ctx, morpc.WithBackendFilter(filter))
   212  
   213  		client, err := logservice.NewTNHAKeeperClient(
   214  			ctx, cfg.HAKeeper.ClientConfig,
   215  		)
   216  		if err != nil {
   217  			return nil, err
   218  		}
   219  		return client, nil
   220  	}
   221  
   222  	// factory to construct client for log service
   223  	logServiceClientFactory := func(shard metadata.TNShard) (logservice.Client, error) {
   224  		ctx, cancel := context.WithTimeout(
   225  			context.Background(), cfg.LogService.ConnectTimeout.Duration,
   226  		)
   227  		defer cancel()
   228  
   229  		// transfer morpc.BackendOption via context
   230  		ctx = logservice.SetBackendOptions(ctx, morpc.WithBackendFilter(filter))
   231  
   232  		return logservice.NewClient(ctx, logservice.ClientConfig{
   233  			Tag:              "Test-TN",
   234  			ReadOnly:         false,
   235  			LogShardID:       shard.LogShardID,
   236  			TNReplicaID:      shard.ReplicaID,
   237  			ServiceAddresses: cfg.HAKeeper.ClientConfig.ServiceAddresses,
   238  		})
   239  	}
   240  
   241  	return []tnservice.Option{
   242  		tnservice.WithHAKeeperClientFactory(hakeeperClientFactory),
   243  		tnservice.WithLogServiceClientFactory(logServiceClientFactory),
   244  		tnservice.WithBackendFilter(filter),
   245  	}
   246  }