Bagikan melalui


Fungsi CfGetPlaceholderRangeInfoForHydration (cfapi.h)

Mendapatkan informasi rentang tentang file atau folder tempat penampung. Informasi rentang ini identik dengan apa yang dikembalikan CfGetPlaceholderRangeInfo . Namun, tidak mengambil fileHandle sebagai parameter. Sebagai gantinya, ia menggunakan ConnectionKey, TransferKey, dan FileId untuk mengidentifikasi file dan aliran yang informasi rentangnya diminta.

Platform ini menyediakan ConnectionKey, TransferKey, dan FileId ke semua fungsi panggilan balik yang terdaftar melalui CfConnectSyncRoot dan penyedia dapat menggunakan parameter ini untuk mendapatkan informasi rentang tentang tempat penampung dari panggilan balik CF_CALLBACK_TYPE_FETCH_DATA tanpa mengharuskannya membuka handel ke file.

Jika file bukan tempat penampung file cloud, API akan gagal. Jika berhasil, informasi rentang dikembalikan sesuai dengan InfoClass tertentu yang diminta.

Catatan

API ini hanya tersedia jika PlatformVersion.IntegrationNumber diperoleh dari CfGetPlatformInfo0x600 atau lebih tinggi.

Sintaks

HRESULT CfGetPlaceholderRangeInfoForHydration(
  [in]            CF_CONNECTION_KEY               ConnectionKey,
  [in]            CF_TRANSFER_KEY                 TransferKey,
  [in]            LARGE_INTEGER                   FileId,
  [in]            CF_PLACEHOLDER_RANGE_INFO_CLASS InfoClass,
  [in]            LARGE_INTEGER                   StartingOffset,
  [in]            LARGE_INTEGER                   RangeLength,
  [out]           PVOID                           InfoBuffer,
  [in]            DWORD                           InfoBufferSize,
  [out, optional] PDWORD                          InfoBufferWritten
);

Parameter

[in] ConnectionKey

Handel buram yang dibuat oleh CfConnectSyncRoot untuk akar sinkronisasi yang dikelola oleh penyedia sinkronisasi. Ini dikembalikan juga dalam CF_CALLBACK_INFO dalam panggilan balik CF_CALLBACK_TYPE_FETCH_DATA dan panggilan balik lainnya.

[in] TransferKey

Handel buram ke file tempat penampung yang panggilan balik CF_CALLBACK_TYPE_FETCH_DATA telah dipanggil. Ini juga dikembalikan dalam CF_CALLBACK_INFO dalam panggilan balik CF_CALLBACK_TYPE_FETCH_DATA . Ini dapat diperoleh secara alternatif oleh CfGetTransferKey jika API tidak dipanggil dari CF_CALLBACK_TYPE_FETCH_DATA Callback.

[in] FileId

ID unik seluruh volume yang dikelola sistem file 64bit dari file/direktori tempat penampung yang akan dilayankan. Seperti TransferKey, ini dikembalikan dalam CF_CALLBACK_INFO di CF_CALLBACK_TYPE_FETCH_DATA dan panggilan balik lainnya sehingga penyedia tidak perlu mengambilnya lagi.

[in] InfoClass

Jenis rentang data tempat penampung. Nilainya bisa menjadi salah satu dari berikut ini:

Nilai Deskripsi
CF_PLACEHOLDER_RANGE_INFO_ONDISK Data pada disk adalah data yang ada secara fisik dalam file. Ini adalah set super dari jenis rentang lainnya.
CF_PLACEHOLDER_RANGE_INFO_VALIDATED Data yang divalidasi adalah subset data pada disk yang saat ini sinkron dengan cloud.
CF_PLACEHOLDER_RANGEINFO_MODIFIED Data yang dimodifikasi adalah subset data pada disk yang saat ini tidak sinkron dengan cloud (yaitu, dimodifikasi atau ditambahkan.)

[in] StartingOffset

Offset titik awal rentang data. StartingOffset dan RangeLength menentukan rentang dalam file tempat penampung yang informasinya seperti yang dijelaskan oleh parameter InfoClass diminta

[in] RangeLength

Panjang rentang data. Penyedia dapat menentukan CF_EOF untuk RangeLength untuk menunjukkan bahwa rentang yang informasinya diminta adalah dari StartingOffset ke akhir file.

[out] InfoBuffer

Penunjuk ke buffer yang akan menerima data. Buffer adalah array struktur CF_FILE_RANGE , yang merupakan pasangan offset/panjang, yang menjelaskan rentang yang diminta.

[in] InfoBufferSize

Panjang InfoBuffer dalam byte.

[out, optional] InfoBufferWritten

Menerima jumlah byte yang dikembalikan di InfoBuffer.

Menampilkan nilai

Jika fungsi ini berhasil, fungsi akan mengembalikan S_OK. Jika tidak, kode kesalahan HRESULT akan dikembalikan. Beberapa kode kesalahan umum tercantum dalam tabel berikut:

Kode kesalahan Makna
HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ) Ini berarti bahwa StartingOffset>= posisi akhir file.
HRESULT_FROM_WIN32( ERROR_MORE_DATA ) Ini menyiratkan bahwa entri CF_FILE_RANGE berikutnya tidak cocok dalam buffer yang disediakan. Pemanggil harus memverifikasi apakah ada entri yang diterima atau tidak menggunakan nilai InfoBufferWritten yang dikembalikan.

Keterangan

Meskipun API untuk mengkueri rentang file terhidrasi dari tempat penampung sudah ada, API baru diperlukan untuk meningkatkan keandalan platform.

API yang ada, CfGetPlaceholderRangeInfo, memerlukan handel yang dibuka ke file lalu memicu FSCTL_HSM_CONTROL menggunakan handel tersebut. Penyedia/Mesin Sinkronisasi biasanya menggunakan API ini untuk menilai bagian file mana yang tidak terhidrasi dari konteks panggilan balik CF_CALLBACK_TYPE_FETCH_DATA yang dipanggil oleh filter untuk menghidrasi file untuk memenuhi IO.

Filter mini di tumpukan IO dapat mengeluarkan pemindaian data pada file ketika penyedia/Mesin sinkronisasi mencoba membuka handel ke file untuk diteruskan sebagai parameter ke CfGetPlaceholderRangeInfo. Atau, filter mini dapat memblokir FSCTL_HSM_CONTROL yang dipicu CfGetPlaceholderRangeInfo secara internal.

Filter cldflt dirancang untuk memanggil hanya satu panggilan balik CF_CALLBACK_TYPE_FETCH_DATA per rentang file yang diperlukan untuk menghidrasi file. Sebagai akibat dari salah satu kasus di atas, pemindaian data terjebak di belakang CF_CALLBACK_TYPE_FETCH_DATA asli atau CF_CALLBACK_TYPE_FETCH_DATA terjebak di belakang FSCTL yang diblokir. Hal ini menyebabkan kebuntuan di jalur hidrasi.

Oleh karena itu, API ini diperlukan. Ini melakukan fungsionalitas yang sama dengan CfGetPlaceholderRangeInfo, tetapi berkomunikasi ke filter secara langsung menggunakan port pesan filter yang melewati tumpukan IO menengah. Oleh karena itu, tidak ada filter mini perantara yang dapat menghalangi CreateFile atau FSCTL_HSM_CONTROL.

Perhatikan bahwa pemanggil selalu memiliki ConnectionKey yang diperoleh melalui CfConnectSyncRoot. Ini dapat memperoleh TransferKey melalui CfGetTransferKey dan mendapatkan FileId menggunakan GetFileInformationByHandle. Tetapi pendekatan ini membutuhkan handel untuk dibuka ke file dan karenanya tidak berbeda dengan menggunakan CfGetPlaceholderRangeInfo.

Untuk meringkas, ketika info rentang diperlukan dari konteks panggilan balik CF_CALLBACK_TYPE_FETCH_DATA , API ini harus digunakan. Dalam semua kasus lain, termasuk ketika penyedia ingin menghidrasi file tanpa diminta oleh filter, CfGetPlaceholderRangeInfo harus digunakan. Platform tidak dapat mengenali API mana yang dipanggil dalam konteks tertentu dan karenanya onus ada di penyedia/Mesin Sinkronisasi untuk melakukan hal yang benar.

Contoh

Ini adalah contoh sederhana di mana fungsi melewati InfoBuffer cukup untuk mengambil hanya satu entri CF_FILE_RANGE pada satu waktu. Dalam praktiknya, pemanggil dapat meneruskan InfoBuffer yang dapat sesuai dengan beberapa entri CF_FILE_RANGE per pemanggilan API. Kode kesalahan HRESULT_FROM_WIN32( ERROR_MORE_DATA ) dapat digunakan untuk melewati buffer yang lebih besar jika perlu.

#include <cfapi.h>

// ******************************************************************************************************
// From within the CF_CALLBACK_TYPE_FETCH_DATA Callback, the provider can use
// g_PlatformInfo.IntegrationNumber to see if the new API is supported. If it is, the provider can pass
// ConnectionKey, TransferKey and FileId along with other parameters to obtain information about file
// ranges which have already been hydrated.
// *******************************************************************************************************

// The provider could obtain file ranges that are hydrated like this:
std::vector<CF_FILE_RANGE> hydratedRanges = GetFileRangesFromCallback( CallbackInfo->ConnectionKey,
                                                                       CallbackInfo->TransferKey,
                                                                       CallbackInfo->FileId,
                                                                       CF_PLACEHOLDER_RANGE_INFO_ONDISK
                                                                       0,
                                                                       CF_EOF);

// Based on these hydratedRanges, the provider can chose to hydrate only ranges which aren’t on the disk.

// ******************************************************************************************************
// Implementation of a function that eventually calls this API.
// ******************************************************************************************************

typedef HRESULT( __stdcall* t_CfGetPlaceholderRangeInfoForHydration )(
    CF_CONNECTION_KEY ConnectionKey,
    CF_TRANSFER_KEY TransferKey,
    LARGE_INTEGER FileId,
    CF_PLACEHOLDER_RANGE_INFO_CLASS InfoClass,
    LARGE_INTEGER StartingOffset,
    LARGE_INTEGER RangeLength,
    PVOID InfoBuffer,
    DWORD InfoBufferSize,
    PDWORD InfoBufferWritten );

t_CfGetPlaceholderRangeInfoForHydration _CfGetPlaceholderRangeInfoForHydration = nullptr;

std::vector<CF_FILE_RANGE>
GetFileRangesFromCallback( CF_CONNECTION_KEY ConnectionKey,
                           CF_TRANSFER_KEY TransferKey,
                           LARGE_INTEGER FileId,
                           CF_PLACEHOLDER_RANGE_INFO_CLASS RangeInfoClass,
                           long long StartOffset,
                           long long Length,
                           PBOOLEAN UseOldAPI )
{

    long long StartOffset = 0;
    CF_FILE_RANGE fileRange;
    long long Length = 0;
    LARGE_INTEGER queryOffset = ll2li( StartOffset );
    LARGE_INTEGER queryLength = ll2li( Length );
    DWORD inforBufferWritten = 0;

    // This will contain all the hydrated ranges in the file if the function succeeds.
    std::vector<CF_FILE_RANGE> ranges;
    bool stop = false;

    CF_PLATFORM_INFO platformInfo;

    hr = (CfGetPlatformInfo( &platformInfo ));
    if(FAILED(hr)) {
        *UseOldAPI = TRUE;
        return ranges; //empty.
    }

    if (platformInfo.IntegrationNumber < 600) {
        *UseOldAPI = TRUE;
        return ranges; //empty.
    }

    wil::unique_hmodule CloudFilesApi( LoadLibrary( L"cldapi.dll" ) );
    THROW_LAST_ERROR_IF_NULL( CloudFilesApi );

    _CfGetPlaceholderRangeInfoForHydration = reinterpret_cast<t_CfGetPlaceholderRangeInfoForHydration>(
            GetProcAddress( CloudFilesApi.get(), "CfGetPlaceholderRangeInfoForHydration" ) );
    THROW_LAST_ERROR_IF_NULL( _CfGetPlaceholderRangeInfoForHydration );

    while ( !stop ) {

        hr = _CfGetPlaceholderRangeInfoForHydration ( ConnectionKey,
                                                      TransferKey,
                                                      FileId,
                                                      RangeInfoClass,
                                                      queryOffset,
                                                      queryLength,
                                                      &fileRange,
                                                      sizeof( fileRange ),
                                                      &infoBufferWritten );

        if ( hr == HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ) ||
             hr == HRESULT_FROM_WIN32( ERROR_MORE_DATA ) ) {

            // We need to break the loop only if there is no more data.
            if ( hr == HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ) ) {
                stop = true;
            }

            hr = S_OK;
        }

        if ( FAILED( hr ) || infoBufferWritten == 0 ) {
            return ranges;
        }

        ranges.push_back( fileRange );
        queryOffset.QuadPart = fileRange.StartingOffset.QuadPart + fileRange.Length.QuadPart;

        if ( Length != CF_EOF && queryOffset.QuadPart >= ( StartOffset + Length ) ) {
            stop = true;
        } else if ( Length != CF_EOF) {
            // Update the new query length
            queryLength.QuadPart = StartOffset + Length - queryOffset.QuadPart
        
            if ( queryLength.QuadPart <= 0 ) {
                stop = true;
            }
        }
    }

    return ranges;
}

Persyaratan

Persyaratan Nilai
Header cfapi.h

Lihat juga

CF_PLACEHOLDER_RANGE_INFO_CLASS

CfGetPlaceholderRangeInfo

CfConnectSyncRoot

CfGetPlatformInfo

CfGetTransferKey