in component/block_cache/block_cache.go [399:452]
func (bc *BlockCache) OpenFile(options internal.OpenFileOptions) (*handlemap.Handle, error) {
log.Trace("BlockCache::OpenFile : name=%s, flags=%X, mode=%s", options.Name, options.Flags, options.Mode)
attr, err := bc.NextComponent().GetAttr(internal.GetAttrOptions{Name: options.Name})
if err != nil {
log.Err("BlockCache::OpenFile : Failed to get attr of %s [%s]", options.Name, err.Error())
return nil, err
}
handle := handlemap.NewHandle(options.Name)
handle.Mtime = attr.Mtime
handle.Size = attr.Size
if attr.ETag != "" {
handle.SetValue("ETAG", attr.ETag)
}
log.Debug("BlockCache::OpenFile : Size of file handle.Size %v", handle.Size)
bc.prepareHandleForBlockCache(handle)
if options.Flags&os.O_TRUNC != 0 {
// If file is opened in truncate or wronly mode then we need to wipe out the data consider current file size as 0
log.Debug("BlockCache::OpenFile : Truncate %v to 0", options.Name)
handle.Size = 0
handle.Flags.Set(handlemap.HandleFlagDirty)
} else if handle.Size != 0 && (options.Flags&os.O_RDWR != 0 || options.Flags&os.O_APPEND != 0) {
// File is not opened in read-only mode so we need to get the list of blocks and validate the size
// As there can be a potential write on this file, currently configured block size and block size of the file in container
// has to match otherwise it will corrupt the file. Fail the open call if this is not the case.
blockList, err := bc.NextComponent().GetCommittedBlockList(options.Name)
if err != nil || blockList == nil {
log.Err("BlockCache::OpenFile : Failed to get block list of %s [%v]", options.Name, err)
return nil, fmt.Errorf("failed to retrieve block list for %s", options.Name)
}
valid := bc.validateBlockList(handle, options, blockList)
if !valid {
return nil, fmt.Errorf("block size mismatch for %s", options.Name)
}
}
if handle.Size > 0 {
// This shall be done after the refresh only as this will populate the queues created by above method
if handle.Size < int64(bc.blockSize) {
// File is small and can fit in one block itself
_ = bc.refreshBlock(handle, 0, false)
} else if bc.prefetchOnOpen && !bc.noPrefetch {
// Prefetch to start on open
_ = bc.startPrefetch(handle, 0, false)
}
}
return handle, nil
}