⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 data.c

📁 linux下bt下载C源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	return 0;
}

// 将16MB缓冲区中已下载的piece写入硬盘,这样可以释放缓冲区
int write_btcache_to_harddisk(Peer *peer)
{
	Btcache          *p = btcache_head;
	int     slice_count = piece_length / (16*1024);
	int     index_count = 0;
	int      full_count = 0;
	int     first_index;

	while(p != NULL) {
		if(index_count % slice_count == 0) {
			full_count = 0;
			first_index = index_count;
		}

		if( (p->in_use  == 1) && (p->read_write == 1) && 
			(p->is_full == 1) && (p->is_writed  == 0) ) {
			full_count++;
		}

		if(full_count == slice_count) {
			write_piece_to_harddisk(first_index,peer);
		}

		index_count++;
		p = p->next;
	}

	return 0;
}

// 当缓冲区不够用时,释放那些从硬盘上读取的piece
int release_read_btcache_node(int base_count)
{
	Btcache           *p = btcache_head;
	Btcache           *q = NULL;
	int            count = 0;
	int       used_count = 0;
	int      slice_count = piece_length / (16*1024);

	if(base_count < 0)  return -1;

	while(p != NULL) {
		if(count % slice_count == 0)  { used_count = 0; q = p; }
		if(p->in_use==1 && p->read_write==0)  used_count += p->access_count;
		if(used_count == base_count)  break;  // 找到一个空闲的piece
		
		count++;
		p = p->next;
	}

	if(p != NULL) {
		p = q;
		while(slice_count > 0) {
			p->index  = -1;
			p->begin  = -1;
			p->length = -1;
			
			p->in_use       =  0;
			p->read_write   = -1;
			p->is_full      =  0;
			p->is_writed    =  0;
			p->access_count =  0;

			slice_count--;
			p = p->next;
		}
	}

	return 0;
}

// 下载完一个slice后,检查是否该slice为一个piece最后一块
// 若是则写入硬盘,只对刚刚开始下载时起作用,这样可以立即使peer得知
int is_a_complete_piece(int index, int *sequnce)
{
	Btcache          *p = btcache_head;
	int     slice_count = piece_length / (16*1024);
	int           count = 0;
	int             num = 0;
	int        complete = 0;

	while(p != NULL) {
		if( count%slice_count==0 && p->index!=index ) {
			num = slice_count;
			while(num>0 && p!=NULL)  { p = p->next; num--; count++; }
			continue;
		}
		if( count%slice_count!=0 || p->read_write!=1 || p->is_full!=1) 
			break;

		*sequnce = count;
		num = slice_count;
	
		while(num>0 && p!=NULL) {
			if(p->index==index && p->read_write==1 && p->is_full==1)
				 complete++;
			else break;
	
			num--;
			p = p->next;
		}

		break;
	}

	if(complete == slice_count) return 1;
	else return 0;
}

// 将16MB的缓冲区中所存的所有数据清空
void clear_btcache()
{
	Btcache *node = btcache_head;
	while(node != NULL) {
		node->index  = -1;
		node->begin  = -1;
		node->length = -1;
		
		node->in_use       =  0;
		node->read_write   = -1;
		node->is_full      =  0;
		node->is_writed    =  0;
		node->access_count =  0;
		
		node = node->next;
	}
}

// 将从peer处获取的一个slice存储到缓冲区中
int write_slice_to_btcache(int index,int begin,int length,
						   unsigned char *buff,int len,Peer *peer)
{
	int     count = 0, slice_count, unuse_count;
	Btcache *p = btcache_head, *q = NULL;  // q指向每个piece第一个slice
	
	if(p == NULL)  return -1;
	if(index>=pieces_length/20 || begin>piece_length-16*1024)  return -1;
	if(buff==NULL || peer==NULL)  return -1;

	if(index == last_piece_index) {
		write_slice_to_last_piece(index,begin,length,buff,len,peer);
		return 0;
	}

	if(end_mode == 1) {
		if( get_bit_value(bitmap,index) == 1 )  return 0;
	}
	
	// 遍历缓冲区,检查当前slice所在的piece的其他数据是否已存在
	// 若存在说明不是一个新的piece,若不存在说明是一个新的piece
	slice_count = piece_length / (16*1024);
	while(p != NULL) {
		if(count%slice_count == 0)  q = p;
		if(p->index==index && p->in_use==1)  break;

		count++;
		p = p->next;
	}
	
	// p非空说明当前slice所在的piece的有些数据已经下载
	if(p != NULL) {
		count = begin / (16*1024);  // count存放当前要存的slice在piece中的索引
		p = q;
		while(count > 0)  { p = p->next; count--; }
		
		if(p->begin==begin && p->in_use==1 && p->read_write==1 && p->is_full==1)
			return 0; // 该slice已存在
		
		p->index  = index;
		p->begin  = begin;
		p->length = length;
		
		p->in_use       = 1;
		p->read_write   = 1;
		p->is_full      = 1;
		p->is_writed    = 0;
		p->access_count = 0;
		
		memcpy(p->buff,buff,len);
		printf("+++++ write a slice to btcache index:%-6d begin:%-6x +++++\n",
			   index,begin);
		
		// 如果是刚刚开始下载(下载到的piece不足10个),则立即写入硬盘,并告知peer
		if(download_piece_num < 1000) {
			int sequece;
			int ret;
			ret = is_a_complete_piece(index,&sequece);
			if(ret == 1) {
				printf("###### begin write a piece to harddisk ######\n");
				write_piece_to_harddisk(sequece,peer);
				printf("###### end   write a piece to harddisk ######\n");
			}
		}
		return 0;
	}
	
	// p为空说明当前slice是其所在的piece的第一块下载到的数据
	// 首先判断是否存在空的缓冲区,若不存在,则将已下载的写入硬盘
	int i = 4;
	while(i > 0) {
		slice_count = piece_length / (16*1024);
		count       = 0;  // 计数当前指向第几个slice
		unuse_count = 0;  // 计数当前piece中有多少个空的slice
		Btcache *q;       
		p = btcache_head;
		
		while(p != NULL) {
			if(count%slice_count == 0)  { unuse_count = 0; q = p; }
			if(p->in_use == 0) unuse_count++;
			if(unuse_count == slice_count)  break;  // 找到一个空闲的piece
			
			count++;
			p = p->next;
		}
		
		if(p != NULL) {
			p = q;
			count = begin / (16*1024);
			while(count > 0)  { p = p->next; count--; }

			p->index  = index;
			p->begin  = begin;
			p->length = length;
			
			p->in_use       = 1;
			p->read_write   = 1;
			p->is_full      = 1;
			p->is_writed    = 0;
			p->access_count = 0;
			
			memcpy(p->buff,buff,len);
			printf("+++++ write a slice to btcache index:%-6d begin:%-6x +++++\n",
				   index,begin);
			return 0;
		}
		
		if(i == 4) write_btcache_to_harddisk(peer);
		if(i == 3) release_read_btcache_node(16);
		if(i == 2) release_read_btcache_node(8);
		if(i == 1) release_read_btcache_node(0);
		i--;
	}
	
	// 如果还没有空闲的缓冲区,丢弃下载到这个slice
	printf("+++++ write a slice to btcache FAILED :NO BUFFER +++++\n");
	clear_btcache();

	return 0;
}

// 从缓冲区获取一个slice,读取的slice存放到buff指向的数组中
// 若缓冲区中不存在该slice,则从硬盘读slice所在的piece到缓冲区中
int read_slice_for_send(int index,int begin,int length,Peer *peer)
{
	Btcache  *p = btcache_head, *q;  // q指向每个piece第一个slice
	int       ret;
	
	// 检查参数是否有误
	if(index>=pieces_length/20 || begin>piece_length-16*1024)  return -1;

	ret = get_bit_value(bitmap,index);
	if(ret < 0)  { printf("peer requested slice did not download\n"); return -1; }

	if(index == last_piece_index) {
		read_slice_for_send_last_piece(index,begin,length,peer);
		return 0;
	}

	// 待获取得slice缓冲区中已存在
	while(p != NULL) {
		if(p->index==index && p->begin==begin && p->length==length &&
		   p->in_use==1 && p->is_full==1) {
			// 构造piece消息
			ret = create_piece_msg(index,begin,p->buff,p->length,peer);
			if(ret < 0) { printf("Function create piece msg error\n"); return -1; }
			p->access_count = 1;
			return 0;
		}
		p = p->next;
	}

	int i = 4, count, slice_count, unuse_count;
	while(i > 0) {
		slice_count = piece_length / (16*1024);
		count = 0;  // 计数当前指向第几个slice
		p = btcache_head;

		while(p != NULL) {
			if(count%slice_count == 0)  { unuse_count = 0; q = p; }
			if(p->in_use == 0) unuse_count++;
			if(unuse_count == slice_count)  break;  // 找到一个空闲的piece
			
			count++;
			p = p->next;
		}
		
		if(p != NULL) {
			read_piece_from_harddisk(q,index);

			p = q;
			while(p != NULL) {
				if(p->index==index && p->begin==begin && p->length==length &&
					p->in_use==1 && p->is_full==1) {
					// 构造piece消息
					ret = create_piece_msg(index,begin,p->buff,p->length,peer);
					if(ret < 0) { printf("Function create piece msg error\n"); return -1; }
					p->access_count = 1;
					return 0;
				}
				p = p->next;
			}
		}
		
		if(i == 4) write_btcache_to_harddisk(peer);
		if(i == 3) release_read_btcache_node(16);
		if(i == 2) release_read_btcache_node(8);
		if(i == 1) release_read_btcache_node(0);
		i--;
	}

	// 如果实在没有缓冲区了,就不读slice所在的piece到缓冲区中
	p = initialize_btcache_node();
	if(p == NULL)  { printf("%s:%d allocate memory error",__FILE__,__LINE__); return -1; }
	p->index  = index;
	p->begin  = begin;
	p->length = length;
	read_slice_from_harddisk(p);
	// 构造piece消息
	ret = create_piece_msg(index,begin,p->buff,p->length,peer);
	if(ret < 0) { printf("Function create piece msg error\n"); return -1; }
	// 释放刚刚申请的内存
	if(p->buff != NULL)  free(p->buff);
	if(p != NULL) free(p);

	return 0;
}

void clear_btcache_before_peer_close(Peer *peer)
{
	Request_piece  *req = peer->Request_piece_head;
	int			   i = 0, index[2] = {-1, -1};

	if(req == NULL)  return;
	while(req != NULL && i < 2) {
		if(req->index != index[i]) { index[i] = req->index; i++; }
		req = req->next;
	}

	Btcache *p = btcache_head;
	while( p != NULL ) {
		if( p->index != -1 && (p->index==index[0] || p->index==index[1]) ) {
			p->index  = -1;
			p->begin  = -1;
			p->length = -1;
			
			p->in_use       =  0;
			p->read_write   = -1;
			p->is_full      =  0;
			p->is_writed    =  0;
			p->access_count =  0;
		}
		p = p->next;
	}
}


// 针对下载最后一个piece的问题,修改以下几处:
// 在data.c头部增加了几个全局变量
// 在data.c中修改了初始分配动态内存函数和最终释放动态内存的函数
// 在rate.c中修改了create_req_slice_msg函数
// 在data.c中增加了以下4个函数
int write_last_piece_to_btcache(Peer *peer)
{
	int            index = last_piece_index, i;
	unsigned char  piece_hash1[20], piece_hash2[20];
	Btcache        *p = last_piece;

	// 校验piece的HASH值
	SHA1_CTX ctx;
	SHA1Init(&ctx);
	while(p != NULL) {
		SHA1Update(&ctx,p->buff,p->length);
		p = p->next;
	}
	SHA1Final(piece_hash1,&ctx);
	
	for(i = 0; i < 20; i++)  piece_hash2[i] = pieces[index*20+i];

	if(memcmp(piece_hash1,piece_hash2,20) == 0) {
		printf("@@@@@@  last piece downlaod OK @@@@@@\n");
	} else {
		printf("@@@@@@  last piece downlaod NOT OK @@@@@@\n");
		return -1;
	}

	p = last_piece;
	while( p != NULL) {
		write_btcache_node_to_harddisk(p);
		p = p->next;
	}
	printf("@@@@@@  last piece write to harddisk OK @@@@@@\n");

	// 在peer中的请求队列中删除piece请求

	// 更新位图
	set_bit_value(bitmap,index,1);
	
	// 准备发送have消息
	for(i = 0; i < 64; i++) {
		if(have_piece_index[i] == -1) { 
			have_piece_index[i] = index; 
			break; 
		}
	}

	download_piece_num++;
	if(download_piece_num % 10 == 0)  restore_bitmap();

	return 0;
}

int write_slice_to_last_piece(int index,int begin,int length,
							  unsigned char *buff,int len,Peer *peer)
{
	if(index != last_piece_index || begin > (last_piece_count-1)*16*1024)
		return -1;
	if(buff==NULL || peer==NULL)  return -1;

	// 定位到要写入哪个slice
	int count = begin / (16*1024);
	Btcache *p = last_piece;
	while(p != NULL && count > 0) {
		count--;
		p = p->next;
	}

	if(p->begin==begin && p->in_use==1 && p->is_full==1)
		return 0; // 该slice已存在
	
	p->index  = index;
	p->begin  = begin;
	p->length = length;

	p->in_use       = 1;
	p->read_write   = 1;
	p->is_full      = 1;
	p->is_writed    = 0;
	p->access_count = 0;
	
	memcpy(p->buff,buff,len);

	p = last_piece;
	while(p != NULL) {
		if(p->is_full != 1)  break;
		p = p->next;
	}
	if(p == NULL) {
		write_last_piece_to_btcache(peer);
	}

	return 0;
}

int read_last_piece_from_harddisk(Btcache *p, int index)
{
	Btcache  *node_ptr   = p;
	int      begin       = 0;
	int      length      = 16*1024;
	int      slice_count = last_piece_count; 
	int      ret;
	
	if(p==NULL || index != last_piece_index)  return -1;
	
	while(slice_count > 0) {
		node_ptr->index  = index;
		node_ptr->begin  = begin;
		node_ptr->length = length;
		if(begin == (last_piece_count-1)*16*1024) 
		node_ptr->length = last_slice_len;
		
		ret = read_slice_from_harddisk(node_ptr);
		if(ret < 0) return -1;
		
		node_ptr->in_use       = 1;
		node_ptr->read_write   = 0;
		node_ptr->is_full      = 1;
		node_ptr->is_writed    = 0;
		node_ptr->access_count = 0;
		
		begin += 16*1024;
		slice_count--;
		node_ptr = node_ptr->next;
	}
	
	return 0;
}

int read_slice_for_send_last_piece(int index,int begin,int length,Peer *peer)
{
	Btcache  *p;
	int       ret, count = begin / (16*1024);
	
	// 检查参数是否有误
	if(index != last_piece_index || begin > (last_piece_count-1)*16*1024)
		return -1;
	
	ret = get_bit_value(bitmap,index);
	if(ret < 0)  {printf("peer requested slice did not download\n"); return -1;}

	p = last_piece;
	while(count > 0) {
		p = p->next;
		count --;
	}
	if(p->is_full != 1) {
		ret = read_last_piece_from_harddisk(last_piece,index);
		if(ret < 0)  return -1;
	}
	
	if(p->in_use == 1 && p->is_full == 1) {
		ret = create_piece_msg(index,begin,p->buff,p->length,peer);
	}

	if(ret == 0)  return 0;
	else return -1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -