github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libkbfs/file_block_map_disk.go (about)

     1  // Copyright 2019 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package libkbfs
     6  
     7  import (
     8  	"context"
     9  
    10  	"github.com/keybase/client/go/kbfs/data"
    11  	"github.com/keybase/client/go/kbfs/kbfsblock"
    12  	"github.com/keybase/client/go/kbfs/libkey"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  type fileBlockMapDiskInfo struct {
    17  	pps data.PathPartString
    18  	ptr data.BlockPointer
    19  }
    20  
    21  // fileBlockMapDisk tracks block info while making a revision, by
    22  // using a disk-based block cache.
    23  type fileBlockMapDisk struct {
    24  	dirtyBcache *DirtyBlockCacheDisk
    25  	kmd         libkey.KeyMetadata
    26  	ptrs        map[data.BlockPointer]map[string]fileBlockMapDiskInfo
    27  }
    28  
    29  var _ fileBlockMap = (*fileBlockMapDisk)(nil)
    30  
    31  func newFileBlockMapDisk(
    32  	dirtyBcache *DirtyBlockCacheDisk, kmd libkey.KeyMetadata) *fileBlockMapDisk {
    33  	return &fileBlockMapDisk{
    34  		dirtyBcache: dirtyBcache,
    35  		kmd:         kmd,
    36  		ptrs:        make(map[data.BlockPointer]map[string]fileBlockMapDiskInfo),
    37  	}
    38  }
    39  
    40  func (fbmd *fileBlockMapDisk) putTopBlock(
    41  	ctx context.Context, parentPtr data.BlockPointer,
    42  	childName data.PathPartString, topBlock *data.FileBlock) error {
    43  	// To reuse the DirtyBlockCacheDisk code, we need to assign a
    44  	// random BlockPointer to this block.
    45  	id, err := kbfsblock.MakeTemporaryID()
    46  	if err != nil {
    47  		return err
    48  	}
    49  	ptr := data.BlockPointer{ID: id}
    50  
    51  	err = fbmd.dirtyBcache.Put(
    52  		ctx, fbmd.kmd.TlfID(), ptr, data.MasterBranch, topBlock)
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	ptrMap, ok := fbmd.ptrs[parentPtr]
    58  	if !ok {
    59  		ptrMap = make(map[string]fileBlockMapDiskInfo)
    60  		fbmd.ptrs[parentPtr] = ptrMap
    61  	}
    62  
    63  	ptrMap[childName.Plaintext()] = fileBlockMapDiskInfo{childName, ptr}
    64  	return nil
    65  }
    66  
    67  func (fbmd *fileBlockMapDisk) GetTopBlock(
    68  	ctx context.Context, parentPtr data.BlockPointer,
    69  	childName data.PathPartString) (*data.FileBlock, error) {
    70  	ptrMap, ok := fbmd.ptrs[parentPtr]
    71  	if !ok {
    72  		return nil, errors.Errorf("No such parent %s", parentPtr)
    73  	}
    74  	info, ok := ptrMap[childName.Plaintext()]
    75  	if !ok {
    76  		return nil, errors.Errorf(
    77  			"No such name %s in parent %s", childName, parentPtr)
    78  	}
    79  	block, err := fbmd.dirtyBcache.Get(
    80  		ctx, fbmd.kmd.TlfID(), info.ptr, data.MasterBranch)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  	fblock, ok := block.(*data.FileBlock)
    85  	if !ok {
    86  		return nil, errors.Errorf(
    87  			"Unexpected block type for file block: %T", block)
    88  	}
    89  	return fblock, nil
    90  }
    91  
    92  func (fbmd *fileBlockMapDisk) getFilenames(
    93  	_ context.Context, parentPtr data.BlockPointer) (
    94  	names []data.PathPartString, err error) {
    95  	ptrMap, ok := fbmd.ptrs[parentPtr]
    96  	if !ok {
    97  		return nil, nil
    98  	}
    99  	names = make([]data.PathPartString, 0, len(ptrMap))
   100  	for _, info := range ptrMap {
   101  		names = append(names, info.pps)
   102  	}
   103  	return names, nil
   104  }