Fix multiple downloads on ReadFile()
This commit is contained in:
@@ -39,6 +39,140 @@ private:
|
|||||||
DWORD AttributesAndFlags;
|
DWORD AttributesAndFlags;
|
||||||
} OpenFileInfo;
|
} OpenFileInfo;
|
||||||
|
|
||||||
|
class DownloadToCacheBegin :
|
||||||
|
public CEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DownloadToCacheBegin(const OpenFileInfo& openFileInfo, const SString& tempFilePath) :
|
||||||
|
_openFileInfo(openFileInfo),
|
||||||
|
_tempFilePath(tempFilePath)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~DownloadToCacheBegin() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const OpenFileInfo _openFileInfo;
|
||||||
|
const SString _tempFilePath;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual SString GetSingleLineMessage() const override
|
||||||
|
{
|
||||||
|
return "DownloadToCacheBegin|FP|" + _openFileInfo.CacheFilePath +
|
||||||
|
"|SP|" + _openFileInfo.SiaPath +
|
||||||
|
"|TP|" + _tempFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::shared_ptr<CEvent> Clone() const override
|
||||||
|
{
|
||||||
|
return std::shared_ptr<CEvent>(new DownloadToCacheBegin(_openFileInfo, _tempFilePath));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DownloadToCacheEnd :
|
||||||
|
public CEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DownloadToCacheEnd(const OpenFileInfo& openFileInfo, const SString& tempFilePath, const bool& result) :
|
||||||
|
_openFileInfo(openFileInfo),
|
||||||
|
_tempFilePath(tempFilePath),
|
||||||
|
_result(result)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~DownloadToCacheEnd() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const OpenFileInfo _openFileInfo;
|
||||||
|
const SString _tempFilePath;
|
||||||
|
const bool _result;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual SString GetSingleLineMessage() const override
|
||||||
|
{
|
||||||
|
return "DownloadToCacheEnd|FP|" + _openFileInfo.CacheFilePath +
|
||||||
|
"|SP|" + _openFileInfo.SiaPath +
|
||||||
|
"|TP|" + _tempFilePath +
|
||||||
|
"|RES|" + SString::FromBool(_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::shared_ptr<CEvent> Clone() const override
|
||||||
|
{
|
||||||
|
return std::shared_ptr<CEvent>(new DownloadToCacheEnd(_openFileInfo, _tempFilePath, _result));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MoveTempToCacheResult :
|
||||||
|
public CEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MoveTempToCacheResult(const OpenFileInfo& openFileInfo, const SString& tempFilePath, const bool& result) :
|
||||||
|
_openFileInfo(openFileInfo),
|
||||||
|
_tempFilePath(tempFilePath),
|
||||||
|
_result(result)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~MoveTempToCacheResult() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const OpenFileInfo _openFileInfo;
|
||||||
|
const SString _tempFilePath;
|
||||||
|
const bool _result;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual SString GetSingleLineMessage() const override
|
||||||
|
{
|
||||||
|
return "MoveTempToCacheResult|FP|" + _openFileInfo.CacheFilePath +
|
||||||
|
"|SP|" + _openFileInfo.SiaPath +
|
||||||
|
"|TP|" + _tempFilePath +
|
||||||
|
"|RES|" + SString::FromBool(_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::shared_ptr<CEvent> Clone() const override
|
||||||
|
{
|
||||||
|
return std::shared_ptr<CEvent>(new MoveTempToCacheResult(_openFileInfo, _tempFilePath, _result));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AddToCacheComplete :
|
||||||
|
public CEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AddToCacheComplete(const OpenFileInfo& openFileInfo, const bool& result) :
|
||||||
|
_openFileInfo(openFileInfo),
|
||||||
|
_result(result)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~AddToCacheComplete() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const OpenFileInfo _openFileInfo;
|
||||||
|
const bool _result;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual SString GetSingleLineMessage() const override
|
||||||
|
{
|
||||||
|
return "AddToCacheComplete|FP|" + _openFileInfo.CacheFilePath +
|
||||||
|
"|SP|" + _openFileInfo.SiaPath +
|
||||||
|
"|RES|" + SString::FromBool(_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::shared_ptr<CEvent> Clone() const override
|
||||||
|
{
|
||||||
|
return std::shared_ptr<CEvent>(new AddToCacheComplete(_openFileInfo, _result));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::mutex _dokanMutex;
|
static std::mutex _dokanMutex;
|
||||||
static CSiaApi* _siaApi;
|
static CSiaApi* _siaApi;
|
||||||
@@ -50,7 +184,7 @@ private:
|
|||||||
static std::unique_ptr<std::thread> _fileListThread;
|
static std::unique_ptr<std::thread> _fileListThread;
|
||||||
static HANDLE _fileListStopEvent;
|
static HANDLE _fileListStopEvent;
|
||||||
static CSiaFileTreePtr _siaFileTree;
|
static CSiaFileTreePtr _siaFileTree;
|
||||||
static std::mutex _fileTreeMutex;
|
static std::mutex _openFileMutex;
|
||||||
static std::unique_ptr<std::thread> _mountThread;
|
static std::unique_ptr<std::thread> _mountThread;
|
||||||
static NTSTATUS _mountStatus;
|
static NTSTATUS _mountStatus;
|
||||||
static SString _mountPoint;
|
static SString _mountPoint;
|
||||||
@@ -70,50 +204,56 @@ private:
|
|||||||
|
|
||||||
static bool AddFileToCache(OpenFileInfo& openFileInfo, PDOKAN_FILE_INFO dokanFileInfo)
|
static bool AddFileToCache(OpenFileInfo& openFileInfo, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
FilePath tempFilePath = FilePath::GetTempDirectory();
|
bool ret = true;
|
||||||
tempFilePath.Append(GenerateSha256(openFileInfo.SiaPath) + ".siatmp");
|
if (openFileInfo.Dummy)
|
||||||
bool ret = ApiSuccess(_siaApi->GetRenter()->DownloadFile(openFileInfo.SiaPath, tempFilePath));
|
|
||||||
if (ret)
|
|
||||||
{
|
{
|
||||||
// Find all open handles for requested file
|
FilePath tempFilePath = FilePath::GetTempDirectory();
|
||||||
std::vector<OpenFileInfo*> matched;
|
tempFilePath.Append(GenerateSha256(openFileInfo.SiaPath) + ".siatmp");
|
||||||
matched.push_back(&openFileInfo);
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> l(_fileTreeMutex);
|
|
||||||
std::for_each(_openFiles.begin(), _openFiles.end(), [&](OpenFileInfo* ofi)
|
|
||||||
{
|
|
||||||
if ((ofi->FileHandle != openFileInfo.FileHandle) && (ofi->SiaPath == openFileInfo.SiaPath))
|
|
||||||
{
|
|
||||||
matched.push_back(ofi);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close all to allow move to complete
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DownloadToCacheBegin(openFileInfo, tempFilePath)));
|
||||||
for (auto* ofi : matched)
|
ret = ApiSuccess(_siaApi->GetRenter()->DownloadFile(openFileInfo.SiaPath, tempFilePath));
|
||||||
{
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DownloadToCacheEnd(openFileInfo, tempFilePath, ret)));
|
||||||
::CloseHandle(ofi->FileHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
FilePath src(tempFilePath);
|
|
||||||
FilePath dest(openFileInfo.CacheFilePath);
|
|
||||||
ret = dest.DeleteFile() && src.MoveFile(dest);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
openFileInfo.Dummy = false;
|
// Find all open handles for requested file
|
||||||
}
|
std::vector<OpenFileInfo*> matched;
|
||||||
else
|
matched.push_back(&openFileInfo);
|
||||||
{
|
std::lock_guard<std::mutex> l(_openFileMutex);
|
||||||
src.DeleteFile();
|
{
|
||||||
}
|
std::for_each(_openFiles.begin(), _openFiles.end(), [&](OpenFileInfo* ofi)
|
||||||
|
{
|
||||||
|
if ((ofi->FileHandle != openFileInfo.FileHandle) && (ofi->SiaPath == openFileInfo.SiaPath))
|
||||||
|
{
|
||||||
|
matched.push_back(ofi);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Re-open all files
|
// Close all to allow move to complete
|
||||||
for (auto& ofi : matched)
|
for (auto* ofi : matched)
|
||||||
{
|
{
|
||||||
ofi->FileHandle = ::CreateFile(&ofi->CacheFilePath[0], ofi->DesiredAccess, ofi->ShareMode, ofi->SecurityAttrib.nLength ? &ofi->SecurityAttrib : nullptr, ofi->CreateDisp, ofi->AttributesAndFlags, nullptr);
|
::CloseHandle(ofi->FileHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePath src(tempFilePath);
|
||||||
|
FilePath dest(openFileInfo.CacheFilePath);
|
||||||
|
ret = dest.DeleteFile() && src.MoveFile(dest);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
src.DeleteFile();
|
||||||
|
}
|
||||||
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(MoveTempToCacheResult(openFileInfo, tempFilePath, ret)));
|
||||||
|
|
||||||
|
// Re-open all files
|
||||||
|
for (auto& ofi : matched)
|
||||||
|
{
|
||||||
|
ofi->FileHandle = ::CreateFile(&ofi->CacheFilePath[0], ofi->DesiredAccess, ofi->ShareMode, ofi->SecurityAttrib.nLength ? &ofi->SecurityAttrib : nullptr, ofi->CreateDisp, ofi->AttributesAndFlags, nullptr);
|
||||||
|
ofi->Dummy = !ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(AddToCacheComplete(openFileInfo, ret)));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +302,7 @@ private:
|
|||||||
::CloseHandle(openFileInfo.FileHandle);
|
::CloseHandle(openFileInfo.FileHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> l(_fileTreeMutex);
|
std::lock_guard<std::mutex> l(_openFileMutex);
|
||||||
_openFiles.erase(std::remove(_openFiles.begin(), _openFiles.end(), &openFileInfo), _openFiles.end());
|
_openFiles.erase(std::remove(_openFiles.begin(), _openFiles.end(), &openFileInfo), _openFiles.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,6 +573,7 @@ private:
|
|||||||
|
|
||||||
if (ret == STATUS_SUCCESS)
|
if (ret == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> l(_openFileMutex);
|
||||||
// Create file as specified
|
// Create file as specified
|
||||||
HANDLE handle = ::CreateFile(
|
HANDLE handle = ::CreateFile(
|
||||||
&cacheFilePath[0],
|
&cacheFilePath[0],
|
||||||
@@ -469,7 +610,6 @@ private:
|
|||||||
ofi->CreateDisp = createDisposition;
|
ofi->CreateDisp = createDisposition;
|
||||||
ofi->AttributesAndFlags = fileAttributesAndFlags;
|
ofi->AttributesAndFlags = fileAttributesAndFlags;
|
||||||
dokanFileInfo->Context = reinterpret_cast<ULONG64>(ofi);
|
dokanFileInfo->Context = reinterpret_cast<ULONG64>(ofi);
|
||||||
std::lock_guard<std::mutex> l(_fileTreeMutex);
|
|
||||||
_openFiles.push_back(ofi);
|
_openFiles.push_back(ofi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1510,7 +1650,7 @@ DOKAN_OPTIONS DokanImpl::_dokanOptions;
|
|||||||
FilePath DokanImpl::_cacheLocation;
|
FilePath DokanImpl::_cacheLocation;
|
||||||
HANDLE DokanImpl::_fileListStopEvent;
|
HANDLE DokanImpl::_fileListStopEvent;
|
||||||
CSiaFileTreePtr DokanImpl::_siaFileTree;
|
CSiaFileTreePtr DokanImpl::_siaFileTree;
|
||||||
std::mutex DokanImpl::_fileTreeMutex;
|
std::mutex DokanImpl::_openFileMutex;
|
||||||
std::unique_ptr<std::thread> DokanImpl::_fileListThread;
|
std::unique_ptr<std::thread> DokanImpl::_fileListThread;
|
||||||
std::unique_ptr<std::thread> DokanImpl::_mountThread;
|
std::unique_ptr<std::thread> DokanImpl::_mountThread;
|
||||||
NTSTATUS DokanImpl::_mountStatus = STATUS_SUCCESS;
|
NTSTATUS DokanImpl::_mountStatus = STATUS_SUCCESS;
|
||||||
|
Reference in New Issue
Block a user