Changeset 9145 for trunk/third-party/dht/dht.c
- Timestamp:
- Sep 19, 2009, 6:09:57 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/third-party/dht/dht.c
r8985 r9145 123 123 struct search_node nodes[SEARCH_NODES]; 124 124 int numnodes; 125 struct search *next; 125 126 }; 126 127 … … 134 135 #ifndef DHT_MAX_PEERS 135 136 #define DHT_MAX_PEERS 2048 137 #endif 138 139 /* The maximum number of searches we keep data about. */ 140 #ifndef DHT_MAX_SEARCHES 141 #define DHT_MAX_SEARCHES 1024 142 #endif 143 144 /* The time after which we consider a search to be expirable. */ 145 #ifndef DHT_SEARCH_EXPIRE_TIME 146 #define DHT_SEARCH_EXPIRE_TIME (62 * 60) 136 147 #endif 137 148 … … 208 219 static struct storage *storage; 209 220 210 /* The maximum number of concurrent searches. */ 211 #ifndef DHT_MAX_SEARCHES 212 #define DHT_MAX_SEARCHES 20 213 #endif 214 215 static struct search searches[DHT_MAX_SEARCHES]; 221 static struct search *searches = NULL; 216 222 static int numsearches; 217 223 static unsigned short search_id; … … 645 651 n = n->next; 646 652 } 647 648 if(!dubious && mybucket) { 653 654 /* If there's only one bucket, split even if there remain doubtful 655 nodes. This violates the spec, but it speeds up bootstrapping. */ 656 if(mybucket && (!dubious || buckets->next == NULL)) { 649 657 debugf("Splitting.\n"); 650 658 b = split_bucket(s, b); … … 725 733 find_search(unsigned short tid) 726 734 { 727 int i; 728 for(i = 0; i < numsearches; i++) { 729 if(searches[i].tid == tid) 730 return &searches[i]; 735 struct search *sr = searches; 736 while(sr) { 737 if(sr->tid == tid) 738 return sr; 739 sr = sr->next; 731 740 } 732 741 return NULL; … … 797 806 sr->nodes[j] = sr->nodes[j + 1]; 798 807 sr->numnodes--; 808 } 809 810 static void 811 expire_searches(void) 812 { 813 struct search *sr = searches, *previous = NULL; 814 815 while(sr) { 816 struct search *next = sr->next; 817 if(sr->step_time < now.tv_sec - DHT_SEARCH_EXPIRE_TIME) { 818 if(previous) 819 previous->next = next; 820 else 821 searches = next; 822 free(sr); 823 numsearches--; 824 } else { 825 previous = sr; 826 } 827 sr = next; 828 } 799 829 } 800 830 … … 910 940 911 941 static struct search * 912 find_free_search_slot(void) 913 { 914 int i; 915 struct search *sr = NULL; 916 917 if(numsearches < DHT_MAX_SEARCHES) 918 return &searches[numsearches++]; 919 920 for(i = 0; i < numsearches; i++) { 921 if(searches[i].done && 922 (sr == NULL || searches[i].step_time < sr->step_time)) 923 sr = &searches[i]; 924 } 925 return sr; 942 new_search(void) 943 { 944 struct search *sr, *oldest = NULL; 945 946 /* Find the oldest done search */ 947 sr = searches; 948 while(sr) { 949 if(sr->done && 950 (oldest == NULL || oldest->step_time > sr->step_time)) 951 oldest = sr; 952 sr = sr->next; 953 } 954 955 /* The oldest slot is expired. */ 956 if(oldest && oldest->step_time < now.tv_sec - DHT_SEARCH_EXPIRE_TIME) 957 return oldest; 958 959 /* Allocate a new slot. */ 960 if(numsearches < DHT_MAX_SEARCHES) { 961 sr = calloc(1, sizeof(struct search)); 962 if(sr != NULL) { 963 sr->next = searches; 964 searches = sr; 965 numsearches++; 966 return sr; 967 } 968 } 969 970 /* Oh, well, never mind. Reuse the oldest slot. */ 971 return oldest; 926 972 } 927 973 … … 946 992 struct search *sr; 947 993 struct bucket *b; 948 int i; 949 950 for(i = 0; i < numsearches; i++) {951 if(id_cmp(s earches[i].id, id) == 0)994 995 sr = searches; 996 while(sr) { 997 if(id_cmp(sr->id, id) == 0) 952 998 break; 953 } 954 955 if(i < numsearches) { 999 sr = sr->next; 1000 } 1001 1002 if(sr) { 956 1003 /* We're reusing data from an old search. Reusing the same tid 957 1004 means that we can merge replies for both searches. */ 958 int j; 959 sr = searches + i; 1005 int i; 960 1006 sr->done = 0; 961 1007 again: 962 for( j = 0; j < sr->numnodes; j++) {1008 for(i = 0; i < sr->numnodes; i++) { 963 1009 struct search_node *n; 964 n = &sr->nodes[ j];1010 n = &sr->nodes[i]; 965 1011 /* Discard any doubtful nodes. */ 966 1012 if(n->pinged >= 3 || n->reply_time < now.tv_sec - 7200) { … … 974 1020 } 975 1021 } else { 976 sr = find_free_search_slot();1022 sr = new_search(); 977 1023 if(sr == NULL) { 978 1024 errno = ENOSPC; 979 1025 return -1; 980 1026 } 981 memset(sr, 0, sizeof(struct search));982 1027 sr->tid = search_id++; 1028 sr->step_time = 0; 983 1029 memcpy(sr->id, id, 20); 1030 sr->done = 0; 984 1031 sr->numnodes = 0; 985 1032 } … … 990 1037 insert_search_bucket(b, sr); 991 1038 992 if(sr->numnodes < 8) {1039 if(sr->numnodes < SEARCH_NODES) { 993 1040 struct bucket *p = previous_bucket(b); 994 1041 if(b->next) … … 1108 1155 broken_node(int s, const unsigned char *id, struct sockaddr_in *sin) 1109 1156 { 1110 int i , j;1157 int i; 1111 1158 1112 1159 debugf("Blacklisting broken node.\n"); 1113 1160 1114 1161 if(id) { 1162 struct node *n; 1163 struct search *sr; 1115 1164 /* Make the node easy to discard. */ 1116 struct node *n;1117 1165 n = find_node(id); 1118 1166 if(n) { … … 1121 1169 } 1122 1170 /* Discard it from any searches in progress. */ 1123 for(i = 0; i < numsearches; i++) { 1124 for(j = 0; j < searches[i].numnodes; j++) 1125 if(id_cmp(searches[i].nodes[j].id, id) == 0) 1126 flush_search_node(&searches[i].nodes[j], 1127 &searches[i]); 1171 sr = searches; 1172 while(sr) { 1173 for(i = 0; i < sr->numnodes; i++) 1174 if(id_cmp(sr->nodes[i].id, id) == 0) 1175 flush_search_node(&sr->nodes[i], sr); 1176 sr = sr->next; 1128 1177 } 1129 1178 } … … 1207 1256 *cached_return = cached; 1208 1257 if(incoming_return) 1209 *incoming_return = cached;1258 *incoming_return = incoming; 1210 1259 return good + dubious; 1211 1260 } … … 1215 1264 dht_dump_tables(FILE *f) 1216 1265 { 1217 int i , j;1266 int i; 1218 1267 struct bucket *b = buckets; 1219 1268 struct storage *st = storage; 1269 struct search *sr = searches; 1220 1270 1221 1271 fprintf(f, "My id "); … … 1251 1301 b = b->next; 1252 1302 } 1253 for(i = 0; i < numsearches; i++) { 1254 struct search *sr = &searches[i]; 1255 fprintf(f, "\nSearch %d id ", i); 1303 while(sr) { 1304 fprintf(f, "\nSearch id "); 1256 1305 print_hex(f, sr->id, 20); 1257 1306 fprintf(f, " age %d%s\n", (int)(now.tv_sec - sr->step_time), 1258 1307 sr->done ? " (done)" : ""); 1259 for( j = 0; j < sr->numnodes; j++) {1260 struct search_node *n = &sr->nodes[ j];1261 fprintf(f, "Node %d id ", j);1308 for(i = 0; i < sr->numnodes; i++) { 1309 struct search_node *n = &sr->nodes[i]; 1310 fprintf(f, "Node %d id ", i); 1262 1311 print_hex(f, n->id, 20); 1263 1312 fprintf(f, " bits %d age ", common_bits(sr->id, n->id)); … … 1271 1320 n->replied ? " (replied)" : ""); 1272 1321 } 1322 sr = sr->next; 1273 1323 } 1274 1324 … … 1306 1356 return -1; 1307 1357 1358 searches = NULL; 1308 1359 numsearches = 0; 1309 1360 … … 1378 1429 free(st); 1379 1430 } 1380 1431 1432 while(searches) { 1433 struct search *sr = searches; 1434 searches = searches->next; 1435 free(sr); 1436 } 1437 1381 1438 return 1; 1382 1439 } … … 1547 1604 sr = find_search(ttid); 1548 1605 if(!sr) { 1549 debugf("Unknown search! ");1606 debugf("Unknown search!\n"); 1550 1607 new_node(s, id, &source, 1); 1551 1608 } else { … … 1572 1629 debugf("Ping (%d)!\n", tid_len); 1573 1630 new_node(s, id, &source, 1); 1574 debugf("Sending pong !\n");1631 debugf("Sending pong.\n"); 1575 1632 send_pong(s, (struct sockaddr*)&source, sizeof(source), 1576 1633 tid, tid_len); … … 1655 1712 expire_buckets(s); 1656 1713 expire_storage(); 1714 expire_searches(); 1657 1715 } 1658 1716 1659 1717 if(search_time > 0 && now.tv_sec >= search_time) { 1660 int i;1661 for(i = 0; i < numsearches; i++) {1662 struct search *sr = &searches[i];1718 struct search *sr; 1719 sr = searches; 1720 while(sr) { 1663 1721 if(!sr->done && sr->step_time + 5 <= now.tv_sec) { 1664 1722 search_step(s, sr, callback, closure); 1665 1723 } 1724 sr = sr->next; 1666 1725 } 1667 1726 1668 1727 search_time = 0; 1669 1670 for(i = 0; i < numsearches; i++) {1671 struct search *sr = &searches[i];1728 1729 sr = searches; 1730 while(sr) { 1672 1731 if(!sr->done) { 1673 1732 time_t tm = sr->step_time + 15 + random() % 10; … … 1675 1734 search_time = tm; 1676 1735 } 1736 sr = sr->next; 1677 1737 } 1678 1738 }
Note: See TracChangeset
for help on using the changeset viewer.