diff options
author | Christian Grothoff <christian@grothoff.org> | 2014-11-24 14:06:23 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2014-11-24 14:06:23 +0000 |
commit | 30a574dc8b01e16a6b70e384a8c4fe05a6ffd861 (patch) | |
tree | 37d16c491c94d3388d2a7d4de959e4c9f591d403 /src/set | |
parent | 82f034f771b4fd8e18c61487f4bd239e0e200408 (diff) | |
download | gnunet-30a574dc8b01e16a6b70e384a8c4fe05a6ffd861.tar.gz gnunet-30a574dc8b01e16a6b70e384a8c4fe05a6ffd861.zip |
-do not do GC for each destroyed operation on client disconnect
Diffstat (limited to 'src/set')
-rw-r--r-- | src/set/gnunet-service-set.c | 59 | ||||
-rw-r--r-- | src/set/gnunet-service-set.h | 4 | ||||
-rw-r--r-- | src/set/gnunet-service-set_intersection.c | 7 | ||||
-rw-r--r-- | src/set/gnunet-service-set_union.c | 10 |
4 files changed, 43 insertions, 37 deletions
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c index ec2bb6484..31676ba3a 100644 --- a/src/set/gnunet-service-set.c +++ b/src/set/gnunet-service-set.c | |||
@@ -327,32 +327,34 @@ collect_generation_garbage (struct Set *set) | |||
327 | 327 | ||
328 | 328 | ||
329 | /** | 329 | /** |
330 | * Destroy the given operation. Call the implementation-specific cancel function | 330 | * Destroy the given operation. Call the implementation-specific |
331 | * of the operation. Disconnects from the remote peer. | 331 | * cancel function of the operation. Disconnects from the remote |
332 | * Does not disconnect the client, as there may be multiple operations per set. | 332 | * peer. Does not disconnect the client, as there may be multiple |
333 | * operations per set. | ||
333 | * | 334 | * |
334 | * @param op operation to destroy | 335 | * @param op operation to destroy |
336 | * @param gc #GNUNET_YES to perform garbage collection on the set | ||
335 | */ | 337 | */ |
336 | void | 338 | void |
337 | _GSS_operation_destroy (struct Operation *op) | 339 | _GSS_operation_destroy (struct Operation *op, |
340 | int gc) | ||
338 | { | 341 | { |
339 | struct Set *set; | 342 | struct Set *set; |
340 | struct GNUNET_CADET_Channel *channel; | 343 | struct GNUNET_CADET_Channel *channel; |
341 | 344 | ||
342 | if (NULL == op->vt) | 345 | if (NULL == op->vt) |
346 | { | ||
347 | /* already in #_GSS_operation_destroy() */ | ||
343 | return; | 348 | return; |
344 | 349 | } | |
345 | set = op->spec->set; | ||
346 | |||
347 | GNUNET_assert (GNUNET_NO == op->is_incoming); | 350 | GNUNET_assert (GNUNET_NO == op->is_incoming); |
348 | GNUNET_assert (NULL != op->spec); | 351 | GNUNET_assert (NULL != op->spec); |
352 | set = op->spec->set; | ||
349 | GNUNET_CONTAINER_DLL_remove (op->spec->set->ops_head, | 353 | GNUNET_CONTAINER_DLL_remove (op->spec->set->ops_head, |
350 | op->spec->set->ops_tail, | 354 | op->spec->set->ops_tail, |
351 | op); | 355 | op); |
352 | |||
353 | op->vt->cancel (op); | 356 | op->vt->cancel (op); |
354 | op->vt = NULL; | 357 | op->vt = NULL; |
355 | |||
356 | if (NULL != op->spec) | 358 | if (NULL != op->spec) |
357 | { | 359 | { |
358 | if (NULL != op->spec->context_msg) | 360 | if (NULL != op->spec->context_msg) |
@@ -363,40 +365,34 @@ _GSS_operation_destroy (struct Operation *op) | |||
363 | GNUNET_free (op->spec); | 365 | GNUNET_free (op->spec); |
364 | op->spec = NULL; | 366 | op->spec = NULL; |
365 | } | 367 | } |
366 | |||
367 | if (NULL != op->mq) | 368 | if (NULL != op->mq) |
368 | { | 369 | { |
369 | GNUNET_MQ_destroy (op->mq); | 370 | GNUNET_MQ_destroy (op->mq); |
370 | op->mq = NULL; | 371 | op->mq = NULL; |
371 | } | 372 | } |
372 | |||
373 | if (NULL != (channel = op->channel)) | 373 | if (NULL != (channel = op->channel)) |
374 | { | 374 | { |
375 | op->channel = NULL; | 375 | op->channel = NULL; |
376 | GNUNET_CADET_channel_destroy (channel); | 376 | GNUNET_CADET_channel_destroy (channel); |
377 | } | 377 | } |
378 | 378 | if (GNUNET_YES == gc) | |
379 | collect_generation_garbage (set); | 379 | collect_generation_garbage (set); |
380 | |||
381 | /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL, | 380 | /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL, |
382 | * there was a channel end handler that will free 'op' on the call stack. */ | 381 | * there was a channel end handler that will free 'op' on the call stack. */ |
383 | } | 382 | } |
384 | 383 | ||
385 | 384 | ||
386 | /** | 385 | /** |
387 | * Iterator over hash map entries to free | 386 | * Iterator over hash map entries to free element entries. |
388 | * element entries. | ||
389 | * | 387 | * |
390 | * @param cls closure | 388 | * @param cls closure |
391 | * @param key current key code | 389 | * @param key current key code |
392 | * @param value a `struct ElementEntry *` to be free'd | 390 | * @param value a `struct ElementEntry *` to be free'd |
393 | * @return #GNUNET_YES if we should continue to | 391 | * @return #GNUNET_YES (continue to iterate) |
394 | * iterate, | ||
395 | * #GNUNET_NO if not. | ||
396 | */ | 392 | */ |
397 | static int | 393 | static int |
398 | destroy_elements_iterator (void *cls, | 394 | destroy_elements_iterator (void *cls, |
399 | const struct GNUNET_HashCode * key, | 395 | const struct GNUNET_HashCode *key, |
400 | void *value) | 396 | void *value) |
401 | { | 397 | { |
402 | struct ElementEntry *ee = value; | 398 | struct ElementEntry *ee = value; |
@@ -407,27 +403,28 @@ destroy_elements_iterator (void *cls, | |||
407 | 403 | ||
408 | 404 | ||
409 | /** | 405 | /** |
410 | * Destroy a set, and free all resources associated with it. | 406 | * Destroy a set, and free all resources and operations associated with it. |
411 | * | 407 | * |
412 | * @param set the set to destroy | 408 | * @param set the set to destroy |
413 | */ | 409 | */ |
414 | static void | 410 | static void |
415 | set_destroy (struct Set *set) | 411 | set_destroy (struct Set *set) |
416 | { | 412 | { |
417 | /* If the client is not dead yet, destroy it. | ||
418 | * The client's destroy callback will destroy the set again. | ||
419 | * We do this so that the channel end handler still has a valid set handle | ||
420 | * to destroy. */ | ||
421 | if (NULL != set->client) | 413 | if (NULL != set->client) |
422 | { | 414 | { |
415 | /* If the client is not dead yet, destroy it. The client's destroy | ||
416 | * callback will call `set_destroy()` again in this case. We do | ||
417 | * this so that the channel end handler still has a valid set handle | ||
418 | * to destroy. */ | ||
423 | struct GNUNET_SERVER_Client *client = set->client; | 419 | struct GNUNET_SERVER_Client *client = set->client; |
420 | |||
424 | set->client = NULL; | 421 | set->client = NULL; |
425 | GNUNET_SERVER_client_disconnect (client); | 422 | GNUNET_SERVER_client_disconnect (client); |
426 | return; | 423 | return; |
427 | } | 424 | } |
428 | GNUNET_assert (NULL != set->state); | 425 | GNUNET_assert (NULL != set->state); |
429 | while (NULL != set->ops_head) | 426 | while (NULL != set->ops_head) |
430 | _GSS_operation_destroy (set->ops_head); | 427 | _GSS_operation_destroy (set->ops_head, GNUNET_NO); |
431 | set->vt->destroy_set (set->state); | 428 | set->vt->destroy_set (set->state); |
432 | set->state = NULL; | 429 | set->state = NULL; |
433 | if (NULL != set->client_mq) | 430 | if (NULL != set->client_mq) |
@@ -1103,7 +1100,9 @@ handle_client_cancel (void *cls, | |||
1103 | return; | 1100 | return; |
1104 | } | 1101 | } |
1105 | 1102 | ||
1106 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client requested cancel for op %u\n", ntohl (msg->request_id)); | 1103 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1104 | "client requested cancel for op %u\n", | ||
1105 | ntohl (msg->request_id)); | ||
1107 | 1106 | ||
1108 | found = GNUNET_NO; | 1107 | found = GNUNET_NO; |
1109 | for (op = set->ops_head; NULL != op; op = op->next) | 1108 | for (op = set->ops_head; NULL != op; op = op->next) |
@@ -1120,9 +1119,11 @@ handle_client_cancel (void *cls, | |||
1120 | * yet and try to cancel the (non non-existent) operation. | 1119 | * yet and try to cancel the (non non-existent) operation. |
1121 | */ | 1120 | */ |
1122 | if (GNUNET_NO != found) | 1121 | if (GNUNET_NO != found) |
1123 | _GSS_operation_destroy (op); | 1122 | _GSS_operation_destroy (op, |
1123 | GNUNET_YES); | ||
1124 | else | 1124 | else |
1125 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client canceled non-existent op\n"); | 1125 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1126 | "client canceled non-existent op\n"); | ||
1126 | 1127 | ||
1127 | 1128 | ||
1128 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1129 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
diff --git a/src/set/gnunet-service-set.h b/src/set/gnunet-service-set.h index b92eb47ff..248b778d9 100644 --- a/src/set/gnunet-service-set.h +++ b/src/set/gnunet-service-set.h | |||
@@ -444,9 +444,11 @@ struct Set | |||
444 | * operations per set. | 444 | * operations per set. |
445 | * | 445 | * |
446 | * @param op operation to destroy | 446 | * @param op operation to destroy |
447 | * @param gc #GNUNET_YES to perform garbage collection on the set | ||
447 | */ | 448 | */ |
448 | void | 449 | void |
449 | _GSS_operation_destroy (struct Operation *op); | 450 | _GSS_operation_destroy (struct Operation *op, |
451 | int gc); | ||
450 | 452 | ||
451 | 453 | ||
452 | /** | 454 | /** |
diff --git a/src/set/gnunet-service-set_intersection.c b/src/set/gnunet-service-set_intersection.c index 20fe8682b..606776154 100644 --- a/src/set/gnunet-service-set_intersection.c +++ b/src/set/gnunet-service-set_intersection.c | |||
@@ -359,7 +359,7 @@ fail_intersection_operation (struct Operation *op) | |||
359 | msg->request_id = htonl (op->spec->client_request_id); | 359 | msg->request_id = htonl (op->spec->client_request_id); |
360 | msg->element_type = htons (0); | 360 | msg->element_type = htons (0); |
361 | GNUNET_MQ_send (op->spec->set->client_mq, ev); | 361 | GNUNET_MQ_send (op->spec->set->client_mq, ev); |
362 | _GSS_operation_destroy (op); | 362 | _GSS_operation_destroy (op, GNUNET_YES); |
363 | } | 363 | } |
364 | 364 | ||
365 | 365 | ||
@@ -525,12 +525,13 @@ send_client_done_and_destroy (void *cls) | |||
525 | struct Operation *op = cls; | 525 | struct Operation *op = cls; |
526 | struct GNUNET_MQ_Envelope *ev; | 526 | struct GNUNET_MQ_Envelope *ev; |
527 | struct GNUNET_SET_ResultMessage *rm; | 527 | struct GNUNET_SET_ResultMessage *rm; |
528 | |||
528 | ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT); | 529 | ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT); |
529 | rm->request_id = htonl (op->spec->client_request_id); | 530 | rm->request_id = htonl (op->spec->client_request_id); |
530 | rm->result_status = htons (GNUNET_SET_STATUS_DONE); | 531 | rm->result_status = htons (GNUNET_SET_STATUS_DONE); |
531 | rm->element_type = htons (0); | 532 | rm->element_type = htons (0); |
532 | GNUNET_MQ_send (op->spec->set->client_mq, ev); | 533 | GNUNET_MQ_send (op->spec->set->client_mq, ev); |
533 | _GSS_operation_destroy (op); | 534 | _GSS_operation_destroy (op, GNUNET_YES); |
534 | } | 535 | } |
535 | 536 | ||
536 | 537 | ||
@@ -1050,7 +1051,7 @@ intersection_peer_disconnect (struct Operation *op) | |||
1050 | GNUNET_MQ_send (op->spec->set->client_mq, ev); | 1051 | GNUNET_MQ_send (op->spec->set->client_mq, ev); |
1051 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1052 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
1052 | "other peer disconnected prematurely\n"); | 1053 | "other peer disconnected prematurely\n"); |
1053 | _GSS_operation_destroy (op); | 1054 | _GSS_operation_destroy (op, GNUNET_YES); |
1054 | return; | 1055 | return; |
1055 | } | 1056 | } |
1056 | // else: the session has already been concluded | 1057 | // else: the session has already been concluded |
diff --git a/src/set/gnunet-service-set_union.c b/src/set/gnunet-service-set_union.c index 10579779b..77e8502d6 100644 --- a/src/set/gnunet-service-set_union.c +++ b/src/set/gnunet-service-set_union.c | |||
@@ -312,7 +312,7 @@ fail_union_operation (struct Operation *op) | |||
312 | msg->request_id = htonl (op->spec->client_request_id); | 312 | msg->request_id = htonl (op->spec->client_request_id); |
313 | msg->element_type = htons (0); | 313 | msg->element_type = htons (0); |
314 | GNUNET_MQ_send (op->spec->set->client_mq, ev); | 314 | GNUNET_MQ_send (op->spec->set->client_mq, ev); |
315 | _GSS_operation_destroy (op); | 315 | _GSS_operation_destroy (op, GNUNET_YES); |
316 | } | 316 | } |
317 | 317 | ||
318 | 318 | ||
@@ -984,12 +984,13 @@ send_done_and_destroy (void *cls) | |||
984 | struct GNUNET_MQ_Envelope *ev; | 984 | struct GNUNET_MQ_Envelope *ev; |
985 | struct GNUNET_SET_ResultMessage *rm; | 985 | struct GNUNET_SET_ResultMessage *rm; |
986 | int keep = op->keep; | 986 | int keep = op->keep; |
987 | |||
987 | ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT); | 988 | ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT); |
988 | rm->request_id = htonl (op->spec->client_request_id); | 989 | rm->request_id = htonl (op->spec->client_request_id); |
989 | rm->result_status = htons (GNUNET_SET_STATUS_DONE); | 990 | rm->result_status = htons (GNUNET_SET_STATUS_DONE); |
990 | rm->element_type = htons (0); | 991 | rm->element_type = htons (0); |
991 | GNUNET_MQ_send (op->spec->set->client_mq, ev); | 992 | GNUNET_MQ_send (op->spec->set->client_mq, ev); |
992 | _GSS_operation_destroy (op); | 993 | _GSS_operation_destroy (op, GNUNET_YES); |
993 | if (GNUNET_YES == keep) | 994 | if (GNUNET_YES == keep) |
994 | GNUNET_free (op); | 995 | GNUNET_free (op); |
995 | } | 996 | } |
@@ -1358,8 +1359,9 @@ union_peer_disconnect (struct Operation *op) | |||
1358 | msg->result_status = htons (GNUNET_SET_STATUS_FAILURE); | 1359 | msg->result_status = htons (GNUNET_SET_STATUS_FAILURE); |
1359 | msg->element_type = htons (0); | 1360 | msg->element_type = htons (0); |
1360 | GNUNET_MQ_send (op->spec->set->client_mq, ev); | 1361 | GNUNET_MQ_send (op->spec->set->client_mq, ev); |
1361 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "other peer disconnected prematurely\n"); | 1362 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
1362 | _GSS_operation_destroy (op); | 1363 | "other peer disconnected prematurely\n"); |
1364 | _GSS_operation_destroy (op, GNUNET_YES); | ||
1363 | return; | 1365 | return; |
1364 | } | 1366 | } |
1365 | // else: the session has already been concluded | 1367 | // else: the session has already been concluded |