?? policy.c
字號:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "parse_metafile.h"
#include "peer.h"
#include "data.h"
#include "message.h"
#include "policy.h"
Unchoke_peers unchoke_peers;
long long total_down = 0L, total_up = 0L;
float total_down_rate = 0.0F, total_up_rate = 0.0F;
int total_peers = 0;
extern int end_mode;
extern Bitmap *bitmap;
extern Peer *peer_head;
extern int pieces_length;
extern int piece_length;
extern Btcache *btcache_head;
extern int last_piece_index;
extern int last_piece_count;
extern int last_slice_len;
extern int download_piece_num;
// 初始化全局變量unchoke_peers
void init_unchoke_peers()
{
int i;
for(i = 0; i < UNCHOKE_COUNT; i++) {
*(unchoke_peers.unchkpeer + i) = NULL;
}
unchoke_peers.count = 0;
unchoke_peers.optunchkpeer = NULL;
}
// 判斷一個peer是否已經存在于unchoke_peers
int is_in_unchoke_peers(Peer *node)
{
int i;
for(i = 0; i < unchoke_peers.count; i++) {
if( node == (unchoke_peers.unchkpeer)[i] ) return 1;
}
return 0;
}
// 從unchoke_peers中獲取下載速度最慢的peer的索引
int get_last_index(Peer **array,int len)
{
int i, j = -1;
if(len <= 0) return j;
else j = 0;
for(i = 0; i < len; i++)
if( array[i]->down_rate < array[j]->down_rate ) j = i;
return j;
}
// 找出當前下載速度最快的4個peer,將其unchoke
int select_unchoke_peer()
{
Peer* p;
Peer* now_fast[UNCHOKE_COUNT];
Peer* force_choke[UNCHOKE_COUNT];
int unchoke_socket[UNCHOKE_COUNT], choke_socket[UNCHOKE_COUNT];
int i, j, index = 0, len = UNCHOKE_COUNT;
for(i = 0; i < len; i++) {
now_fast[i] = NULL;
force_choke[i] = NULL;
unchoke_socket[i] = -1;
choke_socket[i] = -1;
}
// 將那些在過去10秒已斷開連接而又處于unchoke隊列中的peer清除出unchoke隊列
for(i = 0, j = 0; i < unchoke_peers.count; i++) {
p = peer_head;
while(p != NULL) {
if(p == unchoke_peers.unchkpeer[i]) break;
p = p->next;
}
if(p == NULL) { unchoke_peers.unchkpeer[i] = NULL; j++; }
}
if(j != 0) {
unchoke_peers.count = unchoke_peers.count - j;
for(i = 0, j = 0; i < len; i++) {
if(unchoke_peers.unchkpeer[i] != NULL) {
force_choke[j] = unchoke_peers.unchkpeer[i];
j++;
}
}
for(i = 0; i < len; i++) {
unchoke_peers.unchkpeer[i] = force_choke[i];
force_choke[i] = NULL;
}
}
// 將那些在過去10秒上傳速度超過20KB/S而下載速度過小的peer強行阻塞
// 注意:up_rate和down_rate的單位是B/S而不是KB/S
for(i = 0, j = -1; i < unchoke_peers.count; i++) {
if( (unchoke_peers.unchkpeer)[i]->up_rate > 50*1024 &&
(unchoke_peers.unchkpeer)[i]->down_rate < 0.1*1024 ) {
j++;
force_choke[j] = unchoke_peers.unchkpeer[i];
}
}
// 從當前所有Peer中選出下載速度最快的四個peer
p = peer_head;
while(p != NULL) {
if(p->state==DATA && is_interested(bitmap,&(p->bitmap)) && is_seed(p)!=1) {
// p不應該在force_choke數組中
for(i = 0; i < len; i++) {
if(p == force_choke[i]) break;
}
if(i == len) {
if( index < UNCHOKE_COUNT ) {
now_fast[index] = p;
index++;
} else {
j = get_last_index(now_fast,UNCHOKE_COUNT);
if(p->down_rate >= now_fast[j]->down_rate) now_fast[j] = p;
}
}
}
p = p->next;
}
// 假設now_fast中所有的peer都是要unchoke的
for(i = 0; i < index; i++) {
Peer* q = now_fast[i];
unchoke_socket[i] = q->socket;
}
// 假設unchoke_peers.unchkpeer中所有peer都是choke的
for(i = 0; i < unchoke_peers.count; i++) {
Peer* q = (unchoke_peers.unchkpeer)[i];
choke_socket[i] = q->socket;
}
// 如果now_fast某個元素已經存在于unchoke_peers.unchkpeer
// 則沒有必要進行choke或unckoke
for(i = 0; i < index; i++) {
if( is_in_unchoke_peers(now_fast[i]) == 1) {
for(j = 0; j < len; j++) {
Peer* q = now_fast[i];
if(q->socket == unchoke_socket[i]) unchoke_socket[i] = -1;
if(q->socket == choke_socket[i]) choke_socket[i] = -1;
}
}
}
// 更新當前unchoke的peer
for(i = 0; i < index; i++) {
(unchoke_peers.unchkpeer)[i] = now_fast[i];
}
unchoke_peers.count = index;
// 狀態變化后,要對peer的狀態值重新賦值,并且創建choke、unchoke消息
p = peer_head;
while(p != NULL) {
for(i = 0; i < len; i++) {
if(unchoke_socket[i]==p->socket && unchoke_socket[i]!=-1) {
p->am_choking = 0;
create_chock_interested_msg(1,p);
}
if(choke_socket[i]==p->socket && unchoke_socket[i]!=-1) {
p->am_choking = 1;
cancel_requested_list(p);
create_chock_interested_msg(0,p);
}
}
p = p->next;
}
//for(i = 0; i < unchoke_peers.count; i++)
// printf("unchoke peer:%s \n",(unchoke_peers.unchkpeer)[i]->ip);
return 0;
}
// 假設要下載的文件共有100個piece
// 以下函數的功能是將0到99這100個數的順序以隨機的方式打亂
// 從而得到一個隨機的數組,該數組以隨機的方式存儲0~99,供片斷選擇算法使用
int *rand_num = NULL;
int get_rand_numbers(int length)
{
int i, index, piece_count, *temp_num;
if(length == 0) return -1;
piece_count = length;
rand_num = (int *)malloc(piece_count * sizeof(int));
if(rand_num == NULL) return -1;
temp_num = (int *)malloc(piece_count * sizeof(int));
if(temp_num == NULL) return -1;
for(i = 0; i < piece_count; i++) temp_num[i] = i;
srand(time(NULL));
for(i = 0; i < piece_count; i++) {
index = (int)( (float)(piece_count-i) * rand() / (RAND_MAX+1.0) );
rand_num[i] = temp_num[index];
temp_num[index] = temp_num[piece_count-1-i];
}
if(temp_num != NULL) free(temp_num);
return 0;
}
// 從peer隊列中選擇一個優化非阻塞peer
int select_optunchoke_peer()
{
int count = 0, index, i = 0, j, ret;
Peer *p = peer_head;
// 獲取peer隊列中peer的總數
while(p != NULL) {
count++;
p = p->next;
}
// 如果peer總數太少(小于等于4),則沒有必要選擇優化非阻塞peer
if(count <= UNCHOKE_COUNT) return 0;
ret = get_rand_numbers(count);
if(ret < 0) {
printf("%s:%d get rand numbers error\n",__FILE__,__LINE__);
return -1;
}
while(i < count) {
// 隨機選擇一個數,該數在0~count-1之間
index = rand_num[i];
p = peer_head;
j = 0;
while(j < index && p != NULL) {
p = p->next;
j++;
}
if( is_in_unchoke_peers(p) != 1 && is_seed(p) != 1 && p->state == DATA &&
p != unchoke_peers.optunchkpeer && is_interested(bitmap,&(p->bitmap)) ) {
if( (unchoke_peers.optunchkpeer) != NULL ) {
Peer *temp = peer_head;
while( temp != NULL ) {
if(temp == unchoke_peers.optunchkpeer) break;
temp = temp->next;
}
if(temp != NULL) {
(unchoke_peers.optunchkpeer)->am_choking = 1;
create_chock_interested_msg(0,unchoke_peers.optunchkpeer);
}
}
p->am_choking = 0;
create_chock_interested_msg(1,p);
unchoke_peers.optunchkpeer = p;
//printf("*** optunchoke:%s ***\n",p->ip);
break;
}
i++;
}
if(rand_num != NULL) { free(rand_num); rand_num = NULL; }
return 0;
}
// 計算最近一段時間(如10秒)每個peer的上傳下載速度
int compute_rate()
{
Peer *p = peer_head;
time_t time_now = time(NULL);
long t = 0;
while(p != NULL) {
if(p->last_down_timestamp == 0) {
p->down_rate = 0.0f;
p->down_count = 0;
} else {
t = time_now - p->last_down_timestamp;
if(t == 0) printf("%s:%d time is 0\n",__FILE__,__LINE__);
else p->down_rate = p->down_count / t;
p->down_count = 0;
p->last_down_timestamp = 0;
}
if(p->last_up_timestamp == 0) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -