aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2010-09-17 15:55:34 +0000
committerNathan S. Evans <evans@in.tum.de>2010-09-17 15:55:34 +0000
commit0e13b1098620c73c9e611eb18ec1cebb7e2aedbf (patch)
tree2b3878bb628ef3b5d353f33f13ce69013fdbc207 /src
parentdfe33ba624030d36f6bf664c338a7f844007c4b0 (diff)
downloadgnunet-0e13b1098620c73c9e611eb18ec1cebb7e2aedbf.tar.gz
gnunet-0e13b1098620c73c9e611eb18ec1cebb7e2aedbf.zip
some fixes, debugging churn nonsense
Diffstat (limited to 'src')
-rw-r--r--src/dht/dht_api.c5
-rw-r--r--src/dht/gnunet-dht-driver.c244
-rw-r--r--src/dht/gnunet-service-dht.c2
3 files changed, 171 insertions, 80 deletions
diff --git a/src/dht/dht_api.c b/src/dht/dht_api.c
index 5d17e996e..413ecb83a 100644
--- a/src/dht/dht_api.c
+++ b/src/dht/dht_api.c
@@ -392,6 +392,8 @@ transmit_pending (void *cls, size_t size, void *buf)
392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
393 "`%s': In transmit_pending\n", "DHT API"); 393 "`%s': In transmit_pending\n", "DHT API");
394#endif 394#endif
395 handle->th = NULL;
396
395 if (buf == NULL) 397 if (buf == NULL)
396 { 398 {
397#if DEBUG_DHT_API 399#if DEBUG_DHT_API
@@ -402,8 +404,6 @@ transmit_pending (void *cls, size_t size, void *buf)
402 return 0; 404 return 0;
403 } 405 }
404 406
405 handle->th = NULL;
406
407 if (handle->current != NULL) 407 if (handle->current != NULL)
408 { 408 {
409 tsize = ntohs (handle->current->msg->size); 409 tsize = ntohs (handle->current->msg->size);
@@ -437,6 +437,7 @@ process_pending_message (struct GNUNET_DHT_Handle *handle)
437 return; /* action already pending */ 437 return; /* action already pending */
438 if (GNUNET_YES != try_connect (handle)) 438 if (GNUNET_YES != try_connect (handle))
439 { 439 {
440 handle->th = NULL;
440 finish (handle, GNUNET_SYSERR); 441 finish (handle, GNUNET_SYSERR);
441 return; 442 return;
442 } 443 }
diff --git a/src/dht/gnunet-dht-driver.c b/src/dht/gnunet-dht-driver.c
index e343e911f..89e7ad217 100644
--- a/src/dht/gnunet-dht-driver.c
+++ b/src/dht/gnunet-dht-driver.c
@@ -53,6 +53,9 @@
53/* Time to allow a find peer request to take */ 53/* Time to allow a find peer request to take */
54#define DEFAULT_FIND_PEER_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 40) 54#define DEFAULT_FIND_PEER_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 40)
55 55
56/* Time to wait for all peers disconnected due to to churn to actually be removed from system */
57#define DEFAULT_PEER_DISCONNECT_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
58
56#define DEFAULT_SECONDS_PER_PEER_START GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 45) 59#define DEFAULT_SECONDS_PER_PEER_START GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 45)
57 60
58#define DEFAULT_TEST_DATA_SIZE 8 61#define DEFAULT_TEST_DATA_SIZE 8
@@ -255,6 +258,8 @@ struct TopologyIteratorContext
255 unsigned int total_iterations; 258 unsigned int total_iterations;
256 unsigned int current_iteration; 259 unsigned int current_iteration;
257 unsigned int total_connections; 260 unsigned int total_connections;
261 unsigned int total_peers;
262 struct GNUNET_CONTAINER_MultiHashMap *peers_seen;
258 struct GNUNET_PeerIdentity *peer; 263 struct GNUNET_PeerIdentity *peer;
259 GNUNET_SCHEDULER_Task cont; 264 GNUNET_SCHEDULER_Task cont;
260 void *cls; 265 void *cls;
@@ -782,6 +787,11 @@ void log_topology_cb (void *cls,
782 struct TopologyIteratorContext *topo_ctx = cls; 787 struct TopologyIteratorContext *topo_ctx = cls;
783 if ((first != NULL) && (second != NULL)) 788 if ((first != NULL) && (second != NULL))
784 { 789 {
790 if ((topo_ctx->peers_seen != NULL) && (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(topo_ctx->peers_seen, &first->hashPubKey)))
791 {
792 GNUNET_CONTAINER_multihashmap_put(topo_ctx->peers_seen, &first->hashPubKey, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
793 topo_ctx->total_peers++;
794 }
785 topo_ctx->total_connections++; 795 topo_ctx->total_connections++;
786 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno(config, "dht_testing", "mysql_logging_extended")) 796 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno(config, "dht_testing", "mysql_logging_extended"))
787 dhtlog_handle->insert_extended_topology(first, second); 797 dhtlog_handle->insert_extended_topology(first, second);
@@ -789,10 +799,12 @@ void log_topology_cb (void *cls,
789 else 799 else
790 { 800 {
791 GNUNET_assert(dhtlog_handle != NULL); 801 GNUNET_assert(dhtlog_handle != NULL);
792 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Topology iteration (%u/%u) finished (%u connections)\n", topo_ctx->current_iteration, topo_ctx->total_iterations, topo_ctx->total_connections); 802 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Topology iteration (%u/%u) finished (%u connections, %u peers)\n", topo_ctx->current_iteration, topo_ctx->total_iterations, topo_ctx->total_connections, topo_ctx->total_peers);
793 dhtlog_handle->update_topology(topo_ctx->total_connections); 803 dhtlog_handle->update_topology(topo_ctx->total_connections);
794 if (topo_ctx->cont != NULL) 804 if (topo_ctx->cont != NULL)
795 GNUNET_SCHEDULER_add_now (sched, topo_ctx->cont, topo_ctx->cls); 805 GNUNET_SCHEDULER_add_now (sched, topo_ctx->cont, topo_ctx->cls);
806 if (topo_ctx->peers_seen != NULL)
807 GNUNET_CONTAINER_multihashmap_destroy(topo_ctx->peers_seen);
796 GNUNET_free(topo_ctx); 808 GNUNET_free(topo_ctx);
797 } 809 }
798} 810}
@@ -1089,60 +1101,6 @@ send_find_peer_request (void *cls, const struct GNUNET_SCHEDULER_TaskContext * t
1089 &handle_find_peer_sent, test_find_peer); 1101 &handle_find_peer_sent, test_find_peer);
1090} 1102}
1091 1103
1092/**
1093 * Set up a single find peer request for each peer in the topology. Do this
1094 * until the settle time is over, limited by the number of outstanding requests
1095 * and the time allowed for each one!
1096 */
1097static void
1098schedule_churn_find_peer_requests (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
1099{
1100 struct FindPeerContext *find_peer_ctx = cls;
1101 struct TestFindPeer *test_find_peer;
1102 struct PeerCount *peer_count;
1103 uint32_t i;
1104
1105 if (find_peer_ctx->previous_peers == 0) /* First time, go slowly */
1106 find_peer_ctx->total = 1;
1107 else if (find_peer_ctx->current_peers - find_peer_ctx->previous_peers > MAX_FIND_PEER_CUTOFF) /* Found LOTS of peers, still go slowly */
1108 find_peer_ctx->total = find_peer_ctx->last_sent - (find_peer_ctx->last_sent / 8);
1109 else
1110 find_peer_ctx->total = find_peer_ctx->last_sent * 2;
1111
1112 if (find_peer_ctx->total > max_outstanding_find_peers)
1113 find_peer_ctx->total = max_outstanding_find_peers;
1114
1115 find_peer_ctx->last_sent = find_peer_ctx->total;
1116 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending %u find peer messages (after churn)\n", find_peer_ctx->total);
1117
1118 find_peer_offset = GNUNET_TIME_relative_divide(find_peer_delay, find_peer_ctx->total);
1119 for (i = 0; i < find_peer_ctx->total; i++)
1120 {
1121 test_find_peer = GNUNET_malloc(sizeof(struct TestFindPeer));
1122 /* If we have sent requests, choose peers with a low number of connections to send requests from */
1123 peer_count = GNUNET_CONTAINER_heap_remove_root(find_peer_ctx->peer_min_heap);
1124 GNUNET_CONTAINER_multihashmap_remove(find_peer_ctx->peer_hash, &peer_count->peer_id.hashPubKey, peer_count);
1125 test_find_peer->daemon = GNUNET_TESTING_daemon_get_by_id(pg, &peer_count->peer_id);
1126 GNUNET_assert(test_find_peer->daemon != NULL);
1127 test_find_peer->find_peer_context = find_peer_ctx;
1128 GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_relative_multiply(find_peer_offset, i), &send_find_peer_request, test_find_peer);
1129 }
1130
1131 if ((find_peer_ctx->peer_hash == NULL) && (find_peer_ctx->peer_min_heap == NULL))
1132 {
1133 find_peer_ctx->peer_hash = GNUNET_CONTAINER_multihashmap_create(num_peers);
1134 find_peer_ctx->peer_min_heap = GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN);
1135 }
1136 else
1137 {
1138 GNUNET_CONTAINER_multihashmap_iterate(find_peer_ctx->peer_hash, &remove_peer_count, find_peer_ctx);
1139 GNUNET_CONTAINER_multihashmap_destroy(find_peer_ctx->peer_hash);
1140 find_peer_ctx->peer_hash = GNUNET_CONTAINER_multihashmap_create(num_peers);
1141 }
1142
1143 GNUNET_assert(0 == GNUNET_CONTAINER_multihashmap_size(find_peer_ctx->peer_hash));
1144 GNUNET_assert(0 == GNUNET_CONTAINER_heap_get_size(find_peer_ctx->peer_min_heap));
1145}
1146 1104
1147/** 1105/**
1148 * Add a connection to the find_peer_context given. This may 1106 * Add a connection to the find_peer_context given. This may
@@ -1213,7 +1171,12 @@ static int iterate_min_heap_peers (void *cls,
1213 if (cost == 0) 1171 if (cost == 0)
1214 { 1172 {
1215 d1 = GNUNET_TESTING_daemon_get_by_id (pg, &peer_count->peer_id); 1173 d1 = GNUNET_TESTING_daemon_get_by_id (pg, &peer_count->peer_id);
1216 d2 = GNUNET_TESTING_daemon_get(pg, GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, num_peers)); 1174 d2 = d1;
1175 while ((d2 == d1) || (GNUNET_YES != GNUNET_TESTING_daemon_running(d2)))
1176 {
1177 d2 = GNUNET_TESTING_daemon_get(pg, GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, num_peers));
1178 }
1179
1217 /** Just try to connect the peers, don't worry about callbacks, etc. **/ 1180 /** Just try to connect the peers, don't worry about callbacks, etc. **/
1218 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Peer %s has 0 connections. Trying to connect to %s...\n", GNUNET_i2s(&peer_count->peer_id), d2->shortname); 1181 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Peer %s has 0 connections. Trying to connect to %s...\n", GNUNET_i2s(&peer_count->peer_id), d2->shortname);
1219 timeout = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, DEFAULT_CONNECT_TIMEOUT); 1182 timeout = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, DEFAULT_CONNECT_TIMEOUT);
@@ -1230,6 +1193,12 @@ static int iterate_min_heap_peers (void *cls,
1230} 1193}
1231 1194
1232/** 1195/**
1196 * Forward declaration.
1197 */
1198static void
1199schedule_churn_find_peer_requests (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc);
1200
1201/**
1233 * Callback for iterating over all the peer connections of a peer group. 1202 * Callback for iterating over all the peer connections of a peer group.
1234 * Used after we have churned on some peers to find which ones have zero 1203 * Used after we have churned on some peers to find which ones have zero
1235 * connections so we can make them issue find peer requests. 1204 * connections so we can make them issue find peer requests.
@@ -1303,13 +1272,14 @@ void count_peers_churn_cb (void *cls,
1303 * into the general testing churn options seems like overkill because 1272 * into the general testing churn options seems like overkill because
1304 * these are very specialized cases. 1273 * these are very specialized cases.
1305 */ 1274 */
1275 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Out of %u peers, fewest connections is %d\n", GNUNET_CONTAINER_heap_get_size(find_peer_context->peer_min_heap), peer_count->count);
1306 if ((peer_count->count == 0) && (GNUNET_TIME_absolute_get_remaining(find_peer_context->endtime).value > 0)) 1276 if ((peer_count->count == 0) && (GNUNET_TIME_absolute_get_remaining(find_peer_context->endtime).value > 0))
1307 { 1277 {
1308 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Found peer with no connections, will choose some peer(s) at random to connect to!\n"); 1278 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Found peer with no connections, will choose some peer(s) at random to connect to!\n");
1309 GNUNET_CONTAINER_heap_iterate (find_peer_context->peer_min_heap, &iterate_min_heap_peers, find_peer_context); 1279 GNUNET_CONTAINER_heap_iterate (find_peer_context->peer_min_heap, &iterate_min_heap_peers, find_peer_context);
1310 GNUNET_SCHEDULER_add_now(sched, &schedule_churn_find_peer_requests, find_peer_context); 1280 GNUNET_SCHEDULER_add_now(sched, &schedule_churn_find_peer_requests, find_peer_context);
1311 } 1281 }
1312 else if (GNUNET_TIME_absolute_get_remaining(find_peer_context->endtime).value > 0) 1282 else if ((GNUNET_TIME_absolute_get_remaining(find_peer_context->endtime).value > 0) && (find_peer_context->last_sent != 0))
1313 { 1283 {
1314 GNUNET_SCHEDULER_add_now(sched, &schedule_churn_find_peer_requests, find_peer_context); 1284 GNUNET_SCHEDULER_add_now(sched, &schedule_churn_find_peer_requests, find_peer_context);
1315 } 1285 }
@@ -1326,6 +1296,7 @@ void count_peers_churn_cb (void *cls,
1326 topo_ctx->cont = &do_get; 1296 topo_ctx->cont = &do_get;
1327 topo_ctx->cls = all_gets; 1297 topo_ctx->cls = all_gets;
1328 topo_ctx->timeout = DEFAULT_GET_TIMEOUT; 1298 topo_ctx->timeout = DEFAULT_GET_TIMEOUT;
1299 topo_ctx->peers_seen = GNUNET_CONTAINER_multihashmap_create(num_peers);
1329 die_task = GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_relative_add(GNUNET_TIME_relative_add(DEFAULT_GET_TIMEOUT, all_get_timeout), DEFAULT_TOPOLOGY_CAPTURE_TIMEOUT), 1300 die_task = GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_relative_add(GNUNET_TIME_relative_add(DEFAULT_GET_TIMEOUT, all_get_timeout), DEFAULT_TOPOLOGY_CAPTURE_TIMEOUT),
1330 &end_badly, "from do gets (count_peers_churn_cb)"); 1301 &end_badly, "from do gets (count_peers_churn_cb)");
1331 GNUNET_SCHEDULER_add_now(sched, &capture_current_topology, topo_ctx); 1302 GNUNET_SCHEDULER_add_now(sched, &capture_current_topology, topo_ctx);
@@ -1341,6 +1312,79 @@ void count_peers_churn_cb (void *cls,
1341} 1312}
1342 1313
1343/** 1314/**
1315 * Set up a single find peer request for each peer in the topology. Do this
1316 * until the settle time is over, limited by the number of outstanding requests
1317 * and the time allowed for each one!
1318 */
1319static void
1320schedule_churn_find_peer_requests (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
1321{
1322 struct FindPeerContext *find_peer_ctx = cls;
1323 struct TestFindPeer *test_find_peer;
1324 struct PeerCount *peer_count;
1325 uint32_t i;
1326
1327 if (find_peer_ctx->previous_peers == 0) /* First time, go slowly */
1328 find_peer_ctx->total = 1;
1329 else if (find_peer_ctx->current_peers - find_peer_ctx->previous_peers < MIN_FIND_PEER_CUTOFF)
1330 find_peer_ctx->total = find_peer_ctx->total / 2;
1331 else if (find_peer_ctx->current_peers - find_peer_ctx->previous_peers > MAX_FIND_PEER_CUTOFF) /* Found LOTS of peers, still go slowly */
1332 find_peer_ctx->total = find_peer_ctx->last_sent - (find_peer_ctx->last_sent / 8);
1333 else
1334 find_peer_ctx->total = find_peer_ctx->last_sent * 2;
1335
1336 if (find_peer_ctx->total > max_outstanding_find_peers)
1337 find_peer_ctx->total = max_outstanding_find_peers;
1338
1339 find_peer_ctx->last_sent = find_peer_ctx->total;
1340 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending %u find peer messages (after churn)\n", find_peer_ctx->total);
1341
1342 if (find_peer_ctx->total > 0)
1343 find_peer_offset = GNUNET_TIME_relative_divide(find_peer_delay, find_peer_ctx->total);
1344 else
1345 {
1346 find_peer_ctx->previous_peers = find_peer_ctx->current_peers;
1347 find_peer_ctx->current_peers = 0;
1348 GNUNET_TESTING_get_topology (pg, &count_peers_churn_cb, find_peer_ctx);
1349 }
1350
1351
1352 for (i = 0; i < find_peer_ctx->total; i++)
1353 {
1354 test_find_peer = GNUNET_malloc(sizeof(struct TestFindPeer));
1355 /* If we have sent requests, choose peers with a low number of connections to send requests from */
1356 peer_count = GNUNET_CONTAINER_heap_remove_root(find_peer_ctx->peer_min_heap);
1357 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending find peer request from peer with %u connections\n", peer_count->count);
1358 GNUNET_CONTAINER_multihashmap_remove(find_peer_ctx->peer_hash, &peer_count->peer_id.hashPubKey, peer_count);
1359 test_find_peer->daemon = GNUNET_TESTING_daemon_get_by_id(pg, &peer_count->peer_id);
1360 GNUNET_assert(test_find_peer->daemon != NULL);
1361 test_find_peer->find_peer_context = find_peer_ctx;
1362 GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_relative_multiply(find_peer_offset, i), &send_find_peer_request, test_find_peer);
1363 }
1364
1365 if ((find_peer_ctx->peer_hash == NULL) && (find_peer_ctx->peer_min_heap == NULL))
1366 {
1367 find_peer_ctx->peer_hash = GNUNET_CONTAINER_multihashmap_create(num_peers);
1368 find_peer_ctx->peer_min_heap = GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN);
1369 }
1370 else
1371 {
1372 GNUNET_CONTAINER_multihashmap_iterate(find_peer_ctx->peer_hash, &remove_peer_count, find_peer_ctx);
1373 GNUNET_CONTAINER_multihashmap_destroy(find_peer_ctx->peer_hash);
1374 find_peer_ctx->peer_hash = GNUNET_CONTAINER_multihashmap_create(num_peers);
1375 }
1376
1377 GNUNET_assert(0 == GNUNET_CONTAINER_multihashmap_size(find_peer_ctx->peer_hash));
1378 GNUNET_assert(0 == GNUNET_CONTAINER_heap_get_size(find_peer_ctx->peer_min_heap));
1379}
1380
1381static void schedule_churn_get_topology (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
1382{
1383 struct FindPeerContext *find_peer_context = cls;
1384 GNUNET_TESTING_get_topology (pg, &count_peers_churn_cb, find_peer_context);
1385}
1386
1387/**
1344 * Called when churning of the topology has finished. 1388 * Called when churning of the topology has finished.
1345 * 1389 *
1346 * @param cls closure unused 1390 * @param cls closure unused
@@ -1353,6 +1397,7 @@ static void churn_complete (void *cls, const char *emsg)
1353 unsigned int i; 1397 unsigned int i;
1354 struct GNUNET_TESTING_Daemon *temp_daemon; 1398 struct GNUNET_TESTING_Daemon *temp_daemon;
1355 struct TopologyIteratorContext *topo_ctx; 1399 struct TopologyIteratorContext *topo_ctx;
1400 struct GNUNET_TIME_Relative calc_timeout;
1356 1401
1357 if (emsg != NULL) 1402 if (emsg != NULL)
1358 { 1403 {
@@ -1368,37 +1413,51 @@ static void churn_complete (void *cls, const char *emsg)
1368 */ 1413 */
1369 if (find_peer_context != NULL) 1414 if (find_peer_context != NULL)
1370 { 1415 {
1371 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "We have churned on some peers, so we must schedule find peer requests for them!\n"); 1416 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "We have churned on some peers, so we must schedule find peer requests for them!\n");
1417 count_added = 0;
1372 for (i = 0; i < num_peers; i ++) 1418 for (i = 0; i < num_peers; i ++)
1373 { 1419 {
1374 temp_daemon = GNUNET_TESTING_daemon_get(pg, i); 1420 temp_daemon = GNUNET_TESTING_daemon_get(pg, i);
1375 peer_count = GNUNET_malloc(sizeof(struct PeerCount)); 1421 if (GNUNET_YES == GNUNET_TESTING_daemon_running(temp_daemon))
1376 memcpy(&peer_count->peer_id, &temp_daemon->id, sizeof(struct GNUNET_PeerIdentity)); 1422 {
1377 peer_count->heap_node = GNUNET_CONTAINER_heap_insert(find_peer_context->peer_min_heap, peer_count, peer_count->count); 1423 peer_count = GNUNET_malloc (sizeof(struct PeerCount));
1378 GNUNET_CONTAINER_multihashmap_put(find_peer_context->peer_hash, &temp_daemon->id.hashPubKey, peer_count, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 1424 memcpy(&peer_count->peer_id, &temp_daemon->id, sizeof(struct GNUNET_PeerIdentity));
1425 GNUNET_assert(peer_count->count == 0);
1426 peer_count->heap_node = GNUNET_CONTAINER_heap_insert(find_peer_context->peer_min_heap, peer_count, peer_count->count);
1427 GNUNET_CONTAINER_multihashmap_put(find_peer_context->peer_hash, &temp_daemon->id.hashPubKey, peer_count, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1428 count_added++;
1429 }
1379 } 1430 }
1380 GNUNET_TESTING_get_topology (pg, &count_peers_churn_cb, find_peer_context); 1431 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Added %d peers to heap, total size %d\n", count_added, GNUNET_CONTAINER_heap_get_size(find_peer_context->peer_min_heap));
1432 GNUNET_SCHEDULER_add_delayed(sched, DEFAULT_PEER_DISCONNECT_TIMEOUT, &schedule_churn_get_topology, find_peer_context);
1433 //GNUNET_TESTING_get_topology (pg, &count_peers_churn_cb, find_peer_context);
1381 } 1434 }
1382 else 1435 else
1383 { 1436 {
1384 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Only churned off peers, no find peer requests, scheduling more gets...\n"); 1437 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Only churned off peers, no find peer requests, scheduling more gets (after allowing time for peers to disconnect properly!)...\n");
1385 if (dhtlog_handle != NULL) 1438 if (dhtlog_handle != NULL)
1386 { 1439 {
1387 topo_ctx = GNUNET_malloc(sizeof(struct TopologyIteratorContext)); 1440 topo_ctx = GNUNET_malloc(sizeof(struct TopologyIteratorContext));
1388 topo_ctx->cont = &do_get; 1441 topo_ctx->cont = &do_get;
1389 topo_ctx->cls = all_gets; 1442 topo_ctx->cls = all_gets;
1390 topo_ctx->timeout = DEFAULT_GET_TIMEOUT; 1443 topo_ctx->timeout = DEFAULT_GET_TIMEOUT;
1391 die_task = GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_relative_add(GNUNET_TIME_relative_add(DEFAULT_GET_TIMEOUT, all_get_timeout), DEFAULT_TOPOLOGY_CAPTURE_TIMEOUT), 1444 topo_ctx->peers_seen = GNUNET_CONTAINER_multihashmap_create(num_peers);
1445 calc_timeout = GNUNET_TIME_relative_add(DEFAULT_GET_TIMEOUT, all_get_timeout);
1446 calc_timeout = GNUNET_TIME_relative_add(calc_timeout, DEFAULT_TOPOLOGY_CAPTURE_TIMEOUT);
1447 calc_timeout = GNUNET_TIME_relative_add(calc_timeout, DEFAULT_PEER_DISCONNECT_TIMEOUT);
1448 die_task = GNUNET_SCHEDULER_add_delayed (sched, calc_timeout,
1392 &end_badly, "from do gets (churn_complete)"); 1449 &end_badly, "from do gets (churn_complete)");
1393 GNUNET_SCHEDULER_add_now(sched, &capture_current_topology, topo_ctx); 1450 GNUNET_SCHEDULER_add_delayed(sched, DEFAULT_PEER_DISCONNECT_TIMEOUT, &capture_current_topology, topo_ctx);
1394 } 1451 }
1395 else 1452 else
1396 { 1453 {
1397 die_task = GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_relative_add(GNUNET_TIME_relative_add(DEFAULT_GET_TIMEOUT, all_get_timeout), DEFAULT_TOPOLOGY_CAPTURE_TIMEOUT), 1454 calc_timeout = GNUNET_TIME_relative_add(DEFAULT_GET_TIMEOUT, all_get_timeout);
1455 calc_timeout = GNUNET_TIME_relative_add(calc_timeout, DEFAULT_PEER_DISCONNECT_TIMEOUT);
1456 die_task = GNUNET_SCHEDULER_add_delayed (sched, calc_timeout,
1398 &end_badly, "from do gets (churn_complete)"); 1457 &end_badly, "from do gets (churn_complete)");
1399 if (dhtlog_handle != NULL) 1458 if (dhtlog_handle != NULL)
1400 dhtlog_handle->insert_round(DHT_ROUND_GET, rounds_finished); 1459 dhtlog_handle->insert_round(DHT_ROUND_GET, rounds_finished);
1401 GNUNET_SCHEDULER_add_now(sched, &do_get, all_gets); 1460 GNUNET_SCHEDULER_add_delayed(sched, DEFAULT_PEER_DISCONNECT_TIMEOUT, &do_get, all_gets);
1402 } 1461 }
1403 } 1462 }
1404} 1463}
@@ -1441,8 +1500,9 @@ churn_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
1441 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "This will leave NO peers running (mistake in churn configuration?)!"); 1500 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "This will leave NO peers running (mistake in churn configuration?)!");
1442 churn_down = count_running; 1501 churn_down = count_running;
1443 } 1502 }
1444 timeout = GNUNET_TIME_relative_multiply(seconds_per_peer_start, churn_up > 0 ? churn_up : churn_down); 1503 //timeout = GNUNET_TIME_relative_multiply(seconds_per_peer_start, churn_up > 0 ? churn_up : churn_down);
1445 1504 //timeout = GNUNET_TIME_relative_multiply (seconds_per_peer_start, churn_up > 0 ? churn_up : churn_down);
1505 timeout = DEFAULT_TIMEOUT; /* FIXME: Lack of intelligent choice here */
1446 find_peer_context = NULL; 1506 find_peer_context = NULL;
1447 if (churn_up > 0) /* Only need to do find peer requests if we turned new peers on */ 1507 if (churn_up > 0) /* Only need to do find peer requests if we turned new peers on */
1448 { 1508 {
@@ -1451,10 +1511,13 @@ churn_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
1451 find_peer_context->previous_peers = 0; 1511 find_peer_context->previous_peers = 0;
1452 find_peer_context->current_peers = 0; 1512 find_peer_context->current_peers = 0;
1453 find_peer_context->endtime = GNUNET_TIME_relative_to_absolute(timeout); 1513 find_peer_context->endtime = GNUNET_TIME_relative_to_absolute(timeout);
1514 find_peer_context->peer_hash = GNUNET_CONTAINER_multihashmap_create(num_peers);
1515 find_peer_context->peer_min_heap = GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN);
1454 } 1516 }
1455 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "churn_peers: want %u total, %u running, starting %u, stopping %u\n", 1517 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "churn_peers: want %u total, %u running, starting %u, stopping %u\n",
1456 churn_array[current_churn_round], count_running, churn_up, churn_down); 1518 churn_array[current_churn_round], count_running, churn_up, churn_down);
1457 GNUNET_TESTING_daemons_churn(pg, churn_down, churn_up, timeout, &churn_complete, find_peer_context); 1519 GNUNET_TESTING_daemons_churn (pg, churn_down, churn_up, timeout, &churn_complete, find_peer_context);
1520 current_churn_round++;
1458} 1521}
1459 1522
1460/** 1523/**
@@ -1465,9 +1528,14 @@ get_stop_finished (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
1465{ 1528{
1466 struct TestGetContext *test_get = cls; 1529 struct TestGetContext *test_get = cls;
1467 struct TopologyIteratorContext *topo_ctx; 1530 struct TopologyIteratorContext *topo_ctx;
1468 outstanding_gets--; /* GET is really finished */ 1531
1469 GNUNET_DHT_disconnect(test_get->dht_handle); 1532 /* The dht_handle may be null if this get was scheduled from a down peer */
1470 test_get->dht_handle = NULL; 1533 if (test_get->dht_handle != NULL)
1534 {
1535 GNUNET_DHT_disconnect(test_get->dht_handle);
1536 outstanding_gets--; /* GET is really finished */
1537 test_get->dht_handle = NULL;
1538 }
1471 1539
1472 /* Reset the uid (which item to search for) and the daemon (which peer to search from) for later get request iterations */ 1540 /* Reset the uid (which item to search for) and the daemon (which peer to search from) for later get request iterations */
1473 test_get->uid = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, num_puts); 1541 test_get->uid = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, num_puts);
@@ -1495,6 +1563,7 @@ get_stop_finished (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
1495 { 1563 {
1496 topo_ctx = GNUNET_malloc(sizeof(struct TopologyIteratorContext)); 1564 topo_ctx = GNUNET_malloc(sizeof(struct TopologyIteratorContext));
1497 topo_ctx->cont = &log_dht_statistics; 1565 topo_ctx->cont = &log_dht_statistics;
1566 topo_ctx->peers_seen = GNUNET_CONTAINER_multihashmap_create(num_peers);
1498 GNUNET_SCHEDULER_add_now(sched, &capture_current_topology, topo_ctx); 1567 GNUNET_SCHEDULER_add_now(sched, &capture_current_topology, topo_ctx);
1499 } 1568 }
1500 else 1569 else
@@ -1505,7 +1574,6 @@ get_stop_finished (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
1505 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Current churn round %u, real round %u, scheduling next round of churn.\n", current_churn_round, rounds_finished + 1); 1574 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Current churn round %u, real round %u, scheduling next round of churn.\n", current_churn_round, rounds_finished + 1);
1506 gets_completed = 0; 1575 gets_completed = 0;
1507 gets_failed = 0; 1576 gets_failed = 0;
1508 current_churn_round++;
1509 1577
1510 if (dhtlog_handle != NULL) 1578 if (dhtlog_handle != NULL)
1511 dhtlog_handle->insert_round(DHT_ROUND_CHURN, rounds_finished); 1579 dhtlog_handle->insert_round(DHT_ROUND_CHURN, rounds_finished);
@@ -1518,9 +1586,6 @@ get_stop_finished (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
1518 gets_completed = 0; 1586 gets_completed = 0;
1519 gets_failed = 0; 1587 gets_failed = 0;
1520 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Round %u of %llu finished, scheduling next round.\n", rounds_finished, total_rounds); 1588 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Round %u of %llu finished, scheduling next round.\n", rounds_finished, total_rounds);
1521 /** Make sure we only get here after churning appropriately */
1522 GNUNET_assert(current_churn_round == churn_rounds);
1523 current_churn_round = 0;
1524 1589
1525 /** We reset the peer daemon for puts and gets on each disconnect, so all we need to do is start another round! */ 1590 /** We reset the peer daemon for puts and gets on each disconnect, so all we need to do is start another round! */
1526 if (GNUNET_YES == in_dht_replication) /* Replication done in DHT, don't redo puts! */ 1591 if (GNUNET_YES == in_dht_replication) /* Replication done in DHT, don't redo puts! */
@@ -1623,12 +1688,22 @@ do_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
1623 GNUNET_SCHEDULER_cancel(sched, die_task); 1688 GNUNET_SCHEDULER_cancel(sched, die_task);
1624 GNUNET_SCHEDULER_add_now(sched, &finish_testing, NULL); 1689 GNUNET_SCHEDULER_add_now(sched, &finish_testing, NULL);
1625 } 1690 }
1691
1626 if (test_get == NULL) 1692 if (test_get == NULL)
1627 return; /* End of the list */ 1693 return; /* End of the list */
1628 1694
1629 /* Set this here in case we are re-running gets */ 1695 /* Set this here in case we are re-running gets */
1630 test_get->succeeded = GNUNET_NO; 1696 test_get->succeeded = GNUNET_NO;
1631 1697
1698 if (GNUNET_YES != GNUNET_TESTING_daemon_running(test_get->daemon)) /* If the peer has been churned off, don't try issuing request from it! */
1699 {
1700 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Peer we should issue get request from is down, skipping.\n");
1701 gets_failed++;
1702 GNUNET_SCHEDULER_add_now (sched, &get_stop_finished, test_get);
1703 GNUNET_SCHEDULER_add_now (sched, &do_get, test_get->next);
1704 return;
1705 }
1706
1632 /* Check if more gets are outstanding than should be */ 1707 /* Check if more gets are outstanding than should be */
1633 if (outstanding_gets > max_outstanding_gets) 1708 if (outstanding_gets > max_outstanding_gets)
1634 { 1709 {
@@ -1692,6 +1767,7 @@ put_finished (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
1692 topo_ctx->cont = &do_get; 1767 topo_ctx->cont = &do_get;
1693 topo_ctx->cls = all_gets; 1768 topo_ctx->cls = all_gets;
1694 topo_ctx->timeout = DEFAULT_GET_TIMEOUT; 1769 topo_ctx->timeout = DEFAULT_GET_TIMEOUT;
1770 topo_ctx->peers_seen = GNUNET_CONTAINER_multihashmap_create(num_peers);
1695 die_task = GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_relative_add(GNUNET_TIME_relative_add(DEFAULT_GET_TIMEOUT, all_get_timeout), DEFAULT_TOPOLOGY_CAPTURE_TIMEOUT), 1771 die_task = GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_relative_add(GNUNET_TIME_relative_add(DEFAULT_GET_TIMEOUT, all_get_timeout), DEFAULT_TOPOLOGY_CAPTURE_TIMEOUT),
1696 &end_badly, "from do gets (put finished)"); 1772 &end_badly, "from do gets (put finished)");
1697 GNUNET_SCHEDULER_add_now(sched, &capture_current_topology, topo_ctx); 1773 GNUNET_SCHEDULER_add_now(sched, &capture_current_topology, topo_ctx);
@@ -1721,6 +1797,14 @@ do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
1721 if (test_put == NULL) 1797 if (test_put == NULL)
1722 return; /* End of list */ 1798 return; /* End of list */
1723 1799
1800 if (GNUNET_YES != GNUNET_TESTING_daemon_running(test_put->daemon)) /* If the peer has been churned off, don't try issuing request from it! */
1801 {
1802 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Peer we should issue put request at is down, skipping.\n");
1803 update_meter(put_meter);
1804 GNUNET_SCHEDULER_add_now (sched, &do_put, test_put->next);
1805 return;
1806 }
1807
1724 for (i = 0; i < sizeof(data); i++) 1808 for (i = 0; i < sizeof(data); i++)
1725 { 1809 {
1726 memset(&data[i], GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, (uint32_t)-1), 1); 1810 memset(&data[i], GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, (uint32_t)-1), 1);
@@ -1979,11 +2063,13 @@ continue_puts_and_gets (void *cls, const struct GNUNET_SCHEDULER_TaskContext * t
1979 topo_ctx = GNUNET_malloc(sizeof(struct TopologyIteratorContext)); 2063 topo_ctx = GNUNET_malloc(sizeof(struct TopologyIteratorContext));
1980 topo_ctx->current_iteration = i; 2064 topo_ctx->current_iteration = i;
1981 topo_ctx->total_iterations = max; 2065 topo_ctx->total_iterations = max;
2066 topo_ctx->peers_seen = GNUNET_CONTAINER_multihashmap_create(num_peers);
1982 //fprintf(stderr, "scheduled topology iteration in %d minutes\n", i); 2067 //fprintf(stderr, "scheduled topology iteration in %d minutes\n", i);
1983 GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, i * 3), &capture_current_topology, topo_ctx); 2068 GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, i * 3), &capture_current_topology, topo_ctx);
1984 } 2069 }
1985 topo_ctx = GNUNET_malloc(sizeof(struct TopologyIteratorContext)); 2070 topo_ctx = GNUNET_malloc(sizeof(struct TopologyIteratorContext));
1986 topo_ctx->cont = &setup_puts_and_gets; 2071 topo_ctx->cont = &setup_puts_and_gets;
2072 topo_ctx->peers_seen = GNUNET_CONTAINER_multihashmap_create(num_peers);
1987 GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, settle_time), &capture_current_topology, topo_ctx); 2073 GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, settle_time), &capture_current_topology, topo_ctx);
1988 } 2074 }
1989 else 2075 else
@@ -2217,6 +2303,7 @@ topology_callback (void *cls,
2217 { 2303 {
2218 topo_ctx = GNUNET_malloc(sizeof(struct TopologyIteratorContext)); 2304 topo_ctx = GNUNET_malloc(sizeof(struct TopologyIteratorContext));
2219 topo_ctx->cont = &setup_malicious_peers; 2305 topo_ctx->cont = &setup_malicious_peers;
2306 topo_ctx->peers_seen = GNUNET_CONTAINER_multihashmap_create(num_peers);
2220 //topo_ctx->cont = &continue_puts_and_gets; 2307 //topo_ctx->cont = &continue_puts_and_gets;
2221 GNUNET_SCHEDULER_add_now(sched, &capture_current_topology, topo_ctx); 2308 GNUNET_SCHEDULER_add_now(sched, &capture_current_topology, topo_ctx);
2222 } 2309 }
@@ -2493,6 +2580,7 @@ run (void *cls,
2493 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Read %u rounds from churn file\n", churn_rounds); 2580 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Read %u rounds from churn file\n", churn_rounds);
2494 buf = &churn_data[count + 1]; 2581 buf = &churn_data[count + 1];
2495 churn_array = GNUNET_malloc(sizeof(unsigned int) * churn_rounds); 2582 churn_array = GNUNET_malloc(sizeof(unsigned int) * churn_rounds);
2583 break; /* Done with this part */
2496 } 2584 }
2497 } 2585 }
2498 2586
diff --git a/src/dht/gnunet-service-dht.c b/src/dht/gnunet-service-dht.c
index 3668b3847..6655c76ba 100644
--- a/src/dht/gnunet-service-dht.c
+++ b/src/dht/gnunet-service-dht.c
@@ -1455,8 +1455,10 @@ static void remove_peer (struct PeerInfo *peer,
1455 k_buckets[bucket].tail, 1455 k_buckets[bucket].tail,
1456 peer); 1456 peer);
1457 k_buckets[bucket].peers_size--; 1457 k_buckets[bucket].peers_size--;
1458#if CHANGE_LOWEST
1458 if ((bucket == lowest_bucket) && (k_buckets[lowest_bucket].peers_size == 0) && (lowest_bucket < MAX_BUCKETS - 1)) 1459 if ((bucket == lowest_bucket) && (k_buckets[lowest_bucket].peers_size == 0) && (lowest_bucket < MAX_BUCKETS - 1))
1459 lowest_bucket++; 1460 lowest_bucket++;
1461#endif
1460} 1462}
1461 1463
1462/** 1464/**