DownloadMTR.cpp
上传用户:oadesign
上传日期:2013-12-25
资源大小:265k
文件大小:26k
- // DownloadMTR.cpp: implementation of the CDownloadMTR class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "NetDownMTR.h"
- #include "DownloadMTR.h"
- #include <io.h>
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- void DownloadNotify ( int nIndex, UINT nNotityType, LPVOID lpNotifyData, LPVOID pDownloadMTR );
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CDownloadMTR::CDownloadMTR()
- : m_nThreadCount ( DEFAULT_THREAD_COUNT )
- , m_pDownloadPub_MTR ( NULL )
- , m_pDownloadPub_Info ( NULL )
- , m_pDownloadCellInfo ( NULL )
- , m_hThread ( NULL )
- , m_bForceDownload ( FALSE )
- , m_nTotalDownloadedSize_ThisTimes ( 0 )
- {
- memset ( &m_BaseDownInfo, 0, sizeof(t_BaseDownInfo) );
- m_hEvtEndModule = ::CreateEvent ( NULL, TRUE, FALSE, NULL );
- m_dwDownloadStartTime = GetTickCount();
- }
- CDownloadMTR::~CDownloadMTR()
- {
- StopDownload ();
- }
- //
- // 设置下载的线程数
- //
- BOOL CDownloadMTR::SetThreadCount(int nThreadCount)
- {
- if ( nThreadCount <= 0 || nThreadCount > MAX_DOWNLOAD_THREAD_COUNT )
- {
- Log ( L_WARNING, "Thread count %d is invalid. Rang [%d-%d]", nThreadCount, 1, MAX_DOWNLOAD_THREAD_COUNT );
- return FALSE;
- }
- if ( nThreadCount == m_nThreadCount )
- return TRUE;
- m_nThreadCount = nThreadCount;
- return TRUE;
- }
- //
- // 下载任务的线程函数
- //
- DWORD WINAPI ThreadProc_DownloadMTR(
- LPVOID lpParameter // thread data
- )
- {
- CDownloadMTR *pDownloadMTR = (CDownloadMTR*)lpParameter;
- ASSERT ( pDownloadMTR );
- pDownloadMTR->ThreadProc_DownloadMTR ();
- TRACE ( "下载任务的线程函数 执行完毕n" );
- return TRUE;
- }
- BOOL CDownloadMTR::ThreadProc_DownloadMTR()
- {
- // 启动多线程下载任务
- int nRet = StartMTRDownload ();
- if ( nRet == 2 ) return HandleDownloadFinished(ENUM_DOWNLOAD_RESULT_SUCCESS);
- if ( nRet == 0 ) return HandleDownloadFinished(ENUM_DOWNLOAD_RESULT_FAILED);
- // 等待所有线程下载完成
- ENUM_DOWNLOAD_RESULT eDownloadResult = WaitForDownloadFinished ();
- if ( eDownloadResult == ENUM_DOWNLOAD_RESULT_SUCCESS && !GetDownloadResult () )
- {
- eDownloadResult = ENUM_DOWNLOAD_RESULT_FAILED;
- }
- return HandleDownloadFinished ( eDownloadResult );
- }
- //
- // 多线程断点续传下载一个文件
- //
- BOOL CDownloadMTR::Download (
- LPCTSTR lpszDownloadURL,
- LPCTSTR lpszSavePath,
- LPCTSTR lpszSaveOnlyFileName,
- LPCTSTR lpszUsername/*=NULL*/,
- LPCTSTR lpszPassword/*=NULL*/,
- BOOL bForceDownload/*=FALSE*/ // 如果为 TRUE 表示强制性重新下载,以下载的部分将会被删除,FALSE 表示断点续传
- )
- {
- if ( !HANDLE_IS_VALID(m_hEvtEndModule) )
- return FALSE;
- if ( !lpszSavePath || strlen(lpszSavePath) < 1 )
- return FALSE;
- m_csSavePath = lpszSavePath;
- m_csSaveOnlyFileName = GET_SAFE_STRING(lpszSaveOnlyFileName);
- m_bForceDownload = bForceDownload;
- CString csServer, csObject;
- USHORT nPort = 0;
- if ( !ParseURL ( lpszDownloadURL, csServer, csObject, nPort, m_csProtocolType ) )
- {
- Log ( L_ERROR, "Download URL [%s] invalid", lpszDownloadURL );
- return FALSE;
- }
- m_csDownloadURL = lpszDownloadURL;
- // 创建取站点信息对象
- if ( !( m_pDownloadPub_Info = CreateDownloadObject () ) )
- {
- Log ( L_ERROR, "Create download object failed" );
- return HandleDownloadFinished(ENUM_DOWNLOAD_RESULT_FAILED);
- }
- // 设置取站点信息对象的参数
- m_pDownloadPub_Info->SetAuthorization ( lpszUsername, lpszPassword );
- m_pDownloadPub_Info->m_pDownloadMTR = this;
- m_pDownloadPub_Info->SetDownloadUrl ( lpszDownloadURL );
- // 创建一个下载线程
- DWORD dwThreadId = 0;
- m_hThread = CreateThread ( NULL, 0, ::ThreadProc_DownloadMTR, LPVOID(this), 0, &dwThreadId );
- if ( !HANDLE_IS_VALID(m_hThread) )
- {
- Log ( L_WARNING, "Create download thread failed" );
- return FALSE;
- }
- return TRUE;
- }
- //
- // 创建下载对象
- //
- CDownloadPub* CDownloadMTR::CreateDownloadObject ( int nCount/*=1*/ )
- {
- if ( nCount < 1 ) return NULL;
- CDownloadPub *pDownloadPub = NULL;
- if ( m_csProtocolType.CompareNoCase ( "http" ) == 0 )
- {
- pDownloadPub = (CDownloadPub*)new CDownloadHttp[nCount];
- }
- else if ( m_csProtocolType.CompareNoCase ( "ftp" ) == 0 )
- {
- pDownloadPub = (CDownloadPub*)new CDownloadFtp[nCount];
- }
- else return NULL;
- return pDownloadPub;
- }
- //
- // 删除下载对象
- //
- void CDownloadMTR::DeleteDownloadObject ( CDownloadPub *pDownloadPub )
- {
- if ( m_csProtocolType.CompareNoCase ( "http" ) == 0 )
- {
- delete[] ( (CDownloadHttp*)pDownloadPub );
- }
- else if ( m_csProtocolType.CompareNoCase ( "ftp" ) == 0 )
- {
- delete[] ( (CDownloadFtp*)pDownloadPub );
- }
- else delete[] pDownloadPub;
- }
- void Callback_SaveDownloadInfo ( int nIndex, int nDownloadedSize, int nSimpleSaveSize, WPARAM wParam )
- {
- CDownloadMTR *pDownloadMTR = (CDownloadMTR*)wParam;
- ASSERT ( pDownloadMTR );
- pDownloadMTR->Callback_SaveDownloadInfo ( nIndex, nDownloadedSize, nSimpleSaveSize );
- }
- void CDownloadMTR::Callback_SaveDownloadInfo ( int nIndex, int nDownloadedSize, int nSimpleSaveSize )
- {
- if ( nIndex >= 0 && nIndex < m_nThreadCount )
- {
- m_pDownloadCellInfo[nIndex].nDownloadedSize = nDownloadedSize;
- if ( nDownloadedSize > 0 )
- {
- m_CSFor_DownloadedData.Lock();
- m_BaseDownInfo.nTotalDownloadedSize += nSimpleSaveSize;
- m_nTotalDownloadedSize_ThisTimes += nSimpleSaveSize;
- m_CSFor_DownloadedData.Unlock ();
- }
- }
- }
- //
- // 创建多线程下载使用的对象和数据缓冲
- //
- BOOL CDownloadMTR::CreateDownloadObjectAndDataMTR ()
- {
- DeleteDownloadObjectAndDataMTR ();
- ASSERT ( !m_pDownloadPub_MTR && m_pDownloadPub_Info );
- m_pDownloadPub_MTR = CreateDownloadObject ( m_nThreadCount );
- // 设置多线程下载使用的对象的参数
- if ( m_pDownloadPub_MTR )
- {
- for ( int nIndex=0; nIndex<m_nThreadCount; nIndex++ )
- {
- m_pDownloadPub_MTR[nIndex].m_nIndex = nIndex;
- m_pDownloadPub_MTR[nIndex].m_pDownloadMTR = this;
- m_pDownloadPub_MTR[nIndex].Set_SaveDownloadInfo_Callback ( ::Callback_SaveDownloadInfo, WPARAM(this) );
- m_pDownloadPub_MTR[nIndex].SetAuthorization ( m_pDownloadPub_Info->Get_UserName(), m_pDownloadPub_Info->Get_GetPassword() );
- m_pDownloadPub_MTR[nIndex].SetDownloadUrl ( m_pDownloadPub_Info->Get_DownloadUrl () );
- if ( !m_pDownloadPub_MTR[nIndex].SetSaveFileName ( GetTempFilePath() ) )
- return FALSE;
- }
- }
- // 创建多线程下载使用的数据缓冲
- ASSERT ( !m_pDownloadCellInfo );
- m_pDownloadCellInfo = new t_DownloadCellInfo[m_nThreadCount];
- if ( m_pDownloadCellInfo )
- memset ( m_pDownloadCellInfo, 0, m_nThreadCount*sizeof(t_DownloadCellInfo) );
- if ( m_pDownloadPub_MTR != NULL && m_pDownloadCellInfo != NULL )
- return TRUE;
- Log ( L_WARNING, "Create MTR download object or buffer failed" );
- return FALSE;
- }
- //
- // 删除多线程下载使用的对象和数据缓冲
- //
- void CDownloadMTR::DeleteDownloadObjectAndDataMTR()
- {
- if ( m_pDownloadPub_MTR )
- {
- DeleteDownloadObject ( m_pDownloadPub_MTR );
- m_pDownloadPub_MTR = NULL;
- }
- if ( m_pDownloadCellInfo )
- {
- delete[] m_pDownloadCellInfo;
- m_pDownloadCellInfo = NULL;
- }
- }
- //
- // 删除取站点信息的下载对象
- //
- void CDownloadMTR::DeleteDownloadObject_Info()
- {
- if ( m_pDownloadPub_Info )
- {
- DeleteDownloadObject ( m_pDownloadPub_Info );
- m_pDownloadPub_Info = NULL;
- }
- }
- //
- // 启动多线程下载,返回 0 表示失败,1表示成功,2表示不用下载了,因为该文件已经下载过了
- //
- int CDownloadMTR::StartMTRDownload ()
- {
- m_dwDownloadStartTime = GetTickCount();
- DownloadNotify ( -1, NOTIFY_TYPE_START_DOWNLOAD, (LPVOID)NULL, this );
- // 先获取站点信息
- ASSERT ( m_pDownloadPub_Info );
- if ( !m_pDownloadPub_Info->GetRemoteSiteInfo () )
- return 0;
- DbgLog ( "要下载的文件大小是:%d 字节n", m_pDownloadPub_Info->Get_FileTotalSize () );
- StandardSaveFileName ();
- // 要保存的文件是否已经存在,且大小和创建时间一致,如果不是强制性下载,则不需要再下载了。
- CFileStatus fileStatus;
- if ( CFile::GetStatus(m_csSavePathFileName,fileStatus) )
- {
- if (
- (
- fileStatus.m_mtime.GetTime() - m_pDownloadPub_Info->Get_TimeLastModified() <=2 &&
- m_pDownloadPub_Info->Get_TimeLastModified()-fileStatus.m_mtime.GetTime() <=2
- )
- &&
- fileStatus.m_size == m_pDownloadPub_Info->Get_FileTotalSize ()
- &&
- !m_bForceDownload
- )
- {
- return 2;
- }
- // 需要重新下载
- ::DeleteFile ( m_csSavePathFileName );
- ::DeleteFile ( GetTempFilePath() );
- }
- BOOL bMustCreateNullFile = TRUE;
- // 读取下载信息,如果能读到说明上次下载尚未完成
- if ( m_pDownloadPub_Info->Is_SupportResume() )
- {
- if ( CFile::GetStatus(GetTempFilePath(),fileStatus) &&
- fileStatus.m_size == m_pDownloadPub_Info->Get_FileTotalSize()+GetDownloadInfoWholeSize() )
- {
- if ( ReadDownloadInfo () )
- bMustCreateNullFile = FALSE;
- }
- }
-
- if ( bMustCreateNullFile )
- {
- int nFileSize = m_pDownloadPub_Info->Get_FileTotalSize();
- int nTempFileSize = nFileSize+GetDownloadInfoWholeSize();
- if ( nFileSize < 0 || !m_pDownloadPub_Info->Is_SupportResume() )
- nTempFileSize = 0;
- // 创建一个用来保存下载数据的空文件
- if ( !CreateNullFile ( GetTempFilePath(), nTempFileSize ) )
- return FALSE;
- }
- // 分配下载任务
- if ( !AssignDownloadTask () )
- {
- Log ( L_WARNING, "Assign task failed" );
- return 0;
- }
- m_dwDownloadStartTime = GetTickCount();
- return 1;
- }
- //
- // 得到临时数据保存的路径文件名
- //
- CString CDownloadMTR::GetTempFilePath ()
- {
- ASSERT ( !m_csSavePathFileName.IsEmpty () );
- CString csTempFileName;
- csTempFileName.Format ( "%s.~xhw~", m_csSavePathFileName );
- ::SetFileAttributes ( csTempFileName, FILE_ATTRIBUTE_HIDDEN );
- return csTempFileName;
- }
- //
- // 分配下载任务
- //
- BOOL CDownloadMTR::AssignDownloadTask()
- {
- ASSERT ( m_pDownloadPub_Info );
- if ( !m_pDownloadPub_Info->Is_SupportResume() )
- {
- DeleteDownloadObjectAndDataMTR ();
- Log ( L_WARNING, "Site [%s] not support resume download", m_pDownloadPub_Info->Get_ServerName() );
- }
- // 文件大小未知,采用单线程
- if ( m_pDownloadPub_Info->Get_FileTotalSize () <= 0 || !m_pDownloadPub_Info->Is_SupportResume() )
- {
- if ( m_nThreadCount != 1 )
- {
- DeleteDownloadObjectAndDataMTR ();
- SetThreadCount ( 1 );
- }
- }
- if ( !DownloadInfoIsValid() || !m_pDownloadPub_MTR || !m_pDownloadCellInfo )
- {
- if ( !CreateDownloadObjectAndDataMTR () )
- return FALSE;
- }
- ASSERT ( m_pDownloadPub_MTR && m_pDownloadCellInfo );
- // 下载任务尚未分配
- if ( !DownloadInfoIsValid() )
- {
- int nWillDownloadSize = -1, nWillDownloadStartPos = 0, nNoAssignSize = 0;
- if ( m_pDownloadPub_Info->Get_FileTotalSize () > 0 )
- {
- nWillDownloadSize = m_pDownloadPub_Info->Get_FileTotalSize () / m_nThreadCount;
- // 均分后剩下的部分,让第一个线程来承担下载
- nNoAssignSize = m_pDownloadPub_Info->Get_FileTotalSize () % m_nThreadCount;
- }
- DbgLog ( "任务分配如下:--------------------n" );
- for ( int nIndex=0; nIndex<m_nThreadCount; nIndex++ )
- {
- m_pDownloadCellInfo[nIndex].nWillDownloadStartPos = nWillDownloadStartPos;
- m_pDownloadCellInfo[nIndex].nWillDownloadSize = nWillDownloadSize;
- if ( nIndex == 0 && m_pDownloadPub_Info->Get_FileTotalSize () > 0 )
- {
- m_pDownloadCellInfo[nIndex].nWillDownloadSize += nNoAssignSize;
- }
- DbgLog ( "线程.%d 从 %d(0x%08x) 下载到 %d(0x%08x) 共 %d(0x%08x) 字节n", nIndex,
- m_pDownloadCellInfo[nIndex].nWillDownloadStartPos, m_pDownloadCellInfo[nIndex].nWillDownloadStartPos,
- m_pDownloadCellInfo[nIndex].nWillDownloadStartPos+m_pDownloadCellInfo[nIndex].nWillDownloadSize,
- m_pDownloadCellInfo[nIndex].nWillDownloadStartPos+m_pDownloadCellInfo[nIndex].nWillDownloadSize,
- m_pDownloadCellInfo[nIndex].nWillDownloadSize, m_pDownloadCellInfo[nIndex].nWillDownloadSize );
- nWillDownloadStartPos += m_pDownloadCellInfo[nIndex].nWillDownloadSize;
- }
- }
- // 启动下载任务
- for ( int nIndex=0; nIndex<m_nThreadCount; nIndex++ )
- {
- if ( !m_pDownloadPub_MTR[nIndex].Download ( m_pDownloadCellInfo[nIndex].nWillDownloadStartPos,
- m_pDownloadCellInfo[nIndex].nWillDownloadSize, m_pDownloadCellInfo[nIndex].nDownloadedSize ) )
- return FALSE;
- }
- m_BaseDownInfo.dwThreadCount = m_nThreadCount;
- return TRUE;
- }
- //
- // 从下载信息文件中读取下载信息
- //
- BOOL CDownloadMTR::ReadDownloadInfo()
- {
- CString csTempFileName = GetTempFilePath ();
- BOOL bRet = FALSE;
- CFile file;
- TRY
- {
- if ( file.Open ( csTempFileName, CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite|CFile::typeBinary|CFile::shareDenyNone ) )
- {
- if ( file.Seek ( -(int)sizeof(t_BaseDownInfo), CFile::end ) == (int)(file.GetLength() - sizeof(t_BaseDownInfo)) )
- {
- if ( (UINT)file.Read ( &m_BaseDownInfo, sizeof(t_BaseDownInfo) ) == sizeof(t_BaseDownInfo) )
- {
- if ( (m_BaseDownInfo.dwThreadCount > 0 && m_BaseDownInfo.dwThreadCount <= MAX_DOWNLOAD_THREAD_COUNT)&&
- SetThreadCount ( m_BaseDownInfo.dwThreadCount ) )
- {
- if ( CreateDownloadObjectAndDataMTR () )
- {
- if ( file.Seek ( -GetDownloadInfoWholeSize(), CFile::end ) == int(file.GetLength() - GetDownloadInfoWholeSize()) )
- {
- if ( file.Read ( m_pDownloadCellInfo, sizeof(t_DownloadCellInfo)*m_nThreadCount ) == sizeof(t_DownloadCellInfo)*m_nThreadCount )
- {
- bRet = TRUE;
- }
- else
- {
- memset ( m_pDownloadCellInfo, 0, sizeof(t_DownloadCellInfo)*m_nThreadCount );
- }
- }
- }
- }
- }
- }
- }
- }
- CATCH( CFileException, e )
- {
- e->Delete ();
- bRet = FALSE;
- }
- END_CATCH
- if ( HANDLE_IS_VALID(file.m_hFile) )
- file.Close ();
- return bRet;
- }
- BOOL CDownloadMTR::SaveDownloadInfo ()
- {
- if ( !m_pDownloadPub_Info->Is_SupportResume() )
- return TRUE;
- CString csTempFileName = GetTempFilePath ();
- BOOL bRet = FALSE;
- CFile file;
- TRY
- {
- if ( file.Open ( csTempFileName, CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite|CFile::typeBinary|CFile::shareDenyNone ) )
- {
- if ( file.Seek ( -(int)sizeof(t_BaseDownInfo), CFile::end ) == (int)(file.GetLength() - sizeof(t_BaseDownInfo)) )
- {
- file.Write ( &m_BaseDownInfo, sizeof(t_BaseDownInfo) );
- if ( file.Seek ( -GetDownloadInfoWholeSize(), CFile::end ) == int(file.GetLength() - GetDownloadInfoWholeSize()) )
- {
- file.Write ( m_pDownloadCellInfo, m_nThreadCount*sizeof(t_DownloadCellInfo) );
- bRet = TRUE;
- }
- }
- }
- }
- CATCH( CFileException, e )
- {
- e->Delete ();
- bRet = FALSE;
- }
- END_CATCH
- if ( HANDLE_IS_VALID ( file.m_hFile ) )
- file.Close ();
- if ( !bRet ) Log ( L_WARNING, "Save download info failed. %s", hwFormatMessage ( GetLastError() ) );
- return bRet;
- }
- BOOL CDownloadMTR::HandleDownloadFinished(ENUM_DOWNLOAD_RESULT eDownloadResult)
- {
- CString csTempFileName;
- CFileStatus fileStatus;
- BOOL bRet = FALSE;
- CFile file;
- if ( eDownloadResult != ENUM_DOWNLOAD_RESULT_SUCCESS )
- {
- SaveDownloadInfo ();
- goto Finished;
- }
- csTempFileName = GetTempFilePath ();
- // 设置文件大小
- if ( m_pDownloadPub_Info->Is_SupportResume() && m_pDownloadPub_Info->Get_FileTotalSize() > 0 )
- {
- TRY
- {
- file.Open ( csTempFileName, CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite|CFile::typeBinary|CFile::shareDenyNone );
- file.SetLength(m_pDownloadPub_Info->Get_FileTotalSize ());
- bRet = TRUE;
- }
- CATCH( CFileException, e )
- {
- e->Delete ();
- bRet = FALSE;
- }
- END_CATCH
- if ( HANDLE_IS_VALID(file.m_hFile) )
- file.Close ();
- if ( !bRet )
- {
- Log ( L_WARNING, "Set [%s] length failed", csTempFileName );
- eDownloadResult = ENUM_DOWNLOAD_RESULT_FAILED;
- goto Finished;
- }
- }
- if ( _access(csTempFileName,04) == 0 )
- {
- // 将文件改名
- bRet = FALSE;
- DeleteFile ( m_csSavePathFileName );
- TRY
- {
- CFile::Rename ( csTempFileName, m_csSavePathFileName );
- bRet = TRUE;
- }
- CATCH( CFileException, e )
- {
- e->Delete ();
- bRet = FALSE;
- }
- END_CATCH
-
- if ( !bRet )
- {
- Log ( L_WARNING, "Rename [%s] failed. %s", csTempFileName, hwFormatMessage(GetLastError()) );
- eDownloadResult = ENUM_DOWNLOAD_RESULT_FAILED;
- goto Finished;
- }
- // 设置文件属性,时间设置和服务器一致
- bRet = FALSE;
- if ( CFile::GetStatus(m_csSavePathFileName,fileStatus) )
- {
- fileStatus.m_mtime = m_pDownloadPub_Info->Get_TimeLastModified();
- fileStatus.m_attribute = CFile::normal;
- CFile::SetStatus ( m_csSavePathFileName, fileStatus );
- bRet = TRUE;
- }
- if ( !bRet )
- {
- Log ( L_WARNING, "Set file [%s] status failed. %s", csTempFileName, hwFormatMessage(GetLastError()) );
- eDownloadResult = ENUM_DOWNLOAD_RESULT_FAILED;
- goto Finished;
- }
- }
- Finished:
- DownloadNotify ( -1, NOTIFY_TYPE_END_DOWNLOAD, (LPVOID)eDownloadResult, this );
- return bRet;
- }
- BOOL CDownloadMTR::GetDownloadResult()
- {
- for ( int nIndex=0; nIndex<m_nThreadCount; nIndex++ )
- {
- if ( !m_pDownloadPub_MTR[nIndex].Is_DownloadSuccess() )
- return FALSE;
- }
- return TRUE;
- }
- //
- // 下载信息是否有效
- //
- BOOL CDownloadMTR::DownloadInfoIsValid()
- {
- BOOL bValid = FALSE;
- int nIndex = 0;
- if ( !m_pDownloadCellInfo ) goto Invalid;
- if ( m_BaseDownInfo.dwThreadCount < 1 || m_BaseDownInfo.dwThreadCount > MAX_DOWNLOAD_THREAD_COUNT )
- goto Invalid;
-
- for ( nIndex=0; nIndex<m_nThreadCount; nIndex++ )
- {
- if ( m_pDownloadCellInfo[nIndex].nWillDownloadSize > 0 )
- {
- bValid = TRUE;
- break;
- }
- }
- if ( !bValid ) goto Invalid;
- return TRUE;
- Invalid:
- if ( m_pDownloadCellInfo )
- memset ( m_pDownloadCellInfo, 0, m_nThreadCount*sizeof(t_DownloadCellInfo) );
- memset ( &m_BaseDownInfo, 0, sizeof(t_BaseDownInfo) );
- return FALSE;
- }
- //
- // 找到剩余未下载的数量最大的那个对象编号
- //
- int CDownloadMTR::GetUndownloadMaxBytes( int &nUndownloadBytes )
- {
- nUndownloadBytes = 0;
- int nMaxIndex = -1;
- for ( int nIndex=0; nIndex<m_nThreadCount; nIndex++ )
- {
- int nTempBytes = m_pDownloadPub_MTR[nIndex].GetUndownloadBytes ();
- if ( nUndownloadBytes < nTempBytes )
- {
- nUndownloadBytes = nTempBytes;
- nMaxIndex = nIndex;
- }
- }
- return nMaxIndex;
- }
- //
- // 编号为 nIndex 的对象调度任务,为下载任务最繁重的对象减轻负担
- //
- BOOL CDownloadMTR::AttemperDownloadTask(int nIndex)
- {
- ASSERT ( m_pDownloadPub_MTR && m_pDownloadCellInfo );
- if ( m_nThreadCount <= 1 || m_pDownloadCellInfo[nIndex].nWillDownloadSize == -1 )
- return FALSE;
- int nUndownloadBytes = 0;
- int nIndex_Heavy = GetUndownloadMaxBytes ( nUndownloadBytes );
- if ( nIndex_Heavy == -1 || nIndex_Heavy == nIndex || nUndownloadBytes < 10*1024 )
- return FALSE;
- ASSERT ( nIndex_Heavy >= 0 && nIndex_Heavy < m_nThreadCount );
- ASSERT ( m_pDownloadPub_MTR[nIndex_Heavy].Get_WillDownloadStartPos() == m_pDownloadCellInfo[nIndex_Heavy].nWillDownloadStartPos );
- DbgLog ( "下载对象.%d 帮 %d 减轻负担n", nIndex, nIndex_Heavy );
- // 给空闲下载对象分配新任务
- m_pDownloadCellInfo[nIndex].nWillDownloadSize = nUndownloadBytes / 2;
- m_pDownloadCellInfo[nIndex].nWillDownloadStartPos = m_pDownloadPub_MTR[nIndex_Heavy].Get_WillDownloadStartPos() +
- m_pDownloadPub_MTR[nIndex_Heavy].Get_WillDownloadSize() - m_pDownloadCellInfo[nIndex].nWillDownloadSize;
- m_pDownloadCellInfo[nIndex].nDownloadedSize = 0;
- DbgLog ( "空闲下载对象.%d 分配新任务: %d(0x%08x) - %d(0x%08x) 共 %d(0x%08x)n", nIndex, m_pDownloadCellInfo[nIndex].nWillDownloadStartPos, m_pDownloadCellInfo[nIndex].nWillDownloadStartPos,
- m_pDownloadCellInfo[nIndex].nWillDownloadStartPos + m_pDownloadCellInfo[nIndex].nWillDownloadSize, m_pDownloadCellInfo[nIndex].nWillDownloadStartPos + m_pDownloadCellInfo[nIndex].nWillDownloadSize,
- m_pDownloadCellInfo[nIndex].nWillDownloadSize, m_pDownloadCellInfo[nIndex].nWillDownloadSize );
- // 减轻繁忙下载对象的任务
- m_pDownloadCellInfo[nIndex_Heavy].nWillDownloadSize -= m_pDownloadCellInfo[nIndex].nWillDownloadSize;
- m_pDownloadPub_MTR[nIndex_Heavy].Set_WillDownloadSize ( m_pDownloadCellInfo[nIndex_Heavy].nWillDownloadSize );
- DbgLog ( "繁忙下载对象.%d 下载了 %d(0x%08x) 未完 %d(0x%08x) 字节,调整任务为: %d(0x%08x) - %d(0x%08x) 共 %d(0x%08x)n",
- nIndex_Heavy, m_pDownloadPub_MTR[nIndex_Heavy].Get_DownloadedSize(), m_pDownloadPub_MTR[nIndex_Heavy].Get_DownloadedSize(),
- nUndownloadBytes, nUndownloadBytes,
- m_pDownloadCellInfo[nIndex_Heavy].nWillDownloadStartPos, m_pDownloadCellInfo[nIndex_Heavy].nWillDownloadStartPos,
- m_pDownloadCellInfo[nIndex_Heavy].nWillDownloadStartPos + m_pDownloadCellInfo[nIndex_Heavy].nWillDownloadSize, m_pDownloadCellInfo[nIndex_Heavy].nWillDownloadStartPos + m_pDownloadCellInfo[nIndex_Heavy].nWillDownloadSize,
- m_pDownloadCellInfo[nIndex_Heavy].nWillDownloadSize, m_pDownloadCellInfo[nIndex_Heavy].nWillDownloadSize );
- // 启动空闲下载对象的下载任务
- m_pDownloadPub_MTR[nIndex].ResetVar ();
- if ( !m_pDownloadPub_MTR[nIndex].Download ( m_pDownloadCellInfo[nIndex].nWillDownloadStartPos,
- m_pDownloadCellInfo[nIndex].nWillDownloadSize, m_pDownloadCellInfo[nIndex].nDownloadedSize ) )
- return FALSE;
- return TRUE;
- }
- //
- // 等待下载结束
- //
- ENUM_DOWNLOAD_RESULT CDownloadMTR::WaitForDownloadFinished()
- {
- ASSERT ( HANDLE_IS_VALID(m_hEvtEndModule) );
- int nCount = m_nThreadCount + 1;
- ENUM_DOWNLOAD_RESULT eDownloadResult = ENUM_DOWNLOAD_RESULT_FAILED;
- HANDLE *lpHandles = new HANDLE[nCount];
- if ( !lpHandles ) goto End;
- while ( TRUE )
- {
- nCount = 0;
- for ( int nIndex=0; nIndex<m_nThreadCount; nIndex++ )
- {
- HANDLE hThread = m_pDownloadPub_MTR[nIndex].Get_Thread_Handle ();
- if ( HANDLE_IS_VALID(hThread) )
- lpHandles[nCount++] = hThread;
- }
- lpHandles[nCount++] = m_hEvtEndModule;
- if ( nCount == 1 )
- {
- if ( m_BaseDownInfo.nTotalDownloadedSize >= m_pDownloadPub_Info->Get_FileTotalSize() )
- eDownloadResult = ENUM_DOWNLOAD_RESULT_SUCCESS;
- else
- eDownloadResult = ENUM_DOWNLOAD_RESULT_FAILED;
- goto End;
- }
- int nRet = (int)WaitForMultipleObjects ( nCount, lpHandles, FALSE, INFINITE ) - WAIT_OBJECT_0;
- // 某下载对象完成任务了
- if ( nRet >= 0 && nRet < nCount-1 )
- {
- nIndex = FindIndexByThreadHandle ( lpHandles[nRet] );
- if ( ( nIndex >= 0 && nIndex < m_nThreadCount ) )
- {
- if ( !m_pDownloadPub_MTR[nIndex].Is_DownloadSuccess() ||
- !AttemperDownloadTask ( nIndex ) )
- {
- m_pDownloadPub_MTR[nIndex].Clear_Thread_Handle ();
- }
- }
- else
- {
- eDownloadResult = ENUM_DOWNLOAD_RESULT_CANCEL;
- goto End;
- }
- }
- // 模块结束
- else
- {
- eDownloadResult = ENUM_DOWNLOAD_RESULT_CANCEL;
- goto End;
- }
- }
- End:
- // 等待所有下载线程结束
- if ( eDownloadResult != ENUM_DOWNLOAD_RESULT_SUCCESS )
- {
- nCount = 0;
- for ( int nIndex=0; nIndex<m_nThreadCount; nIndex++ )
- {
- HANDLE hThread = m_pDownloadPub_MTR[nIndex].Get_Thread_Handle ();
- if ( HANDLE_IS_VALID(hThread) )
- lpHandles[nCount++] = hThread;
- }
- WaitForMultipleObjects ( nCount, lpHandles, TRUE, 500*1000 );
- }
- if ( lpHandles ) delete[] lpHandles;
- return eDownloadResult;
- }
- int CDownloadMTR::FindIndexByThreadHandle(HANDLE hThread)
- {
- for ( int nIndex=0; nIndex<m_nThreadCount; nIndex++ )
- {
- HANDLE hThread_Temp = m_pDownloadPub_MTR[nIndex].Get_Thread_Handle ();
- if ( HANDLE_IS_VALID(hThread_Temp) && hThread_Temp == hThread )
- return nIndex;
- }
- return -1;
- }
- int CDownloadMTR::GetDownloadInfoWholeSize()
- {
- return ( sizeof(t_DownloadCellInfo)*m_nThreadCount + sizeof(t_BaseDownInfo) );
- }
- //
- // 获取下载所消耗的时间(毫秒),可用来计算下载速度和推算剩余时间
- //
- DWORD CDownloadMTR::GetDownloadElapsedTime()
- {
- return (GetTickCount() - m_dwDownloadStartTime);
- }
- //
- // 停止下载。将所有下载线程关闭,将下载对象删除,文件关闭
- //
- void CDownloadMTR::StopDownload()
- {
- if ( HANDLE_IS_VALID(m_hEvtEndModule) )
- {
- ::SetEvent ( m_hEvtEndModule );
- }
- // 设置多线程下载使用的对象的参数
- if ( m_pDownloadPub_MTR )
- {
- for ( int nIndex=0; nIndex<m_nThreadCount; nIndex++ )
- {
- m_pDownloadPub_MTR[nIndex].StopDownload ();
- }
- }
- if ( HANDLE_IS_VALID(m_hThread) )
- {
- WaitForThreadEnd ( m_hThread,30*1000 );
- CLOSE_HANDLE ( m_hThread )
- }
- DeleteDownloadObjectAndDataMTR ();
- DeleteDownloadObject_Info ();
- CLOSE_HANDLE ( m_hEvtEndModule );
- }
- void CDownloadMTR::StandardSaveFileName ()
- {
- ASSERT ( m_csSavePath.GetLength() > 0 );
- StandardizationPathBuffer ( m_csSavePath.GetBuffer(MAX_PATH), MAX_PATH );
- m_csSavePath.ReleaseBuffer ();
- MakeSureDirectory ( m_csSavePath );
- char szOnlyFileName_NoExt_User[MAX_PATH] = {0};
- char szExtensionName_User[MAX_PATH] = {0};
- // 如果用户指定了新的保存文件名,就用新的。
- if ( m_csSaveOnlyFileName.GetLength() > 0 )
- {
- CString csFileNameByURL = GetLocalFileNameByURL ( m_csDownloadURL );
- if ( csFileNameByURL.CompareNoCase(m_csSaveOnlyFileName) != 0 )
- {
- PartFileAndExtensionName ( m_csSaveOnlyFileName, szOnlyFileName_NoExt_User, MAX_PATH, szExtensionName_User, MAX_PATH );
- }
- }
- CString csExtensionName_Remote;
- CString csFileName_Remote = m_pDownloadPub_Info->GetDownloadObjectFileName ( &csExtensionName_Remote );
- if ( strlen(szOnlyFileName_NoExt_User) > 0 )
- {
- if ( strlen(szExtensionName_User) < 1 )
- STRNCPY_CS ( szExtensionName_User, csExtensionName_Remote );
- m_csSavePathFileName.Format ( "%s%s.%s", StandardizationFileForPathName(m_csSavePath,FALSE),
- StandardizationFileForPathName(szOnlyFileName_NoExt_User,TRUE), StandardizationFileForPathName(szExtensionName_User,TRUE) );
- }
- else
- {
- m_csSavePathFileName.Format ( "%s%s", StandardizationFileForPathName(m_csSavePath,FALSE), StandardizationFileForPathName(csFileName_Remote,TRUE) );
- }
- }
- //
- // 根据 URL 来获取本地保存的文件名
- //
- CString CDownloadMTR::GetLocalFileNameByURL ( LPCTSTR lpszDownloadURL )
- {
- if ( !lpszDownloadURL || strlen(lpszDownloadURL) < 1 )
- return "";
- char szOnlyPath[MAX_PATH] = {0};
- char szOnlyFileName[MAX_PATH] = {0};
- if ( !PartFileAndPathByFullPath ( lpszDownloadURL, szOnlyFileName, MAX_PATH, szOnlyPath, MAX_PATH ) )
- return "";
- return szOnlyFileName;
- }
- //
- // 获取文件大小
- //
- int CDownloadMTR::Get_FileTotaleSize()
- {
- if ( !m_pDownloadPub_Info ) return -1;
- return m_pDownloadPub_Info->Get_FileTotalSize ();
- }
- //
- // 获取已下载的字节数
- //
- int CDownloadMTR::Get_TotalDownloadedSize()
- {
- m_CSFor_DownloadedData.Lock ();
- int nTotalDownloadedSize = m_BaseDownInfo.nTotalDownloadedSize;
- m_CSFor_DownloadedData.Unlock ();
- return nTotalDownloadedSize;
- }