github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/objstorage/objstorageprovider/vfs.go (about)

     1  // Copyright 2023 The LevelDB-Go and Pebble Authors. All rights reserved. Use
     2  // of this source code is governed by a BSD-style license that can be found in
     3  // the LICENSE file.
     4  
     5  package objstorageprovider
     6  
     7  import (
     8  	"context"
     9  
    10  	"github.com/cockroachdb/errors"
    11  	"github.com/cockroachdb/pebble/internal/base"
    12  	"github.com/cockroachdb/pebble/objstorage"
    13  	"github.com/cockroachdb/pebble/vfs"
    14  )
    15  
    16  func (p *provider) vfsPath(fileType base.FileType, fileNum base.DiskFileNum) string {
    17  	return base.MakeFilepath(p.st.FS, p.st.FSDirName, fileType, fileNum)
    18  }
    19  
    20  func (p *provider) vfsOpenForReading(
    21  	ctx context.Context,
    22  	fileType base.FileType,
    23  	fileNum base.DiskFileNum,
    24  	opts objstorage.OpenOptions,
    25  ) (objstorage.Readable, error) {
    26  	filename := p.vfsPath(fileType, fileNum)
    27  	file, err := p.st.FS.Open(filename, vfs.RandomReadsOption)
    28  	if err != nil {
    29  		if opts.MustExist {
    30  			base.MustExist(p.st.FS, filename, p.st.Logger, err)
    31  		}
    32  		return nil, err
    33  	}
    34  	return newFileReadable(file, p.st.FS, filename)
    35  }
    36  
    37  func (p *provider) vfsCreate(
    38  	_ context.Context, fileType base.FileType, fileNum base.DiskFileNum,
    39  ) (objstorage.Writable, objstorage.ObjectMetadata, error) {
    40  	filename := p.vfsPath(fileType, fileNum)
    41  	file, err := p.st.FS.Create(filename)
    42  	if err != nil {
    43  		return nil, objstorage.ObjectMetadata{}, err
    44  	}
    45  	file = vfs.NewSyncingFile(file, vfs.SyncingFileOptions{
    46  		NoSyncOnClose: p.st.NoSyncOnClose,
    47  		BytesPerSync:  p.st.BytesPerSync,
    48  	})
    49  	meta := objstorage.ObjectMetadata{
    50  		DiskFileNum: fileNum,
    51  		FileType:    fileType,
    52  	}
    53  	return newFileBufferedWritable(file), meta, nil
    54  }
    55  
    56  func (p *provider) vfsRemove(fileType base.FileType, fileNum base.DiskFileNum) error {
    57  	return p.st.FSCleaner.Clean(p.st.FS, fileType, p.vfsPath(fileType, fileNum))
    58  }
    59  
    60  // vfsInit finds any local FS objects.
    61  func (p *provider) vfsInit() error {
    62  	listing := p.st.FSDirInitialListing
    63  	if listing == nil {
    64  		var err error
    65  		listing, err = p.st.FS.List(p.st.FSDirName)
    66  		if err != nil {
    67  			return errors.Wrapf(err, "pebble: could not list store directory")
    68  		}
    69  	}
    70  
    71  	for _, filename := range listing {
    72  		fileType, fileNum, ok := base.ParseFilename(p.st.FS, filename)
    73  		if ok && fileType == base.FileTypeTable {
    74  			o := objstorage.ObjectMetadata{
    75  				FileType:    fileType,
    76  				DiskFileNum: fileNum,
    77  			}
    78  			p.mu.knownObjects[o.DiskFileNum] = o
    79  		}
    80  	}
    81  	return nil
    82  }
    83  
    84  func (p *provider) vfsSync() error {
    85  	p.mu.Lock()
    86  	shouldSync := p.mu.localObjectsChanged
    87  	p.mu.localObjectsChanged = false
    88  	p.mu.Unlock()
    89  
    90  	if !shouldSync {
    91  		return nil
    92  	}
    93  	if err := p.fsDir.Sync(); err != nil {
    94  		p.mu.Lock()
    95  		defer p.mu.Unlock()
    96  		p.mu.localObjectsChanged = true
    97  		return err
    98  	}
    99  	return nil
   100  }
   101  
   102  func (p *provider) vfsSize(fileType base.FileType, fileNum base.DiskFileNum) (int64, error) {
   103  	filename := p.vfsPath(fileType, fileNum)
   104  	stat, err := p.st.FS.Stat(filename)
   105  	if err != nil {
   106  		return 0, err
   107  	}
   108  	return stat.Size(), nil
   109  }