📄 partfile.cpp
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.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 <math.h>
#include <sys/stat.h>
#include <io.h>
#include <winioctl.h>
#ifdef _DEBUG
#include "DebugHelpers.h"
#endif
#include "emule.h"
#include "PartFile.h"
#include "UpDownClient.h"
#include "UrlClient.h"
#include "ED2KLink.h"
#include "Preview.h"
#include "ArchiveRecovery.h"
#include "SearchList.h"
#include "Kademlia/Kademlia/Kademlia.h"
#include "kademlia/kademlia/search.h"
#include "kademlia/kademlia/SearchManager.h"
#include "kademlia/utils/MiscUtils.h"
#include "kademlia/kademlia/prefs.h"
#include "DownloadQueue.h"
#include "IPFilter.h"
#include "MMServer.h"
#include "OtherFunctions.h"
#include "Packets.h"
#include "Preferences.h"
#include "SafeFile.h"
#include "SharedFileList.h"
#include "ListenSocket.h"
#include "Sockets.h"
#include "Server.h"
#include "KnownFileList.h"
#include "emuledlg.h"
#include "TransferWnd.h"
#include "TaskbarNotifier.h"
#include "ClientList.h"
#include "Statistics.h"
#include "shahashset.h"
#include "PeerCacheSocket.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);
IMPLEMENT_DYNAMIC(CPartFile, CKnownFile)
CPartFile::CPartFile()
{
Init();
}
CPartFile::CPartFile(CSearchFile* searchresult)
{
Init();
md4cpy(m_abyFileHash, searchresult->GetFileHash());
for (int i = 0; i < searchresult->taglist.GetCount();i++){
const CTag* pTag = searchresult->taglist[i];
switch (pTag->GetNameID()){
case FT_FILENAME:{
ASSERT( pTag->IsStr() );
if (pTag->IsStr()){
#ifdef _UNICODE
if (GetFileName().IsEmpty())
#endif
SetFileName(pTag->GetStr(), true);
}
break;
}
case FT_FILESIZE:{
ASSERT( pTag->IsInt() );
if (pTag->IsInt())
SetFileSize(pTag->GetInt());
break;
}
default:{
bool bTagAdded = false;
if (pTag->GetNameID() != 0 && pTag->GetName() == NULL && (pTag->IsStr() || pTag->IsInt()))
{
static const struct
{
uint8 nName;
uint8 nType;
} _aMetaTags[] =
{
{ FT_MEDIA_ARTIST, 2 },
{ FT_MEDIA_ALBUM, 2 },
{ FT_MEDIA_TITLE, 2 },
{ FT_MEDIA_LENGTH, 3 },
{ FT_MEDIA_BITRATE, 3 },
{ FT_MEDIA_CODEC, 2 },
{ FT_FILETYPE, 2 },
{ FT_FILEFORMAT, 2 }
};
for (int t = 0; t < ARRSIZE(_aMetaTags); t++)
{
if (pTag->GetType() == _aMetaTags[t].nType && pTag->GetNameID() == _aMetaTags[t].nName)
{
// skip string tags with empty string values
if (pTag->IsStr() && pTag->GetStr().IsEmpty())
break;
// skip integer tags with '0' values
if (pTag->IsInt() && pTag->GetInt() == 0)
break;
TRACE(_T("CPartFile::CPartFile(CSearchFile*): added tag %s\n"), pTag->GetFullInfo());
CTag* newtag = new CTag(*pTag);
taglist.Add(newtag);
bTagAdded = true;
break;
}
}
}
if (!bTagAdded)
TRACE(_T("CPartFile::CPartFile(CSearchFile*): ignored tag %s\n"), pTag->GetFullInfo());
}
}
}
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) {
TCHAR buffer[200];
_stprintf(buffer,GetResString(IDS_ERR_INVALIDLINK),error.GetBuffer());
AddLogLine(true, GetResString(IDS_ERR_LINKERROR), buffer);
SetStatus(PS_ERROR);
}
delete pLink;
}
void CPartFile::InitializeFromLink(CED2KFileLink* fileLink)
{
Init();
try{
SetFileName(fileLink->GetName(), true);
SetFileSize(fileLink->GetSize());
md4cpy(m_abyFileHash, fileLink->GetHashKey());
if (!theApp.downloadqueue->IsFileExisting(m_abyFileHash))
{
if (fileLink->m_hashset && fileLink->m_hashset->GetLength() > 0)
{
try
{
if (!LoadHashsetFromFile(fileLink->m_hashset, true))
{
ASSERT( hashlist.GetCount() == 0 );
AddDebugLogLine(false, _T("eD2K link \"%s\" specified with invalid hashset"), fileLink->GetName());
}
else
hashsetneeded = false;
}
catch (CFileException* e)
{
TCHAR szError[MAX_CFEXP_ERRORMSG];
e->GetErrorMessage(szError, ARRSIZE(szError));
AddDebugLogLine(false, _T("Error: Failed to process hashset for eD2K link \"%s\" - %s"), fileLink->GetName(), szError);
e->Delete();
}
}
CreatePartFile();
}
else
SetStatus(PS_ERROR);
}
catch(CString error){
TCHAR buffer[200];
_stprintf(buffer, GetResString(IDS_ERR_INVALIDLINK), error.GetBuffer());
AddLogLine(true, GetResString(IDS_ERR_LINKERROR), buffer);
SetStatus(PS_ERROR);
}
}
CPartFile::CPartFile(CED2KFileLink* fileLink)
{
InitializeFromLink(fileLink);
}
void CPartFile::Init(){
newdate = true;
lastsearchtime = 0;
lastpurgetime = ::GetTickCount();
paused = false;
stopped= false;
status = PS_EMPTY;
insufficient = false;
m_bCompletionError = false;
transfered = 0;
m_iLastPausePurge = time(NULL);
m_AllocateThread=NULL;
m_iAllocinfo = 0;
if(thePrefs.GetNewAutoDown()){
m_iDownPriority = PR_HIGH;
m_bAutoDownPriority = true;
}
else{
m_iDownPriority = PR_NORMAL;
m_bAutoDownPriority = false;
}
srcarevisible = false;
memset(m_anStates,0,sizeof(m_anStates));
datarate = 0;
hashsetneeded = true;
count = 0;
percentcompleted = 0;
completedsize=0;
m_bPreviewing = false;
lastseencomplete = NULL;
availablePartsCount=0;
m_ClientSrcAnswered = 0;
m_LastNoNeededCheck = 0;
m_uRating = 0;
(void)m_strComment;
m_nTotalBufferData = 0;
m_nLastBufferFlushTime = 0;
m_bRecoveringArchive = false;
m_iGainDueToCompression = 0;
m_iLostDueToCorruption = 0;
m_iTotalPacketsSavedDueToICH = 0;
hasRating = false;
hasComment = false;
hasBadRating= false;
m_category=0;
m_lastRefreshedDLDisplay = 0;
m_is_A4AF_auto=false;
m_bLocalSrcReqQueued = false;
memset(src_stats,0,sizeof(src_stats));
memset(net_stats,0,sizeof(net_stats));
m_nCompleteSourcesTime = time(NULL);
m_nCompleteSourcesCount = 0;
m_nCompleteSourcesCountLo = 0;
m_nCompleteSourcesCountHi = 0;
m_dwFileAttributes = 0;
m_bDeleteAfterAlloc=false;
m_tActivated = 0;
m_nDlActiveTime = 0;
m_tLastModified = 0;
m_tCreated = 0;
m_eFileOp = PFOP_NONE;
m_uFileOpProgress = 0;
m_bpreviewprio = false;
m_random_update_wait = (uint32)(rand()/(RAND_MAX/1000));
lastSwapForSourceExchangeTick = ::GetTickCount();
m_DeadSourceList.Init(false);
}
CPartFile::~CPartFile()
{
// Barry - Ensure all buffered data is written
try{
if (m_AllocateThread != NULL){
HANDLE hThread = m_AllocateThread->m_hThread;
// 2 minutes to let the thread finish
if (WaitForSingleObject(hThread, 120000) == WAIT_TIMEOUT)
TerminateThread(hThread, 100);
}
if (m_hpartfile.m_hFile != INVALID_HANDLE_VALUE)
FlushBuffer(true);
}
catch(CFileException* e){
e->Delete();
}
if (m_hpartfile.m_hFile != INVALID_HANDLE_VALUE){
// commit file and directory entry
m_hpartfile.Close();
// Update met file (with current directory entry)
SavePartFile();
}
for (POSITION pos = gaplist.GetHeadPosition();pos != 0;)
delete gaplist.GetNext(pos);
pos = m_BufferedData_list.GetHeadPosition();
while (pos){
PartFileBufferedData *item = m_BufferedData_list.GetNext(pos);
delete[] item->data;
delete item;
}
}
#ifdef _DEBUG
void CPartFile::AssertValid() const
{
CKnownFile::AssertValid();
(void)lastsearchtime;
(void)lastsearchtimeKad;
srclist.AssertValid();
A4AFsrclist.AssertValid();
(void)lastseencomplete;
m_hpartfile.AssertValid();
m_FileCompleteMutex.AssertValid();
(void)src_stats;
(void)net_stats;
CHECK_BOOL(m_bPreviewing);
CHECK_BOOL(m_bRecoveringArchive);
CHECK_BOOL(m_bLocalSrcReqQueued);
CHECK_BOOL(srcarevisible);
CHECK_BOOL(hashsetneeded);
(void)m_iLastPausePurge;
(void)count;
(void)m_anStates;
ASSERT( completedsize <= m_nFileSize );
(void)m_iLostDueToCorruption;
(void)m_iGainDueToCompression;
(void)m_iTotalPacketsSavedDueToICH;
(void)datarate;
(void)m_fullname;
(void)m_partmetfilename;
(void)transfered;
CHECK_BOOL(paused);
CHECK_BOOL(stopped);
CHECK_BOOL(insufficient);
CHECK_BOOL(m_bCompletionError);
ASSERT( m_iDownPriority == PR_LOW || m_iDownPriority == PR_NORMAL || m_iDownPriority == PR_HIGH );
CHECK_BOOL(m_bAutoDownPriority);
ASSERT( status == PS_READY || status == PS_EMPTY || status == PS_WAITINGFORHASH || status == PS_ERROR || status == PS_COMPLETING || status == PS_COMPLETE );
CHECK_BOOL(newdate);
(void)lastpurgetime;
(void)m_LastNoNeededCheck;
gaplist.AssertValid();
requestedblocks_list.AssertValid();
m_SrcpartFrequency.AssertValid();
ASSERT( percentcompleted >= 0.0F && percentcompleted <= 100.0F );
corrupted_list.AssertValid();
(void)availablePartsCount;
(void)m_ClientSrcAnswered;
(void)s_LoadBar;
(void)s_ChunkBar;
CHECK_BOOL(hasRating);
CHECK_BOOL(hasBadRating);
CHECK_BOOL(hasComment);
(void)m_lastRefreshedDLDisplay;
m_downloadingSourceList.AssertValid();
m_BufferedData_list.AssertValid();
(void)m_nTotalBufferData;
(void)m_nLastBufferFlushTime;
(void)m_category;
CHECK_BOOL(m_is_A4AF_auto);
(void)m_dwFileAttributes;
}
void CPartFile::Dump(CDumpContext& dc) const
{
CKnownFile::Dump(dc);
}
#endif
void CPartFile::CreatePartFile()
{
// use lowest free partfilenumber for free file (InterCeptor)
int i = 0;
CString filename;
do{
i++;
filename.Format(_T("%s\\%03i.part"), thePrefs.GetTempDir(), i);
}
while (PathFileExists(filename));
m_partmetfilename.Format(_T("%03i.part.met"), i);
SetPath(thePrefs.GetTempDir());
m_fullname.Format(_T("%s\\%s"), thePrefs.GetTempDir(), m_partmetfilename);
CTag* partnametag = new CTag(FT_PARTFILENAME,RemoveFileExtension(m_partmetfilename));
taglist.Add(partnametag);
Gap_Struct* gap = new Gap_Struct;
gap->start = 0;
gap->end = m_nFileSize-1;
gaplist.AddTail(gap);
CString partfull(RemoveFileExtension(m_fullname));
SetFilePath(partfull);
if (!m_hpartfile.Open(partfull,CFile::modeCreate|CFile::modeReadWrite|CFile::shareDenyWrite|CFile::osSequentialScan)){
AddLogLine(false,GetResString(IDS_ERR_CREATEPARTFILE));
SetStatus(PS_ERROR);
}
else{
struct _stat fileinfo;
if (_tstat(partfull, &fileinfo) == 0){
m_tLastModified = fileinfo.st_mtime;
m_tCreated = fileinfo.st_ctime;
}
else
AddDebugLogLine(false, _T("Failed to get file date for \"%s\" - %hs"), partfull, strerror(errno));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -