func()

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
}