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

📄 partfile.cpp

📁 非常出名开源客户端下载的程序emule
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	}
	delete packet;
	paused = true;
	datarate = 0;
	transferingsrc = 0;
	//theApp.emuledlg->transferwnd.downloadlistctrl.UpdateItem(this);
	UpdateDisplayedInfo(true);
	SavePartFile();
}

void CPartFile::ResumeFile(){
	if (status==PS_COMPLETE || status==PS_COMPLETING) return;
	paused = false;
	stopped=false;
	lastsearchtime = 0;
	SavePartFile();
	//theApp.emuledlg->transferwnd.downloadlistctrl.UpdateItem(this);
	UpdateDisplayedInfo(true);
}

CString CPartFile::getPartfileStatus(){ 

	switch(GetStatus()){
		case PS_HASHING:
		case PS_WAITINGFORHASH:
			return GetResString(IDS_HASHING);
		case PS_COMPLETING:
			return GetResString(IDS_COMPLETING);
		case PS_COMPLETE:
			return GetResString(IDS_COMPLETE);
		case PS_PAUSED:
			return GetResString(IDS_PAUSED);
		case PS_ERROR:
			return GetResString(IDS_ERRORLIKE);
	}
	if(GetTransferingSrcCount() > 0)
		return GetResString(IDS_DOWNLOADING);
	else
		return GetResString(IDS_WAITING);
} 

int CPartFile::getPartfileStatusRang(){ 
	
	int tempstatus=0;
	if (GetTransferingSrcCount()==0) tempstatus=1;
	switch (GetStatus()) {
		case PS_HASHING: 
		case PS_WAITINGFORHASH:
			tempstatus=3;
			break; 
		case PS_COMPLETING:
			tempstatus=4;
			break; 
		case PS_COMPLETE:
			tempstatus=5;
			break; 
		case PS_PAUSED:
			tempstatus=2;
			break; 
		case PS_ERROR:
			tempstatus=6;
			break;
	}

	return tempstatus;
} 

sint32 CPartFile::getTimeRemaining(){ 
	if (GetDatarate()==0) return -1;
	
	return( (GetFileSize()-GetCompletedSize())/ GetDatarate());
} 

void CPartFile::PreviewFile(){
	if (IsArchive())
	{
		if ((!m_bRecoveringArchive) && (!m_bPreviewing))
			CArchiveRecovery::recover(this, true);
		return;
	}

	if (!PreviewAvailable()){
		ASSERT( false );
		return;
	}


	if (theApp.glob_prefs->IsMoviePreviewBackup()) {
		m_bPreviewing = true;
		CPreviewThread* pThread = (CPreviewThread*) AfxBeginThread(RUNTIME_CLASS(CPreviewThread), THREAD_PRIORITY_NORMAL,0, CREATE_SUSPENDED);
		pThread->SetValues(this,theApp.glob_prefs->GetVideoPlayer());
		pThread->ResumeThread();
	} else {
		CString strLine = this->GetFullName();
		if (theApp.glob_prefs->GetVideoPlayer().Find("vlc.exe")) strLine.Replace(".met","");

		char shortPath[512]; //Cax2 short path for vlc
		GetShortPathName(strLine,shortPath,512);

		CString path=theApp.glob_prefs->GetVideoPlayer();
		int pos=path.ReverseFind('\\');
		if (pos==-1) path=""; else path=path.Left(pos+1);

		if (theApp.glob_prefs->GetVideoPlayer().GetLength()>0) ShellExecute(NULL, "open", theApp.glob_prefs->GetVideoPlayer() ,strLine/* shortPath*/, path, SW_SHOWNORMAL);
			else ShellExecute(NULL, "open", strLine, NULL,NULL, SW_SHOWNORMAL);
	}
}

bool CPartFile::PreviewAvailable(){
	uint64 space;
	space = 0;
	space = GetFreeDiskSpaceX(theApp.glob_prefs->GetTempDir());
	// Barry - Allow preview of archives of any length > 1k
	if (IsArchive()) 
		if (GetStatus() != PS_COMPLETE &&  GetStatus() != PS_COMPLETING && ( GetFileSize() > 1024) && (!m_bRecoveringArchive) && ((space + 100000000) > (2*GetFileSize())))
			return true; else return false;

	if (theApp.glob_prefs->IsMoviePreviewBackup())
		return !( (GetStatus() != PS_READY && GetStatus() != PS_PAUSED) 
			|| m_bPreviewing || GetPartCount() < 5 || !IsMovie() || (space + 100000000) < GetFileSize() 
			|| ( !IsComplete(0,PARTSIZE-1) || !IsComplete(PARTSIZE*(GetPartCount()-1),GetFileSize()-1)));
	else 
		return !((GetStatus() != PS_READY && GetStatus() != PS_PAUSED) 
				|| m_bPreviewing || GetPartCount() < 2 || !IsMovie() || !IsComplete(0,PARTSIZE-1)); 
}

void CPartFile::UpdateAvailablePartsCount(){
	uint8 availablecounter = 0;
	bool breakflag = false;
	uint16 iPartCount = GetPartCount();
	for (uint32 ixPart = 0; ixPart < iPartCount; ixPart++){
		breakflag = false;
		for (uint32 sl = 0; sl < SOURCESSLOTS && !breakflag; sl++){
			if (!srclists[sl].IsEmpty()){
				for(POSITION pos = srclists[sl].GetHeadPosition(); pos && !breakflag; ){
					if (srclists[sl].GetNext(pos)->IsPartAvailable(ixPart)){ 
						availablecounter++; 
						breakflag = true;
					}
				}
			}
		}
	}
	if (iPartCount == availablecounter && availablePartsCount < iPartCount)
		lastseencomplete = CTime::GetCurrentTime();
	availablePartsCount = availablecounter;
}

Packet*	CPartFile::CreateSrcInfoPacket(CUpDownClient* forClient){
	int sl;
	bool empty=true;
	for (sl=0;sl<SOURCESSLOTS;sl++) if (!srclists[sl].IsEmpty()) {empty=false;break;}
	if (empty) return 0;

	CMemFile data;
	uint16 nCount = 0;

	data.Write(m_abyFileHash,16);
	data.Write(&nCount,2);
	bool bNeeded;
	for (sl=0;sl<SOURCESSLOTS;sl++) if (!srclists[sl].IsEmpty())
	for (POSITION pos = srclists[sl].GetHeadPosition();pos != 0;srclists[sl].GetNext(pos)){
		bNeeded = false;
		CUpDownClient* cur_src = srclists[sl].GetAt(pos);
		if (cur_src->HasLowID())
			continue;
		// only send source which have needed parts for this client if possible
		if (forClient->reqfile == this && forClient->GetPartStatus() && cur_src->GetPartStatus()){
			uint8* reqstatus = forClient->GetPartStatus();
			uint8* srcstatus = cur_src->GetPartStatus();
			for (int x = 0; x < GetPartCount(); x++){
				if (srcstatus[x] && !reqstatus[x]){
					bNeeded = true;
					break;
				}
			}
		}
		if( bNeeded ){
			nCount++;
			uint32 dwID = cur_src->GetUserID();
			uint16 nPort = cur_src->GetUserPort();
			uint32 dwServerIP = cur_src->GetServerIP();
			uint16 nServerPort = cur_src->GetServerPort();
			data.Write(&dwID, 4);
			data.Write(&nPort, 2);
			data.Write(&dwServerIP, 4);
			data.Write(&nServerPort, 2);
			if (forClient->GetSourceExchangeVersion() > 1)
				data.Write(cur_src->GetUserHash(),16);
			if (nCount > 500)
				break;
		}
	}
	if (!nCount)
		return 0;
	data.Seek(16, 0);
	data.Write(&nCount, 2);

	Packet* result = new Packet(&data, OP_EMULEPROT);
	result->opcode = OP_ANSWERSOURCES;
	if (nCount > 28)
		result->PackPacket();
	theApp.emuledlg->AddDebugLogLine( false, "Send:Source User(%s) File(%s) Count(%i)", forClient->GetUserName(), GetFileName(), nCount );
	return result;
}

void CPartFile::AddClientSources(CMemFile* sources, uint8 sourceexchangeversion){
	if (stopped) return;
	uint16 nCount;
	sources->Read(&nCount,2);
	theApp.emuledlg->AddDebugLogLine( false, "RCV:Sources File(%s) Count(%i)", GetFileName(), nCount );
	for (int i = 0;i != nCount;i++){
		uint32 dwID;
		uint16 nPort;
		uint32 dwServerIP;
		uint16 nServerPort;
		uchar m_achUserHash[16];
		sources->Read(&dwID,4);
		sources->Read(&nPort,2);
		sources->Read(&dwServerIP,4);
		sources->Read(&nServerPort,2);
		if (sourceexchangeversion > 1)
			sources->Read(m_achUserHash,16);
		// check first if we are this source
		if (theApp.serverconnect->GetClientID() < 16777216 && theApp.serverconnect->IsConnected()){
			if ((theApp.serverconnect->GetClientID() == dwID) && theApp.serverconnect->GetCurrentServer()->GetIP() == dwServerIP)
				continue;
		}
		else if (theApp.serverconnect->GetClientID() == dwID)
			continue;
		else if (dwID < 16777216)
			continue;
		if( theApp.glob_prefs->GetMaxSourcePerFile() > this->GetSourceCount() ){
			CUpDownClient* newsource = new CUpDownClient(nPort,dwID,dwServerIP,nServerPort,this);
			if (sourceexchangeversion > 1)
				newsource->SetUserHash(m_achUserHash);
			theApp.downloadqueue->CheckAndAddSource(this,newsource);
		} 
	}
}

// making this function return a higher when more sources have the extended
// protocol will force you to ask a larger variety of people for sources
int CPartFile::GetCommonFilePenalty() {
	//TODO: implement, but never return less than MINCOMMONPENALTY!
	return MINCOMMONPENALTY;
}

/* Barry - Replaces BlockReceived() 

           Originally this only wrote to disk when a full 180k block 
           had been received from a client, and only asked for data in 
		   180k blocks.

		   This meant that on average 90k was lost for every connection
		   to a client data source. That is a lot of wasted data.

		   To reduce the lost data, packets are now written to a buffer
		   and flushed to disk regularly regardless of size downloaded.
		   This includes compressed packets.

		   Data is also requested only where gaps are, not in 180k blocks.
		   The requests will still not exceed 180k, but may be smaller to
		   fill a gap.
*/
uint32 CPartFile::WriteToBuffer(uint32 transize, BYTE *data, uint32 start, uint32 end, Requested_Block_Struct *block)
{
	// Increment transfered bytes counter for this file
	transfered += transize;

	// This is needed a few times
	uint32 lenData = end - start + 1;

	if( lenData > transize )
		m_iGainDueToCompression += lenData-transize;

	// Occasionally packets are duplicated, no point writing it twice
	if (IsComplete(start, end))
	{
		theApp.emuledlg->AddDebugLogLine(false, "File '%s' has already been written from %ld to %ld", GetFileName(), start, end);
		return 0;
	}

	// Create copy of data as new buffer
	BYTE *buffer = new BYTE[lenData];
	memcpy(buffer, data, lenData);

	// Create a new buffered queue entry
	PartFileBufferedData *item = new PartFileBufferedData;
	item->data = buffer;
	item->start = start;
	item->end = end;
	item->block = block;

	// Add to the queue in the correct position (most likely the end)
	PartFileBufferedData *queueItem;
	bool added = false;
	POSITION pos = m_BufferedData_list.GetTailPosition();
	while (pos != NULL)
	{	
		queueItem = m_BufferedData_list.GetPrev(pos);
		if (item->end > queueItem->end)
		{
			added = true;
			m_BufferedData_list.InsertAfter(pos, item);
			break;
		}
	}
	if (!added)
		m_BufferedData_list.AddHead(item);

	// Increment buffer size marker
	m_nTotalBufferData += lenData;

	// Mark this small section of the file as filled
	FillGap(item->start, item->end);

	// Update the flushed mark on the requested block 
	// The loop here is unfortunate but necessary to detect deleted blocks.
	pos = requestedblocks_list.GetHeadPosition();
	while (pos != NULL)
	{	
		if (requestedblocks_list.GetNext(pos) == item->block)
			item->block->transferred += lenData;
	}

	if (gaplist.IsEmpty()) FlushBuffer();

	// Return the length of data written to the buffer
	return lenData;
}

void CPartFile::FlushBuffer(void)
{
	m_nLastBufferFlushTime = GetTickCount();
	if (m_BufferedData_list.IsEmpty())
		return;

	uint32 partCount = GetPartCount();
	bool *changedPart = new bool[partCount];

//	theApp.emuledlg->AddDebugLogLine(false, "Flushing file %s - buffer size = %ld bytes (%ld queued items) transfered = %ld [time = %ld]\n", GetFileName(), m_nTotalBufferData, m_BufferedData_list.GetCount(), transfered, m_nLastBufferFlushTime);

	try
	{
		// Remember which parts need to be checked at the end of the flush
		for (int partNumber=0; (uint32)partNumber<partCount; partNumber++)
		{
			changedPart[partNumber] = false;
		}

		// Ensure file is big enough to write data to (the last item will be the furthest from the start)
		PartFileBufferedData *item = m_BufferedData_list.GetTail();
		if (m_hpartfile.GetLength() <= item->end)
			m_hpartfile.SetLength(item->end + 1);

		// Loop through queue
		for (int i = m_BufferedData_list.GetCount(); i>0; i--)
		{
			// Get top item
			item = m_BufferedData_list.GetHead();

			// This is needed a few times
			uint32 lenData = item->end - item->start + 1;

			int curpart = item->start/PARTSIZE;
			changedPart[curpart] = true;

			// Go to the correct position in file and write block of data			
			m_hpartfile.Seek(item->start, CFile::begin);
			m_hpartfile.Write(item->data, lenData);
			
			// Remove item from queue
			m_BufferedData_list.RemoveHead();

			// Decrease buffer size
			m_nTotalBufferData -= lenData;

			// Release memory used by this item
			delete [] item->data;
			delete item;
		}

		// Flush to disk
		m_hpartfile.Flush();

		// Check each part of the file
		uint32 partRange = (m_hpartfile.GetLength() % PARTSIZE) - 1;
		for (int partNumber = partCount-1; partNumber >= 0; partNumber--)
		{
			if (changedPart[partNumber] == false)
			{
				// Any parts other than last must be full size
				partRange = PARTSIZE - 1;
				continue;
			}

			// Is this 9MB part complete
			if ( IsComplete(PARTSIZE * partNumber, (PARTSIZE * (partNumber + 1)) - 1 ) )
			{
				// Is part corrupt
				if (!HashSinglePart(partNumber))
				{
					theApp.emuledlg->AddLogLine(true, GetResString(IDS_ERR_PARTCORRUPT), partNumber, GetFileName());
					AddGap(PARTSIZE*partNumber, (PARTSIZE*partNumber + partRange));
					corrupted_list.AddTail(partNumber);
					// Reduce transfered amount by corrupt amount
					this->m_iLostDueToCorruption += (partRange + 1);
				}
				else
				{
					// Successfully completed part, make it available for sharing
					if (status == PS_EMPTY)
					{
						status = PS_READY;
						

⌨️ 快捷键说明

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