📄 partfile.cpp
字号:
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "StdAfx.h"
#include "partfile.h"
#include "emule.h"
#include "updownclient.h"
#include <math.h>
#include "ED2KLink.h"
#include "Preview.h"
#include "ini2.h"
#include "ArchiveRecovery.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// Barry - use this constant for both places
#define PROGRESS_HEIGHT 3
CBarShader CPartFile::s_LoadBar(PROGRESS_HEIGHT); // Barry - was 5
CBarShader CPartFile::s_ChunkBar(16);
CPartFile::CPartFile()
{
Init();
}
CPartFile::CPartFile(CSearchFile* searchresult)
{
Init();
memcpy(m_abyFileHash, searchresult->GetFileHash(), 16);
for (int i = 0; i != searchresult->taglist.GetCount();i++){
switch (searchresult->taglist[i]->tag->specialtag){
case FT_FILENAME:{
m_pszFileName = nstrdup(searchresult->taglist[i]->tag->stringvalue);
break;
}
case FT_FILESIZE:{
m_nFileSize = searchresult->taglist[i]->tag->intvalue;
break;
}
default:
CTag* newtag = new CTag(searchresult->taglist[i]->tag);
taglist.Add(newtag);
}
}
if(m_nFileSize < PARTSIZE )
hashsetneeded = false;
CreatePartFile();
}
CPartFile::CPartFile(CString edonkeylink)
{
CED2KLink* pLink = 0;
try {
pLink = CED2KLink::CreateLinkFromUrl(edonkeylink);
_ASSERT( pLink != 0 );
CED2KFileLink* pFileLink = pLink->GetFileLink();
if (pFileLink==0)
throw GetResString(IDS_ERR_NOTAFILELINK);
InitializeFromLink(pFileLink);
} catch (CString error) {
OUTPUT_DEBUG_TRACE();
char buffer[200];
sprintf(buffer,GetResString(IDS_ERR_INVALIDLINK),error.GetBuffer());
theApp.emuledlg->AddLogLine(true, GetResString(IDS_ERR_LINKERROR), buffer);
status = PS_ERROR;
}
delete pLink;
}
void
CPartFile::InitializeFromLink(CED2KFileLink* fileLink)
{
Init();
try{
m_pszFileName = nstrdup( fileLink->GetName() );
m_nFileSize = fileLink->GetSize();
if(m_nFileSize < PARTSIZE )
hashsetneeded = false;
memcpy(m_abyFileHash, fileLink->GetHashKey(), sizeof(m_abyFileHash));
if (!theApp.downloadqueue->IsFileExisting(m_abyFileHash))
CreatePartFile();
else
status = PS_ERROR;
}
catch(CString error){
OUTPUT_DEBUG_TRACE();
char buffer[200];
sprintf(buffer, GetResString(IDS_ERR_INVALIDLINK), error.GetBuffer());
theApp.emuledlg->AddLogLine(true, GetResString(IDS_ERR_LINKERROR), buffer);
status = PS_ERROR;
}
}
CPartFile::CPartFile(CED2KFileLink* fileLink)
{
InitializeFromLink(fileLink);
}
void CPartFile::Init(){
fullname = 0;
newdate = true;
lastsearchtime = 0;
lastpurgetime = ::GetTickCount();
paused = false;
stopped= false;
status = PS_EMPTY;
transfered = 0;
if(theApp.glob_prefs->GetNewAutoDown()){
m_iDownPriority = PR_HIGH;
m_bAutoDownPriority = true;
}
else{
m_iDownPriority = PR_NORMAL;
m_bAutoDownPriority = false;
}
srcarevisible = false;
transferingsrc = 0;
datarate = 0;
hashsetneeded = true;
count = 0;
percentcompleted = 0;
partmetfilename = 0;
completedsize=0;
m_bPreviewing = false;
lastseencomplete = NULL;
availablePartsCount=0;
m_ClientSrcAnswered = 0;
m_LastNoNeededCheck = 0;
m_iRate = 0;
m_strComment = "";
m_nTotalBufferData = 0;
m_nLastBufferFlushTime = 0;
m_bPercentUpdated = false;
m_bRecoveringArchive = false;
m_iGainDueToCompression = 0;
m_iLostDueToCorruption = 0;
m_iTotalPacketsSavedDueToICH = 0;
hasRating = false;
hasComment = false;
m_lastdatetimecheck=0;
m_category=0;
}
CPartFile::~CPartFile(){
// Barry - Ensure all buffered data is written
FlushBuffer();
if (fullname)
delete[] fullname;
if (partmetfilename)
delete[] partmetfilename;
m_SrcpartFrequency.RemoveAll();
for (POSITION pos = gaplist.GetHeadPosition();pos != 0;gaplist.GetNext(pos))
delete gaplist.GetAt(pos);
}
void CPartFile::CreatePartFile(){
// use lowest free partfilenumber for free file (InterCeptor)
int i = 0;
CString filename;
do
{
i++;
filename.Format("%s\\%03i.part", theApp.glob_prefs->GetTempDir(), i);
}while(PathFileExists(filename));
partmetfilename = new char[15];
sprintf(partmetfilename,"%03i.part.met",i);
directory = nstrdup(theApp.glob_prefs->GetIncomingDir());
fullname = new char[strlen(theApp.glob_prefs->GetTempDir())+strlen(partmetfilename)+MAX_PATH];
sprintf(fullname,"%s\\%s",theApp.glob_prefs->GetTempDir(),partmetfilename);
char* buffer = nstrdup(partmetfilename);
buffer[strlen(buffer)-4] = 0;
CTag* partnametag = new CTag(FT_PARTFILENAME,buffer);
delete[] buffer;
taglist.Add(partnametag);
Gap_Struct* gap = new Gap_Struct;
gap->start = 0;
gap->end = m_nFileSize-1;
gaplist.AddTail(gap);
char* partfull = nstrdup(fullname);
partfull[strlen(partfull)-4] = 0;
if (!m_hpartfile.Open(partfull,CFile::modeCreate|CFile::modeReadWrite|CFile::shareDenyWrite|CFile::osSequentialScan)){
//if (!m_hpartfile.Open(partfull,CFile::modeCreate|CFile::modeReadWrite|CFile::shareDenyWrite|CFile::osSequentialScan|CFile::osWriteThrough)){
theApp.emuledlg->AddLogLine(false,GetResString(IDS_ERR_CREATEPARTFILE));
status = PS_ERROR;
}
delete[] partfull;
m_SrcpartFrequency.SetSize(GetPartCount());
for (uint32 i = 0; i != GetPartCount();i++)
m_SrcpartFrequency.Add(0);
paused = false;
SavePartFile();
}
bool CPartFile::LoadPartFile(char* in_directory,char* in_filename)
{
CMap<uint16, uint16, Gap_Struct*, Gap_Struct*> gap_map; // Slugfiller
transfered = 0;
partmetfilename = nstrdup(in_filename);
directory = nstrdup(in_directory);
char* buffer = new char[strlen(directory)+strlen(partmetfilename)+2];
sprintf(buffer, "%s\\%s", directory, partmetfilename);
fullname = buffer;
CSafeFile metFile;
try{
// readfile data form part.met file
if (!metFile.Open(fullname, CFile::modeRead)){
theApp.emuledlg->AddLogLine(false, GetResString(IDS_ERR_OPENMET), partmetfilename, m_pszFileName);
return false;
}
uint8 version;
metFile.Read(&version,1);
if (version != PARTFILE_VERSION){
if (metFile.m_hFile != INVALID_HANDLE_VALUE)
metFile.Close();
theApp.emuledlg->AddLogLine(false, GetResString(IDS_ERR_BADMETVERSION), partmetfilename, m_pszFileName);
return false;
}
LoadDateFromFile(&metFile);
LoadHashsetFromFile(&metFile, false);
uint32 tagcount;
metFile.Read(&tagcount, 4);
for (uint32 j = 0; j != tagcount; j++){
CTag* newtag = new CTag(&metFile);
switch(newtag->tag->specialtag){
case FT_FILENAME:{
if(newtag->tag->stringvalue == NULL) {
theApp.emuledlg->AddLogLine(true, GetResString(IDS_ERR_METCORRUPT), partmetfilename, m_pszFileName);
delete newtag;
return false;
}
m_pszFileName = nstrdup(newtag->tag->stringvalue);
delete newtag;
break;
}
case FT_LASTSEENCOMPLETE: {
lastseencomplete = newtag->tag->intvalue;
delete newtag;
break;
}
case FT_FILESIZE:{
m_nFileSize = newtag->tag->intvalue;
delete newtag;
break;
}
case FT_TRANSFERED:{
transfered = newtag->tag->intvalue;
delete newtag;
break;
}
case FT_CATEGORY:{
m_category = newtag->tag->intvalue;
delete newtag;
break;
}
case FT_DLPRIORITY:{
m_iDownPriority = newtag->tag->intvalue;
delete newtag;
if( m_iDownPriority == PR_AUTO ){
m_iDownPriority = PR_HIGH;
SetAutoDownPriority(true);
}
else
SetAutoDownPriority(false);
break;
}
case FT_STATUS:{
paused = newtag->tag->intvalue;
stopped=paused;
delete newtag;
break;
}
case FT_ULPRIORITY:{
SetUpPriority(newtag->tag->intvalue, false);
delete newtag;
if( GetUpPriority() == PR_AUTO ){
SetUpPriority(PR_HIGH, false);
SetAutoUpPriority(true);
}
else
SetAutoUpPriority(false);
break;
}
default:{
// Start Changes by Slugfiller for better exception handling
if ((!newtag->tag->specialtag) &&
(newtag->tag->tagname[0] == FT_GAPSTART ||
newtag->tag->tagname[0] == FT_GAPEND)){
Gap_Struct* gap;
uint16 gapkey = atoi(&newtag->tag->tagname[1]);
if (!gap_map.Lookup(gapkey, gap))
{
gap = new Gap_Struct;
gap_map.SetAt(gapkey, gap);
gap->start = -1;
gap->end = -1;
}
if (newtag->tag->tagname[0] == FT_GAPSTART)
gap->start = newtag->tag->intvalue;
if (newtag->tag->tagname[0] == FT_GAPEND)
gap->end = newtag->tag->intvalue-1;
delete newtag;
// End Changes by Slugfiller for better exception handling
}
else
taglist.Add(newtag);
}
}
}
if (metFile.m_hFile != INVALID_HANDLE_VALUE)
metFile.Close();
}
catch(CFileException* error){
OUTPUT_DEBUG_TRACE();
if (error->m_cause == CFileException::endOfFile)
theApp.emuledlg->AddLogLine(true, GetResString(IDS_ERR_METCORRUPT), partmetfilename, m_pszFileName);
else{
char buffer[150];
error->GetErrorMessage(buffer,150);
theApp.emuledlg->AddLogLine(true, GetResString(IDS_ERR_FILEERROR), partmetfilename, m_pszFileName, error);
}
error->Delete();
return false;
}
// Now to flush the map into the list (Slugfiller)
for (POSITION pos = gap_map.GetStartPosition(); pos != NULL; ){
Gap_Struct* gap;
uint16 gapkey;
gap_map.GetNextAssoc(pos, gapkey, gap);
if (gap->start >= 0 && gap->end >=0 && gap->start <= gap->end)
gaplist.AddTail(gap); // All tags accounted for
else
delete gap; // Some of the tags were missing
}
//check if this is a backup
if(stricmp(strrchr(fullname, '.'), ".backup") == 0) {
char *shorten = strrchr(fullname, '.');
*shorten = 0;
fullname = (char*)realloc(fullname, strlen(fullname) + 1);
}
// open permanent handle
char* searchpath = nstrdup(fullname);
searchpath[strlen(fullname)-4] = 0;
if (!m_hpartfile.Open(searchpath, CFile::modeReadWrite|CFile::shareDenyWrite|CFile::osSequentialScan)){
//if (!m_hpartfile.Open(searchpath, CFile::modeReadWrite|CFile::shareDenyWrite|CFile::osSequentialScan|CFile::osWriteThrough)){
theApp.emuledlg->AddLogLine(false, GetResString(IDS_ERR_FILEOPEN), fullname, m_pszFileName);
delete[] searchpath;
return false;
}
delete[] searchpath;
m_SrcpartFrequency.SetSize(GetPartCount());
for (uint32 i = 0; i != GetPartCount();i++)
m_SrcpartFrequency.Add(0);
status = PS_EMPTY;
// check hashcount, filesatus etc
if (hashlist.GetCount() < GetPartCount() && GetFileSize() >= PARTSIZE){
hashsetneeded = true;
return true;
}
else {
hashsetneeded = false;
for (int i = 0; i != hashlist.GetSize(); i++){
if (IsComplete(i*PARTSIZE,((i+1)*PARTSIZE)-1)){
status = PS_READY;
}
}
}
if (gaplist.IsEmpty()){ // is this file complete already?
CompleteFile(false);
return true;
}
// check date of .part file - if its wrong, rehash file
CFileStatus filestatus;
m_hpartfile.GetStatus(filestatus); // this; "...returns m_attribute without high-order flags" indicates a known MFC bug, wonder how many unknown there are... :)
if (date != mktime(filestatus.m_mtime.GetLocalTm())){
theApp.emuledlg->AddLogLine(false, GetResString(IDS_ERR_REHASH), buffer, m_pszFileName);
// rehash
status = PS_WAITINGFORHASH;
CAddFileThread* addfilethread = (CAddFileThread*) AfxBeginThread(RUNTIME_CLASS(CAddFileThread), THREAD_PRIORITY_NORMAL,0, CREATE_SUSPENDED);
addfilethread->SetValues(0, directory, m_hpartfile.GetFileName().GetBuffer(), this);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -