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  }