github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitpage/checkpoint.go (about)

     1  // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors.
     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 bitpage
    16  
    17  import (
    18  	"os"
    19  	"path"
    20  
    21  	"github.com/cockroachdb/errors"
    22  	"github.com/cockroachdb/errors/oserror"
    23  	"github.com/zuoyebang/bitalosdb/internal/utils"
    24  	"github.com/zuoyebang/bitalosdb/internal/vfs"
    25  )
    26  
    27  func (b *Bitpage) Checkpoint(fs vfs.FS, dstDir string) (err error) {
    28  	if _, err = os.Stat(dstDir); !oserror.IsNotExist(err) {
    29  		return errors.Errorf("bitpage: checkpoint dir exist %s", dstDir)
    30  	}
    31  
    32  	var dir vfs.File
    33  	var files []string
    34  
    35  	err = os.Mkdir(dstDir, 0755)
    36  	if err != nil {
    37  		return err
    38  	}
    39  	dir, err = fs.OpenDir(dstDir)
    40  	if err != nil {
    41  		return err
    42  	}
    43  
    44  	b.pages.Range(func(k, v interface{}) bool {
    45  		pn := k.(PageNum)
    46  		p := v.(*page)
    47  		if b.PageSplitted(pn) {
    48  			return true
    49  		}
    50  
    51  		p.mu.Lock()
    52  		defer p.mu.Unlock()
    53  
    54  		if p.mu.stMutable != nil {
    55  			if err = p.makeMutableForWrite(true); err != nil {
    56  				return false
    57  			}
    58  		}
    59  
    60  		for i := range p.mu.stQueue {
    61  			if !p.mu.stQueue[i].empty() {
    62  				files = append(files, p.mu.stQueue[i].path())
    63  				idxPath := p.mu.stQueue[i].idxFilePath()
    64  				if utils.IsFileExist(idxPath) {
    65  					files = append(files, idxPath)
    66  				}
    67  			}
    68  		}
    69  
    70  		if p.mu.arrtable != nil {
    71  			files = append(files, p.mu.arrtable.path())
    72  		}
    73  
    74  		return true
    75  	})
    76  	if err != nil {
    77  		return err
    78  	}
    79  
    80  	for i := range files {
    81  		newname := path.Join(dstDir, fs.PathBase(files[i]))
    82  		if err = vfs.LinkOrCopy(fs, files[i], newname); err != nil {
    83  			return err
    84  		}
    85  		b.opts.Logger.Infof("bitpage checkpoint save %s to %s", files[i], newname)
    86  	}
    87  
    88  	metaFile := makeFilepath(b.dirname, fileTypeManifest, 0, 0)
    89  	metaNewFile := makeFilepath(dstDir, fileTypeManifest, 0, 0)
    90  	if err = vfs.Copy(fs, metaFile, metaNewFile); err != nil {
    91  		return err
    92  	}
    93  	b.opts.Logger.Infof("bitpage checkpoint save %s to %s", metaFile, metaNewFile)
    94  
    95  	err = dir.Sync()
    96  	if err != nil {
    97  		return err
    98  	}
    99  	return dir.Close()
   100  }