From 42dbd0d48e6bd38d58c7d58d523f5f71efed22a0 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 25 Oct 2009 10:57:43 +0000 Subject: [PATCH] make sure stats that are being set can be committed on destroy --- src/Makefile.am | 4 +- src/datastore/plugin_datastore_sqlite.c | 3 +- src/hostlist/gnunet-daemon-hostlist.c | 3 +- src/include/gnunet_statistics_service.h | 7 +- src/statistics/gnunet-statistics.c | 5 +- src/statistics/statistics_api.c | 221 ++++++++++++++++-------- src/statistics/test_statistics_api.c | 2 +- 7 files changed, 167 insertions(+), 78 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index d89e4ca09..c30045c9b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,7 +13,6 @@ SUBDIRS = \ arm \ fragmentation \ hello \ - nat \ peerinfo \ statistics \ datacache \ @@ -24,5 +23,6 @@ SUBDIRS = \ testing \ $(HOSTLIST_DIR) \ topology \ - fs + fs \ + nat diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c index 57ff6266f..f083a12e5 100644 --- a/src/datastore/plugin_datastore_sqlite.c +++ b/src/datastore/plugin_datastore_sqlite.c @@ -1631,7 +1631,8 @@ libgnunet_plugin_datastore_sqlite_done (void *cls) if (plugin->drop_on_shutdown) fn = GNUNET_strdup (plugin->fn); database_shutdown (plugin); - GNUNET_STATISTICS_destroy (plugin->statistics); + GNUNET_STATISTICS_destroy (plugin->statistics, + GNUNET_YES); plugin->env = NULL; plugin->payload = 0; GNUNET_free (api); diff --git a/src/hostlist/gnunet-daemon-hostlist.c b/src/hostlist/gnunet-daemon-hostlist.c index 7d075cf80..5aa4e70ea 100644 --- a/src/hostlist/gnunet-daemon-hostlist.c +++ b/src/hostlist/gnunet-daemon-hostlist.c @@ -115,7 +115,8 @@ cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (stats != NULL) { - GNUNET_STATISTICS_destroy (stats); + GNUNET_STATISTICS_destroy (stats, + GNUNET_NO); stats = NULL; } } diff --git a/src/include/gnunet_statistics_service.h b/src/include/gnunet_statistics_service.h index d8f17b8a1..0fc84cfc3 100644 --- a/src/include/gnunet_statistics_service.h +++ b/src/include/gnunet_statistics_service.h @@ -84,8 +84,13 @@ struct GNUNET_STATISTICS_Handle /** * Destroy a handle (free all state associated with * it). + * + * @param h statistics handle to destroy + * @param sync_first set to GNUNET_YES if pending SET requests should + * be completed */ -void GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *handle); +void GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, + int sync_first); /** diff --git a/src/statistics/gnunet-statistics.c b/src/statistics/gnunet-statistics.c index dd9850418..f51452699 100644 --- a/src/statistics/gnunet-statistics.c +++ b/src/statistics/gnunet-statistics.c @@ -91,7 +91,8 @@ cleanup (void *cls, int success) if (success != GNUNET_OK) ret = 1; if (h != NULL) - GNUNET_STATISTICS_destroy (h); + GNUNET_STATISTICS_destroy (h, + GNUNET_NO); } @@ -130,7 +131,7 @@ run (void *cls, return; } GNUNET_STATISTICS_set (h, name, (uint64_t) val, persistent); - GNUNET_STATISTICS_destroy (h); + GNUNET_STATISTICS_destroy (h, GNUNET_YES); return; } h = GNUNET_STATISTICS_create (sched, "gnunet-statistics", cfg); diff --git a/src/statistics/statistics_api.c b/src/statistics/statistics_api.c index 49709cc72..9606d20d1 100644 --- a/src/statistics/statistics_api.c +++ b/src/statistics/statistics_api.c @@ -161,6 +161,11 @@ struct GNUNET_STATISTICS_Handle */ struct ActionItem *current; + /** + * Should this handle auto-destruct once all actions have + * been processed? + */ + int do_destroy; }; @@ -198,60 +203,27 @@ free_action_item (struct ActionItem *ai) } + + + /** - * Get handle for the statistics service. - * - * @param sched scheduler to use - * @param subsystem name of subsystem using the service - * @param cfg services configuration in use - * @return handle to use + * Schedule the next action to be performed. */ -struct GNUNET_STATISTICS_Handle * -GNUNET_STATISTICS_create (struct GNUNET_SCHEDULER_Handle *sched, - const char *subsystem, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_STATISTICS_Handle *ret; - - GNUNET_assert (subsystem != NULL); - GNUNET_assert (sched != NULL); - GNUNET_assert (cfg != NULL); - ret = GNUNET_malloc (sizeof (struct GNUNET_STATISTICS_Handle)); - ret->sched = sched; - ret->cfg = cfg; - ret->subsystem = GNUNET_strdup (subsystem); - try_connect (ret); - return ret; -} +static void schedule_action (struct GNUNET_STATISTICS_Handle *h); /** - * Destroy a handle (free all state associated with - * it). + * GET processing is complete, tell client about it. */ -void -GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h) +static void +finish (struct GNUNET_STATISTICS_Handle *h, int code) { - struct ActionItem *pos; - if (NULL != h->th) - { - GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); - h->th = NULL; - } - if (h->current != NULL) - free_action_item (h->current); - while (NULL != (pos = h->action_head)) - { - h->action_head = pos->next; - free_action_item (pos); - } - if (h->client != NULL) - { - GNUNET_CLIENT_disconnect (h->client); - h->client = NULL; - } - GNUNET_free (h->subsystem); - GNUNET_free (h); + struct ActionItem *pos = h->current; + h->current = NULL; + schedule_action (h); + if (pos->cont != NULL) + pos->cont (pos->cls, code); + free_action_item (pos); } @@ -308,28 +280,6 @@ process_message (struct GNUNET_STATISTICS_Handle *h, } - -/** - * Schedule the next action to be performed. - */ -static void schedule_action (struct GNUNET_STATISTICS_Handle *h); - - -/** - * GET processing is complete, tell client about it. - */ -static void -finish (struct GNUNET_STATISTICS_Handle *h, int code) -{ - struct ActionItem *pos = h->current; - h->current = NULL; - schedule_action (h); - if (pos->cont != NULL) - pos->cont (pos->cls, code); - free_action_item (pos); -} - - /** * Function called with messages from stats service. * @@ -506,6 +456,127 @@ transmit_action (void *cls, size_t size, void *buf) } +/** + * Get handle for the statistics service. + * + * @param sched scheduler to use + * @param subsystem name of subsystem using the service + * @param cfg services configuration in use + * @return handle to use + */ +struct GNUNET_STATISTICS_Handle * +GNUNET_STATISTICS_create (struct GNUNET_SCHEDULER_Handle *sched, + const char *subsystem, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct GNUNET_STATISTICS_Handle *ret; + + GNUNET_assert (subsystem != NULL); + GNUNET_assert (sched != NULL); + GNUNET_assert (cfg != NULL); + ret = GNUNET_malloc (sizeof (struct GNUNET_STATISTICS_Handle)); + ret->sched = sched; + ret->cfg = cfg; + ret->subsystem = GNUNET_strdup (subsystem); + try_connect (ret); + return ret; +} + + +/** + * Destroy a handle (free all state associated with + * it). + * + * @param h statistics handle to destroy + * @param sync_first set to GNUNET_YES if pending SET requests should + * be completed + */ +void +GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, + int sync_first) +{ + struct ActionItem *pos; + struct ActionItem *next; + struct ActionItem *prev; + struct GNUNET_TIME_Relative timeout; + + if (sync_first) + { + if (h->current != NULL) + { + if (h->current->type == ACTION_GET) + { + GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); + h->th = NULL; + } + } + pos = h->action_head; + prev = NULL; + while (pos != NULL) + { + next = pos->next; + if (pos->type == ACTION_GET) + { + if (prev == NULL) + h->action_head = next; + else + prev->next = next; + free_action_item (pos); + } + else + { + prev = pos; + } + pos = next; + } + h->action_tail = prev; + if (h->current == NULL) + { + h->current = h->action_head; + if (h->action_head != NULL) + { + h->action_head = h->action_head->next; + if (h->action_head == NULL) + h->action_tail = NULL; + } + } + if ( (h->current != NULL) && + (h->th == NULL) ) + { + timeout = GNUNET_TIME_absolute_get_remaining (h->current->timeout); + h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, + h->current->msize, + timeout, + GNUNET_YES, + &transmit_action, h); + GNUNET_assert (NULL != h->th); + } + h->do_destroy = GNUNET_YES; + return; + } + if (NULL != h->th) + { + GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); + h->th = NULL; + } + if (h->current != NULL) + free_action_item (h->current); + while (NULL != (pos = h->action_head)) + { + h->action_head = pos->next; + free_action_item (pos); + } + if (h->client != NULL) + { + GNUNET_CLIENT_disconnect (h->client); + h->client = NULL; + } + GNUNET_free (h->subsystem); + GNUNET_free (h); +} + + + /** * Schedule the next action to be performed. */ @@ -525,7 +596,14 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h) /* schedule next action */ h->current = h->action_head; if (NULL == h->current) - return; + { + if (h->do_destroy) + { + h->do_destroy = GNUNET_NO; + GNUNET_STATISTICS_destroy (h, GNUNET_YES); + } + return; + } h->action_head = h->action_head->next; if (NULL == h->action_head) h->action_tail = NULL; @@ -590,6 +668,7 @@ GNUNET_STATISTICS_get (struct GNUNET_STATISTICS_Handle *handle, GNUNET_assert (handle != NULL); GNUNET_assert (proc != NULL); + GNUNET_assert (GNUNET_NO == handle->do_destroy); if (GNUNET_YES != try_connect (handle)) { #if DEBUG_STATISTICS @@ -673,6 +752,7 @@ GNUNET_STATISTICS_set (struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent) { + GNUNET_assert (GNUNET_NO == handle->do_destroy); add_setter_action (handle, name, make_persistent, value, ACTION_SET); } @@ -691,6 +771,7 @@ GNUNET_STATISTICS_update (struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent) { + GNUNET_assert (GNUNET_NO == handle->do_destroy); add_setter_action (handle, name, make_persistent, (unsigned long long) delta, ACTION_UPDATE); } diff --git a/src/statistics/test_statistics_api.c b/src/statistics/test_statistics_api.c index 97e2f59c7..a03a8c3ed 100644 --- a/src/statistics/test_statistics_api.c +++ b/src/statistics/test_statistics_api.c @@ -74,7 +74,7 @@ next_fin (void *cls, int success) { int *ok = cls; - GNUNET_STATISTICS_destroy (h); + GNUNET_STATISTICS_destroy (h, GNUNET_NO); GNUNET_assert (success == GNUNET_OK); *ok = 0; } -- 2.25.1