github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/logstore/driver/logservicedriver/replay.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  	"bytes"
    19  	"context"
    20  	"encoding/binary"
    21  	"fmt"
    22  	"io"
    23  	"math"
    24  	"time"
    25  
    26  	"github.com/matrixorigin/matrixone/pkg/logutil"
    27  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logstore/driver"
    28  )
    29  
    30  type replayer struct {
    31  	readMaxSize int
    32  
    33  	truncatedLogserviceLsn uint64
    34  
    35  	minDriverLsn uint64
    36  	maxDriverLsn uint64
    37  
    38  	driverLsnLogserviceLsnMap map[uint64]uint64 //start-lsn
    39  
    40  	replayHandle  driver.ApplyHandle
    41  	replayedLsn   uint64
    42  	inited        bool
    43  	safeLsn       uint64
    44  	nextToReadLsn uint64
    45  	d             *LogServiceDriver
    46  	appended      []uint64
    47  
    48  	applyDuration time.Duration
    49  }
    50  
    51  func newReplayer(h driver.ApplyHandle, readmaxsize int, d *LogServiceDriver) *replayer {
    52  	truncated := d.getLogserviceTruncate()
    53  	logutil.Infof("truncated %d", truncated)
    54  	return &replayer{
    55  		minDriverLsn:              math.MaxUint64,
    56  		driverLsnLogserviceLsnMap: make(map[uint64]uint64),
    57  		replayHandle:              h,
    58  		readMaxSize:               readmaxsize,
    59  		nextToReadLsn:             truncated + 1,
    60  		replayedLsn:               math.MaxUint64,
    61  		d:                         d,
    62  		appended:                  make([]uint64, 0),
    63  	}
    64  }
    65  
    66  func (r *replayer) replay() {
    67  	var err error
    68  	r.truncatedLogserviceLsn = r.d.getLogserviceTruncate()
    69  	for !r.readRecords() {
    70  		for r.replayedLsn < r.safeLsn {
    71  			err := r.replayLogserviceEntry(r.replayedLsn+1, true)
    72  			if err != nil {
    73  				panic(err)
    74  			}
    75  		}
    76  	}
    77  	err = r.replayLogserviceEntry(r.replayedLsn+1, false)
    78  	for err != ErrAllRecordsRead {
    79  		err = r.replayLogserviceEntry(r.replayedLsn+1, false)
    80  
    81  	}
    82  	r.d.lsns = make([]uint64, 0)
    83  }
    84  
    85  func (r *replayer) readRecords() (readEnd bool) {
    86  	nextLsn, safeLsn := r.d.readFromLogServiceInReplay(r.nextToReadLsn, r.readMaxSize, func(lsn uint64, record *recordEntry) {
    87  		if record.meta.metaType == TReplay {
    88  			cmd := NewEmptyReplayCmd()
    89  			cmd.Unmarshal(record.payload)
    90  			r.removeEntries(cmd.skipLsns)
    91  			return
    92  		}
    93  		drlsn := record.GetMinLsn()
    94  		r.driverLsnLogserviceLsnMap[drlsn] = lsn
    95  		if drlsn < r.replayedLsn {
    96  			if r.inited {
    97  				panic("logic err")
    98  			}
    99  			r.replayedLsn = drlsn - 1
   100  		}
   101  	})
   102  	if nextLsn == r.nextToReadLsn {
   103  		return true
   104  	}
   105  	r.nextToReadLsn = nextLsn
   106  	if safeLsn > r.safeLsn {
   107  		r.safeLsn = safeLsn
   108  	}
   109  	return false
   110  }
   111  func (r *replayer) removeEntries(skipMap map[uint64]uint64) {
   112  	for lsn := range skipMap {
   113  		if _, ok := r.driverLsnLogserviceLsnMap[lsn]; !ok {
   114  			panic(fmt.Sprintf("lsn %d not existed, map is %v", lsn, r.driverLsnLogserviceLsnMap))
   115  		}
   116  		delete(r.driverLsnLogserviceLsnMap, lsn)
   117  	}
   118  }
   119  func (r *replayer) replayLogserviceEntry(lsn uint64, safe bool) error {
   120  	logserviceLsn, ok := r.driverLsnLogserviceLsnMap[lsn]
   121  	if !ok {
   122  		if safe {
   123  			logutil.Infof("drlsn %d has been truncated", lsn)
   124  			r.minDriverLsn = lsn + 1
   125  			r.replayedLsn++
   126  			return nil
   127  		}
   128  		if len(r.driverLsnLogserviceLsnMap) == 0 {
   129  			return ErrAllRecordsRead
   130  		}
   131  		r.AppendSkipCmd(r.driverLsnLogserviceLsnMap)
   132  		logutil.Infof("skip lsns %v", r.driverLsnLogserviceLsnMap)
   133  		return ErrAllRecordsRead
   134  	}
   135  	record, err := r.d.readFromCache(logserviceLsn)
   136  	if err == ErrAllRecordsRead {
   137  		return err
   138  	}
   139  	if err != nil {
   140  		panic(err)
   141  	}
   142  	t0 := time.Now()
   143  	intervals := record.replay(r.replayHandle)
   144  	r.applyDuration += time.Since(t0)
   145  	r.d.onReplayRecordEntry(logserviceLsn, intervals)
   146  	r.onReplayDriverLsn(intervals.GetMax())
   147  	r.onReplayDriverLsn(intervals.GetMin())
   148  	r.d.dropRecordByLsn(logserviceLsn)
   149  	r.replayedLsn = record.GetMaxLsn()
   150  	r.inited = true
   151  	delete(r.driverLsnLogserviceLsnMap, lsn)
   152  	return nil
   153  }
   154  
   155  func (r *replayer) AppendSkipCmd(skipMap map[uint64]uint64) {
   156  	cmd := NewReplayCmd(skipMap)
   157  	recordEntry := newRecordEntry()
   158  	recordEntry.meta.metaType = TReplay
   159  	recordEntry.cmd = cmd
   160  	size := recordEntry.prepareRecord()
   161  	c, lsn := r.d.getClient()
   162  	r.appended = append(r.appended, lsn)
   163  	c.TryResize(size)
   164  	record := c.record
   165  	copy(record.Payload(), recordEntry.payload)
   166  	record.ResizePayload(size)
   167  	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
   168  	_, err := c.c.Append(ctx, c.record)
   169  	cancel()
   170  	if err != nil {
   171  		err = RetryWithTimeout(r.d.config.RetryTimeout, func() (shouldReturn bool) {
   172  			ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
   173  			_, err := c.c.Append(ctx, c.record)
   174  			cancel()
   175  			return err == nil
   176  		})
   177  		if err != nil {
   178  			panic(err)
   179  		}
   180  	}
   181  }
   182  func (r *replayer) onReplayDriverLsn(lsn uint64) {
   183  	if lsn == 0 {
   184  		return
   185  	}
   186  	if lsn < r.minDriverLsn {
   187  		r.minDriverLsn = lsn
   188  	}
   189  	if lsn > r.maxDriverLsn {
   190  		r.maxDriverLsn = lsn
   191  	}
   192  }
   193  
   194  type ReplayCmd struct {
   195  	skipLsns map[uint64]uint64
   196  }
   197  
   198  func NewReplayCmd(skipLsns map[uint64]uint64) *ReplayCmd {
   199  	return &ReplayCmd{
   200  		skipLsns: skipLsns,
   201  	}
   202  }
   203  func NewEmptyReplayCmd() *ReplayCmd {
   204  	return &ReplayCmd{
   205  		skipLsns: make(map[uint64]uint64),
   206  	}
   207  }
   208  
   209  func (c *ReplayCmd) WriteTo(w io.Writer) (n int64, err error) {
   210  	length := uint16(len(c.skipLsns))
   211  	if err = binary.Write(w, binary.BigEndian, length); err != nil {
   212  		return
   213  	}
   214  	n += 2
   215  	for drlsn, logserviceLsn := range c.skipLsns {
   216  		if err = binary.Write(w, binary.BigEndian, drlsn); err != nil {
   217  			return
   218  		}
   219  		n += 8
   220  		if err = binary.Write(w, binary.BigEndian, logserviceLsn); err != nil {
   221  			return
   222  		}
   223  		n += 8
   224  	}
   225  	return
   226  }
   227  
   228  func (c *ReplayCmd) ReadFrom(r io.Reader) (n int64, err error) {
   229  	length := uint16(0)
   230  	if err = binary.Read(r, binary.BigEndian, &length); err != nil {
   231  		return
   232  	}
   233  	n += 2
   234  	for i := 0; i < int(length); i++ {
   235  		drlsn := uint64(0)
   236  		lsn := uint64(0)
   237  		if err = binary.Read(r, binary.BigEndian, &drlsn); err != nil {
   238  			return
   239  		}
   240  		n += 8
   241  		if err = binary.Read(r, binary.BigEndian, &lsn); err != nil {
   242  			return
   243  		}
   244  		n += 8
   245  		c.skipLsns[drlsn] = lsn
   246  	}
   247  	return
   248  }
   249  
   250  func (c *ReplayCmd) Unmarshal(buf []byte) error {
   251  	bbuf := bytes.NewBuffer(buf)
   252  	_, err := c.ReadFrom(bbuf)
   253  	return err
   254  }
   255  
   256  func (c *ReplayCmd) Marshal() (buf []byte, err error) {
   257  	var bbuf bytes.Buffer
   258  	if _, err = c.WriteTo(&bbuf); err != nil {
   259  		return
   260  	}
   261  	buf = bbuf.Bytes()
   262  	return
   263  }