void CALLBACK cfApiFetchDataCallback(const CF_CALLBACK_INFO *callbackInfo, const CF_CALLBACK_PARAMETERS *callbackParameters)
{
qDebug(lcCfApiWrapper) << "Fetch data callback called. File size:" << callbackInfo->FileSize.QuadPart;
+ qDebug(lcCfApiWrapper) << "Fetch data requested by proccess id:" << callbackInfo->ProcessInfo->ProcessId;
+ qDebug(lcCfApiWrapper) << "Fetch data requested by application id:" << QString(QString::fromWCharArray(callbackInfo->ProcessInfo->ApplicationId));
+
const auto sendTransferError = [=] {
cfApiSendTransferInfo(callbackInfo->ConnectionKey,
callbackInfo->TransferKey,
const auto path = QString(QString::fromWCharArray(callbackInfo->VolumeDosName) + QString::fromWCharArray(callbackInfo->NormalizedPath));
const auto requestId = QString::number(callbackInfo->TransferKey.QuadPart, 16);
+ qCDebug(lcCfApiWrapper) << "Request hydration for" << path << requestId;
+
const auto invokeResult = QMetaObject::invokeMethod(vfs, [=] { vfs->requestHydration(requestId, path); }, Qt::QueuedConnection);
if (!invokeResult) {
qCCritical(lcCfApiWrapper) << "Failed to trigger hydration for" << path << requestId;
return;
}
+ qCDebug(lcCfApiWrapper) << "Successfully triggered hydration for" << path << requestId;
+
// Block and wait for vfs to signal back the hydration is ready
bool hydrationRequestResult = false;
QEventLoop loop;
QObject::connect(vfs, &OCC::VfsCfApi::hydrationRequestReady, &loop, [&](const QString &id) {
if (requestId == id) {
hydrationRequestResult = true;
+ qCDebug(lcCfApiWrapper) << "Hydration request ready for" << path << requestId;
loop.quit();
}
});
QObject::connect(vfs, &OCC::VfsCfApi::hydrationRequestFailed, &loop, [&](const QString &id) {
if (requestId == id) {
hydrationRequestResult = false;
+ qCDebug(lcCfApiWrapper) << "Hydration request failed for" << path << requestId;
loop.quit();
}
});
+
+ qCDebug(lcCfApiWrapper) << "Starting event loop 1";
loop.exec();
- QObject::disconnect(vfs, nullptr, &loop, nullptr);
- qCInfo(lcCfApiWrapper) << "VFS replied for hydration of" << path << requestId << "status was:" << hydrationRequestResult;
+ QObject::disconnect(vfs, nullptr, &loop, nullptr); // Ensure we properly cancel hydration on server errors
+ qCInfo(lcCfApiWrapper) << "VFS replied for hydration of" << path << requestId << "status was:" << hydrationRequestResult;
if (!hydrationRequestResult) {
+ qCCritical(lcCfApiWrapper) << "Failed to trigger hydration for" << path << requestId;
sendTransferError();
return;
}
auto hydrationRequestCancelled = false;
QObject::connect(&signalSocket, &QLocalSocket::readyRead, &loop, [&] {
hydrationRequestCancelled = true;
+ qCCritical(lcCfApiWrapper) << "Hydration canceled for " << path << requestId;
});
// CFAPI expects sent blocks to be of a multiple of a block size.
const auto alignAndSendData = [&](const QByteArray &receivedData) {
QByteArray data = protrudingData + receivedData;
+ qCWarning(lcCfApiWrapper) << "protrudingData + receivedData:" << data;
protrudingData.clear();
if (data.size() < cfapiBlockSize) {
protrudingData = data;
+ qCWarning(lcCfApiWrapper) << "protrudingData:" << protrudingData;
+ sendTransferInfo(data, dataOffset);
+ dataOffset += data.size();
return;
}
const auto protudingSize = data.size() % cfapiBlockSize;
+ qCWarning(lcCfApiWrapper) << "protudingSize:" << protudingSize;
protrudingData = data.right(protudingSize);
+ qCWarning(lcCfApiWrapper) << "data.right(protudingSize):" << protrudingData;
data.chop(protudingSize);
-
+ qCWarning(lcCfApiWrapper) << "data.chop(protudingSize)" << data;
+ qCWarning(lcCfApiWrapper) << "sendTransferInfo(data:" << data << ", dataOffset:" << dataOffset << ")";
sendTransferInfo(data, dataOffset);
dataOffset += data.size();
+ qCWarning(lcCfApiWrapper) << "dataOffset:" << dataOffset;
};
QObject::connect(&socket, &QLocalSocket::readyRead, &loop, [&] {
}
});
+ qCDebug(lcCfApiWrapper) << "Starting event loop 2";
loop.exec();
if (!hydrationRequestCancelled && !protrudingData.isEmpty()) {