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

     1  package block
     2  
     3  import (
     4  	"log"
     5  	"math"
     6  
     7  	"github.com/Microsoft/azure-vhd-utils/vhdcore"
     8  	"github.com/Microsoft/azure-vhd-utils/vhdcore/common"
     9  )
    10  
    11  // FixedDiskBlockFactory is a type which is used for following purposes
    12  // To create a Block instance representing a fixed disk block
    13  // To get the number of blocks in the fixed disk
    14  // To get the block size of the block in fixed disk
    15  // To get a Sector instance representing sector of fixed disk's block
    16  // To get the logical footer range of the fixed disk
    17  //
    18  type FixedDiskBlockFactory struct {
    19  	params           *FactoryParams
    20  	sectorFactory    *SectorFactory
    21  	blockDataReader  DataReader
    22  	blockCount       int64
    23  	blockSize        int64
    24  	extraBlockIndex  *int64
    25  	cachedFixedBlock *Block
    26  }
    27  
    28  // NewFixedDiskBlockFactoryWithDefaultBlockSize creates a FixedDiskBlockFactory instance which can
    29  // be used to create a Block object representing fixed disk block of default size 512 KB.
    30  // parameter params contains header, footer of the fixed disk and reader to read the disk.
    31  //
    32  func NewFixedDiskBlockFactoryWithDefaultBlockSize(params *FactoryParams) *FixedDiskBlockFactory {
    33  	return NewFixedDiskBlockFactory(params, vhdcore.VhdDefaultBlockSize)
    34  }
    35  
    36  // NewFixedDiskBlockFactory creates a FixedDiskBlockFactory instance which can be used to create a
    37  // Block objects representing fixed disk block of a specific size, parameter params contains header,
    38  // footer of the fixed disk and reader to read the disk, parameter blockSize represents the size
    39  // of blocks in the fixed disk
    40  //
    41  func NewFixedDiskBlockFactory(params *FactoryParams, blockSize int64) *FixedDiskBlockFactory {
    42  	blockFactory := &FixedDiskBlockFactory{params: params}
    43  
    44  	// VirtualSize is the current size of the fixed disk in bytes.
    45  	c := float64(blockFactory.params.VhdFooter.VirtualSize) / float64(blockSize)
    46  	cf := int64(math.Floor(c))
    47  	cc := int64(math.Ceil(c))
    48  	if cf < cc {
    49  		blockFactory.extraBlockIndex = &cf
    50  	} else {
    51  		blockFactory.extraBlockIndex = nil
    52  	}
    53  	blockFactory.blockCount = cc
    54  	blockFactory.blockSize = blockSize
    55  	blockFactory.sectorFactory = NewSectorFactory(blockFactory.params.VhdReader,
    56  		func(blockIndex uint32) bool {
    57  			return blockIndex != vhdcore.VhdNoDataInt
    58  		},
    59  		func(blockIndex uint32) int64 {
    60  			return int64(blockIndex) * blockSize
    61  		},
    62  	)
    63  	blockFactory.blockDataReader = NewFixedDiskBlockReader(blockFactory.params.VhdReader, uint32(blockSize))
    64  	return blockFactory
    65  }
    66  
    67  // GetBlockCount returns the number of blocks in the fixed disk.
    68  //
    69  func (f *FixedDiskBlockFactory) GetBlockCount() int64 {
    70  	return f.blockCount
    71  }
    72  
    73  // GetBlockSize returns the size of the block in bytes of the fixed disk.
    74  //
    75  func (f *FixedDiskBlockFactory) GetBlockSize() int64 {
    76  	return f.blockSize
    77  }
    78  
    79  // GetFooterRange returns the logical range of the footer of the fixed disk, logical range of footer
    80  // is the absolute start and end byte offset of the footer.
    81  //
    82  func (f *FixedDiskBlockFactory) GetFooterRange() *common.IndexRange {
    83  	footerStartIndex := f.params.VhdReader.Size - vhdcore.VhdFooterSize
    84  	return common.NewIndexRangeFromLength(footerStartIndex, vhdcore.VhdFooterSize)
    85  }
    86  
    87  // Create returns an instance of Block which represents a fixed disk block, the parameter blockIndex
    88  // identifies the block.
    89  //
    90  func (f *FixedDiskBlockFactory) Create(blockIndex uint32) (*Block, error) {
    91  	if f.cachedFixedBlock == nil || f.cachedFixedBlock.BlockIndex != blockIndex {
    92  		var logicalRange *common.IndexRange
    93  		if f.extraBlockIndex != nil && *f.extraBlockIndex == int64(blockIndex) {
    94  			logicalRange = f.getExtraBlockLogicalRange()
    95  		} else {
    96  			logicalRange = common.NewIndexRangeFromLength(int64(blockIndex)*f.blockSize, f.blockSize)
    97  		}
    98  
    99  		f.cachedFixedBlock = &Block{
   100  			BlockIndex:      blockIndex,
   101  			LogicalRange:    logicalRange,
   102  			VhdUniqueID:     f.params.VhdFooter.UniqueID,
   103  			BitMap:          nil, // Bitmap applies to dynamic and differentials disks
   104  			BlockDataReader: f.blockDataReader,
   105  		}
   106  
   107  		f.cachedFixedBlock.IsEmpty = blockIndex == vhdcore.VhdNoDataInt
   108  	}
   109  	return f.cachedFixedBlock, nil
   110  }
   111  
   112  // GetSector returns an instance of Sector in a fixed disk, parameter block describes the block containing the
   113  // sector, the parameter sectorIndex identifies the sector in the block. This function return error if the sector
   114  // cannot be created due to any read error or if the requested sector index is invalid.
   115  //
   116  func (f *FixedDiskBlockFactory) GetSector(block *Block, sectorIndex uint32) (*Sector, error) {
   117  	blockIndex := block.BlockIndex
   118  	if block.IsEmpty {
   119  		return f.sectorFactory.CreateEmptySector(blockIndex, sectorIndex), nil
   120  	}
   121  
   122  	return f.sectorFactory.Create(block, sectorIndex)
   123  }
   124  
   125  // getExtraBlockLogicalRange returns the IndexRange representing the additional block if any. Additional block
   126  // is the last block whose size < FixedDiskBlockFactory.BlockSize
   127  //
   128  func (f *FixedDiskBlockFactory) getExtraBlockLogicalRange() *common.IndexRange {
   129  	if f.extraBlockIndex == nil {
   130  		log.Panicf("Unexpected state, extraBlockIndex not set")
   131  	}
   132  
   133  	startIndex := *(f.extraBlockIndex) * f.blockSize
   134  	size := f.params.VhdReader.Size - startIndex - vhdcore.VhdFooterSize
   135  	return common.NewIndexRangeFromLength(startIndex, size)
   136  }