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

📄 downloadwithfile.cpp

📁 p2p软件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// DownloadWithFile.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza 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.
//
// Shareaza 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 Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "Downloads.h"
#include "DownloadWithFile.h"
#include "DownloadSource.h"
#include "DownloadTransfer.h"
#include "DownloadGroups.h"
#include "FragmentedFile.h"
#include "Uploads.h"

#include "ID3.h"
#include "SHA.h"
#include "XML.h"
#include "Schema.h"
#include "LibraryBuilderInternals.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


//////////////////////////////////////////////////////////////////////
// CDownloadWithFile construction

CDownloadWithFile::CDownloadWithFile()
{
	m_pFile		= new CFragmentedFile();
	m_tReceived	= GetTickCount();
	m_bDiskFull	= FALSE;
}

CDownloadWithFile::~CDownloadWithFile()
{
	if ( m_pFile != NULL ) delete m_pFile;
}

//////////////////////////////////////////////////////////////////////
// CDownloadWithFile open the file

BOOL CDownloadWithFile::OpenFile()
{
	if ( m_pFile == NULL || m_sRemoteName.IsEmpty() || m_nSize == SIZE_UNKNOWN ) return FALSE;
	if ( m_pFile->IsOpen() ) return TRUE;
	
	SetModified();
	
	if ( m_pFile->IsValid() )
	{
		if ( m_pFile->Open( m_sLocalName ) ) return TRUE;
		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_FILE_OPEN_ERROR, (LPCTSTR)m_sLocalName );
	}
	else if ( ! Downloads.IsSpaceAvailable( m_nSize ) )
	{
		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_DISK_SPACE,
			(LPCTSTR)m_sRemoteName,
			(LPCTSTR)Settings.SmartVolume( m_nSize, FALSE ) );
	}
	else
	{
		CString strLocalName = m_sLocalName;
		m_sLocalName.Empty();
		
		GenerateLocalName();
		
		for ( int nTry = 0 ; nTry < 5 ; nTry++ )
		{
			CString strName;

			if ( nTry == 0 )
				strName = m_sLocalName;
			else
				strName.Format( _T("%s.x%i"), (LPCTSTR)m_sLocalName, rand() % 128 );
			
            theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FILE_CREATE, (LPCTSTR)strName );
			
			if ( m_pFile->Create( strName, m_nSize ) )
			{
				theApp.WriteProfileString( _T("Delete"), strName, NULL );
				MoveFile( strLocalName + _T(".sd"), strName + _T(".sd") );
				m_sLocalName = strName;
				return TRUE;
			}
			
			theApp.Message( MSG_ERROR, IDS_DOWNLOAD_FILE_CREATE_ERROR, (LPCTSTR)strName );
		}
		
		m_sLocalName = strLocalName;
	}
	
	m_bDiskFull = TRUE;
	
	return FALSE;
}

//////////////////////////////////////////////////////////////////////
// CDownloadWithFile close the file

void CDownloadWithFile::CloseFile()
{
	if ( m_pFile != NULL ) m_pFile->Close();
}

//////////////////////////////////////////////////////////////////////
// CDownloadWithFile prepare file

BOOL CDownloadWithFile::PrepareFile()
{
	return OpenFile() && m_pFile->GetRemaining() > 0;
}

//////////////////////////////////////////////////////////////////////
// CDownloadWithFile delete the file

void CDownloadWithFile::DeleteFile(BOOL bForce)
{
	if ( m_pFile != NULL && m_pFile->IsValid() == FALSE ) return;
	
	Uploads.OnRename( m_sLocalName, NULL );
	
	int nPos = m_sLocalName.ReverseFind( '\\' );
	CString strMetadata;
	
	if ( nPos > 0 )
	{
		strMetadata = m_sLocalName.Left( nPos ) + _T("\\Metadata") + m_sLocalName.Mid( nPos ) + _T(".xml");
	}
	
	if ( m_pFile != NULL )
	{
		if ( GetVolumeComplete() == 0 || ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) == 0 )
		{
			if ( ! ::DeleteFile( m_sLocalName ) )
				theApp.WriteProfileString( _T("Delete"), m_sLocalName, _T("") );
			if ( strMetadata.GetLength() ) ::DeleteFile( strMetadata );
		}
		else
		{
			MoveFile( m_sLocalName, m_sLocalName + _T(".aborted") );
		}
	}
	else if ( bForce )
	{
		if ( ! ::DeleteFile( m_sLocalName ) )
			theApp.WriteProfileString( _T("Delete"), m_sLocalName, _T("") );
		if ( strMetadata.GetLength() ) ::DeleteFile( strMetadata );
	}
	
	SetModified();
}

//////////////////////////////////////////////////////////////////////
// CDownloadWithFile statistics

float CDownloadWithFile::GetProgress() const
{
	if ( m_nSize == 0 || m_nSize == SIZE_UNKNOWN ) return 0;
	return (float)GetVolumeComplete() / (float)m_nSize;
}

QWORD CDownloadWithFile::GetVolumeComplete() const
{
	if ( m_pFile != NULL )
	{
		if ( m_pFile->IsValid() )
			return m_pFile->GetCompleted();
		else
			return 0;
	}
	else
	{
		return m_nSize;
	}
}

QWORD CDownloadWithFile::GetVolumeRemaining() const
{
	if ( m_pFile != NULL )
	{
		if ( m_pFile->IsValid() )
			return m_pFile->GetRemaining();
		else if ( m_nSize != SIZE_UNKNOWN )
			return m_nSize;
	}
	
	return 0;
}

DWORD CDownloadWithFile::GetTimeRemaining() const
{
	QWORD nRemaining	= GetVolumeRemaining();
	DWORD nSpeed		= GetAverageSpeed();
	if ( nSpeed == 0 ) return 0xFFFFFFFF;
	return (DWORD)( nRemaining / nSpeed );
}

CString CDownloadWithFile::GetDisplayName() const
{
	if ( m_sRemoteName.GetLength() ) return m_sRemoteName;
	
	CString strName;
	
	if ( m_bSHA1 )
		strName = _T("sha1:") + CSHA::HashToString( &m_pSHA1 );
	else
		strName = _T("Unknown File");
	
	return strName;
}

//////////////////////////////////////////////////////////////////////
// CDownloadWithFile get the first empty fragment

CFileFragment* CDownloadWithFile::GetFirstEmptyFragment() const
{
	return m_pFile ? m_pFile->GetFirstEmptyFragment() : NULL;
}

//////////////////////////////////////////////////////////////////////
// CDownloadWithFile get a list of possible download fragments

CFileFragment* CDownloadWithFile::GetPossibleFragments(CFileFragment* pAvailable, QWORD* pnLargestOffset, QWORD* pnLargestLength)
{
	if ( ! PrepareFile() ) return NULL;
	
	CFileFragment* pPossible;
	
	if ( pAvailable != NULL )
	{
		pPossible = m_pFile->GetFirstEmptyFragment();
		pPossible = pPossible->CreateAnd( pAvailable );
	}
	else
	{
		pPossible = m_pFile->CopyFreeFragments();
	}
	
	if ( pPossible == NULL ) return NULL;
	
	if ( pnLargestOffset && pnLargestLength )
	{
		if ( CFileFragment* pLargest = pPossible->GetLargest() )
		{
			*pnLargestOffset = pLargest->m_nOffset;
			*pnLargestLength = pLargest->m_nLength;
		}
		else
		{
			ASSERT( FALSE );
			return NULL;
		}
	}
	
	for ( CDownloadTransfer* pTransfer = GetFirstTransfer() ; pTransfer && pPossible ; pTransfer = pTransfer->m_pDlNext )
	{
		pTransfer->SubtractRequested( &pPossible );
	}
	
	return pPossible;
}

//////////////////////////////////////////////////////////////////////
// CDownloadWithFile select a fragment for a transfer

BOOL CDownloadWithFile::GetFragment(CDownloadTransfer* pTransfer)
{
	if ( ! PrepareFile() ) return NULL;
	
	QWORD nLargestOffset = SIZE_UNKNOWN, nLargestLength = SIZE_UNKNOWN;
	
	CFileFragment* pPossible = GetPossibleFragments(
		pTransfer->m_pSource->m_pAvailable,
		&nLargestOffset, &nLargestLength );
	
	if ( nLargestOffset == SIZE_UNKNOWN )
	{
		ASSERT( pPossible == NULL );
		return FALSE;
	}
	
	if ( pPossible != NULL )
	{
		CFileFragment* pRandom = pPossible;
		pRandom = pPossible->GetRandom( TRUE );
		if ( pRandom == NULL ) return FALSE;
		
		pTransfer->m_nOffset = pRandom->m_nOffset;
		pTransfer->m_nLength = pRandom->m_nLength;
		
		pPossible->DeleteChain();
		
		return TRUE;
	}
	else
	{
		CDownloadTransfer* pExisting = NULL;
		
		for ( CDownloadTransfer* pOther = GetFirstTransfer() ; pOther ; pOther = pOther->m_pDlNext )
		{
			if ( pOther->m_bRecvBackwards )
			{
				if ( pOther->m_nOffset + pOther->m_nLength - pOther->m_nPosition
					 != nLargestOffset + nLargestLength ) continue;
			}
			else
			{
				if ( pOther->m_nOffset + pOther->m_nPosition != nLargestOffset ) continue;
			}
			
			pExisting = pOther;
			break;
		}
		
		if ( pExisting == NULL )
		{
			pTransfer->m_nOffset = nLargestOffset;
			pTransfer->m_nLength = nLargestLength;
			return TRUE;
		}
		
		if ( nLargestLength < 32 ) return FALSE;
		
		DWORD nOldSpeed	= pExisting->GetAverageSpeed();
		DWORD nNewSpeed	= pTransfer->GetAverageSpeed();
		QWORD nLength	= nLargestLength / 2;
		
		if ( nOldSpeed > 5 && nNewSpeed > 5 )

⌨️ 快捷键说明

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