#include "myhead.h"
struct info
{
char src_file[100];//节点源目录文件名
char dest_file[100];//节点目标目录文件名
long int start_site;//大文件断点光标起始位置
long int end_site;//大文件断点光标结束位置
struct info * next;//双向循环链表
struct info * prev;
};
struct thread_pool //线程池结构体
{
pthread_mutex_t mutex;//线程互斥锁
pthread_cond_t cond;//线程条件变量
int thread_num;//线程个数
pthread_t *tid;//记录线程的id
//struct info * head;//任务队列头
int shutdown ; // 和子线程说 “干完活可以走了”
};
struct info * head;//定义全局变量
struct thread_pool *pool ;
int n = 0;
struct info* mallocfile(void) //堆空间大小申请
{
struct info* node = malloc(sizeof(struct info));
if(node == NULL)
{
perror("malloc failed:");
exit(-1);
}
return node;
}
int find_file(char * src_name, char * dest_name)//目录遍历
{
printf("%s\n",src_name );
char new_src_name[100];//源文件与目录新结合名
char new_dest_name[100];//目标文件与目录新结合名
//mkdir(dest_name, 0777);
//size_t file_size = get_filesize(infd);
//打开源目录
DIR * dp = opendir(src_name);
if (dp == NULL)
{
perror("opendir dir failed:");
return -1;
}
struct dirent * st;
while(1)
{
st = readdir(dp);// 读目录项
if(st == NULL)
{
perror("readdir result:");
printf("******%s end ****** \n",src_name);
break;
}
else
{
printf("---%s \n ",st->d_name);
}
bzero(new_src_name , 100);
bzero(new_dest_name , 100);
sprintf(new_src_name , "%s/%s" ,src_name, st->d_name);//源文件与目录新结合名
sprintf(new_dest_name , "%s/%s" ,dest_name, st->d_name);//目标文件与目录新结合名
printf("new_src_name:%s\n",new_src_name);
struct info* node = mallocfile();//定义新节点
long int block;//断点个数
printf("new_dest_name:%s\n",new_dest_name);
switch(st->d_type)
{
//目录文件
case DT_DIR://目录文件
if((strcmp(st->d_name , ".")==0) || (strcmp(st->d_name , "..")==0))
break;
printf("dir_name: %s\n",st->d_name);
printf("new_src_name: %s\n",new_src_name);
if(-1 == find_file (new_src_name,new_dest_name)) // 开始读子目录的内容
return -1;
break;
case DT_REG://普通文件
{ struct stat buf; //计算文件属性大小
int ret = stat(new_src_name,&buf);
if(ret<0)
{
perror("stat fail");
return -1;
}
long int file_size = buf.st_size;
if(file_size > 1024*1024) //如果为大文件
{
printf("这是大文件!!!!\n");
if(file_size%(1024*1024) == 0)
block = file_size/(1024*1024);//分段
else
block = file_size/(1024*1024) + 1; // 68.9 ==> 68+1 block69
if(block == 0)
return 0;
long int percent = file_size / block;//一段大小为percent
printf("file_size = %ld ---\n block = %ld---\n percent = %ld ---\n",file_size,block,percent);
for(int i = 0;i <= block;i++)
{
///记录到的位置大小
node->start_site = i*percent;
node->end_site = node->start_site+percent;
printf("start_site = %ld \n",node->start_site);
printf("end_site = %ld\n",node->end_site);
strcpy( node->src_file,new_src_name);
strcpy( node->dest_file,new_dest_name);
node->next= node->prev = NULL;//node
//添加到队列中, 队列是共享资源
pthread_mutex_lock(&(pool->mutex));//上互斥锁,以防止被破坏结构
//头插法
node->prev = head;
node->next = head->next;
head->next->prev = node;
head->next = node;
n++;
//发送条件变量
pthread_cond_signal(&(pool->cond));//只加一个节点,就只和任意一个线程说,发送信号
pthread_mutex_unlock(&(pool->mutex));//解互斥锁,其它线程可以进来。
}
break;
}
else
{
printf("这是小文件!!!\n");
printf("file_size = %ld ---\n ",file_size);
strcpy( node->src_file,new_src_name);
strcpy( node->dest_file,new_dest_name);
printf("node->src_file:%s\n",node->src_file);
printf("node->dest_file:%s\n",node->dest_file);
node->start_site = node->end_site = 0;
node->next= node->prev = NULL;//node
//添加到队列中, 队列是共享资源
pthread_mutex_lock(&(pool->mutex));
//头插法
node->prev = head;
node->next = head->next;
head->next->prev = node;
head->next = node;
n++;
//发送条件变量
pthread_cond_signal(&(pool->cond));//只加一个节点,就只和任意一个线程说
pthread_mutex_unlock(&(pool->mutex));
break;
}
}
}
}
closedir(dp);
return 0;
}
int file_cp(char * src_name, char * dest_name,long int start_site)
{
int fd_s,fd_d;
char buf[1024*1024+1];
fd_s = open(src_name,O_RDWR);
if(fd_s == -1)
{ perror("open y failed ");
return -1;
}
fd_d = open(dest_name,O_CREAT|O_WRONLY,0777);
if(fd_d == -1)
{ perror("open c failed ");
return -1;
}
//int now_copy = 1;
//struct info* node = head;
//while(1)
//{
bzero(buf,1024*1024+1);
lseek(fd_s, start_site, SEEK_SET); //若传进来的是小文件 则start_site=0 光标位置为0开始 若传进来的是大文件,start_site是记录断点位置,从断点位置开始// 67
printf("读取:%ld",start_site);
lseek(fd_d, start_site, SEEK_SET);
printf("复制:%ld",start_site);
int ret1 = read(fd_s, buf, 1024*1024+1);//读数据到BUF区
printf("%s\n",buf);
if(ret1 == -1)
{
perror("read failed");
return -1;
}
int ret2 = write(fd_d, buf, ret1);//将BUF区的数据读到目标文件中
if(ret2 == -1)
{
perror("write failed");
return -1;
}
/*if(ret1 == 0)
{
break;
} */
//now_copy++;// 69
//printf("%d\n",now_copy);
//}
printf("asdadadada\n");
close(fd_s);
close(fd_d);
}
void * routine(void * arg)
{
while(1)//不断取节点,开始复制
{
pthread_mutex_lock(&(pool->mutex));//上锁
while( head->next == head && pool->shutdown == 0 )// 管理线程还没有来得及添加节点
pthread_cond_wait(&(pool->cond) ,&(pool->mutex)); // 再次判断是不是为空,能不能结束
if(head->next == head && pool->shutdown == 1)// 说明现在已经可以结束
{
pthread_mutex_unlock(&(pool->mutex));
pthread_exit(NULL);
}
//解除最后一个节点
struct info *tmp;
//tmp = mallocfile();
tmp = head->prev;
(tmp->prev)->next = head;
head->prev = tmp->prev;
pthread_mutex_unlock(&pool->mutex); //开锁1
file_cp (tmp->src_file, tmp->dest_file,tmp->start_site); //复制文件
free(tmp); //释放节点
}
}
int main(int argc, char ** argv) // ./target src_name dest_name
{
head = mallocfile();
head->next = head;
head->prev = head;
if(argc != 3)
{
printf("enter fail! \n");
return -1;
}
//申请空间
pool = malloc(sizeof(struct thread_pool));
if(pool== NULL)
{
perror("malloc pool failed:");
return -1;
}
// 初始化同步控制
pool->shutdown = 0;
pthread_mutex_init(&(pool->mutex),NULL);
pthread_cond_init(&(pool->cond),NULL);
//主线程就开始遍历,往队列中加节点
find_file(argv[1] , argv[2]);
// 创建线程
if(n%20 == 0)
pool->thread_num = n/20;// 3个子线程
else
pool->thread_num = n/20+1;
//pool->thread_num = 3;
printf("--------------***************%d***************-------------\n",n);
printf("------