1
0

Fix multiple downloads on ReadFile()

This commit is contained in:
Scott E. Graves
2017-04-07 14:30:56 -05:00
parent d9189c80bb
commit 0c8c47f8a1

View File

@@ -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;