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  }