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 + -
显示快捷键?