VirtualBox

Changeset 66598 in vbox


Ignore:
Timestamp:
Apr 17, 2017 3:52:56 PM (7 years ago)
Author:
vboxsync
Message:

iprt: Added 'pull' VFS chain element provider/factory using the existing read-ahead code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/vfs/vfsreadahead.cpp

    r62562 r66598  
    814814}
    815815
     816
     817/**
     818 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnValidate}
     819 */
     820static DECLCALLBACK(int) rtVfsChainReadAhead_Validate(PCRTVFSCHAINELEMENTREG pProviderReg, PRTVFSCHAINSPEC pSpec,
     821                                                      PRTVFSCHAINELEMSPEC pElement, uint32_t *poffError)
     822{
     823    RT_NOREF(pProviderReg, poffError);
     824
     825    /*
     826     * Basics.
     827     */
     828    if (pElement->enmTypeIn == RTVFSOBJTYPE_INVALID)
     829        return VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT;
     830    if (pElement->cArgs > 2)
     831        return VERR_VFS_CHAIN_AT_MOST_TWO_ARGS;
     832    if (   pElement->enmType != RTVFSOBJTYPE_FILE
     833        && pElement->enmType != RTVFSOBJTYPE_IO_STREAM)
     834        return VERR_VFS_CHAIN_ONLY_FILE_OR_IOS;
     835    if (pSpec->fOpenFile & RTFILE_O_WRITE)
     836        return VERR_VFS_CHAIN_READ_ONLY_IOS;
     837
     838    /*
     839     * Parse the two optional arguments.
     840     */
     841    uint32_t cBuffers = 0;
     842    if (pElement->cArgs > 0)
     843    {
     844        const char *psz = pElement->paArgs[0].psz;
     845        if (*psz)
     846        {
     847            int rc = RTStrToUInt32Full(psz, 0, &cBuffers);
     848            if (RT_FAILURE(rc))
     849            {
     850                *poffError = pElement->paArgs[0].offSpec;
     851                return VERR_VFS_CHAIN_INVALID_ARGUMENT;
     852            }
     853        }
     854    }
     855
     856    uint32_t cbBuffer = 0;
     857    if (pElement->cArgs > 1)
     858    {
     859        const char *psz = pElement->paArgs[1].psz;
     860        if (*psz)
     861        {
     862            int rc = RTStrToUInt32Full(psz, 0, &cbBuffer);
     863            if (RT_FAILURE(rc))
     864            {
     865                *poffError = pElement->paArgs[1].offSpec;
     866                return VERR_VFS_CHAIN_INVALID_ARGUMENT;
     867            }
     868        }
     869    }
     870
     871    /*
     872     * Save the parsed arguments in the spec since their both optional.
     873     */
     874    pSpec->uProvider = RT_MAKE_U64(cBuffers, cbBuffer);
     875
     876    return VINF_SUCCESS;
     877}
     878
     879
     880/**
     881 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnInstantiate}
     882 */
     883static DECLCALLBACK(int) rtVfsChainReadAhead_Instantiate(PCRTVFSCHAINELEMENTREG pProviderReg, PCRTVFSCHAINSPEC pSpec,
     884                                                         PCRTVFSCHAINELEMSPEC pElement, RTVFSOBJ hPrevVfsObj,
     885                                                         PRTVFSOBJ phVfsObj, uint32_t *poffError)
     886{
     887    RT_NOREF(pProviderReg, pSpec, pElement, poffError);
     888    AssertReturn(hPrevVfsObj != NIL_RTVFSOBJ, VERR_VFS_CHAIN_IPE);
     889
     890    /* Try for a file if we can. */
     891    int rc;
     892    RTVFSFILE hVfsFileIn = RTVfsObjToFile(hPrevVfsObj);
     893    if (hVfsFileIn != NIL_RTVFSFILE)
     894    {
     895        RTVFSFILE hVfsFile = NIL_RTVFSFILE;
     896        rc = RTVfsCreateReadAheadForFile(hVfsFileIn, 0 /*fFlags*/, RT_LO_U32(pSpec->uProvider),
     897                                         RT_HI_U32(pSpec->uProvider), &hVfsFile);
     898        RTVfsFileRelease(hVfsFileIn);
     899        if (RT_SUCCESS(rc))
     900        {
     901            *phVfsObj = RTVfsObjFromFile(hVfsFile);
     902            RTVfsFileRelease(hVfsFile);
     903            if (*phVfsObj != NIL_RTVFSOBJ)
     904                return VINF_SUCCESS;
     905            rc = VERR_VFS_CHAIN_CAST_FAILED;
     906        }
     907    }
     908    else if (pElement->enmType == RTVFSOBJTYPE_IO_STREAM)
     909    {
     910        RTVFSIOSTREAM hVfsIosIn = RTVfsObjToIoStream(hPrevVfsObj);
     911        if (hVfsIosIn != NIL_RTVFSIOSTREAM)
     912        {
     913            RTVFSIOSTREAM hVfsIos = NIL_RTVFSIOSTREAM;
     914            rc = RTVfsCreateReadAheadForIoStream(hVfsIosIn, 0 /*fFlags*/, RT_LO_U32(pSpec->uProvider),
     915                                                 RT_HI_U32(pSpec->uProvider), &hVfsIos);
     916            RTVfsIoStrmRelease(hVfsIosIn);
     917            if (RT_SUCCESS(rc))
     918            {
     919                *phVfsObj = RTVfsObjFromIoStream(hVfsIos);
     920                RTVfsIoStrmRelease(hVfsIos);
     921                if (*phVfsObj != NIL_RTVFSOBJ)
     922                    return VINF_SUCCESS;
     923                rc = VERR_VFS_CHAIN_CAST_FAILED;
     924            }
     925        }
     926        else
     927            rc = VERR_VFS_CHAIN_CAST_FAILED;
     928    }
     929    else
     930        rc = VERR_VFS_CHAIN_CAST_FAILED;
     931    return rc;
     932}
     933
     934
     935/**
     936 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnCanReuseElement}
     937 */
     938static DECLCALLBACK(bool) rtVfsChainReadAhead_CanReuseElement(PCRTVFSCHAINELEMENTREG pProviderReg,
     939                                                              PCRTVFSCHAINSPEC pSpec, PCRTVFSCHAINELEMSPEC pElement,
     940                                                              PCRTVFSCHAINSPEC pReuseSpec, PCRTVFSCHAINELEMSPEC pReuseElement)
     941{
     942    RT_NOREF(pProviderReg, pSpec, pElement, pReuseSpec, pReuseElement);
     943    return false;
     944}
     945
     946
     947/** VFS chain element 'pull'. */
     948static RTVFSCHAINELEMENTREG g_rtVfsChainReadAheadReg =
     949{
     950    /* uVersion = */            RTVFSCHAINELEMENTREG_VERSION,
     951    /* fReserved = */           0,
     952    /* pszName = */             "pull",
     953    /* ListEntry = */           { NULL, NULL },
     954    /* pszHelp = */             "Takes an I/O stream or file and provides read-ahead caching.\n"
     955                                "Optional first argument specifies how many buffers to use, 0 indicating the default.\n"
     956                                "Optional second argument specifies the buffer size, 0 indicating the default.",
     957    /* pfnValidate = */         rtVfsChainReadAhead_Validate,
     958    /* pfnInstantiate = */      rtVfsChainReadAhead_Instantiate,
     959    /* pfnCanReuseElement = */  rtVfsChainReadAhead_CanReuseElement,
     960    /* uEndMarker = */          RTVFSCHAINELEMENTREG_VERSION
     961};
     962
     963RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(&g_rtVfsChainReadAheadReg, rtVfsChainReadAheadReg);
     964
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette