📄 partfile.cpp
字号:
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 + -