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 }