github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/logstore/driver/logservicedriver/driver.go (about)

     1  // Copyright 2021 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 logservicedriver
    16  
    17  import (
    18  	"context"
    19  	"time"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    22  	"github.com/matrixorigin/matrixone/pkg/logutil"
    23  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    24  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logstore/driver"
    25  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logstore/sm"
    26  	"github.com/panjf2000/ants/v2"
    27  )
    28  
    29  const (
    30  	ReplayReadSize = mpool.MB * 64
    31  	MaxReadSize    = mpool.MB * 64
    32  )
    33  
    34  func RetryWithTimeout(timeoutDuration time.Duration, fn func() (shouldReturn bool)) error {
    35  	ctx, cancel := context.WithTimeout(context.Background(), timeoutDuration)
    36  	defer cancel()
    37  	for {
    38  		select {
    39  		case <-ctx.Done():
    40  			return ErrRetryTimeOut
    41  		default:
    42  			if fn() {
    43  				return nil
    44  			}
    45  		}
    46  	}
    47  }
    48  
    49  type LogServiceDriver struct {
    50  	clientPool *clientpool
    51  	config     *Config
    52  	appendable *driverAppender
    53  	*driverInfo
    54  	*readCache
    55  
    56  	closeCtx        context.Context
    57  	closeCancel     context.CancelFunc
    58  	preAppendLoop   sm.Queue
    59  	appendQueue     chan any
    60  	appendedQueue   chan any
    61  	appendedLoop    *sm.Loop
    62  	postAppendQueue chan any
    63  	postAppendLoop  *sm.Loop
    64  
    65  	appendPool *ants.Pool
    66  
    67  	truncateQueue sm.Queue
    68  
    69  	flushtimes  int
    70  	appendtimes int
    71  
    72  	readDuration time.Duration
    73  }
    74  
    75  func NewLogServiceDriver(cfg *Config) *LogServiceDriver {
    76  	clientpoolConfig := &clientConfig{
    77  		cancelDuration:        cfg.NewClientDuration,
    78  		recordSize:            cfg.RecordSize,
    79  		clientFactory:         cfg.ClientFactory,
    80  		GetClientRetryTimeOut: cfg.GetClientRetryTimeOut,
    81  		retryDuration:         cfg.RetryTimeout,
    82  	}
    83  
    84  	// the tasks submitted to LogServiceDriver.appendPool append entries to logservice,
    85  	// and we hope the task will crash all the tn service if append failed.
    86  	// so, set panic to pool.options.PanicHandler here, or it will only crash
    87  	// the goroutine the append task belongs to.
    88  	pool, _ := ants.NewPool(cfg.ClientMaxCount, ants.WithPanicHandler(func(v interface{}) {
    89  		panic(v)
    90  	}))
    91  
    92  	d := &LogServiceDriver{
    93  		clientPool:      newClientPool(cfg.ClientMaxCount, clientpoolConfig),
    94  		config:          cfg,
    95  		appendable:      newDriverAppender(),
    96  		driverInfo:      newDriverInfo(),
    97  		readCache:       newReadCache(),
    98  		appendQueue:     make(chan any, 10000),
    99  		appendedQueue:   make(chan any, 10000),
   100  		postAppendQueue: make(chan any, 10000),
   101  		appendPool:      pool,
   102  	}
   103  	d.closeCtx, d.closeCancel = context.WithCancel(context.Background())
   104  	d.preAppendLoop = sm.NewSafeQueue(10000, 10000, d.onPreAppend)
   105  	d.preAppendLoop.Start()
   106  	d.appendedLoop = sm.NewLoop(d.appendedQueue, d.postAppendQueue, d.onAppendedQueue, 10000)
   107  	d.appendedLoop.Start()
   108  	d.postAppendLoop = sm.NewLoop(d.postAppendQueue, nil, d.onPostAppendQueue, 10000)
   109  	d.postAppendLoop.Start()
   110  	d.truncateQueue = sm.NewSafeQueue(10000, 10000, d.onTruncate)
   111  	d.truncateQueue.Start()
   112  	return d
   113  }
   114  
   115  func (d *LogServiceDriver) Close() error {
   116  	logutil.Infof("append%d,flush%d", d.appendtimes, d.flushtimes)
   117  	d.clientPool.Close()
   118  	d.closeCancel()
   119  	d.preAppendLoop.Stop()
   120  	d.appendedLoop.Stop()
   121  	d.postAppendLoop.Stop()
   122  	d.truncateQueue.Stop()
   123  	close(d.appendQueue)
   124  	close(d.appendedQueue)
   125  	close(d.postAppendQueue)
   126  	d.appendPool.Release()
   127  	return nil
   128  }
   129  
   130  func (d *LogServiceDriver) Replay(h driver.ApplyHandle) error {
   131  	d.PreReplay()
   132  	r := newReplayer(h, ReplayReadSize, d)
   133  	r.replay()
   134  	d.onReplay(r)
   135  	r.d.resetReadCache()
   136  	d.PostReplay()
   137  	logutil.Info("open-tae", common.OperationField("replay"),
   138  		common.OperandField("wal"),
   139  		common.AnyField("backend", "logservice"),
   140  		common.AnyField("apply cost", r.applyDuration),
   141  		common.AnyField("read cost", d.readDuration),
   142  		common.AnyField("read count", r.readCount),
   143  		common.AnyField("internal count", r.internalCount),
   144  		common.AnyField("apply count", r.applyCount),
   145  	)
   146  
   147  	return nil
   148  }