mgfilemanager.cpp
来自「一款LINUX下的下载软件」· C++ 代码 · 共 1,343 行 · 第 1/3 页
CPP
1,343 行
return m_Index.size();
//*/
}
//get file length,check if the length ok
llong CMgFileManager::FileSize( string sFileName )
{
ifstream f;
f.open( sFileName.c_str(), ios::binary | ios::in );
if ( !f.good() || f.eof() || !f.is_open() )
{
return 0;
}
f.seekg( 0, ios::beg );
ifstream::pos_type begin_pos = f.tellg();
f.seekg( 0, std::ios::end );
llong len = static_cast<llong>( f.tellg() - begin_pos );
f.close();
return len;
}
struct SAscendingDateSort
{
bool operator() ( bindex a, bindex b )
{
return a.start < b.start;
}
};
//order the index
void CMgFileManager::OrderIndex()
{ //按起点顺序从小到大排序
if ( m_Index.size() <= 1 )
return ;
sort( m_Index.begin(), m_Index.end(), SAscendingDateSort() );
}
//lastsize returned for sometime thread can't get filesize ahead till task finish
bool CMgFileManager::IsTaskFinish( llong& lastsize )
{
if ( m_Index.size() == 1 &&
m_Index[ 0 ].start == 0 &&
m_Index[ 0 ].end == m_nFileLen
)
{
lastsize = m_nFileLen;
return true;
}
else
{
if ( m_nFileLen == 0 ) { lastsize=0; return true; } else {
lastsize = m_nFileLen;
return false; }
}
}
//对索引合并,应该加锁使用
//对没有作标记的0长度索引,删除
void CMgFileManager::MergeIndex()
{
if ( m_Index.empty() )
return ;
if ( m_Index.size() == 1 )
{
if ( !m_Index.front().mark && m_Index.front().start == m_Index.front().end )
{
m_Index.clear();
return ;
}
}
vector<bindex> icopy;
vector<bindex>::iterator it;
bindex lastindex = m_Index.front();
for ( it = m_Index.begin() + 1;it != m_Index.end();it++ )
{
if ( lastindex.end >= it->start )
{
if ( lastindex.end < it->end )
{
lastindex.end = it->end;
lastindex.mark = it->mark;
}
else
{
continue;
}
}
else
{
if ( !lastindex.mark && lastindex.start == lastindex.end )
{
}
else
{
icopy.push_back( lastindex );
}
lastindex = *it;
}
}
icopy.push_back( lastindex );
m_Index.swap( icopy );
}
//thread give his data by calling this function
//if >0 returned thread should continue to get data
//if =0 returned thread should stop.
//if <0 returned ,means something error with write data,thread should stop.
//tid is 1 based
int CMgFileManager::FileData( int tid, llong offset, int len, void *data, bool end, int& us )
{
//if posible ,check file length
if ( end )
{
llong flen = offset + len;
if ( m_nFileLen != -1 )
{ //have size
if ( m_nFileLen != flen )
{ //socket close maybe not indicate the file end.
//sometime overload server will close the connection
//so we don't use this info if we alread have file size
OutMsg( _MGSTR( _S_FILEMGR_ERRORCLOSESOCK ), MSG_WARNNING );
}
else
{
OutMsg( _MGSTR( _S_FILEMGR_FILELENCONFIRM ), MSG_SUCCESS );
}
}
else
{ //no filesize,asume the flen is filesize,because server closed the connection
//no function convert long long to string
char lenstr[ 24 ];
sprintf( lenstr, "%lld", flen );
m_nFileLen = flen;
OutMsg( _MGSTR( _S_FILEMGR_ENDFILELEN ) + string( lenstr ) );
}
}
pthread_mutex_lock( &m_IndexMutex );
us = gSpeedCtrl.DataIn( len ); //speed control
bool combine;
//write data to file
int wret = WriteData( offset, len, data, combine );
if ( wret >= 0 )
{
WriteIndex(); //write index
if ( combine )
{
m_nSumBytes = SumBytes() - m_nOriginBytes;
}
else
{
m_nSumBytes += len; //record data to calcu speed
}
}
else
{
goto quit;
//pthread_mutex_unlock(&m_IndexMutex);
//return wret;
}
//OK,update ui data
if ( m_bUpdateUI && m_pShowWin )
{
struct bindex data[ 20 ];
for ( int i = 0;i < int( m_Index.size() ) && i < 20;i++ )
{
data[ i ] = m_Index[ i ];
}
m_pShowWin->SetData( m_Index.size(), data );
}
quit:
m_UrlList[ m_AntId2UrlIndex[ tid - 1 ] ].prior++; //multi url prior
m_AntSpeed[ tid - 1 ] ++;
m_SumPack++;
if ( m_UrlList.size() > 1 && m_nSwap > 0 )
{
if ( m_nSwap == tid )
{
if ( wret > 0 )
wret = -3;
memset( m_AntSpeed, 0, 10 * sizeof( int ) );
m_SumPack = 0;
m_nSwap = -1;
}
pthread_mutex_unlock( &m_IndexMutex );
return wret;
}
//10M check
if ( m_SumPack * RECVBUF > 10 * 1024 * 1024 && m_UrlList.size() > 1 )
{
//检查我们这个线程的速度和最大速度的差异,如果>=2就试图切换
//本线程速度=m_AntSpeed[tid-1];
//找最大速度
int maxspeed = -1;
for ( int i = 0;i < 10;i++ )
{
if ( m_AntSpeed[ i ] > maxspeed )
maxspeed = m_AntSpeed[ i ];
}
int minspeed = 1000000;
int minpos = -1;
//找最小速度
for ( int i = 0;i < 10;i++ )
{
if ( m_AntSpeed[ i ] > 0 && m_AntSpeed[ i ] < minspeed )
{
minspeed = m_AntSpeed[ i ];
minpos = i;
}
}
//check if have new mirror.
bool havenew = false;
pthread_mutex_lock( &m_UListMutex );
std::vector<_ul>::const_iterator itm;
for ( itm = m_UrlList.begin();itm != m_UrlList.end();itm++ )
{
if ( !itm->bused )
{
havenew = true;
break;
}
}
pthread_mutex_unlock( &m_UListMutex );
if ( havenew )
{
m_nSwap = minpos + 1;
if ( m_nSwap == tid )
{
if ( wret > 0 )
wret = -3;
memset( m_AntSpeed, 0, 10 * sizeof( int ) );
m_SumPack = 0;
m_nSwap = -1;
}
}
else if ( float( maxspeed ) / minspeed >= 2.0 )
{
m_nSwap = minpos + 1;
if ( m_nSwap == tid )
{
if ( wret > 0 )
wret = -3;
memset( m_AntSpeed, 0, 10 * sizeof( int ) );
m_SumPack = 0;
m_nSwap = -1;
}
}
else
{ //wait for next
memset( m_AntSpeed, 0, 10 * sizeof( int ) );
m_SumPack = 0;
m_nSwap = -1;
}
}
pthread_mutex_unlock( &m_IndexMutex );
//if socks closed the end this session
//2006/10/09 comment out 2 lines
//if(end && wret<0) return wret;
//else if(end && wret>=0) return 0;
return wret;
}
//write data to file
//return:
// <0 error
// =0 merged with other block,stop
// >0 continue
int CMgFileManager::WriteData( llong offset, int len, void *data, bool& combine )
{
FILE * fp;
combine = false;//use wxwidgets preprocesser ,mac and bsd only have fopen
#if defined(WIN32) || defined(__BSD__) || defined(__WINDOWS__) || defined(__DARWIN__)
if ( NULL != ( fp = fopen( m_PartName.c_str(), "rb+" ) ) )
#else
if ( NULL != ( fp = fopen64( m_PartName.c_str(), "r+" ) ) )
#endif
{
#ifdef WIN32
if ( 0 != fseek( fp, offset, SEEK_SET ) )
#else
if ( 0 != fseeko( fp, offset, SEEK_SET ) )
#endif
{
OutMsg( "fseeko fail.", MSG_ERROR );
return -1;
}
//似乎要在这里防止数据过载,否则文件末尾会变化
if ( m_nFileLen != -1 )
{ //know filelen
if ( offset + ( llong ) len <= m_nFileLen )
{
if ( len != int( fwrite( data, 1, len, fp ) ) )
{
OutMsg( "fwrite fail.", MSG_ERROR );
return -1;
}
}
else if ( m_nFileLen - offset > 0 )
{
OutMsg( "data overload", MSG_ERROR );
if ( m_nFileLen - offset != int( fwrite( data, 1, m_nFileLen - offset, fp ) ) )
{
OutMsg( "fwrite fail.", MSG_ERROR );
return -1;
}
}
else
{
OutMsg( "data overload", MSG_ERROR );
}
}
else //unknow filelen
{
if ( len != int( fwrite( data, 1, len, fp ) ) )
{
OutMsg( "fwrite fail.", MSG_ERROR );
return -1;
}
}
fclose( fp );
//是否继续下载要判断是否这段数据已经连接到了下一个已下载的数据段
//首先找到这个数据段在索引中的项目,然后查找下一个索引的起点位置,如果能够重合,就停止本线程下载
//bool found=false;
for ( int i = 0;i < int( m_Index.size() );i++ )
{
if ( m_Index[ i ].end == offset )
{
//found
if ( i == int( m_Index.size() - 1 ) )
{ //last block
m_Index[ i ].end += len;
if ( m_nFileLen != -1 )
{ //have filelen,we can judge if data end
if ( m_Index[ i ].end > m_nFileLen )
{
OutMsg( _MGSTR( _S_FILEMGR_DATAOVERLOAD ), MSG_WARNNING );
m_Index[ i ].end = m_nFileLen;
combine = true;
}
return m_Index[ i ].end == m_nFileLen ? 0 : 1;
}
else //2006/10/02 add
{ //no filelen,we can't judge if data end,just continue
return 1;
}
}
else if ( m_Index[ i + 1 ].start <= offset + len )
{ //block merge with next block
//是否让本线程退出取决于数据是否超越了下一个块的末尾,如果超越了下个快的末尾
//那么应该让本线程继续,否则应该退出本线程,继续选择下一个下载点。
int nret = m_Index[ i + 1 ].end > offset + len ? 0 : 1;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?