/* Myget - A download accelerator for GNU/Linux
* Homepage: http://myget.sf.net
* Copyright (C) 2005- xiaosuo
*
* 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.
*/
#include <signal.h>
#include <errno.h>
#include "downloader.h"
#include "macro.h"
#include "utils.h"
#include "ftpplugin.h"
#include "httpplugin.h"
#include "progressbar.h"
#include "debug.h"
typedef void* (*PthreadFunction) (void*);
bool global_sigint_received = false;
bool global_downloading = false;
void
catch_ctrl_c(int signo)
{
if(global_downloading){
global_sigint_received = true;
}else{
pthread_exit(0);
}
};
Downloader::Downloader(void)
{
plugin = NULL;
blocks = NULL;
localPath = NULL;
localMg = NULL;
pb = new ProgressBar;
signal(SIGPIPE, SIG_IGN);
signal(SIGINT, &catch_ctrl_c);
};
Downloader::~Downloader(void)
{
delete[] blocks;
delete[] localPath;
delete[] localMg;
delete pb;
delete plugin;
signal(SIGPIPE, SIG_DFL);
signal(SIGINT, SIG_DFL);
};
int
Downloader::init_plugin(void)
{
if(task.proxy.get_type() == HTTP_PROXY){
delete plugin;
plugin = new HttpPlugin;
}else{
switch(task.url.get_protocol()){
case HTTP:
#ifdef HAVE_SSL
case HTTPS:
#endif
delete plugin;
plugin = new HttpPlugin;
break;
case FTP:
delete plugin;
plugin = new FtpPlugin;
break;
default:
return -1;
}
}
return 0;
};
int
Downloader::init_task(void)
{
int i;
int ret;
_reinit_plugin:
if(init_plugin() < 0){
cerr<<"Unknown protocol"<<endl;
return -1;
}
for(i = 0; task.tryCount <= 0 || i < task.tryCount; i ++){
ret = plugin->get_info(&task);
if(ret == -1){
return -1;
}else if(ret == S_REDIRECT){
cerr<<"Redirect to: "<<task.url.get_url()<<endl;
goto _reinit_plugin;
}else if(ret == 0){
return 0;
}else{
continue;
}
}
return E_MAX_COUNT;
};
int
Downloader::init_local_file_name(void)
{
int length;
char *tmpStr;
length = task.get_local_dir() ? strlen(task.get_local_dir()) : 1;
length += task.get_local_file() ? strlen(task.get_local_file()) :
strlen(task.url.get_file());
length += 6;
tmpStr = new char[length];
snprintf( tmpStr, length, "%s/%s.mg!",
task.get_local_dir() ? task.get_local_dir() : ".",
task.get_local_file() ? task.get_local_file() :
task.url.get_file() );
delete[] localPath;
delete[] localMg;
tmpStr[length - 5] = '\0';
localPath = StrDup(tmpStr);
tmpStr[length - 5] = '.';
localMg = tmpStr;
return 0;
};
int
Downloader::init_threads_from_mg(void)
{
FILE *fd;
int i;
struct stat file_stat;
if(stat(localMg, &file_stat) < 0){
perror("Can not get the info of the temp file");
return -1;
}
if(file_stat.st_size < task.fileSize + sizeof(threadNum)){
cerr<<"the temp file: \""<<localMg<<"\" is not correct"<<endl;
return -1;
}
fd = fopen(localMg, "r");
if(fd == NULL && errno == EACCES){
cerr<<"Can not access the temp file: "<<localMg<<endl;
return -1;
}
fseeko(fd, task.fileSize, SEEK_CUR);
fread(&threadNum, sizeof(threadNum), 1, fd);
if(file_stat.st_size != task.fileSize + sizeof(threadNum) + sizeof(off_t)*threadNum*3){
cerr<<"the temp file: \""<<localMg<<"\" is not correct"<<endl;
fclose(fd);
return -1;
}
delete[] blocks;
blocks = new Block[threadNum];
for(i = 0; i < threadNum; i ++){
fread(&blocks[i].startPoint, sizeof(off_t), 1, fd);
fread(&blocks[i].downloaded, sizeof(off_t), 1, fd);
fread(&blocks[i].size, sizeof(off_t), 1, fd);
if(blocks[i].bufferFile.open(localMg) < 0){
perror("Can not open the temp file to write");
return -1;
}
}
fclose(fd);
return 0;
};
int
Downloader::init_threads_from_info(void)
{
off_t block_size;
int i;
threadNum = task.threadNum > 0 ? task.threadNum : 1;
block_size = task.fileSize / threadNum;
if(block_size <= 0){ // too small file
threadNum = 1;
block_size = task.fileSize;
}
delete[] blocks;
blocks = new Block[threadNum];
for(i = 0; i < threadNum; i ++){
blocks[i].startPoint = i * block_size;
blocks[i].size = block_size;
if(blocks[i].bufferFile.open(localMg) < 0){
perror("Can not open the temp file to write");
return -1;
}
}
blocks[threadNum - 1].size = task.fileSize - block_size * ( threadNum - 1);
return 0;
};
int
Downloader::thread_create(void)
{
pthread_t pid;
int i;
while(1){
i = pthread_create(&pid, NULL,
(PthreadFunction)&download_thread, (void*)this);
if(i == 0) break;
usleep(250000);
}
for(i = 0; i < threadNum; i ++){
if(blocks[i].pid == 0){ // found an empty slot
blocks[i].pid = pid;
break;
}
}
if(i == threadNum) return -1;
return 0;
};
// return the source'id of the current thread
int
Downloader::self(void)
{
pthread_t self;
self = pthread_self();
int i;
while(1){
for(i = 0; i < threadNum; i ++){
if(blocks[i].pid == self) return i;
}
// the parent thread maybe slower than me
}
};
// this function will be called by pthread_create, because c++
// not allow non-static function convert to the right function,
// so make it static, but this will be safe
int
Downloader::download_thread(Downloader *downloader)
{
int self, ret, i;
self = downloader->self();
/*
for(i = 0; downloader->task.tryCount <= 0 ||
i < downloader->task.tryCount; i ++){
*/
while(1){
ret = downloader->plugin->download(downloader->task, downloader->blocks + self);
if(ret == E_SYS){ // system error
downloader->blocks[self].state = EXIT;
return -1;
}else if(ret == 0){
downloader->blocks[self].state = EXIT;
return 0;
}else{
continue;
}
}
downloader->blocks[self].state = EXIT;
return E_MAX_COUNT;
};
// schedule the thread, when the thread exit joined it or wake up it if
// the next thread have not begun to downloading from the serve,
// return the number of the running threads
int
Downloader::schedule(void)
{
int i, j;
int joined;
joined = 0;
for(i = 0; i < threadNum; i ++){
if(blocks[i].state == WAIT){
for(j = i + 1; j < threadNum; j ++){
if(blocks[i].startPoint + blocks[i].size == blocks[j].startPoint){
break;
}
}
if(j < threadNum && blocks[j].downloaded == 0){
if(blocks[j].state == STOP || blocks[j].state == EXIT){
pthread_cancel(blocks[j].pid);
pthread_join(blocks[j].pid, NULL);
blocks[j].state = JOINED;
blocks[j].bufferFile.close();
}else if(blocks[j].state != JOINED){
continue;
}
blocks[i].size += blocks[j].size;
blocks[i].state = WAKEUP;
blocks[j].startPoint = -1;
blocks[j].downloaded = 0;
blocks[j].size = 0;
i = j;
joined += j - i;
off_t *data = new off_t[threadNum];
for(j = 0; j < threadNum; j ++){
data[j] = blocks[j].startPoint;
}
pb->set_start_point(data);
delete[] data;
}
}else if(blocks[i].state == EXIT){
pthread_join(blocks[i].pid, NULL);
blocks[i].state = JOINED;
blocks[i].bufferFile.close();
joined ++;
}else if(blocks[i].state == JOINED){
joined ++;
}else{
continue;
}
}
return threadNum - joined;
}; // end of schedule
int
Downloader::save_temp_file_exit(void)
{
int i;
FILE *fd;
for(i = 0; i < threadNum; i ++){
if(blocks[i].state != JOINED){
pthread_cancel(blocks[i].pid);
pthread_join(blocks[i].pid, NULL);
blocks[i].bufferFile.close();
}
};
// if know the filesize, maybe can resume through other link address
// but if the filesize is unknow
没有合适的资源?快使用搜索试试~ 我知道了~
mytget linux下的下载工具
4星 · 超过85%的资源 需积分: 9 39 下载量 61 浏览量
2008-10-02
08:59:26
上传
评论
收藏 225KB GZ 举报
温馨提示
共66个文件
h:19个
cpp:19个
in:5个
支持多线程,支持断点续传,速度很快。是linux下的迅雷。
资源推荐
资源详情
资源评论
收起资源包目录
myget-0.1.2.tar.gz (66个子文件)
myget-0.1.2
missing 9KB
ltmain.sh 182KB
COPYING 18KB
autom4te.cache
output.0 249KB
traces.0 22KB
requests 5KB
aclocal.m4 37KB
INSTALL 8KB
config.h.in 2KB
mkinstalldirs 729B
stamp-h.inT 10B
configure 249KB
ChangeLog 428B
BUGS 999B
script
insert_copyright.sed 888B
install-sh 5KB
Makefile.in 16KB
depcomp 12KB
stamp-h.in 10B
configure.in 1KB
AUTHORS 57B
src
macro.h 2KB
ftpplugin.h 1KB
ftp.cpp 8KB
httpplugin.cpp 6KB
progressbar.cpp 6KB
tcp.h 3KB
proxy.cpp 2KB
ftpparser.h 1KB
http.h 3KB
mytget.cpp 4KB
header.cpp 3KB
httpplugin.h 1KB
plugin.cpp 1KB
downloader.h 2KB
utils.h 2KB
ftpparser.cpp 6KB
ftpplugin.cpp 7KB
tcp.cpp 10KB
advio.h 3KB
debug.cpp 1KB
myget.cpp 0B
downloader.cpp 13KB
Makefile.in 15KB
block.h 1KB
myget.h 1KB
url.cpp 12KB
http.cpp 8KB
ftp.h 3KB
plugin.h 1KB
task.cpp 2KB
task.h 2KB
header.h 2KB
url.h 2KB
proxy.h 1KB
advio.cpp 9KB
progressbar.h 2KB
Makefile.am 592B
debug.h 969B
block.cpp 960B
utils.cpp 5KB
config.guess 42KB
README 49B
config.sub 30KB
NEWS 0B
Makefile.am 14B
共 66 条
- 1
资源评论
- 坎布里其2013-12-12用的人好少啊,没学会。
zxywd
- 粉丝: 158
- 资源: 18
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- 关于mybatis的一些相关资源
- 关于mybatist的一些相关资源
- uni-app实战社区交友类app开发&带视频教程
- mybatis动态sql的一些相关资源
- 隐马尔可夫模型在期货市场的应用_曾琦裕 (1).caj
- 极域解控和极域反控!!!
- 安卓android-serialport-api 串口demo源代码.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功