Fix multiple downloads on ReadFile()
This commit is contained in:
@@ -39,6 +39,140 @@ private:
|
||||
DWORD AttributesAndFlags;
|
||||
} 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:
|
||||
static std::mutex _dokanMutex;
|
||||
static CSiaApi* _siaApi;
|
||||
@@ -50,7 +184,7 @@ private:
|
||||
static std::unique_ptr<std::thread> _fileListThread;
|
||||
static HANDLE _fileListStopEvent;
|
||||
static CSiaFileTreePtr _siaFileTree;
|
||||
static std::mutex _fileTreeMutex;
|
||||
static std::mutex _openFileMutex;
|
||||
static std::unique_ptr<std::thread> _mountThread;
|
||||
static NTSTATUS _mountStatus;
|
||||
static SString _mountPoint;
|
||||
@@ -70,50 +204,56 @@ private:
|
||||
|
||||
static bool AddFileToCache(OpenFileInfo& openFileInfo, PDOKAN_FILE_INFO dokanFileInfo)
|
||||
{
|
||||
FilePath tempFilePath = FilePath::GetTempDirectory();
|
||||
tempFilePath.Append(GenerateSha256(openFileInfo.SiaPath) + ".siatmp");
|
||||
bool ret = ApiSuccess(_siaApi->GetRenter()->DownloadFile(openFileInfo.SiaPath, tempFilePath));
|
||||
if (ret)
|
||||
bool ret = true;
|
||||
if (openFileInfo.Dummy)
|
||||
{
|
||||
// Find all open handles for requested file
|
||||
std::vector<OpenFileInfo*> matched;
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
FilePath tempFilePath = FilePath::GetTempDirectory();
|
||||
tempFilePath.Append(GenerateSha256(openFileInfo.SiaPath) + ".siatmp");
|
||||
|
||||
// Close all to allow move to complete
|
||||
for (auto* ofi : matched)
|
||||
{
|
||||
::CloseHandle(ofi->FileHandle);
|
||||
}
|
||||
|
||||
FilePath src(tempFilePath);
|
||||
FilePath dest(openFileInfo.CacheFilePath);
|
||||
ret = dest.DeleteFile() && src.MoveFile(dest);
|
||||
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DownloadToCacheBegin(openFileInfo, tempFilePath)));
|
||||
ret = ApiSuccess(_siaApi->GetRenter()->DownloadFile(openFileInfo.SiaPath, tempFilePath));
|
||||
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DownloadToCacheEnd(openFileInfo, tempFilePath, ret)));
|
||||
if (ret)
|
||||
{
|
||||
openFileInfo.Dummy = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
src.DeleteFile();
|
||||
}
|
||||
// Find all open handles for requested file
|
||||
std::vector<OpenFileInfo*> matched;
|
||||
matched.push_back(&openFileInfo);
|
||||
std::lock_guard<std::mutex> l(_openFileMutex);
|
||||
{
|
||||
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
|
||||
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);
|
||||
// Close all to allow move to complete
|
||||
for (auto* ofi : matched)
|
||||
{
|
||||
::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;
|
||||
}
|
||||
|
||||
@@ -162,7 +302,7 @@ private:
|
||||
::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());
|
||||
}
|
||||
|
||||
@@ -433,6 +573,7 @@ private:
|
||||
|
||||
if (ret == STATUS_SUCCESS)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(_openFileMutex);
|
||||
// Create file as specified
|
||||
HANDLE handle = ::CreateFile(
|
||||
&cacheFilePath[0],
|
||||
@@ -469,7 +610,6 @@ private:
|
||||
ofi->CreateDisp = createDisposition;
|
||||
ofi->AttributesAndFlags = fileAttributesAndFlags;
|
||||
dokanFileInfo->Context = reinterpret_cast<ULONG64>(ofi);
|
||||
std::lock_guard<std::mutex> l(_fileTreeMutex);
|
||||
_openFiles.push_back(ofi);
|
||||
}
|
||||
}
|
||||
@@ -1510,7 +1650,7 @@ DOKAN_OPTIONS DokanImpl::_dokanOptions;
|
||||
FilePath DokanImpl::_cacheLocation;
|
||||
HANDLE DokanImpl::_fileListStopEvent;
|
||||
CSiaFileTreePtr DokanImpl::_siaFileTree;
|
||||
std::mutex DokanImpl::_fileTreeMutex;
|
||||
std::mutex DokanImpl::_openFileMutex;
|
||||
std::unique_ptr<std::thread> DokanImpl::_fileListThread;
|
||||
std::unique_ptr<std::thread> DokanImpl::_mountThread;
|
||||
NTSTATUS DokanImpl::_mountStatus = STATUS_SUCCESS;
|
||||
|
Reference in New Issue
Block a user