aboutsummaryrefslogtreecommitdiff
path: root/src/set
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2014-11-24 14:06:23 +0000
committerChristian Grothoff <christian@grothoff.org>2014-11-24 14:06:23 +0000
commit30a574dc8b01e16a6b70e384a8c4fe05a6ffd861 (patch)
tree37d16c491c94d3388d2a7d4de959e4c9f591d403 /src/set
parent82f034f771b4fd8e18c61487f4bd239e0e200408 (diff)
downloadgnunet-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.c59
-rw-r--r--src/set/gnunet-service-set.h4
-rw-r--r--src/set/gnunet-service-set_intersection.c7
-rw-r--r--src/set/gnunet-service-set_union.c10
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 */
336void 338void
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 */
397static int 393static int
398destroy_elements_iterator (void *cls, 394destroy_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 */
414static void 410static void
415set_destroy (struct Set *set) 411set_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 */
448void 449void
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