ssize_t FdEntity::Read()

in src/fdcache_entity.cpp [1760:1864]


ssize_t FdEntity::Read(int fd, char* bytes, off_t start, size_t size, bool force_load)
{
    S3FS_PRN_DBG("[path=%s][pseudo_fd=%d][physical_fd=%d][offset=%lld][size=%zu]", path.c_str(), fd, physical_fd, static_cast<long long int>(start), size);

    PseudoFdInfo* pseudo_obj = NULL;
    if(-1 == physical_fd || NULL == (pseudo_obj = CheckPseudoFdFlags(fd, false))){
        S3FS_PRN_DBG("pseudo_fd(%d) to physical_fd(%d) for path(%s) is not opened or not readable", fd, physical_fd, path.c_str());
        return -EBADF;
    }

    AutoLock auto_lock(&fdent_lock);
    AutoLock auto_lock2(&fdent_data_lock);

    ssize_t rsize = 0;

    if(is_direct_read){
        if (DirectReader::GetDirectReadLocalFileCacheSize() == 0) {
            return pseudo_obj->DirectReadAndPrefetch(bytes, start, size);
        }

        // mix-direct-read mode
        // enter direct-read-and-prefetch when the total_downloaded_size >= the threshold
        if (pseudo_obj->GetLoadedSize() >= DirectReader::GetDirectReadLocalFileCacheSize()) {
            if (pagelist.IsPageLoaded(start, size)) {
                // Reading
                if(-1 == (rsize = pread(physical_fd, bytes, size, start))){
                    S3FS_PRN_ERR("pread failed. errno(%d)", errno);
                    return -errno;
                }
                
                return rsize;
            }

            S3FS_PRN_DBG("start direct read. total_loaded_size = %lld, offset = %lld", pseudo_obj->GetLoadedSize(), start);
            return pseudo_obj->DirectReadAndPrefetch(bytes, start, size);
        }
    }

    CheckAndFreeDiskCacheIfNeeded();

    if(force_load){
        pagelist.SetPageLoadedStatus(start, size, PageList::PAGE_NOT_LOAD_MODIFIED);
    }

    int result = 0;
    uint64_t downloaded_size = 0;
    bool read_from_oss_directly = false;
    // check disk space
    if(0 < pagelist.GetTotalUnloadedPageSize(start, size)){
        // load size(for prefetch)
        size_t load_size = size;
        if(start + static_cast<ssize_t>(size) < pagelist.Size()){
            ssize_t prefetch_max_size = std::max(static_cast<off_t>(size), S3fsCurl::GetMultipartSize() * S3fsCurl::GetMaxParallelCount());

            if(start + prefetch_max_size < pagelist.Size()){
                load_size = prefetch_max_size;
            }else{
                load_size = pagelist.Size() - start;
            }
        }

        if(!ReserveDiskSpace(load_size)){
            S3FS_PRN_WARN("could not reserve disk space for pre-fetch download");
            load_size = size;
            if(!ReserveDiskSpace(load_size)){
                S3FS_PRN_WARN("could not reserve disk space for pre-fetch download");
                read_from_oss_directly = true;
            }
        }

        if(!read_from_oss_directly) {
            if(0 < size){
                // Loading
                result = LoadWithSizeInfo(start, load_size, AutoLock::ALREADY_LOCKED, downloaded_size);
            }

            FdManager::FreeReservedDiskSpace(load_size);
            if(0 != result){
                S3FS_PRN_WARN("could not download. start(%lld), size(%zu), errno(%d)", static_cast<long long int>(start), size, result);
                read_from_oss_directly = true;
            } else {
                pseudo_obj->AddLoadedSize(downloaded_size);
            }
        }
    }

    if(read_from_oss_directly){
        // direct read from oss, but no prefetch
        S3FS_PRN_WARN("could not reserve disk space for download, direct read from cloud.");
        S3fsCurl s3fscurl;
        result = s3fscurl.GetObjectStreamRequest(path.c_str(), bytes, start, size, rsize);
        if(0 != result){
            S3FS_PRN_ERR("could not download. start(%lld), size(%zu), errno(%d)", static_cast<long long int>(start), size, result);
            return result;
        }
        return rsize;
    }

    // Reading
    if(-1 == (rsize = pread(physical_fd, bytes, size, start))){
        S3FS_PRN_ERR("pread failed. errno(%d)", errno);
        return -errno;
    }
    return rsize;
}