📄 hashthread.cpp
字号:
//This file is part of eMule
//Copyright (C)2003 eMule Project ( http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "StdAfx.h"
#include "HashThread.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern volatile BYTE g_byHashThreadRunning; // declared in SharedFileList.cpp
//volatile bool g_bHashThreadRunning; // TODO: switch the byte to bool...
volatile HANDLE CFileHashThread::s_hSharedFilesThread = NULL;
CRITICAL_SECTION CFileHashThread::s_lockPartFileThread;
CFileHashThread::CFileHashThread(CFilePtrList* pList)
{
m_dwThreadId = 0;
m_hThreadHandle = NULL;
m_pFilesToHashList = pList;
m_pPartFileOwner = NULL;
}
CFileHashThread::CFileHashThread(CPartFile* pOwner, char* pszDir, char* pszName)
{
(CFilePtrList*) m_pFilesToHashList = new CFilePtrList;
UnknownFileStruct* pToHash = new UnknownFileStruct;
m_dwThreadId = 0;
m_hThreadHandle = NULL;
pToHash->pszFileDirectory = pszDir;
pToHash->pszFileName = pszName;
m_pFilesToHashList->AddTail(pToHash);
m_pPartFileOwner = pOwner;
}
CFileHashThread::~CFileHashThread()
{
// do some cleaning...
while (!m_pFilesToHashList->IsEmpty()){
UnknownFileStruct* pTemp = m_pFilesToHashList->RemoveHead();
delete[] pTemp->pszFileDirectory;
delete[] pTemp->pszFileName;
delete pTemp;
}
if (m_pPartFileOwner)
delete m_pFilesToHashList;
if (m_hThreadHandle)
::CloseHandle(m_hThreadHandle);
}
bool CFileHashThread::BeginThread(int nPriority, UINT nStackSize, LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{
m_hThreadHandle = ::CreateThread(lpSecurityAttrs, nStackSize, (LPTHREAD_START_ROUTINE)HashThreadProcStub, this, 0, &m_dwThreadId);
if (m_hThreadHandle == NULL){
TRACE("Failed to create hash thread!\n");
return false;
}
TRACE("Successfully created the hash thread: %d, @%d\n", m_hThreadHandle, ::GetTickCount());
::SetThreadPriority(m_hThreadHandle, nPriority);
if (!m_pPartFileOwner)
s_hSharedFilesThread = m_hThreadHandle;
if((g_byHashThreadRunning&SHAREDFILESTHREAD) && m_pPartFileOwner)
::SuspendThread(s_hSharedFilesThread);
#ifdef _DEBUG
if (m_pPartFileOwner)
TRACE("Starting Part File Thread:%d, @%d\n", m_hThreadHandle, ::GetTickCount());
else
TRACE("Starting Shared Files Thread:%d, @%d\n", m_hThreadHandle, ::GetTickCount());
#endif // _DEBUG
return true;
}
void WINAPI CFileHashThread::HashThreadProcStub(LPVOID pObj)
{
((CFileHashThread*)pObj)->HashThreadProc(pObj);
ExitThread(0);
}
void CFileHashThread::HashThreadProc(LPVOID pParam)
{
if (m_pPartFileOwner)
::EnterCriticalSection(&s_lockPartFileThread); // Lock this so only one part file thread can run at a time...
// (I don't like to use critical section here but I guess it is as good as any other sync object... :) )
uint32 nFileCount = m_pFilesToHashList->GetCount();
do
{
UnknownFileStruct* pFileToHash = m_pFilesToHashList->RemoveHead();
CKnownFile* pNewRecord = CreateNewKnownFile(pFileToHash);
if (pNewRecord && (theApp.emuledlg->m_app_state == APP_STATE_RUNNING)) // no deadlocks?
::SendMessage(theApp.emuledlg->m_hWnd, TM_FINISHEDHASHING, (WPARAM)m_pPartFileOwner, (LPARAM)pNewRecord);
else if (theApp.emuledlg->m_app_state == APP_STATE_SHUTINGDOWN){ // maybe use a event object instead...
::SetThreadPriority(m_hThreadHandle, THREAD_PRIORITY_ABOVE_NORMAL); // Boost the priority when we are shutting down...
TRACE("The App is shutting down, exiting hash thread: %d, @%d\n", m_hThreadHandle, ::GetTickCount());
delete pNewRecord;
delete pFileToHash;
if (m_pPartFileOwner)
::LeaveCriticalSection(&s_lockPartFileThread);
return;
}
delete pFileToHash;
}
while (!m_pFilesToHashList->IsEmpty());
::SetThreadPriority(m_hThreadHandle, THREAD_PRIORITY_ABOVE_NORMAL); // Boost the priority when we are shutting down...
if (!m_pPartFileOwner)
while(!::PostMessage(theApp.emuledlg->m_hWnd, TM_HASHTHREADFINISHED,(WPARAM)nFileCount, (LPARAM)pParam))
::Sleep(200); // the queue was full, we're now going to sleep and retry in 200ms... (shouldn't really happen, but just in case)
else{
while (!::PostMessage(theApp.emuledlg->m_hWnd, TM_HASHTHREADFINISHED,(WPARAM)0xFFFFFFFF, (LPARAM)pParam))
::Sleep(200); // the queue was full, we're now going to sleep and retry in 200ms...
::LeaveCriticalSection(&s_lockPartFileThread);
}
#ifdef _DEBUG
if (m_pPartFileOwner)
TRACE("Exiting Part File Thread:%d, @%d\n", m_hThreadHandle, ::GetTickCount());
else
TRACE("Exiting Shared Files Thread:%d, @%d\n", m_hThreadHandle, ::GetTickCount());
#endif // _DEBUG
}
CKnownFile* CFileHashThread::CreateNewKnownFile(UnknownFileStruct* pFileToHash)
{
CKnownFile* pNewKnownFile = new CKnownFile();
pNewKnownFile->directory = pFileToHash->pszFileDirectory;
pNewKnownFile->filename = pFileToHash->pszFileName;
char* pFileNameBuffer = new char[strlen(pFileToHash->pszFileDirectory)+strlen(pFileToHash->pszFileName)+2];
sprintf(pFileNameBuffer, "%s\\%s", pFileToHash->pszFileDirectory, pFileToHash->pszFileName);
HANDLE hFile; // maybe use memory mapped files to see if we can get some better performance...
if (m_pPartFileOwner){
hFile = HANDLE(m_pPartFileOwner->m_hpartfile);
::SetFilePointer(hFile, 0, 0, FILE_BEGIN); //reset the file pointer if it has been set earlier...
}
else
hFile = ::CreateFile(pFileNameBuffer, GENERIC_READ, FILE_SHARE_READ /*NULL*/, NULL, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
delete[] pFileNameBuffer;
if (hFile == INVALID_HANDLE_VALUE){
DWORD dwError = ::GetLastError();
delete pNewKnownFile;
return NULL;
}
uint32 nBytesLeft = ::GetFileSize(hFile, NULL);
pNewKnownFile->filesize = nBytesLeft;
uint32 nNumberOfHashes = (nBytesLeft/PARTSIZE)+((nBytesLeft%PARTSIZE)? 1 : 0);;
uchar* pHashSetBuffer = new uchar[nNumberOfHashes*16];
uint32 iHashCount = 0;
uint32 nNumberOfBytesRead = 0;
while (nBytesLeft > PARTSIZE) // PARTSIZE = 9728000
{
pNewKnownFile->CreateHashFromInput(hFile, NULL, PARTSIZE, pHashSetBuffer+(iHashCount*16));
nBytesLeft -= PARTSIZE;
iHashCount++;
if (theApp.emuledlg->m_app_state == APP_STATE_SHUTINGDOWN){
// try to clean up as much as possible if the user terminates the app when the thread is running...
if (!m_pPartFileOwner)
::CloseHandle(hFile);
delete[] pHashSetBuffer;
return pNewKnownFile;
}
}
pNewKnownFile->CreateHashFromInput(hFile, NULL, nBytesLeft, pHashSetBuffer+(iHashCount*16));
if (!iHashCount)
memcpy(pNewKnownFile->filehash, pHashSetBuffer, 16);
else{
for (uint32 i = 0; i != nNumberOfHashes; i++){
uchar* pTempHash = new uchar[16];
memcpy(pTempHash, pHashSetBuffer+(i*16), 16);
pNewKnownFile->hashlist.Add(pTempHash);
}
pNewKnownFile->CreateHashFromInput(NULL, pHashSetBuffer, nNumberOfHashes*16, pNewKnownFile->filehash);
}
delete[] pHashSetBuffer;
// TODO: Add filetags
// Get Time of last modification of file
struct _stat fileinfo;
int tempHandle = _open_osfhandle((intptr_t)hFile, 0);
_fstat(tempHandle, &fileinfo);
pNewKnownFile->date = fileinfo.st_mtime;
if (!m_pPartFileOwner)
_close(tempHandle);
return pNewKnownFile;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -