github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/db/checkpoint/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 checkpoint
    16  
    17  import (
    18  	"context"
    19  	"sort"
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    24  	"github.com/matrixorigin/matrixone/pkg/container/types"
    25  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    26  	"github.com/matrixorigin/matrixone/pkg/logutil"
    27  	"github.com/matrixorigin/matrixone/pkg/objectio"
    28  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    29  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    30  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    31  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/dataio/blockio"
    32  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/logtail"
    33  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tasks"
    34  )
    35  
    36  type metaFile struct {
    37  	index int
    38  	start types.TS
    39  	end   types.TS
    40  }
    41  
    42  func (r *runner) Replay(dataFactory catalog.DataFactory) (maxTs types.TS, err error) {
    43  	ctx := context.Background()
    44  	dirs, err := r.fs.ListDir(CheckpointDir)
    45  	if err != nil {
    46  		return
    47  	}
    48  	if len(dirs) == 0 {
    49  		return
    50  	}
    51  	metaFiles := make([]*metaFile, 0)
    52  	var readDuration, applyDuration time.Duration
    53  	for i, dir := range dirs {
    54  		start, end := blockio.DecodeCheckpointMetadataFileName(dir.Name)
    55  		metaFiles = append(metaFiles, &metaFile{
    56  			start: start,
    57  			end:   end,
    58  			index: i,
    59  		})
    60  	}
    61  	sort.Slice(metaFiles, func(i, j int) bool {
    62  		return metaFiles[i].end.Less(metaFiles[j].end)
    63  	})
    64  	targetIdx := metaFiles[len(metaFiles)-1].index
    65  	dir := dirs[targetIdx]
    66  	reader, err := objectio.NewObjectReader(CheckpointDir+dir.Name, r.fs.Service)
    67  	if err != nil {
    68  		return
    69  	}
    70  	bs, err := reader.ReadAllMeta(ctx, dir.Size, common.DefaultAllocator)
    71  	if err != nil {
    72  		return
    73  	}
    74  	bat := containers.NewBatch()
    75  	defer bat.Close()
    76  	colNames := CheckpointSchema.Attrs()
    77  	colTypes := CheckpointSchema.Types()
    78  	nullables := CheckpointSchema.Nullables()
    79  	t0 := time.Now()
    80  	for i := range colNames {
    81  		if bs[0].GetExtent().End() == 0 {
    82  			continue
    83  		}
    84  		col, err2 := bs[0].GetColumn(uint16(i))
    85  		if err2 != nil {
    86  			return types.TS{}, err2
    87  		}
    88  		data, err2 := col.GetData(ctx, nil)
    89  		if err2 != nil {
    90  			return types.TS{}, err2
    91  		}
    92  		pkgVec := vector.New(colTypes[i])
    93  		v := make([]byte, len(data.Entries[0].Object.([]byte)))
    94  		copy(v, data.Entries[0].Object.([]byte))
    95  		if err = pkgVec.Read(v); err != nil {
    96  			return
    97  		}
    98  		var vec containers.Vector
    99  		if pkgVec.Length() == 0 {
   100  			vec = containers.MakeVector(colTypes[i], nullables[i])
   101  		} else {
   102  			vec = containers.NewVectorWithSharedMemory(pkgVec, nullables[i])
   103  		}
   104  		bat.AddVector(colNames[i], vec)
   105  	}
   106  	readDuration += time.Since(t0)
   107  	datas := make([]*logtail.CheckpointData, bat.Length())
   108  	defer func() {
   109  		for _, data := range datas {
   110  			if data != nil {
   111  				data.Close()
   112  			}
   113  		}
   114  	}()
   115  
   116  	jobScheduler := tasks.NewParallelJobScheduler(200)
   117  	defer jobScheduler.Stop()
   118  	entries := make([]*CheckpointEntry, bat.Length())
   119  	emptyFile := make([]*CheckpointEntry, 0)
   120  	var emptyFileMu sync.RWMutex
   121  	var wg sync.WaitGroup
   122  	readfn := func(i int) {
   123  		defer wg.Done()
   124  		start := bat.GetVectorByName(CheckpointAttr_StartTS).Get(i).(types.TS)
   125  		end := bat.GetVectorByName(CheckpointAttr_EndTS).Get(i).(types.TS)
   126  		metaloc := string(bat.GetVectorByName(CheckpointAttr_MetaLocation).Get(i).([]byte))
   127  		isIncremental := bat.GetVectorByName(CheckpointAttr_EntryType).Get(i).(bool)
   128  		typ := ET_Global
   129  		if isIncremental {
   130  			typ = ET_Incremental
   131  		}
   132  		checkpointEntry := &CheckpointEntry{
   133  			start:     start,
   134  			end:       end,
   135  			location:  metaloc,
   136  			state:     ST_Finished,
   137  			entryType: typ,
   138  		}
   139  		var err2 error
   140  		if datas[i], err2 = checkpointEntry.Read(ctx, jobScheduler, r.fs); err2 != nil {
   141  			logutil.Warnf("read %v failed: %v", checkpointEntry.String(), err2)
   142  			emptyFileMu.Lock()
   143  			emptyFile = append(emptyFile, checkpointEntry)
   144  			emptyFileMu.Unlock()
   145  		} else {
   146  			entries[i] = checkpointEntry
   147  		}
   148  	}
   149  	wg.Add(bat.Length())
   150  	t0 = time.Now()
   151  	for i := 0; i < bat.Length(); i++ {
   152  		go readfn(i)
   153  	}
   154  	wg.Wait()
   155  	readDuration += time.Since(t0)
   156  	if err != nil {
   157  		return
   158  	}
   159  	t0 = time.Now()
   160  	globalIdx := 0
   161  	for i := 0; i < bat.Length(); i++ {
   162  		checkpointEntry := entries[i]
   163  		if checkpointEntry == nil {
   164  			continue
   165  		}
   166  		if !checkpointEntry.IsIncremental() {
   167  			globalIdx = i
   168  			r.tryAddNewGlobalCheckpointEntry(checkpointEntry)
   169  		} else {
   170  			r.tryAddNewIncrementalCheckpointEntry(checkpointEntry)
   171  		}
   172  	}
   173  	maxGlobal := r.MaxGlobalCheckpoint()
   174  	if maxGlobal != nil {
   175  		logutil.Infof("replay checkpoint %v", maxGlobal)
   176  		err = datas[globalIdx].ApplyReplayTo(r.catalog, dataFactory)
   177  		if err != nil {
   178  			return
   179  		}
   180  		if maxTs.Less(maxGlobal.end) {
   181  			maxTs = maxGlobal.end
   182  		}
   183  	}
   184  	for _, e := range emptyFile {
   185  		if e.end.GreaterEq(maxTs) {
   186  			return types.TS{},
   187  				moerr.NewInternalError(ctx,
   188  					"read checkpoint %v failed",
   189  					e.String())
   190  		}
   191  	}
   192  	for i := 0; i < bat.Length(); i++ {
   193  		checkpointEntry := entries[i]
   194  		if checkpointEntry == nil {
   195  			continue
   196  		}
   197  		if checkpointEntry.end.LessEq(maxTs) {
   198  			continue
   199  		}
   200  		logutil.Infof("replay checkpoint %v", checkpointEntry)
   201  		err = datas[i].ApplyReplayTo(r.catalog, dataFactory)
   202  		if err != nil {
   203  			return
   204  		}
   205  		if maxTs.Less(checkpointEntry.end) {
   206  			maxTs = checkpointEntry.end
   207  		}
   208  	}
   209  	applyDuration = time.Since(t0)
   210  	logutil.Info("open-tae", common.OperationField("replay"),
   211  		common.OperandField("checkpoint"),
   212  		common.AnyField("apply cost", applyDuration),
   213  		common.AnyField("read cost", readDuration))
   214  	r.source.Init(maxTs)
   215  	return
   216  }