github.com/Microsoft/azure-vhd-utils@v0.0.0-20230613175315-7c30a3748a1b/vhdcore/block/sectorFactory.go (about)

     1  package block
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/Microsoft/azure-vhd-utils/vhdcore"
     7  	"github.com/Microsoft/azure-vhd-utils/vhdcore/reader"
     8  )
     9  
    10  // SectorFactory type is used to create Sector instance by reading 512 byte sector from block's 'data section'.
    11  //
    12  type SectorFactory struct {
    13  	vhdReader       *reader.VhdReader
    14  	blockHasData    func(uint32) bool
    15  	getBlockAddress func(uint32) int64
    16  	emptySectorBuf  []byte
    17  }
    18  
    19  // NewSectorFactory creates a new instance of SectorFactory, which can be used to create Sector instances
    20  // by reading 512 byte sector from block's 'data section'
    21  // vhdReader is the reader to be used to read the sector, blockHasData is a function which can be used to
    22  // check a block is empty by providing block identifier, getBlockAddress is a function which can be used
    23  // to fetch the absolute byte offset of a block by providing block identifier.
    24  //
    25  func NewSectorFactory(vhdReader *reader.VhdReader, blockHasData func(uint32) bool, getBlockAddress func(uint32) int64) *SectorFactory {
    26  	return &SectorFactory{
    27  		vhdReader:       vhdReader,
    28  		blockHasData:    blockHasData,
    29  		getBlockAddress: getBlockAddress,
    30  	}
    31  }
    32  
    33  // Create creates an instance of Sector by reading a 512 byte sector from the 'data section' of a block.
    34  // block describes the block containing the sector, sectorIndex identifies the sector to read.
    35  // This function return error if requested sector is invalid or in case of any read error.
    36  //
    37  func (f *SectorFactory) Create(block *Block, sectorIndex uint32) (*Sector, error) {
    38  	if int64(sectorIndex) > block.GetSectorCount() {
    39  		return nil, fmt.Errorf("Total sectors: %d, Requested Sectors: %d", block.GetSectorCount(), sectorIndex)
    40  	}
    41  
    42  	blockIndex := block.BlockIndex
    43  	if !f.blockHasData(blockIndex) {
    44  		return f.CreateEmptySector(blockIndex, sectorIndex), nil
    45  	}
    46  
    47  	blockDataSectionByteOffset := f.getBlockAddress(blockIndex)
    48  	sectorByteOffset := blockDataSectionByteOffset + vhdcore.VhdSectorLength*int64(sectorIndex)
    49  	sectorBuf := make([]byte, vhdcore.VhdSectorLength)
    50  	if _, err := f.vhdReader.ReadBytes(sectorByteOffset, sectorBuf); err != nil {
    51  		return nil, NewSectorReadError(blockIndex, sectorIndex, err)
    52  	}
    53  
    54  	return &Sector{
    55  		BlockIndex:  blockIndex,
    56  		SectorIndex: int64(sectorIndex),
    57  		Data:        sectorBuf,
    58  	}, nil
    59  }
    60  
    61  // CreateEmptySector creates an instance of Sector representing empty sector. The Data property of this sector
    62  // will be a slice of 512 bytes filled with zeros.
    63  //
    64  func (f *SectorFactory) CreateEmptySector(blockIndex, sectorIndex uint32) *Sector {
    65  	if f.emptySectorBuf == nil {
    66  		f.emptySectorBuf = make([]byte, vhdcore.VhdSectorLength)
    67  	}
    68  
    69  	return &Sector{
    70  		BlockIndex:  blockIndex,
    71  		SectorIndex: int64(sectorIndex),
    72  		Data:        f.emptySectorBuf,
    73  	}
    74  }