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

📄 partfile.cpp

📁 非常出名开源客户端下载的程序emule
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		addfilethread->ResumeThread();
	}

	UpdateCompletedInfos();
	if ( completedsize > transfered )
		m_iGainDueToCompression = completedsize - transfered;
	else if ( completedsize != transfered )
		m_iLostDueToCorruption = transfered - completedsize;
	return true;
}

bool CPartFile::SavePartFile(){
	switch (status){
		case PS_WAITINGFORHASH:
		case PS_HASHING:
			return false;
	}
	FILE* file = 0;
	CString BAKName(fullname); // quick hack to make a perm backup of the met file, should probably be changed...
	BAKName.Append(".BAK");

	try{
		//get filedate
		CFileFind ff;
		char* searchpath = nstrdup(fullname);
		searchpath[strlen(fullname)-4] = 0;
		bool end = !ff.FindFile(searchpath,0);
		delete[] searchpath;
		if (!end)
			ff.FindNextFile();
		if (end || ff.IsDirectory())
			throw GetResString(IDS_ERR_PART_FNF);
		CTime lwtime;
		ff.GetLastWriteTime(lwtime);
		date = mktime(lwtime.GetLocalTm());
		ff.Close();
		uint32 lsc = mktime(lastseencomplete.GetLocalTm());
		CString backupName(fullname);
		backupName.Append(".backup");

		remove(backupName);
		rename(fullname, backupName);

		// readfile data form part.met file
		file = fopen(fullname,"wbS");
		if (!file)
			throw GetResString(IDS_ERR_OPENMETFILE);
		//version
		uint8 version = PARTFILE_VERSION;
		fwrite(&version,1,1,file);
		//date
		fwrite(&date,4,1,file);
		//hash
		fwrite(&m_abyFileHash,16,1,file);
		uint16 parts = hashlist.GetCount();
		fwrite(&parts,2,1,file);
		for (int x = 0; x != parts; x++)
			fwrite(hashlist[x],16,1,file);
		//tags
		uint32 tagcount = taglist.GetCount()+8+(gaplist.GetCount()*2);
		fwrite(&tagcount,4,1,file);
		CTag* nametag = new CTag(FT_FILENAME, m_pszFileName);
		nametag->WriteTagToFile(file);
		delete nametag;
		CTag* sizetag = new CTag(FT_FILESIZE, m_nFileSize);
		sizetag->WriteTagToFile(file);
		delete sizetag;
		CTag* transtag = new CTag(FT_TRANSFERED, transfered);
		transtag->WriteTagToFile(file);
		delete transtag;
		CTag* statustag = new CTag(FT_STATUS, (paused)? 1: 0);
		statustag->WriteTagToFile(file);
		delete statustag;
		CTag* prioritytag ;
		uint8 autoprio = PR_AUTO;
		if( this->IsAutoDownPriority() )
			prioritytag = new CTag(FT_DLPRIORITY,autoprio);
		else
			prioritytag = new CTag(FT_DLPRIORITY,m_iDownPriority);
		prioritytag->WriteTagToFile(file);
		delete prioritytag;
		CTag* lsctag = new CTag(FT_LASTSEENCOMPLETE,lsc);
		lsctag->WriteTagToFile(file);
		delete lsctag;
		CTag* ulprioritytag;
		if( this->IsAutoUpPriority() )
			ulprioritytag = new CTag(FT_ULPRIORITY,autoprio);
		else
			ulprioritytag = new CTag(FT_ULPRIORITY,GetUpPriority());
		ulprioritytag->WriteTagToFile(file);
		delete ulprioritytag;

		CTag* categorytag = new CTag(FT_CATEGORY, m_category );
		categorytag->WriteTagToFile(file);
		delete categorytag;

		for (uint32 j = 0; j != taglist.GetCount();j++)
			taglist[j]->WriteTagToFile(file);
		//gaps
		char* namebuffer = new char[10];
		char* number = &namebuffer[1];
		uint16 i_pos = 0;
		for (POSITION pos = gaplist.GetHeadPosition();pos != 0;gaplist.GetNext(pos)){
			itoa(i_pos,number,10);
			namebuffer[0] = FT_GAPSTART;
			CTag* gapstarttag = new CTag(namebuffer,gaplist.GetAt(pos)->start);
			gapstarttag->WriteTagToFile(file);
			// gap start = first missing byte but gap ends = first non-missing byte in edonkey
			// but I think its easier to user the real limits
			namebuffer[0] = FT_GAPEND;
			CTag* gapendtag = new CTag(namebuffer,(gaplist.GetAt(pos)->end)+1);
			gapendtag->WriteTagToFile(file);
			delete gapstarttag;
			delete gapendtag;
			i_pos++;
		}
		delete[] namebuffer;

		if (ferror(file))
			throw CString("unexpected write error");

		remove(backupName);
	}
	catch(char* error){
		OUTPUT_DEBUG_TRACE();
		if (file)
			fclose(file);
		theApp.emuledlg->AddLogLine(false, GetResString(IDS_ERR_SAVEMET), error, partmetfilename, m_pszFileName);
		return false;
	}
	catch(CString error){
		OUTPUT_DEBUG_TRACE();
		if (file)
			fclose(file);
		theApp.emuledlg->AddLogLine(false, GetResString(IDS_ERR_SAVEMET), error.GetBuffer(), partmetfilename, m_pszFileName);
		return false;
	}
	fclose(file);
	::CopyFile(fullname, BAKName, FALSE);
	return true;
}

void CPartFile::PartFileHashFinished(CKnownFile* result){
	newdate = true;
	bool errorfound = false;
	for (uint32 i = 0; i != hashlist.GetSize(); i++){
		if (IsComplete(i*PARTSIZE,((i+1)*PARTSIZE)-1)){
			if (!(result->GetPartHash(i) && !memcmp(result->GetPartHash(i),this->GetPartHash(i),16))){
				theApp.emuledlg->AddLogLine(false, GetResString(IDS_ERR_FOUNDCORRUPTION), i+1, m_pszFileName);		
				AddGap(i*PARTSIZE,((((i+1)*PARTSIZE)-1) >= m_nFileSize) ? m_nFileSize-1 : ((i+1)*PARTSIZE)-1);
				errorfound = true;
			}
		}
	}
	delete result;
	if (!errorfound){
		if (status == PS_COMPLETING){
			CompleteFile(true);
			return;
		}
		else
			theApp.emuledlg->AddLogLine(false, GetResString(IDS_HASHINGDONE), m_pszFileName);
	}
	else{
		status = PS_READY;
		SavePartFile();
		return;
	}
	status = PS_READY;
	SavePartFile();
	theApp.sharedfiles->SafeAddKFile(this);
}

void CPartFile::AddGap(uint32 start, uint32 end){
	POSITION pos1, pos2;
	for (pos1 = gaplist.GetHeadPosition();(pos2 = pos1) != NULL;){
		Gap_Struct* cur_gap = gaplist.GetNext(pos1);
		if (cur_gap->start >= start && cur_gap->end <= end){ // this gap is inside the new gap - delete
			gaplist.RemoveAt(pos2);
			delete cur_gap;
			continue;
		}
		else if (cur_gap->start >= start && cur_gap->start <= end){// a part of this gap is in the new gap - extend limit and delete
			end = cur_gap->end;
			gaplist.RemoveAt(pos2);
			delete cur_gap;
			continue;
		}
		else if (cur_gap->end <= end && cur_gap->end >= start){// a part of this gap is in the new gap - extend limit and delete
			start = cur_gap->start;
			gaplist.RemoveAt(pos2);
			delete cur_gap;
			continue;
		}
		else if (start >= cur_gap->start && end <= cur_gap->end){// new gap is already inside this gap - return
			return;
		}
	}
	Gap_Struct* new_gap = new Gap_Struct;
	new_gap->start = start;
	new_gap->end = end;
	gaplist.AddTail(new_gap);
	//theApp.emuledlg->transferwnd.downloadlistctrl.UpdateItem(this);
	UpdateDisplayedInfo();
	newdate = true;
}

bool CPartFile::IsComplete(uint32 start, uint32 end){
	if (end >= m_nFileSize)
		end = m_nFileSize-1;
	for (POSITION pos = gaplist.GetHeadPosition();pos != 0;gaplist.GetNext(pos)){
		Gap_Struct* cur_gap = gaplist.GetAt(pos);
		if ((cur_gap->start >= start && cur_gap->end <= end)||(cur_gap->start >= start 
			&& cur_gap->start <= end)||(cur_gap->end <= end && cur_gap->end >= start)
			||(start >= cur_gap->start && end <= cur_gap->end))
		{
			return false;	
		}
	}
	return true;
}

bool CPartFile::IsPureGap(uint32 start, uint32 end){
	if (end >= m_nFileSize)
		end = m_nFileSize-1;
	for (POSITION pos = gaplist.GetHeadPosition();pos != 0;gaplist.GetNext(pos)){
		Gap_Struct* cur_gap = gaplist.GetAt(pos);
		if (start >= cur_gap->start  && end <= cur_gap->end ){
			return true;
		}
	}
	return false;
}

bool CPartFile::IsAlreadyRequested(uint32 start, uint32 end){
	for (POSITION pos =  requestedblocks_list.GetHeadPosition();pos != 0; requestedblocks_list.GetNext(pos)){
		Requested_Block_Struct* cur_block =  requestedblocks_list.GetAt(pos);
		if ((start <= cur_block->EndOffset) && (end >= cur_block->StartOffset))
			return true;
	}
	return false;
}

/* rewritten
bool CPartFile::GetNextEmptyBlockInPart(uint16 partnumber,Requested_Block_Struct* result){
	for (uint32 i = 0; i != ceil((float)PARTSIZE/BLOCKSIZE);i++){
		uint32 start = (PARTSIZE*partnumber) + i*BLOCKSIZE;
		uint32 end	 = (PARTSIZE*partnumber) + ((i+1)*BLOCKSIZE)-1;
		if (end >= (uint32)PARTSIZE*(partnumber+1))
			end = (PARTSIZE*(partnumber+1))-1;
		if (start >= GetFileSize())
			break;
		if (end >= GetFileSize())
			end = GetFileSize()-1;
		if ( (!IsComplete(start,end)) && !IsAlreadyRequested(start,end)){
			if (result){
				result->StartOffset = start;
				result->EndOffset = end;
				memcpy(result->FileID,GetFileHash(),16);
			}
			return true;
		}
	}
	return false;
}
*/
bool CPartFile::GetNextEmptyBlockInPart(uint16 partNumber, Requested_Block_Struct *result)
{
	Gap_Struct *firstGap;
	Gap_Struct *currentGap;
	uint32 end;
	uint32 blockLimit;

	// Find start of this part
	uint32 partStart = (PARTSIZE * partNumber);
	uint32 start = partStart;

	// What is the end limit of this block, i.e. can't go outside part (or filesize)
	uint32 partEnd = (PARTSIZE * (partNumber + 1)) - 1;
	if (partEnd >= GetFileSize())
		partEnd = GetFileSize() - 1;

	// Loop until find a suitable gap and return true, or no more gaps and return false
	while (true)
	{
		firstGap = NULL;

		// Find the first gap from the start position
		for (POSITION pos = gaplist.GetHeadPosition(); pos != 0; gaplist.GetNext(pos))
		{
			currentGap = gaplist.GetAt(pos);
			// Want gaps that overlap start<->partEnd
			if ((currentGap->start <= partEnd) && (currentGap->end >= start))
			{
				// Is this the first gap?
				if ((firstGap == NULL) || (currentGap->start < firstGap->start))
					firstGap = currentGap;
			}
		}

		// If no gaps after start, exit
		if (firstGap == NULL)
			return false;

		// Update start position if gap starts after current pos
		if (start < firstGap->start)
			start = firstGap->start;

		// If this is not within part, exit
		if (start > partEnd)
			return false;

		// Find end, keeping within the max block size and the part limit
		end = firstGap->end;
		blockLimit = partStart + (BLOCKSIZE * (((start - partStart) / BLOCKSIZE) + 1)) - 1;
		if (end > blockLimit)
			end = blockLimit;
		if (end > partEnd)
			end = partEnd;
    
		// If this gap has not already been requested, we have found a valid entry
		if (!IsAlreadyRequested(start, end))
		{
			// Was this block to be returned
			if (result != NULL)
			{
				result->StartOffset = start;
				result->EndOffset = end;
				memcpy(result->FileID, GetFileHash(), 16);
				result->transferred = 0;
			}
			return true;
		}
		else
		{
			// Reposition to end of that gap
			start = end + 1;
		}

		// If tried all gaps then break out of the loop
		if (end == partEnd)
			break;
	}

	// No suitable gap found
	return false;
}

void CPartFile::FillGap(uint32 start, uint32 end){
	POSITION pos1, pos2;
	for (pos1 = gaplist.GetHeadPosition();(pos2 = pos1) != NULL;){
		Gap_Struct* cur_gap = gaplist.GetNext(pos1);
		if (cur_gap->start >= start && cur_gap->end <= end){ // our part fills this gap completly
			gaplist.RemoveAt(pos2);
			delete cur_gap;
			continue;
		}
		else if (cur_gap->start >= start && cur_gap->start <= end){// a part of this gap is in the part - set limit
			cur_gap->start = end+1;
		}
		else if (cur_gap->end <= end && cur_gap->end >= start){// a part of this gap is in the part - set limit
			cur_gap->end = start-1;
		}
		else if (start >= cur_gap->start && end <= cur_gap->end){
			uint32 buffer = cur_gap->end;
			cur_gap->end = start-1;
			cur_gap = new Gap_Struct;
			cur_gap->start = end+1;
			cur_gap->end = buffer;
			gaplist.InsertAfter(pos1,cur_gap);
			break; // [Lord KiRon]
		}
	}

	UpdateCompletedInfos();
	//theApp.emuledlg->transferwnd.downloadlistctrl.UpdateItem(this);
	UpdateDisplayedInfo();
	newdate = true;
	// Barry - The met file is now updated in FlushBuffer()
	//SavePartFile();
}

void CPartFile::UpdateCompletedInfos()
{
   	uint32 allgaps = 0; 

	for (POSITION pos = gaplist.GetHeadPosition(); pos != 0; gaplist.GetNext(pos)){ 
		Gap_Struct* cur_gap = gaplist.GetAt(pos); 
		allgaps += cur_gap->end - cur_gap->start;
	}

	if (gaplist.GetCount() || requestedblocks_list.GetCount()){ 
		percentcompleted = (1.0f-(float)allgaps/m_nFileSize) * 100; 
		completedsize = m_nFileSize - allgaps - 1; 
	} 
	else{
		percentcompleted = 100;
		completedsize = m_nFileSize;
	}
}

void CPartFile::DrawShareStatusBar(CDC* dc, RECT* rect, bool onlygreyrect, bool  bFlat){ 
	COLORREF crProgress;
	COLORREF crHave;
	COLORREF crPending;
	COLORREF crMissing = RGB(255, 0, 0);

	if(bFlat) { 
		crProgress = RGB(0, 150, 0);
		crHave = RGB(0, 0, 0);
		crPending = RGB(255,208,0);
	} else { 
		crProgress = RGB(0, 224, 0);
		crHave = RGB(104, 104, 104);
		crPending = RGB(255, 208, 0);
	} 

⌨️ 快捷键说明

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