From: Christian Grothoff Date: Fri, 12 Mar 2010 12:36:50 +0000 (+0000) Subject: enable stats get cancellation X-Git-Tag: initial-import-from-subversion-38251~22497 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=61cfd3340e67672f351ab92dab7da72dca058c79;p=oweals%2Fgnunet.git enable stats get cancellation --- diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c index cededcca8..fac1ff1d0 100644 --- a/src/datastore/gnunet-service-datastore.c +++ b/src/datastore/gnunet-service-datastore.c @@ -1229,6 +1229,24 @@ unload_plugin (struct DatastorePlugin *plug) } +/** + * Final task run after shutdown. Unloads plugins and disconnects us from + * statistics. + */ +static void +unload_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + unload_plugin (plugin); + plugin = NULL; + if (filter != NULL) + { + GNUNET_CONTAINER_bloomfilter_free (filter); + filter = NULL; + } + GNUNET_ARM_stop_services (cfg, tc->sched, "statistics", NULL); +} + + /** * Last task run during shutdown. Disconnects us from * the transport and core. @@ -1256,14 +1274,10 @@ cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) expired_kill_task); expired_kill_task = GNUNET_SCHEDULER_NO_TASK; } - unload_plugin (plugin); - plugin = NULL; - if (filter != NULL) - { - GNUNET_CONTAINER_bloomfilter_free (filter); - filter = NULL; - } - GNUNET_ARM_stop_services (cfg, tc->sched, "statistics", NULL); + GNUNET_SCHEDULER_add_continuation (sched, + &unload_task, + NULL, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); } diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c index 2fc28e13e..9356b79ed 100644 --- a/src/datastore/plugin_datastore_sqlite.c +++ b/src/datastore/plugin_datastore_sqlite.c @@ -91,6 +91,7 @@ #define BUSY_TIMEOUT_MS 250 + /** * Context for all functions in this plugin. */ @@ -125,6 +126,11 @@ struct Plugin * Handle to the statistics service. */ struct GNUNET_STATISTICS_Handle *statistics; + + /** + * Handle for pending get request. + */ + struct GNUNET_STATISTICS_GetHandle *stat_get; /** * How much data are we currently storing @@ -1559,6 +1565,15 @@ process_stat_in (void *cls, #endif return GNUNET_OK; } + + +static void +process_stat_done (void *cls, + int success) +{ + struct Plugin *plugin = cls; + plugin->stat_get = NULL; +} /** @@ -1581,13 +1596,13 @@ libgnunet_plugin_datastore_sqlite_init (void *cls) plugin.statistics = GNUNET_STATISTICS_create (env->sched, "sqlite", env->cfg); - GNUNET_STATISTICS_get (plugin.statistics, - "sqlite", - QUOTA_STAT_NAME, - GNUNET_TIME_UNIT_MINUTES, - NULL, - &process_stat_in, - &plugin); + plugin.stat_get = GNUNET_STATISTICS_get (plugin.statistics, + "sqlite", + QUOTA_STAT_NAME, + GNUNET_TIME_UNIT_MINUTES, + &process_stat_done, + &process_stat_in, + &plugin); if (GNUNET_OK != database_setup (env->cfg, &plugin)) { @@ -1626,6 +1641,11 @@ libgnunet_plugin_datastore_sqlite_done (void *cls) struct GNUNET_DATASTORE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; + if (plugin->stat_get != NULL) + { + GNUNET_STATISTICS_get_cancel (plugin->stat_get); + plugin->stat_get = NULL; + } fn = NULL; if (plugin->drop_on_shutdown) fn = GNUNET_strdup (plugin->fn); diff --git a/src/include/gnunet_statistics_service.h b/src/include/gnunet_statistics_service.h index 0fc84cfc3..5c166d43d 100644 --- a/src/include/gnunet_statistics_service.h +++ b/src/include/gnunet_statistics_service.h @@ -102,6 +102,11 @@ void GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, */ typedef void (*GNUNET_STATISTICS_Callback) (void *cls, int success); +/** + * Handle that can be used to cancel a statistics 'get' operation. + */ +struct GNUNET_STATISTICS_GetHandle; + /** * Get statistic from the peer. * @@ -113,8 +118,9 @@ typedef void (*GNUNET_STATISTICS_Callback) (void *cls, int success); * @param cont continuation to call when done (can be NULL) * @param proc function to call on each value * @param cls closure for proc and cont + * @return NULL on error */ -void +struct GNUNET_STATISTICS_GetHandle * GNUNET_STATISTICS_get (struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, @@ -122,6 +128,17 @@ GNUNET_STATISTICS_get (struct GNUNET_STATISTICS_Handle *handle, GNUNET_STATISTICS_Callback cont, GNUNET_STATISTICS_Iterator proc, void *cls); + +/** + * Cancel a 'get' request. Must be called before the 'cont' + * function is called. + * + * @param gh handle of the request to cancel + */ +void +GNUNET_STATISTICS_get_cancel (struct GNUNET_STATISTICS_GetHandle *gh); + + /** * Set statistic value for the peer. Will always use our * subsystem (the argument used when "handle" was created). diff --git a/src/statistics/gnunet-statistics.c b/src/statistics/gnunet-statistics.c index f51452699..e996bb728 100644 --- a/src/statistics/gnunet-statistics.c +++ b/src/statistics/gnunet-statistics.c @@ -140,8 +140,9 @@ run (void *cls, ret = 1; return; } - GNUNET_STATISTICS_get (h, - subsystem, name, GET_TIMEOUT, &cleanup, &printer, h); + if (NULL == GNUNET_STATISTICS_get (h, + subsystem, name, GET_TIMEOUT, &cleanup, &printer, h)) + cleanup (h, GNUNET_SYSERR); } /** diff --git a/src/statistics/statistics_api.c b/src/statistics/statistics_api.c index 86950ad4c..e9ebe7fa6 100644 --- a/src/statistics/statistics_api.c +++ b/src/statistics/statistics_api.c @@ -25,6 +25,7 @@ */ #include "platform.h" #include "gnunet_client_lib.h" +#include "gnunet_container_lib.h" #include "gnunet_protocols.h" #include "gnunet_server_lib.h" #include "gnunet_statistics_service.h" @@ -48,13 +49,24 @@ enum ActionType /** * Linked list of things we still need to do. */ -struct ActionItem +struct GNUNET_STATISTICS_GetHandle { + + /** + * This is a doubly linked list. + */ + struct GNUNET_STATISTICS_GetHandle *next; + /** - * This is a linked list. + * This is a doubly linked list. */ - struct ActionItem *next; + struct GNUNET_STATISTICS_GetHandle *prev; + /** + * Main statistics handle. + */ + struct GNUNET_STATISTICS_Handle *sh; + /** * What subsystem is this action about? (can be NULL) */ @@ -147,19 +159,19 @@ struct GNUNET_STATISTICS_Handle * Head of the linked list of pending actions (first action * to be performed). */ - struct ActionItem *action_head; + struct GNUNET_STATISTICS_GetHandle *action_head; /** * Tail of the linked list of actions (for fast append). */ - struct ActionItem *action_tail; + struct GNUNET_STATISTICS_GetHandle *action_tail; /** * Action we are currently busy with (action request has been * transmitted, we're now receiving the response from the * service). */ - struct ActionItem *current; + struct GNUNET_STATISTICS_GetHandle *current; /** * Should this handle auto-destruct once all actions have @@ -195,7 +207,7 @@ try_connect (struct GNUNET_STATISTICS_Handle *ret) * Free memory associated with the given action item. */ static void -free_action_item (struct ActionItem *ai) +free_action_item (struct GNUNET_STATISTICS_GetHandle *ai) { GNUNET_free_non_null (ai->subsystem); GNUNET_free_non_null (ai->name); @@ -203,9 +215,6 @@ free_action_item (struct ActionItem *ai) } - - - /** * Schedule the next action to be performed. */ @@ -218,7 +227,7 @@ static void schedule_action (struct GNUNET_STATISTICS_Handle *h); static void finish (struct GNUNET_STATISTICS_Handle *h, int code) { - struct ActionItem *pos = h->current; + struct GNUNET_STATISTICS_GetHandle *pos = h->current; h->current = NULL; schedule_action (h); if (pos->cont != NULL) @@ -264,17 +273,17 @@ process_message (struct GNUNET_STATISTICS_Handle *h, #endif if (GNUNET_OK != h->current->proc (h->current->cls, - service, - name, - GNUNET_ntohll (smsg->value), - 0 != - (ntohl (smsg->uid) & GNUNET_STATISTICS_PERSIST_BIT))) + service, + name, + GNUNET_ntohll (smsg->value), + 0 != + (ntohl (smsg->uid) & GNUNET_STATISTICS_PERSIST_BIT))) { #if DEBUG_STATISTICS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Processing of remaining statistics aborted by client.\n"); + "Processing of remaining statistics aborted by client.\n"); #endif - h->current->aborted = GNUNET_YES; + h->current->aborted = GNUNET_YES; } return GNUNET_OK; } @@ -495,9 +504,9 @@ void GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, int sync_first) { - struct ActionItem *pos; - struct ActionItem *next; - struct ActionItem *prev; + struct GNUNET_STATISTICS_GetHandle *pos; + struct GNUNET_STATISTICS_GetHandle *next; + struct GNUNET_STATISTICS_GetHandle *prev; struct GNUNET_TIME_Relative timeout; if (sync_first) @@ -606,10 +615,9 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h) } return; } - h->action_head = h->action_head->next; - if (NULL == h->action_head) - h->action_tail = NULL; - h->current->next = NULL; + GNUNET_CONTAINER_DLL_remove (h->action_head, + h->action_tail, + h->current); timeout = GNUNET_TIME_absolute_get_remaining (h->current->timeout); if (NULL == (h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, @@ -628,19 +636,14 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h) static void -insert_ai (struct GNUNET_STATISTICS_Handle *h, struct ActionItem *ai) +insert_ai (struct GNUNET_STATISTICS_Handle *h, struct GNUNET_STATISTICS_GetHandle *ai) { - if (h->action_tail == NULL) - { - h->action_head = ai; - h->action_tail = ai; - schedule_action (h); - } - else - { - h->action_tail->next = ai; - h->action_tail = ai; - } + GNUNET_CONTAINER_DLL_insert_after (h->action_head, + h->action_tail, + h->action_tail, + ai); + if (h->action_head == ai) + schedule_action (h); } @@ -655,8 +658,9 @@ insert_ai (struct GNUNET_STATISTICS_Handle *h, struct ActionItem *ai) * @param cont continuation to call when done (can be NULL) * @param proc function to call on each value * @param cls closure for cont and proc + * @return NULL on error */ -void +struct GNUNET_STATISTICS_GetHandle * GNUNET_STATISTICS_get (struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, @@ -666,7 +670,7 @@ GNUNET_STATISTICS_get (struct GNUNET_STATISTICS_Handle *handle, { size_t slen1; size_t slen2; - struct ActionItem *ai; + struct GNUNET_STATISTICS_GetHandle *ai; GNUNET_assert (handle != NULL); GNUNET_assert (proc != NULL); @@ -679,9 +683,7 @@ GNUNET_STATISTICS_get (struct GNUNET_STATISTICS_Handle *handle, strlen (subsystem) ? subsystem : "*", strlen (name) ? name : "*"); #endif - if (cont != NULL) - cont (cls, GNUNET_SYSERR); - return; + return NULL; } if (subsystem == NULL) subsystem = ""; @@ -691,7 +693,8 @@ GNUNET_STATISTICS_get (struct GNUNET_STATISTICS_Handle *handle, slen2 = strlen (name); GNUNET_assert (slen1 + slen2 + sizeof (struct GNUNET_MessageHeader) < GNUNET_SERVER_MAX_MESSAGE_SIZE); - ai = GNUNET_malloc (sizeof (struct ActionItem)); + ai = GNUNET_malloc (sizeof (struct GNUNET_STATISTICS_GetHandle)); + ai->sh = handle; ai->subsystem = GNUNET_strdup (subsystem); ai->name = GNUNET_strdup (name); ai->cont = cont; @@ -701,6 +704,32 @@ GNUNET_STATISTICS_get (struct GNUNET_STATISTICS_Handle *handle, ai->type = ACTION_GET; ai->msize = slen1 + slen2 + sizeof (struct GNUNET_MessageHeader); insert_ai (handle, ai); + return ai; +} + + +/** + * Cancel a 'get' request. Must be called before the 'cont' + * function is called. + * + * @param gh handle of the request to cancel + */ +void +GNUNET_STATISTICS_get_cancel (struct GNUNET_STATISTICS_GetHandle *gh) +{ + if (gh->sh->current == gh) + { + gh->aborted = GNUNET_YES; + } + else + { + GNUNET_CONTAINER_DLL_remove (gh->sh->action_head, + gh->sh->action_tail, + gh); + GNUNET_free (gh->name); + GNUNET_free (gh->subsystem); + GNUNET_free (gh); + } } @@ -710,7 +739,7 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h, int make_persistent, uint64_t value, enum ActionType type) { - struct ActionItem *ai; + struct GNUNET_STATISTICS_GetHandle *ai; size_t slen; size_t nlen; size_t nsize; @@ -727,7 +756,8 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h, GNUNET_break (0); return; } - ai = GNUNET_malloc (sizeof (struct ActionItem)); + ai = GNUNET_malloc (sizeof (struct GNUNET_STATISTICS_GetHandle)); + ai->sh = h; ai->subsystem = GNUNET_strdup (h->subsystem); ai->name = GNUNET_strdup (name); ai->timeout = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT); diff --git a/src/statistics/test_statistics_api.c b/src/statistics/test_statistics_api.c index 8a4a5e911..d7eb90b4d 100644 --- a/src/statistics/test_statistics_api.c +++ b/src/statistics/test_statistics_api.c @@ -83,8 +83,9 @@ static void next (void *cls, int success) { GNUNET_assert (success == GNUNET_OK); - GNUNET_STATISTICS_get (h, NULL, "test-2", - GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, cls); + GNUNET_break (NULL != + GNUNET_STATISTICS_get (h, NULL, "test-2", + GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, cls)); } static void @@ -100,8 +101,9 @@ run (void *cls, GNUNET_STATISTICS_set (h, "test-2", 2, GNUNET_NO); GNUNET_STATISTICS_set (h, "test-3", 2, GNUNET_NO); GNUNET_STATISTICS_update (h, "test-3", 1, GNUNET_YES); - GNUNET_STATISTICS_get (h, NULL, "test-1", - GNUNET_TIME_UNIT_SECONDS, &next, &check_1, cls); + GNUNET_break (NULL != + GNUNET_STATISTICS_get (h, NULL, "test-1", + GNUNET_TIME_UNIT_SECONDS, &next, &check_1, cls)); } static void @@ -112,8 +114,9 @@ run_more (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { h = GNUNET_STATISTICS_create (sched, "test-statistics-api", cfg); - GNUNET_STATISTICS_get (h, NULL, "test-3", - GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_3, cls); + GNUNET_break (NULL != + GNUNET_STATISTICS_get (h, NULL, "test-3", + GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_3, cls)); } static int