📄 partfile.cpp
字号:
if(bFlat) {
crHave = RGB(64, 64, 64);
crPending = RGB(191,168,64);
} else {
crHave = RGB(116, 116, 116);
crPending = RGB(191, 168, 64);
}
}
// SLUGFILLER: grayPause
s_ChunkBar.SetHeight(rect->bottom - rect->top);
s_ChunkBar.SetWidth(rect->right - rect->left);
s_ChunkBar.SetFileSize(m_nFileSize);
s_ChunkBar.Fill(crHave);
if (status == PS_COMPLETE || status == PS_COMPLETING)
{
s_ChunkBar.FillRange(0, m_nFileSize, crProgress);
s_ChunkBar.Draw(dc, rect->left, rect->top, bFlat);
percentcompleted = 100.0F;
completedsize = m_nFileSize;
}
else if (theApp.m_brushBackwardDiagonal.m_hObject && eVirtualState == PS_INSUFFICIENT || status == PS_ERROR)
{
int iOldBkColor = dc->SetBkColor(RGB(255, 255, 0));
dc->FillRect(rect, &theApp.m_brushBackwardDiagonal);
dc->SetBkColor(iOldBkColor);
UpdateCompletedInfos();
}
else
{
// red gaps
uint32 allgaps = 0;
for (POSITION pos = gaplist.GetHeadPosition();pos != 0;){
const Gap_Struct* cur_gap = gaplist.GetNext(pos);
allgaps += cur_gap->end - cur_gap->start + 1;
bool gapdone = false;
uint32 gapstart = cur_gap->start;
uint32 gapend = cur_gap->end;
for (uint32 i = 0; i < GetPartCount(); i++){
if (gapstart >= i*PARTSIZE && gapstart <= (i+1)*PARTSIZE - 1){ // is in this part?
if (gapend <= (i+1)*PARTSIZE - 1)
gapdone = true;
else
gapend = (i+1)*PARTSIZE - 1; // and next part
// paint
COLORREF color;
if (m_SrcpartFrequency.GetCount() >= (INT_PTR)i && m_SrcpartFrequency[(uint16)i])
// SLUGFILLER: grayPause
{
if(notgray)
color = RGB(0,
(210-(22*(m_SrcpartFrequency[(uint16)i]-1)) < 0)? 0:210-(22*(m_SrcpartFrequency[(uint16)i]-1))
,255);
else
color = RGB(64,
(169-(11*(m_SrcpartFrequency[(uint16)i]-1)) < 64)? 64:169-(11*(m_SrcpartFrequency[(uint16)i]-1))
,191);
}
// SLUGFILLER: grayPause
else
color = crMissing;
s_ChunkBar.FillRange(gapstart, gapend + 1, color);
if (gapdone) // finished?
break;
else{
gapstart = gapend + 1;
gapend = cur_gap->end;
}
}
}
}
// yellow pending parts
for (POSITION pos = requestedblocks_list.GetHeadPosition();pos != 0;){
const Requested_Block_Struct* block = requestedblocks_list.GetNext(pos);
s_ChunkBar.FillRange(block->StartOffset + block->transferred, block->EndOffset + 1, crPending);
}
s_ChunkBar.Draw(dc, rect->left, rect->top, bFlat);
// green progress
float blockpixel = (float)(rect->right - rect->left)/(float)m_nFileSize;
RECT gaprect;
gaprect.top = rect->top;
gaprect.bottom = gaprect.top + PROGRESS_HEIGHT; // Barry - was 4
gaprect.left = rect->left;
if(!bFlat) {
s_LoadBar.SetWidth((m_nFileSize - allgaps)*blockpixel + 0.5F);
s_LoadBar.Fill(crProgress);
s_LoadBar.Draw(dc, gaprect.left, gaprect.top, false);
} else {
gaprect.right = rect->left + (uint32)((m_nFileSize - allgaps)*blockpixel + 0.5F);
dc->FillRect(&gaprect, &CBrush(crProgress));
//draw gray progress only if flat
gaprect.left = gaprect.right;
gaprect.right = rect->right;
dc->FillRect(&gaprect, &CBrush(RGB(224,224,224)));
}
UpdateCompletedInfos(allgaps);
}
// additionally show any file op progress (needed for PS_COMPLETING and PS_WAITINGFORHASH)
if (GetFileOp() != PFOP_NONE)
{
float blockpixel = (float)(rect->right - rect->left)/100.0F;
CRect rcFileOpProgress;
rcFileOpProgress.top = rect->top;
rcFileOpProgress.bottom = rcFileOpProgress.top + PROGRESS_HEIGHT;
rcFileOpProgress.left = rect->left;
if (!bFlat)
{
s_LoadBar.SetWidth(GetFileOpProgress()*blockpixel + 0.5F);
s_LoadBar.Fill(RGB(255,208,0));
s_LoadBar.Draw(dc, rcFileOpProgress.left, rcFileOpProgress.top, false);
}
else
{
rcFileOpProgress.right = rcFileOpProgress.left + (UINT)(GetFileOpProgress()*blockpixel + 0.5F);
dc->FillRect(&rcFileOpProgress, &CBrush(RGB(255,208,0)));
rcFileOpProgress.left = rcFileOpProgress.right;
rcFileOpProgress.right = rect->right;
dc->FillRect(&rcFileOpProgress, &CBrush(RGB(224,224,224)));
}
}
}
void CPartFile::WritePartStatus(CSafeMemFile* file) const
{
UINT uED2KPartCount = GetED2KPartCount();
file->WriteUInt16(uED2KPartCount);
UINT uPart = 0;
while (uPart != uED2KPartCount)
{
uint8 towrite = 0;
for (UINT i = 0; i < 8; i++)
{
if (uPart < GetPartCount() && IsComplete(uPart*PARTSIZE, (uPart + 1)*PARTSIZE - 1))
towrite |= (1 << i);
uPart++;
if (uPart == uED2KPartCount)
break;
}
file->WriteUInt8(towrite);
}
}
void CPartFile::WriteCompleteSourcesCount(CSafeMemFile* file) const
{
file->WriteUInt16(m_nCompleteSourcesCount);
}
int CPartFile::GetValidSourcesCount() const
{
int counter = 0;
for (POSITION pos = srclist.GetHeadPosition(); pos != NULL;){
EDownloadState nDLState = srclist.GetNext(pos)->GetDownloadState();
if (nDLState==DS_ONQUEUE || nDLState==DS_DOWNLOADING || nDLState==DS_CONNECTED || nDLState==DS_REMOTEQUEUEFULL)
++counter;
}
return counter;
}
uint16 CPartFile::GetNotCurrentSourcesCount() const
{
UINT counter = 0;
for (POSITION pos = srclist.GetHeadPosition(); pos != NULL;){
EDownloadState nDLState = srclist.GetNext(pos)->GetDownloadState();
if (nDLState!=DS_ONQUEUE && nDLState!=DS_DOWNLOADING)
counter++;
}
return counter;
}
// SLUGFILLER: checkDiskspace
uint32 CPartFile::GetNeededSpace() const
{
if (m_hpartfile.GetLength() > GetFileSize())
return 0; // Shouldn't happen, but just in case
return GetFileSize()-m_hpartfile.GetLength();
}
// SLUGFILLER: checkDiskspace
EPartFileStatus CPartFile::GetStatus(bool ignorepause) const
{
// SLUGFILLER: checkDiskspace
if ((!paused && !insufficient) || status == PS_ERROR || status == PS_COMPLETING || status == PS_COMPLETE || ignorepause)
return status;
else if (paused)
return PS_PAUSED;
else
return PS_INSUFFICIENT;
// SLUGFILLER: checkDiskspace
}
void CPartFile::AddDownloadingSource(CUpDownClient* client){
POSITION pos = m_downloadingSourceList.Find(client); // to be sure
if(pos == NULL){
m_downloadingSourceList.AddTail(client);
}
}
void CPartFile::RemoveDownloadingSource(CUpDownClient* client){
POSITION pos = m_downloadingSourceList.Find(client); // to be sure
if(pos != NULL){
m_downloadingSourceList.RemoveAt(pos);
}
}
uint32 CPartFile::Process(uint32 reducedownload, uint8 m_icounter/*in percent*/)
{
if (thePrefs.m_iDbgHeap >= 2)
ASSERT_VALID(this);
uint16 nOldTransSourceCount = GetSrcStatisticsValue(DS_DOWNLOADING);
DWORD dwCurTick = ::GetTickCount();
// If buffer size exceeds limit, or if not written within time limit, flush data
if ((m_nTotalBufferData > thePrefs.GetFileBufferSize()) || (dwCurTick > (m_nLastBufferFlushTime + BUFFER_TIME_LIMIT)))
{
// Avoid flushing while copying preview file
if (!m_bPreviewing)
FlushBuffer();
}
datarate = 0;
// calculate datarate, set limit etc.
if(m_icounter < 10)
{
uint32 cur_datarate;
for(POSITION pos = m_downloadingSourceList.GetHeadPosition();pos!=0;)
{
CUpDownClient* cur_src = m_downloadingSourceList.GetNext(pos);
if (thePrefs.m_iDbgHeap >= 2)
ASSERT_VALID( cur_src );
if(cur_src && cur_src->GetDownloadState() == DS_DOWNLOADING)
{
ASSERT( cur_src->socket );
if (cur_src->socket)
{
cur_src->CheckDownloadTimeout();
cur_datarate = cur_src->CalculateDownloadRate();
datarate+=cur_datarate;
if(reducedownload)
{
uint32 limit = reducedownload*cur_datarate/1000;
if(limit<1000 && reducedownload == 200)
limit +=1000;
else if(limit<200 && cur_datarate == 0 && reducedownload >= 100)
limit = 200;
else if(limit<60 && cur_datarate < 600 && reducedownload >= 97)
limit = 60;
else if(limit<20 && cur_datarate < 200 && reducedownload >= 93)
limit = 20;
else if(limit<1)
limit = 1;
cur_src->socket->SetDownloadLimit(limit);
if (cur_src->IsDownloadingFromPeerCache() && cur_src->m_pPCDownSocket && cur_src->m_pPCDownSocket->IsConnected())
cur_src->m_pPCDownSocket->SetDownloadLimit(limit);
}
}
}
}
}
else
{
bool downloadingbefore=m_anStates[DS_DOWNLOADING]>0;
// -khaos--+++> Moved this here, otherwise we were setting our permanent variables to 0 every tenth of a second...
memset(m_anStates,0,sizeof(m_anStates));
memset(src_stats,0,sizeof(src_stats));
memset(net_stats,0,sizeof(net_stats));
uint16 nCountForState;
for (POSITION pos = srclist.GetHeadPosition(); pos != NULL;)
{
CUpDownClient* cur_src = srclist.GetNext(pos);
if (thePrefs.m_iDbgHeap >= 2)
ASSERT_VALID( cur_src );
// BEGIN -rewritten- refreshing statistics (no need for temp vars since it is not multithreaded)
nCountForState = cur_src->GetDownloadState();
//special case which is not yet set as downloadstate
if (nCountForState == DS_ONQUEUE)
{
if( cur_src->IsRemoteQueueFull() )
nCountForState = DS_REMOTEQUEUEFULL;
}
if (cur_src->IsBanned())
nCountForState = DS_BANNED;
if (cur_src->GetSourceFrom() >= SF_SERVER && cur_src->GetSourceFrom() <= SF_PASSIVE)
++src_stats[cur_src->GetSourceFrom()];
if (cur_src->GetServerIP() && cur_src->GetServerPort())
{
net_stats[0]++;
if(cur_src->GetKadPort())
net_stats[2]++;
}
if (cur_src->GetKadPort())
net_stats[1]++;
ASSERT( nCountForState < sizeof(m_anStates)/sizeof(m_anStates[0]) );
m_anStates[nCountForState]++;
switch (cur_src->GetDownloadState())
{
case DS_DOWNLOADING:{
ASSERT( cur_src->socket );
if (cur_src->socket)
{
cur_src->CheckDownloadTimeout();
uint32 cur_datarate = cur_src->CalculateDownloadRate();
datarate += cur_datarate;
if (reducedownload && cur_src->GetDownloadState() == DS_DOWNLOADING)
{
uint32 limit = reducedownload*cur_datarate/1000; //(uint32)(((float)reducedownload/100)*cur_datarate)/10;
if (limit < 1000 && reducedownload == 200)
limit += 1000;
else if(limit<200 && cur_datarate == 0 && reducedownload >= 100)
limit = 200;
else if(limit<60 && cur_datarate < 600 && reducedownload >= 97)
limit = 60;
else if(limit<20 && cur_datarate < 200 && reducedownload >= 93)
limit = 20;
else if (limit < 1)
limit = 1;
cur_src->socket->SetDownloadLimit(limit);
if (cur_src->IsDownloadingFromPeerCache() && cur_src->m_pPCDownSocket && cur_src->m_pPCDownSocket->IsConnected())
cur_src->m_pPCDownSocket->SetDownloadLimit(limit);
}
else{
cur_src->socket->DisableDownloadLimit();
if (cur_src->IsDownloadingFromPeerCache() && cur_src->m_pPCDownSocket && cur_src->m_pPCDownSocket->IsConnected())
cur_src->m_pPCDownSocket->DisableDownloadLimit();
}
}
break;
}
// Do nothing with this client..
case DS_BANNED:
break;
// Check if something has changed with our or their ID state..
case DS_LOWTOLOWIP:
{
// To Mods, please stop instantly removing these sources..
// This causes sources to pop in and out creating extra overhead!
//Make sure this source is still a LowID Client..
if( cur_src->HasLowID() )
{
//Make sure we still cannot callback to this Client..
if( !theApp.DoCallback( cur_src ) )
{
//If we are almost maxed on sources, slowly remove these client to see if we can find a better source.
if( ((dwCurTick - lastpurgetime) > SEC2MS(30)) && (this->GetSourceCount() >= (thePrefs.GetMaxSourcePerFile()*.8 )) )
{
theApp.downloadqueue->RemoveSource( cur_src );
lastpurgetime = dwCurTick;
}
break;
}
}
// This should no longer be a LOWTOLOWIP..
cur_src->SetDownloadState(DS_ONQUEUE);
break;
}
case DS_NONEEDEDPARTS:
{
// To Mods, please stop instantly removing these sources..
// This causes sources to pop in and out creating extra overhead!
if( (dwCurTick - lastpurgetime) > SEC2MS(40) ){
lastpurgetime = dwCurTick;
// we only delete them if reaching the limit
if (GetSourceCount() >= (thePrefs.GetMaxSourcePerFile()*.8 )){
theApp.downloadqueue->RemoveSource( cur_src );
break;
}
}
// doubled reasktime for no needed parts - save connections and traffic
if (cur_src->GetTimeUntilReask() > 0)
break;
cur_src->SwapToAnotherFile(_T("A4AF for NNP file. CPartFile::Process()"), true, false, false, NULL, true, true); // ZZ:DownloadManager
// Recheck this client to see if still NNP.. Set to DS_NONE so that we force a TCP reask next time..
cur_src->SetDownloadState(DS_NONE);
break;
}
case DS_ONQUEUE:
{
// To Mods, please stop instantly removing these sources..
// This causes sources to pop in and out creating extra overhead!
if( cur_src->IsRemoteQueueFull() )
{
if( ((dwCurTick - lastpurgetime) > MIN2MS(1)) && (GetSourceCount() >= (thePrefs.GetMaxSourcePerFile()*.8 )) )
{
theApp.downloadqueue->RemoveSource( cur_src );
lastpurgetime = dwCurTick;
break;
}
}
//Give up to 1 min for UDP to respond.. If we are within one min of TCP reask, do not try..
if (theApp.IsConnected() && cur_src->GetTimeUntilReask() < MIN2MS(2) && cur_src->GetTimeUntilReask() > SEC2MS(1) && ::GetTickCount()-cur_src->getLastTriedToConnectTime() > 20*60*1000) // ZZ:DownloadManager (one resk timestamp for each file)
cur_src->UDPReaskForDownload();
}
case DS_CONNECTING:
case DS_TOOMANYCONNS:
case DS_TOOMANYCONNSKAD:
case DS_NONE:
case DS_WAITCALLBACK:
case DS_WAITCALLBACKKAD:
{
if (theApp.IsConnected() && cur_src->GetTimeUntilReask() == 0 && ::GetTickCount()-cur_src->getLastTriedToConnectTime() > 20*60*1000) // ZZ:DownloadManager (one resk timestamp for each file)
{
if(!cur_src->AskForDownload()) // NOTE: This may *delete* the client
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -