github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/logstore/store/checkpoint.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 store
    16  
    17  import (
    18  	"github.com/matrixorigin/matrixone/pkg/logutil"
    19  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    20  	driverEntry "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logstore/driver/entry"
    21  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logstore/entry"
    22  )
    23  
    24  func (w *StoreImpl) FuzzyCheckpoint(gid uint32, indexes []*Index) (ckpEntry entry.Entry, err error) {
    25  	ckpEntry = w.makeFuzzyCheckpointEntry(gid, indexes)
    26  	drentry, _, _ := w.doAppend(GroupCKP, ckpEntry)
    27  	if drentry == nil {
    28  		panic(err)
    29  	}
    30  	_, err = w.checkpointQueue.Enqueue(drentry)
    31  	if err != nil {
    32  		panic(err)
    33  	}
    34  	return
    35  }
    36  
    37  func (w *StoreImpl) makeFuzzyCheckpointEntry(gid uint32, indexes []*Index) (ckpEntry entry.Entry) {
    38  	for _, index := range indexes {
    39  		if index.LSN > 100000000 {
    40  			logutil.Infof("IndexErr: Checkpoint Index: %s", index.String())
    41  		}
    42  	}
    43  	defer func() {
    44  		for _, index := range indexes {
    45  			if index.LSN > 100000000 {
    46  				logutil.Infof("IndexErr: Checkpoint Index: %s", index.String())
    47  			}
    48  		}
    49  	}()
    50  	commands := make(map[uint64]entry.CommandInfo)
    51  	for _, idx := range indexes {
    52  		cmdInfo, ok := commands[idx.LSN]
    53  		if !ok {
    54  			cmdInfo = entry.CommandInfo{
    55  				CommandIds: []uint32{idx.CSN},
    56  				Size:       idx.Size,
    57  			}
    58  		} else {
    59  			existed := false
    60  			for _, csn := range cmdInfo.CommandIds {
    61  				if csn == idx.CSN {
    62  					existed = true
    63  					break
    64  				}
    65  			}
    66  			if existed {
    67  				continue
    68  			}
    69  			cmdInfo.CommandIds = append(cmdInfo.CommandIds, idx.CSN)
    70  			if cmdInfo.Size != idx.Size {
    71  				panic("logic error")
    72  			}
    73  		}
    74  		commands[idx.LSN] = cmdInfo
    75  	}
    76  	info := &entry.Info{
    77  		Group: entry.GTCKp,
    78  		Checkpoints: []*entry.CkpRanges{{
    79  			Group:   gid,
    80  			Command: commands,
    81  		}},
    82  	}
    83  	ckpEntry = entry.GetBase()
    84  	ckpEntry.SetType(entry.ETCheckpoint)
    85  	ckpEntry.SetInfo(info)
    86  	return
    87  }
    88  
    89  func (w *StoreImpl) RangeCheckpoint(gid uint32, start, end uint64) (ckpEntry entry.Entry, err error) {
    90  	ckpEntry = w.makeRangeCheckpointEntry(gid, start, end)
    91  	drentry, _, err := w.doAppend(GroupCKP, ckpEntry)
    92  	if err == common.ErrClose {
    93  		return nil, err
    94  	}
    95  	if err != nil {
    96  		panic(err)
    97  	}
    98  	_, err = w.checkpointQueue.Enqueue(drentry)
    99  	if err != nil {
   100  		panic(err)
   101  	}
   102  	return
   103  }
   104  
   105  func (w *StoreImpl) makeRangeCheckpointEntry(gid uint32, start, end uint64) (ckpEntry entry.Entry) {
   106  	info := &entry.Info{
   107  		Group: entry.GTCKp,
   108  		Checkpoints: []*entry.CkpRanges{{
   109  			Group:  gid,
   110  			Ranges: common.NewClosedIntervalsByInterval(&common.ClosedInterval{Start: start, End: end}),
   111  		}},
   112  	}
   113  	ckpEntry = entry.GetBase()
   114  	ckpEntry.SetType(entry.ETCheckpoint)
   115  	ckpEntry.SetInfo(info)
   116  	return
   117  }
   118  
   119  func (w *StoreImpl) onLogCKPInfoQueue(items ...any) {
   120  	for _, item := range items {
   121  		e := item.(*driverEntry.Entry)
   122  		err := e.WaitDone()
   123  		if err != nil {
   124  			panic(err)
   125  		}
   126  		w.logCheckpointInfo(e.Info)
   127  	}
   128  	w.onCheckpoint()
   129  }
   130  
   131  func (w *StoreImpl) onCheckpoint() {
   132  	w.StoreInfo.onCheckpoint()
   133  	w.ckpCkp()
   134  }
   135  
   136  func (w *StoreImpl) ckpCkp() {
   137  	e := w.makeInternalCheckpointEntry()
   138  	driverEntry, _, err := w.doAppend(GroupInternal, e)
   139  	if err == common.ErrClose {
   140  		return
   141  	}
   142  	if err != nil {
   143  		panic(err)
   144  	}
   145  	w.truncatingQueue.Enqueue(driverEntry)
   146  	err = e.WaitDone()
   147  	if err != nil {
   148  		panic(err)
   149  	}
   150  	e.Free()
   151  }
   152  
   153  func (w *StoreImpl) onTruncatingQueue(items ...any) {
   154  	for _, item := range items {
   155  		e := item.(*driverEntry.Entry)
   156  		err := e.WaitDone()
   157  		if err != nil {
   158  			panic(err)
   159  		}
   160  		w.logCheckpointInfo(e.Info)
   161  	}
   162  	gid, driverLsn := w.getDriverCheckpointed()
   163  	if gid == 0 {
   164  		return
   165  	}
   166  	w.driverCheckpointing.Store(driverLsn)
   167  	_, err := w.truncateQueue.Enqueue(struct{}{})
   168  	if err != nil {
   169  		panic(err)
   170  	}
   171  }
   172  
   173  func (w *StoreImpl) onTruncateQueue(items ...any) {
   174  	lsn := w.driverCheckpointing.Load()
   175  	if lsn != w.driverCheckpointed {
   176  		err := w.driver.Truncate(lsn)
   177  		for err != nil {
   178  			lsn = w.driverCheckpointing.Load()
   179  			err = w.driver.Truncate(lsn)
   180  		}
   181  		w.driverCheckpointed = lsn
   182  	}
   183  }