⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 partfile.cpp

📁 非常出名开源客户端下载的程序emule
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	bool finished = false;
	while (!finished)
	{
		// Need to empty lists to avoid infinite loop when file is smaller than 180k
		// Otherwise it would keep looping to find 3 blocks, there is only one and it is requested
		liGoodParts.RemoveAll();
		liPossibleParts.RemoveAll();
		// Barry - Top priority should be to continue downloading from current blocks (if anything left to download)
		bool foundPriorityPart = false;
		CString gettingParts;
		sender->ShowDownloadingParts(&gettingParts);

		for (int i=(gettingParts.GetLength()-1); i>=0; i--)
		{
			if ((gettingParts.GetAt(i) == 'Y') && (GetNextEmptyBlockInPart(i, 0)))
			{
				liGoodParts.AddHead(i);
				foundPriorityPart = true;
			}
		}
		// Barry - Give priorty to end parts of archives and movies
		if ((!foundPriorityPart) && (IsArchive() || IsMovie()) && theApp.glob_prefs->GetPreviewPrio())
		{
			uint32 partCount = GetPartCount();
			// First part
			if (sender->IsPartAvailable(0) && GetNextEmptyBlockInPart(0, 0))
			{
				liGoodParts.AddHead(0);
				foundPriorityPart = true;
			}
			else if ((partCount > 1))
			{
				// Last part
				if (sender->IsPartAvailable(partCount-1) && GetNextEmptyBlockInPart(partCount-1, 0))
				{
					liGoodParts.AddHead(partCount-1);
					foundPriorityPart = true;
				}
				// Barry - Better to get rarest than these, add to list, but do not exclude all others.
				// These get priority over other parts with same availability.
				else if (partCount > 2)
				{
					// Second part
					if (sender->IsPartAvailable(1) && GetNextEmptyBlockInPart(1, 0))
						liGoodParts.AddHead(1);
					// Penultimate part
					else if (sender->IsPartAvailable(partCount-2) && GetNextEmptyBlockInPart(partCount-2, 0))
						liGoodParts.AddHead(partCount-2);
				}
			}
		}
		if (!foundPriorityPart)
		{
			randomness = (uint16)ROUND(((float)rand()/RAND_MAX)*(GetPartCount()-1));
			for (uint16 i = 0;i != GetPartCount();i++){
				if (sender->IsPartAvailable(randomness))
				{                                        
					if (partsav[randomness] && !IsComplete(randomness*PARTSIZE,((randomness+1)*PARTSIZE)-1)){
						/*if (IsCorruptedPart(randomness)){
						if (GetNextEmptyBlockInPart(randomness,0)){
						goodpart = randomness;
						break;
						}
						}
						else */ 
						if (IsPureGap(randomness*PARTSIZE,((randomness+1)*PARTSIZE)-1))
						{
							if (GetNextEmptyBlockInPart(randomness,0))
								liPossibleParts.AddHead(randomness);
						}
						else if (GetNextEmptyBlockInPart(randomness,0))
							liGoodParts.AddTail(randomness); // Barry - Add after archive/movie entries
					}
				}
				randomness++;
				if (randomness == GetPartCount())
					randomness = 0;
			}
		}
		CList<int,int>* usedlist;
		if (!liGoodParts.IsEmpty())
			usedlist = &liGoodParts;
		else if (!liPossibleParts.IsEmpty())
			usedlist = &liPossibleParts;
		else{
			if (!newblockcount){
				return false;
			}
			else
				break;
		}
		uint16 nRarest = 0xFFFF;
		uint16 usedpart = usedlist->GetHead();
		for (POSITION pos = usedlist->GetHeadPosition();pos != 0;usedlist->GetNext(pos)){
			if (m_SrcpartFrequency.GetCount() >= usedlist->GetAt(pos)
				&& m_SrcpartFrequency[usedlist->GetAt(pos)] < nRarest){
					nRarest = m_SrcpartFrequency[usedlist->GetAt(pos)];
					usedpart = usedlist->GetAt(pos);
				}
		}
		while (true){
			Requested_Block_Struct* block = new Requested_Block_Struct;
			if (GetNextEmptyBlockInPart(usedpart,block)){
				requestedblocks_list.AddTail(block);
				newblocks[newblockcount] = block;
				newblockcount++;
				if (newblockcount == requestedCount){
					finished = true;
					break;
				}
			}
			else
			{
				delete block;
				break;
			}
		}
	} //wend
	*count = newblockcount;
	return true;
}

void  CPartFile::RemoveBlockFromList(uint32 start,uint32 end){
	POSITION pos1,pos2;
	for (pos1 = requestedblocks_list.GetHeadPosition(); ( pos2 = pos1 ) != NULL; ){
	   requestedblocks_list.GetNext(pos1);
		if (requestedblocks_list.GetAt(pos2)->StartOffset <= start && requestedblocks_list.GetAt(pos2)->EndOffset >= end)
			requestedblocks_list.RemoveAt(pos2);
	}
}

void CPartFile::RemoveAllRequestedBlocks(void)
{
	requestedblocks_list.RemoveAll();
}

void CPartFile::CompleteFile(bool bIsHashingDone){
	if( this->srcarevisible )
		theApp.emuledlg->transferwnd.downloadlistctrl.HideSources(this);
	status = PS_COMPLETING;
	if (!bIsHashingDone){
		//m_hpartfile.Flush(); // flush the OS buffer before completing...
		datarate = 0;
		char* partfileb = nstrdup(partmetfilename);
		partfileb[strlen(partmetfilename)-4] = 0;
		CAddFileThread* addfilethread = (CAddFileThread*) AfxBeginThread(RUNTIME_CLASS(CAddFileThread), THREAD_PRIORITY_BELOW_NORMAL,0, CREATE_SUSPENDED);
		addfilethread->SetValues(0,theApp.glob_prefs->GetTempDir(),partfileb,this);
		addfilethread->ResumeThread();	
		delete[] partfileb;
		return;
	}
	else{
		StopFile();
		// guess I was wrong about not need to spaw a thread.. It is if the temp and incoming dirs are on different partitions/drives and the file is large...[oz]
		CWinThread *pThread = AfxBeginThread((AFX_THREADPROC)CompleteThreadProc, this, THREAD_PRIORITY_BELOW_NORMAL, 0, CREATE_SUSPENDED); // Lord KiRon - using threads for file completion
		if (pThread)
			pThread->ResumeThread();
		else
			throw CString(_T(GetResString(IDS_ERR_FILECOMPLETIONTHREAD))); // move this to resources

	}
	theApp.emuledlg->transferwnd.downloadlistctrl.ShowFilesCount();
	UpdateDisplayedInfo(true);
}

UINT CPartFile::CompleteThreadProc(CPartFile* pFile) 
{ 
	if (!pFile)
		return -1; 
   	pFile->PerformFileComplete(); 
   	return 0; 
}

// Lord KiRon - using threads for file completion
BOOL CPartFile::PerformFileComplete() 
{ 
	CSingleLock(&m_FileCompleteMutex,TRUE); // will be unlocked on exit
	char* partfilename = nstrdup(fullname);
	partfilename[strlen(fullname)-4] = 0;
	char* newfilename = nstrdup(GetFileName());
	strcpy(newfilename, (LPCTSTR)theApp.StripInvalidFilenameChars(newfilename));
	char* newname = new char[strlen(newfilename)+strlen(theApp.glob_prefs->GetIncomingDir())+MAX_PATH];
	CString indir;

	if (PathFileExists( theApp.glob_prefs->GetCategory(GetCategory())->incomingpath)) {
		indir=theApp.glob_prefs->GetCategory(GetCategory())->incomingpath;
		sprintf(newname,"%s\\%s",indir,newfilename);
	} else{
		indir=theApp.glob_prefs->GetIncomingDir();
		sprintf(newname,"%s\\%s",indir,newfilename);
	}

	// close permanent handle
	if (m_hpartfile.m_hFile != INVALID_HANDLE_VALUE)
		m_hpartfile.Close();

	bool renamed = false;
	if(PathFileExists(newname))
	{
		renamed = true;
		int namecount = 0;

		size_t length = strlen(newfilename);
		ASSERT(length != 0); //name should never be 0

		//the file extension
		char *ext = strrchr(newfilename, '.');
		if(ext == NULL)
			ext = newfilename + length;

		char *last = ext;  //new end is the file name before extension
		last[0] = 0;  //truncate file name

		//serch for matching ()s and check if it contains a number
		if((ext != newfilename) && (strrchr(newfilename, ')') + 1 == last)) {
			char *first = strrchr(newfilename, '(');
			if(first != NULL) {
				first++;
				bool found = true;
				for(char *step = first; step < last - 1; step++)
					if(*step < '0' || *step > '9') {
						found = false;
						break;
					}
					if(found) {
						namecount = atoi(first);
						last = first - 1;
						last[0] = 0;  //truncate again
					}
			}
		}

		CString strTestName;
		do {
			namecount++;
			strTestName.Format("%s\\%s(%d).%s", theApp.glob_prefs->GetIncomingDir(),
				newfilename, namecount, min(ext + 1, newfilename + length));
		} while(PathFileExists(strTestName));
		delete[] newname;
		newname = nstrdup(strTestName);
	}
	delete newfilename;

	if (rename(partfilename,newname)){
		delete[] partfilename;
		delete[] newname;
		if (this) theApp.emuledlg->AddLogLine(true,GetResString(IDS_ERR_COMPLETIONFAILED),GetFileName());
		paused = true;
		status = PS_ERROR;
		theApp.downloadqueue->StartNextFile();
		return FALSE;
	}
	if (remove(fullname))
		theApp.emuledlg->AddLogLine(true,GetResString(IDS_ERR_DELETEFAILED),fullname);

	CString BAKName(fullname);
	BAKName.Append(".BAK");
	if (::DeleteFile(BAKName) == 0)
		theApp.emuledlg->AddLogLine(true,GetResString(IDS_ERR_DELETE), BAKName);

	delete[] partfilename;
	delete[] fullname;
	fullname = newname;
	delete[] directory;
	directory = nstrdup(indir);
	status = PS_COMPLETE;
	paused = false;
	theApp.emuledlg->AddLogLine(true,GetResString(IDS_DOWNLOADDONE),GetFileName());
	theApp.emuledlg->ShowNotifier(GetResString(IDS_TBN_DOWNLOADDONE)+"\n"+GetFileName(), TBN_DLOAD);
	if (renamed)
		theApp.emuledlg->AddLogLine(true, GetResString(IDS_DOWNLOADRENAMED), strrchr(newname, '\\') + 1);
	theApp.knownfiles->SafeAddKFile(this);
	theApp.downloadqueue->RemoveFile(this);
	//theApp.emuledlg->transferwnd.downloadlistctrl.UpdateItem(this);
	UpdateDisplayedInfo();
	theApp.emuledlg->transferwnd.downloadlistctrl.ShowFilesCount();
	//SHAddToRecentDocs(SHARD_PATH, fullname); // This is a real nasty call that takes ~110 ms on my 1.4 GHz Athlon and isn't really needed afai see...[ozon]

	// Barry - Just in case
	//		transfered = m_nFileSize;
	theApp.downloadqueue->StartNextFile();

	return TRUE;
}

void  CPartFile::RemoveAllSources(bool bTryToSwap){
	//TODO transfer sources to other downloading files if possible
	POSITION pos1,pos2;
	for (int sl=0;sl<SOURCESSLOTS;sl++) if (!srclists[sl].IsEmpty())
	for( pos1 = srclists[sl].GetHeadPosition(); ( pos2 = pos1 ) != NULL; ){
		srclists[sl].GetNext(pos1);
		if (bTryToSwap){
			if (!srclists[sl].GetAt(pos2)->SwapToAnotherFile(true))
				theApp.downloadqueue->RemoveSource(srclists[sl].GetAt(pos2));
		}
		else
			theApp.downloadqueue->RemoveSource(srclists[sl].GetAt(pos2));
	}
	UpdateFileRatingCommentAvail();
}

void CPartFile::DeleteFile(){
	ASSERT ( !m_bPreviewing );

	// Barry - Need to tell any connected clients to stop sending the file
	StopFile();

	theApp.sharedfiles->RemoveFile(this);
	theApp.downloadqueue->RemoveFile(this);
	theApp.emuledlg->transferwnd.downloadlistctrl.RemoveFile(this);

	if (m_hpartfile.m_hFile != INVALID_HANDLE_VALUE)
		m_hpartfile.Close();

	if (remove(fullname))
		theApp.emuledlg->AddLogLine(true,GetResString(IDS_ERR_DELETE),fullname);
	char* partfilename = nstrdup(fullname);
	partfilename[strlen(fullname)-4] = 0;
	if (remove(partfilename))
		theApp.emuledlg->AddLogLine(true,GetResString(IDS_ERR_DELETE),partfilename);

	CString BAKName(fullname);
	BAKName.Append(".BAK");
	if (::DeleteFile(BAKName) == 0)
		theApp.emuledlg->AddLogLine(true,GetResString(IDS_ERR_DELETE), BAKName);

	delete[] partfilename;
	delete this;
}

bool CPartFile::HashSinglePart(uint16 partnumber)
{
	if ((GetHashCount() <= partnumber) && (GetPartCount() > 1)){
		theApp.emuledlg->AddLogLine(true,GetResString(IDS_ERR_HASHERRORWARNING),GetFileName());
		this->hashsetneeded = true;
		return true;
	}
	else if(!GetPartHash(partnumber) && GetPartCount() != 1){
		theApp.emuledlg->AddLogLine(true,GetResString(IDS_ERR_INCOMPLETEHASH),GetFileName());
		this->hashsetneeded = true;
		return true;		
	}
	else{
		uchar hashresult[16];
		m_hpartfile.Seek((LONGLONG)PARTSIZE*partnumber,0);
		uint32 length = PARTSIZE;
		if (PARTSIZE*(partnumber+1) > m_hpartfile.GetLength())
			length = (m_hpartfile.GetLength()- (PARTSIZE*partnumber));
		CreateHashFromFile(&m_hpartfile,length,hashresult);

		if (GetPartCount() > 1){
			if (memcmp(hashresult,GetPartHash(partnumber),16))
				return false;
			else
				return true;
		}
		else{
			if (memcmp(hashresult,m_abyFileHash,16))
				return false;
			else
				return true;
		}
	}
}

bool CPartFile::IsCorruptedPart(uint16 partnumber){
	return corrupted_list.Find(partnumber);
}

bool CPartFile::IsMovie(){
	//TODO use filetags instead ststr
	CString extension = CString(GetFileName()).MakeLower();
	int pos=extension.ReverseFind('.');
	if (pos>=0) extension=extension.Mid(pos);
	return (extension.CompareNoCase(".avi")==0 || extension.CompareNoCase(".mpg")==0 || extension.CompareNoCase(".mpeg")==0 || extension.CompareNoCase(".ogm")==0 || extension.CompareNoCase(".bin")==0);
}

// Barry - Also want to preview zip/rar files
bool CPartFile::IsArchive()
{
	CString extension = CString(GetFileName()).Right(4);
	return ((extension.CompareNoCase(".zip") == 0) || (extension.CompareNoCase(".rar") == 0));
}

void CPartFile::SetDownPriority(uint8 np){
	m_iDownPriority = np;
	UpdateDisplayedInfo(true);
	SavePartFile();
}

void CPartFile::StopFile(){
	// Barry - Need to tell any connected clients to stop sending the file
	PauseFile();

	RemoveAllSources(true);
	paused = true;
	stopped=true;
	datarate = 0;
	transferingsrc = 0;
	FlushBuffer();
	UpdateDisplayedInfo(true);
}

void CPartFile::PauseFile(){
	if (status==PS_COMPLETE || status==PS_COMPLETING) return;
	Packet* packet = new Packet(OP_CANCELTRANSFER,0);
	POSITION pos1,pos2;
	for (int sl=0;sl<SOURCESSLOTS;sl++) if (!srclists[sl].IsEmpty())
	for( pos1 = srclists[sl].GetHeadPosition(); ( pos2 = pos1 ) != NULL; ){
		srclists[sl].GetNext(pos1);
		CUpDownClient* cur_src = srclists[sl].GetAt(pos2);
		if (cur_src->GetDownloadState() == DS_DOWNLOADING){
			theApp.uploadqueue->AddUpDataOverheadOther(packet->size);
			cur_src->socket->SendPacket(packet,false,true);
			cur_src->SetDownloadState(DS_ONQUEUE);
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -