in component/azstorage/block_blob.go [1251:1356]
func (bb *BlockBlob) TruncateFile(name string, size int64) error {
// log.Trace("BlockBlob::TruncateFile : name=%s, size=%d", name, size)
attr, err := bb.GetAttr(name)
if err != nil {
log.Err("BlockBlob::TruncateFile : Failed to get attributes of file %s [%s]", name, err.Error())
if err == syscall.ENOENT {
return err
}
}
if size == 0 || attr.Size == 0 {
// If we are resizing to a value > 1GB then we need to upload multiple blocks to resize
if size > 1*common.GbToBytes {
blkSize := int64(16 * common.MbToBytes)
blobName := filepath.Join(bb.Config.prefixPath, name)
blobClient := bb.Container.NewBlockBlobClient(blobName)
blkList := make([]string, 0)
id := common.GetBlockID(common.BlockIDLength)
for i := 0; size > 0; i++ {
if i == 0 || size < blkSize {
// Only first and last block we upload and rest all we replicate with the first block itself
if size < blkSize {
blkSize = size
id = common.GetBlockID(common.BlockIDLength)
}
data := make([]byte, blkSize)
_, err = blobClient.StageBlock(context.Background(),
id,
streaming.NopCloser(bytes.NewReader(data)),
&blockblob.StageBlockOptions{
CPKInfo: bb.blobCPKOpt,
})
if err != nil {
log.Err("BlockBlob::TruncateFile : Failed to stage block for %s [%s]", name, err.Error())
return err
}
}
blkList = append(blkList, id)
size -= blkSize
}
err = bb.CommitBlocks(blobName, blkList, nil)
if err != nil {
log.Err("BlockBlob::TruncateFile : Failed to commit blocks for %s [%s]", name, err.Error())
return err
}
} else {
err := bb.WriteFromBuffer(name, nil, make([]byte, size))
if err != nil {
log.Err("BlockBlob::TruncateFile : Failed to set the %s to 0 bytes [%s]", name, err.Error())
}
}
return err
}
//If new size is less than 256MB
if size < blockblob.MaxUploadBlobBytes {
data, err := bb.HandleSmallFile(name, size, attr.Size)
if err != nil {
log.Err("BlockBlob::TruncateFile : Failed to read small file %s", name, err.Error())
return err
}
err = bb.WriteFromBuffer(name, nil, data)
if err != nil {
log.Err("BlockBlob::TruncateFile : Failed to write from buffer file %s", name, err.Error())
return err
}
} else {
bol, err := bb.GetFileBlockOffsets(name)
if err != nil {
log.Err("BlockBlob::TruncateFile : Failed to get block list of file %s [%s]", name, err.Error())
return err
}
if bol.SmallFile() {
data, err := bb.HandleSmallFile(name, size, attr.Size)
if err != nil {
log.Err("BlockBlob::TruncateFile : Failed to read small file %s", name, err.Error())
return err
}
err = bb.WriteFromBuffer(name, nil, data)
if err != nil {
log.Err("BlockBlob::TruncateFile : Failed to write from buffer file %s", name, err.Error())
return err
}
} else {
if size < attr.Size {
bol = bb.removeBlocks(bol, size, name)
} else if size > attr.Size {
_, err = bb.createNewBlocks(bol, bol.BlockList[len(bol.BlockList)-1].EndIndex, size-attr.Size)
if err != nil {
log.Err("BlockBlob::TruncateFile : Failed to create new blocks for file %s", name, err.Error())
return err
}
}
err = bb.StageAndCommit(name, bol)
if err != nil {
log.Err("BlockBlob::TruncateFile : Failed to stage and commit file %s", name, err.Error())
return err
}
}
}
return nil
}