X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fstatistics%2Fstatistics_api.c;h=ad4453b2a62a0e8515317e0d972bdd1c740aabab;hb=a015c3df2059a98a8692e7f2b06038e066bbc916;hp=37aa990176aab5d28381c1ac549c2f813d34e877;hpb=3d7b29ec1c5d1c2de96cf4c9badaa112e86ef899;p=oweals%2Fgnunet.git diff --git a/src/statistics/statistics_api.c b/src/statistics/statistics_api.c index 37aa99017..ad4453b2a 100644 --- a/src/statistics/statistics_api.c +++ b/src/statistics/statistics_api.c @@ -222,6 +222,11 @@ struct GNUNET_STATISTICS_Handle */ struct GNUNET_SCHEDULER_Task *backoff_task; + /** + * Task for running #do_destroy(). + */ + struct GNUNET_SCHEDULER_Task *destroy_task; + /** * Time for next connect retry. */ @@ -290,33 +295,39 @@ update_memory_statistics (struct GNUNET_STATISTICS_Handle *h) if (current_heap_size > h->peak_heap_size) { h->peak_heap_size = current_heap_size; - GNUNET_STATISTICS_set (h, "# peak heap size", current_heap_size, GNUNET_NO); + GNUNET_STATISTICS_set (h, + "# peak heap size", + current_heap_size, + GNUNET_NO); } if (current_rss > h->peak_rss) { h->peak_rss = current_rss; - GNUNET_STATISTICS_set (h, "# peak resident set size", current_rss, GNUNET_NO); + GNUNET_STATISTICS_set (h, + "# peak resident set size", + current_rss, + GNUNET_NO); } #endif } /** - * Schedule the next action to be performed. + * Reconnect at a later time, respecting back-off. * - * @param h statistics handle to reconnect + * @param h statistics handle */ static void -schedule_action (struct GNUNET_STATISTICS_Handle *h); +reconnect_later (struct GNUNET_STATISTICS_Handle *h); /** - * Reconnect at a later time, respecting back-off. + * Schedule the next action to be performed. * - * @param h statistics handle + * @param cls statistics handle to reconnect */ static void -reconnect_later (struct GNUNET_STATISTICS_Handle *h); +schedule_action (void *cls); /** @@ -531,6 +542,11 @@ mq_error_handler (void *cls, if (GNUNET_NO != h->do_destroy) { h->do_destroy = GNUNET_NO; + if (NULL != h->destroy_task) + { + GNUNET_SCHEDULER_cancel (h->destroy_task); + h->destroy_task = NULL; + } GNUNET_STATISTICS_destroy (h, GNUNET_NO); return; @@ -546,25 +562,30 @@ mq_error_handler (void *cls, * @param cls the `struct GNUNET_STATISTICS_Handle` */ static void -destroy_task (void *cls) +do_destroy (void *cls) { struct GNUNET_STATISTICS_Handle *h = cls; - GNUNET_STATISTICS_destroy (h, GNUNET_NO); + h->destroy_task = NULL; + h->do_destroy = GNUNET_NO; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Running final destruction\n"); + GNUNET_STATISTICS_destroy (h, + GNUNET_NO); } /** - * Handle a #GNUNET_MESSAGE_TYPE_TEST (sic) message. We receive this - * message at the end of the shutdown when the service confirms that - * all data has been written to disk. + * Handle a #GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM + * message. We receive this message at the end of the shutdown when + * the service confirms that all data has been written to disk. * * @param cls our `struct GNUNET_STATISTICS_Handle *` * @param msg the message */ static void -handle_test (void *cls, - const struct GNUNET_MessageHeader *msg) +handle_disconnect_confirm (void *cls, + const struct GNUNET_MessageHeader *msg) { struct GNUNET_STATISTICS_Handle *h = cls; @@ -576,9 +597,12 @@ handle_test (void *cls, reconnect_later (h); return; } - h->do_destroy = GNUNET_NO; - GNUNET_SCHEDULER_add_now (&destroy_task, - h); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received DISCONNNECT_CONFIRM message from statistics, can complete disconnect\n"); + if (NULL != h->destroy_task) + GNUNET_SCHEDULER_cancel (h->destroy_task); + h->destroy_task = GNUNET_SCHEDULER_add_now (&do_destroy, + h); } @@ -628,23 +652,23 @@ handle_statistics_end (void *cls, static int try_connect (struct GNUNET_STATISTICS_Handle *h) { - GNUNET_MQ_hd_fixed_size (test, - GNUNET_MESSAGE_TYPE_TEST, - struct GNUNET_MessageHeader); - GNUNET_MQ_hd_fixed_size (statistics_end, - GNUNET_MESSAGE_TYPE_STATISTICS_END, - struct GNUNET_MessageHeader); - GNUNET_MQ_hd_var_size (statistics_value, - GNUNET_MESSAGE_TYPE_STATISTICS_VALUE, - struct GNUNET_STATISTICS_ReplyMessage); - GNUNET_MQ_hd_fixed_size (statistics_watch_value, - GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE, - struct GNUNET_STATISTICS_WatchValueMessage); struct GNUNET_MQ_MessageHandler handlers[] = { - make_test_handler (h), - make_statistics_end_handler (h), - make_statistics_value_handler (h), - make_statistics_watch_value_handler (h), + GNUNET_MQ_hd_fixed_size (disconnect_confirm, + GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM, + struct GNUNET_MessageHeader, + h), + GNUNET_MQ_hd_fixed_size (statistics_end, + GNUNET_MESSAGE_TYPE_STATISTICS_END, + struct GNUNET_MessageHeader, + h), + GNUNET_MQ_hd_var_size (statistics_value, + GNUNET_MESSAGE_TYPE_STATISTICS_VALUE, + struct GNUNET_STATISTICS_ReplyMessage, + h), + GNUNET_MQ_hd_fixed_size (statistics_watch_value, + GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE, + struct GNUNET_STATISTICS_WatchValueMessage, + h), GNUNET_MQ_handler_end () }; struct GNUNET_STATISTICS_GetHandle *gh; @@ -654,7 +678,7 @@ try_connect (struct GNUNET_STATISTICS_Handle *h) return GNUNET_NO; if (NULL != h->mq) return GNUNET_YES; - h->mq = GNUNET_CLIENT_connecT (h->cfg, + h->mq = GNUNET_CLIENT_connect (h->cfg, "statistics", handlers, &mq_error_handler, @@ -700,21 +724,6 @@ reconnect_task (void *cls) } -/** - * Task used by #reconnect_later() to shutdown the handle - * - * @param cls the statistics handle - */ -static void -do_destroy (void *cls) -{ - struct GNUNET_STATISTICS_Handle *h = cls; - - GNUNET_STATISTICS_destroy (h, - GNUNET_NO); -} - - /** * Reconnect at a later time, respecting back-off. * @@ -736,14 +745,16 @@ reconnect_later (struct GNUNET_STATISTICS_Handle *h) */ loss = GNUNET_NO; for (gh = h->action_head; NULL != gh; gh = gh->next) - if ( (gh->make_persistent) && (ACTION_SET == gh->type) ) + if ( (gh->make_persistent) && + (ACTION_SET == gh->type) ) loss = GNUNET_YES; if (GNUNET_YES == loss) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Could not save some persistent statistics\n")); - h->do_destroy = GNUNET_NO; - GNUNET_SCHEDULER_add_now (&do_destroy, - h); + if (NULL != h->destroy_task) + GNUNET_SCHEDULER_cancel (h->destroy_task); + h->destroy_task = GNUNET_SCHEDULER_add_now (&do_destroy, + h); return; } h->backoff_task @@ -782,6 +793,9 @@ transmit_get (struct GNUNET_STATISTICS_Handle *handle) 2, c->subsystem, c->name)); + GNUNET_MQ_notify_sent (env, + &schedule_action, + handle); GNUNET_MQ_send (handle->mq, env); } @@ -815,11 +829,15 @@ transmit_watch (struct GNUNET_STATISTICS_Handle *handle) 2, handle->current->subsystem, handle->current->name)); + GNUNET_MQ_notify_sent (env, + &schedule_action, + handle); GNUNET_MQ_send (handle->mq, env); GNUNET_assert (NULL == handle->current->cont); free_action_item (handle->current); handle->current = NULL; + schedule_action (handle); } @@ -857,6 +875,9 @@ transmit_set (struct GNUNET_STATISTICS_Handle *handle) free_action_item (handle->current); handle->current = NULL; update_memory_statistics (handle); + GNUNET_MQ_notify_sent (env, + &schedule_action, + handle); GNUNET_MQ_send (handle->mq, env); } @@ -873,18 +894,18 @@ struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create (const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg) { - struct GNUNET_STATISTICS_Handle *ret; + struct GNUNET_STATISTICS_Handle *h; if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (cfg, "statistics", "DISABLE")) return NULL; - ret = GNUNET_new (struct GNUNET_STATISTICS_Handle); - ret->cfg = cfg; - ret->subsystem = GNUNET_strdup (subsystem); - ret->backoff = GNUNET_TIME_UNIT_MILLISECONDS; - return ret; + h = GNUNET_new (struct GNUNET_STATISTICS_Handle); + h->cfg = cfg; + h->subsystem = GNUNET_strdup (subsystem); + h->backoff = GNUNET_TIME_UNIT_MILLISECONDS; + return h; } @@ -905,14 +926,10 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, if (NULL == h) return; - GNUNET_assert (GNUNET_NO == h->do_destroy); // Don't call twice. - if (NULL != h->backoff_task) - { - GNUNET_SCHEDULER_cancel (h->backoff_task); - h->backoff_task = NULL; - } + GNUNET_assert (GNUNET_NO == h->do_destroy); /* Don't call twice. */ if ( (sync_first) && - (GNUNET_YES == try_connect (h)) ) + (NULL != h->mq) && + (0 != GNUNET_MQ_get_length (h->mq)) ) { if ( (NULL != h->current) && (ACTION_GET == h->current->type) ) @@ -922,8 +939,7 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, { next = pos->next; if ( (ACTION_GET == pos->type) || - (ACTION_WATCH == pos->type) || - (GNUNET_NO == pos->make_persistent) ) + (ACTION_WATCH == pos->type) ) { GNUNET_CONTAINER_DLL_remove (h->action_head, h->action_tail, @@ -933,9 +949,19 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, } h->do_destroy = GNUNET_YES; schedule_action (h); + GNUNET_assert (NULL == h->destroy_task); + h->destroy_task + = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (h->backoff, + 5), + &do_destroy, + h); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Deferring destruction\n"); return; /* do not finish destruction just yet */ } /* do clean up all */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cleaning all up\n"); while (NULL != (pos = h->action_head)) { GNUNET_CONTAINER_DLL_remove (h->action_head, @@ -944,6 +970,17 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, free_action_item (pos); } do_disconnect (h); + if (NULL != h->backoff_task) + { + GNUNET_SCHEDULER_cancel (h->backoff_task); + h->backoff_task = NULL; + } + if (NULL != h->destroy_task) + { + GNUNET_break (0); + GNUNET_SCHEDULER_cancel (h->destroy_task); + h->destroy_task = NULL; + } for (unsigned int i = 0; i < h->watches_size; i++) { if (NULL == h->watches[i]) @@ -963,11 +1000,13 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, /** * Schedule the next action to be performed. * - * @param h statistics handle + * @param cls statistics handle */ static void -schedule_action (struct GNUNET_STATISTICS_Handle *h) +schedule_action (void *cls) { + struct GNUNET_STATISTICS_Handle *h = cls; + if (NULL != h->backoff_task) return; /* action already pending */ if (GNUNET_YES != try_connect (h)) @@ -975,6 +1014,8 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h) reconnect_later (h); return; } + if (0 < GNUNET_MQ_get_length (h->mq)) + return; /* Wait for queue to be reduced more */ /* schedule next action */ while (NULL == h->current) { @@ -987,9 +1028,14 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h) if (GNUNET_YES != h->do_destroy) return; /* nothing to do */ /* let service know that we're done */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Notifying service that we are done\n"); h->do_destroy = GNUNET_SYSERR; /* in 'TEST' mode */ env = GNUNET_MQ_msg (hdr, - GNUNET_MESSAGE_TYPE_TEST); + GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT); + GNUNET_MQ_notify_sent (env, + &schedule_action, + h); GNUNET_MQ_send (h->mq, env); return; @@ -1159,8 +1205,10 @@ GNUNET_STATISTICS_watch_cancel (struct GNUNET_STATISTICS_Handle *handle, continue; if ( (w->proc == proc) && (w->proc_cls == proc_cls) && - (0 == strcmp (w->name, name)) && - (0 == strcmp (w->subsystem, subsystem)) ) + (0 == strcmp (w->name, + name)) && + (0 == strcmp (w->subsystem, + subsystem)) ) { GNUNET_free (w->name); GNUNET_free (w->subsystem); @@ -1205,8 +1253,10 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h, } for (ai = h->action_head; NULL != ai; ai = ai->next) { - if (! ( (0 == strcmp (ai->subsystem, h->subsystem)) && - (0 == strcmp (ai->name, name)) && + if (! ( (0 == strcmp (ai->subsystem, + h->subsystem)) && + (0 == strcmp (ai->name, + name)) && ( (ACTION_UPDATE == ai->type) || (ACTION_SET == ai->type) ) ) ) continue; @@ -1250,8 +1300,10 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h, ai->type = type; } } - ai->timeout = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT); - ai->make_persistent = make_persistent; + ai->timeout + = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT); + ai->make_persistent + = make_persistent; return; } /* no existing entry matches, create a fresh one */