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