mgfilemanager.cpp
来自「一款LINUX下的下载软件」· C++ 代码 · 共 1,343 行 · 第 1/3 页
CPP
1,343 行
/***************************************************************************
* mgfilemanager.cpp
*
* Wed Sep 6 22:19:52 2006
* Copyright 2006 liubin,China
* Email multiget@gmail.com
****************************************************************************/
/*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
filename : mgfilemanager.cpp
create : 2006/09/09
author : liubin
EMAIL : multiget@gmail.com
version : 0.5
license : GPL
|***|***|***|***|***|***|***|***|***|***|***|***|***|***|***|***|***|***|
| | | | | | | | | | | | | | | | | | |
***change log***
***修订历史***
2006/07/06 :
修正GetNextTask()一些细节
2006/07/09 :
增加了写索引时防止中断
2006/07/10 :
修订了文件下载完后索引不一致的问题
2006/07/31 :
修改文件后缀,部分下载末尾加.mg,索引加.mgidx
系统整体修改,支持大文件处理
2006/08/07 :
修改GetNextTask,避免分配文件末尾给线程下载。
2006/08/11 :
修改GetNextTask,在分配新任务前取消原任务标记。
2006/08/12
读取索引时过滤长度为0的索引节点,否则可能索引太长了。
2006/08/13
增加HeartBeat,速度和完成等参数在本地执行
2006/09/07
为兼容VC6做一些修改,取消构造中运行
2006/09/09
为兼容VC6做一些修改
2006/10/02
为不能取得文件长度的任务做数据提交的完善
2006/10/06
multi url support
2006/10/22
some translation 2006/11/14 modify for mac and bsd compile
*/
#include "mgfilemanager.h"
#include "showtablewindow.h"
#include "mgsingletask.h"
#include "mainframe.h"
#include "mgapp.h"
#include "speedctrl.h"
#include "mirroradmin.h"
#include "mgapp.h"
#ifdef WIN32const static int _RECVBUF=16384; //seems lost the define in common.h in win32
#endif
#define _MGSTR(s) wxGetApp().GetStr(s)
extern CSpeedCtrl gSpeedCtrl;
//extern CMirrorAdmin gMirrorAdmin;
using namespace std;
CMgFileManager::CMgFileManager(
CMgSingleTask *parent,
std::string mainurl,
std::string sname,
std::string spath,
llong nlen, //-1 for unknow length
std::string mainrefer //only for http
)
{
#ifdef WIN32
m_sPathFileName = spath + std::string( "\\" ) + sname;
#else
m_sPathFileName = spath + std::string( "/" ) + sname;
#endif
m_sFileName = sname;
m_nFileLen = nlen;
m_bStop = false;
m_pParent = parent;
m_bUpdateUI = parent->UpdateUI();
m_pShowWin = parent->GetShowTableWin();
m_nOriginBytes = 0;
m_nSumBytes = 0;
m_nSpeed = 0;
m_nTimeToFinish = -1;
m_fRatio = 0;
//add the main url to list
_ul tt;
tt.prior = 10000;
tt.url = mainurl;
tt.refer = mainrefer;
tt.bused = false;
m_UrlList.push_back( tt );
memset( m_AntSpeed, 0, 10 * sizeof( int ) );
memset( m_AntId2UrlIndex, 0, 10 * sizeof( int ) );
m_SumPack = 0;
m_nSwap = -1;
pthread_mutex_init ( &m_IndexMutex, NULL );
pthread_mutex_init ( &m_UListMutex, NULL );
}
//if true, init ok
bool CMgFileManager::CheckFile()
{
std::string tempmsg;
OutMsg( _MGSTR( _S_FILEMGR_TASKOBJ ) + m_sPathFileName , MSG_INFO );
//get user home directory
OutMsg( _MGSTR( _S_FILEMGR_GETTEMPDIR ), MSG_INFO );
std::string tempdir;
if ( !GetTempDir( tempdir ) )
{
OutMsg( "get tempdir fail", MSG_ERROR );
return false;
}
OutMsg( _MGSTR( _S_FILEMGR_TEMPDIR ) + tempdir );
#ifdef WIN32
tempdir += std::string( "\\" );
#else
tempdir += std::string( "/" );
#endif
m_IndexName = tempdir + m_sFileName + std::string( ".mgidx" );
m_PartName = tempdir + m_sFileName + std::string( ".mg" );
tempmsg = _MGSTR( _S_FILEMGR_TEMPNAME ) + m_PartName;
OutMsg( tempmsg );
tempmsg = _MGSTR( _S_FILEMGR_INDEXNAME ) + m_IndexName;
OutMsg( tempmsg );
//check if *.mgidx exists
bool bCanResume = ( m_nFileLen == -1 ? false : true );
OutMsg( _MGSTR( _S_FILEMGR_CHECKTEMP ), MSG_INFO );
FILE *fp;
if ( bCanResume && NULL != ( fp = fopen( m_PartName.c_str(), "r" ) ) )
{
fclose( fp );
OutMsg( _MGSTR( _S_FILEMGR_TEMPEXIST ), MSG_INFO );
}
else
{
bCanResume = false;
OutMsg( _MGSTR( _S_FILEMGR_TEMPNOTEXIST ), MSG_WARNNING );
}
if ( bCanResume )
{
OutMsg( _MGSTR( _S_FILEMGR_CHECKINDEX ), MSG_INFO );
if ( bCanResume && NULL != ( fp = fopen( m_IndexName.c_str(), "r" ) ) )
{
fclose( fp );
OutMsg( _MGSTR( _S_FILEMGR_INDEXEXIST ), MSG_INFO );
}
else
{
bCanResume = false;
OutMsg( _MGSTR( _S_FILEMGR_INDEXNOTEXIST ), MSG_WARNNING );
}
}
if ( bCanResume )
{
OutMsg( _MGSTR( _S_FILEMGR_CHECKTEMPLENGTH ) );
if ( bCanResume && m_nFileLen == FileSize( m_PartName ) )
{
OutMsg( _MGSTR( _S_FILEMGR_LENGTHOK ), MSG_SUCCESS );
}
else
{
bCanResume = false;
OutMsg( _MGSTR( _S_FILEMGR_LENGTHFAIL ), MSG_WARNNING );
}
}
//if can't resume,create new file
if ( bCanResume )
{
ReadIndex();
//m_bOldExist = true;
m_nOriginBytes = SumBytes();
}
else
{
OutMsg( _MGSTR( _S_FILEMGR_CREATEFILE ), MSG_INFO );
//m_bOldExist = false;
FILE *fp;
if ( NULL != ( fp = fopen( m_PartName.c_str(), "wb" ) ) )
{
if ( WriteIndex() < 0 )
{
OutMsg( "create index file fail.", MSG_ERROR );
//m_bError = true;
return false;
}
if ( m_nFileLen != -1 )
{
//写入文件长度的0到文件,可以对Linux做优化
#if defined(WIN32) || defined(__WINDOWS__)
char buf[ 1024 ];
memset( buf, 0, 1024 );
llong count = m_nFileLen;
while ( count >= 1024 )
{
fwrite( buf, 1, 1024, fp );
count -= 1024;
};
if ( count > 0 )
fwrite( buf, 1, count, fp );
#else //对Linux的优化分配,2006/07/05#if defined(__BSD__)|| defined(__DARWIN__) //it's wx preprocessor
//bsd and mac haven't ftruncate64
if ( 0 != ftruncate( fileno( fp ), m_nFileLen ) )#else if ( 0 != ftruncate64( fileno( fp ), m_nFileLen ) )#endif
{
OutMsg( "ftruncate fail,quit.\n", MSG_ERROR );
return false;
}
#endif
} //if(m_nFileLen!=-1)
OutMsg( _MGSTR( _S_FILEMGR_CREATEFILE ), MSG_SUCCESS ); //msg should change
fclose( fp );
}
else
{
tempmsg = std::string( "create " ) + m_PartName + string( " fail,quit." );
OutMsg( tempmsg, MSG_ERROR );
return false;
}
}
if ( m_bUpdateUI && m_pShowWin != NULL )
{
struct bindex data[ 20 ];
pthread_mutex_lock( &m_IndexMutex );
int nsize = m_Index.size();
for ( int i = 0;i < nsize && i < 20;i++ )
{
data[ i ] = m_Index[ i ];
}
pthread_mutex_unlock( &m_IndexMutex );
m_pShowWin->SetRange( m_nFileLen, 0, nsize, data );
}
return true;
}
CMgFileManager::~CMgFileManager()
{}
//read the idx file
//maybe more than 10 indexs
int CMgFileManager::ReadIndex()
{
m_Index.clear();
ifstream idxfile( m_IndexName.c_str() );
if ( idxfile.bad() )
{
OutMsg("read index fail1",MSG_ERROR);
return 0;
}
char buf[ 256 ];
while ( idxfile.good() )
{
llong from, to;
idxfile.getline( buf, 256 );
#ifndef WIN32
if ( 2 != sscanf( buf, "(%lld,%lld)", &from, &to ) )
#else
if ( 2 != sscanf( buf, "(%I64d,%I64d)", &from, &to ) )
#endif
{
break;
}
else
{
if ( to <= from )
continue; //invalid data
if ( to < 0 || from < 0 )
continue; //invalid data
bindex node;
node.start = from;
node.end = to;
node.mark = 0;
m_Index.push_back( node );
}
}
idxfile.close();
//check index
if ( m_nFileLen == -1 )
{
m_Index.clear();
}
else
{
vector<bindex>::iterator it;
for ( it = m_Index.begin();it != m_Index.end();it++ )
{
if ( it->start < 0 || it->start > it->end || it->start > m_nFileLen )
{
m_Index.clear();
break;
}
if ( it->end < 0 || it->end < it->start || it->end > m_nFileLen )
{
m_Index.clear();
break;
}
}
}
if(m_Index.size()>=1) OutMsg("get index ok");
return m_Index.size();
}
//ok tid is 1 based
void CMgFileManager::ThreadQuit( int tid )
{
pthread_mutex_lock( &m_IndexMutex );
vector<bindex>::iterator it;
for ( it = m_Index.begin();it != m_Index.end();it++ )
{
if ( it->mark == tid )
{
it->mark = 0;
break;
}
}
MergeIndex(); //clear some nodes
pthread_mutex_unlock( &m_IndexMutex );
}
//write index to file
int CMgFileManager::WriteIndex()
{
/*/
FILE *fp;
fp=fopen( m_IndexName.c_str(),"r");
if(fp==NULL) return -1;
char buf[128];
vector<bindex>::iterator it;
for ( it = m_Index.begin();it != m_Index.end();it++ )
{
sprintf(buf,"(%lld,%lld)\n",it->start,it->end);
fwrite(buf,strlen(buf),1,fp);
}
fclose(fp);
return m_Index.size();
/*/
ofstream idxfile( m_IndexName.c_str(), ios::out | ios::trunc );
if ( idxfile.bad() )
return -1;
vector<bindex>::iterator it;
for ( it = m_Index.begin();it != m_Index.end();it++ )
{
idxfile << "(" << it->start << "," << it->end << ")" << endl;
}
idxfile.close();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?