X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fstatistics%2Fgnunet-service-statistics.c;h=6c3d173c44b78b19eb0386bd4e08745ebce21e80;hb=372afebb55cc8b40d5f7115a398564e6ffd61434;hp=1ec07ad5dc40eb0ee649ead935ea5df36b155f6e;hpb=b3e1d0806fb274c62a5acf19c56369b71f992312;p=oweals%2Fgnunet.git diff --git a/src/statistics/gnunet-service-statistics.c b/src/statistics/gnunet-service-statistics.c index 1ec07ad5d..6c3d173c4 100644 --- a/src/statistics/gnunet-service-statistics.c +++ b/src/statistics/gnunet-service-statistics.c @@ -66,6 +66,12 @@ struct WatchEntry */ uint32_t wid; + /** + * Is last_value valid + * GNUNET_NO : last_value is n/a, GNUNET_YES: last_value is valid + */ + int last_value_set; + }; @@ -152,6 +158,12 @@ struct StatsEntry */ int persistent; + /** + * Is this value set? + * GNUNET_NO : value is n/a, GNUNET_YES: value is valid + */ + int set; + }; /** @@ -202,12 +214,13 @@ static int in_shutdown; * @param client unused * @param msg message to inject */ -static void +static int inject_message (void *cls, void *client, const struct GNUNET_MessageHeader *msg) { struct GNUNET_SERVER_Handle *server = cls; GNUNET_break (GNUNET_OK == GNUNET_SERVER_inject (server, NULL, msg)); + return GNUNET_OK; } @@ -223,17 +236,25 @@ load (struct GNUNET_SERVER_Handle *server) { char *fn; struct GNUNET_BIO_ReadHandle *rh; - struct stat sb; uint64_t fsize; char *buf; struct GNUNET_SERVER_MessageStreamTokenizer *mst; char *emsg; - fn = GNUNET_DISK_get_home_filename (cfg, "statistics", "statistics.data", - NULL); - if (fn == NULL) + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, + "STATISTICS", + "DATABASE", + &fn)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "STATISTICS", + "DATABASE"); return; - if ((GNUNET_OK != GNUNET_DISK_file_size (fn, &fsize, GNUNET_NO, GNUNET_YES)) || (fsize == 0)) + } + if ( (GNUNET_OK != + GNUNET_DISK_file_size (fn, &fsize, GNUNET_NO, GNUNET_YES)) || + (0 == fsize) ) { GNUNET_free (fn); return; @@ -279,15 +300,22 @@ save () struct StatsEntry *pos; char *fn; struct GNUNET_BIO_WriteHandle *wh; - uint16_t size; unsigned long long total; - wh = NULL; - fn = GNUNET_DISK_get_home_filename (cfg, "statistics", "statistics.data", - NULL); - if (fn != NULL) - wh = GNUNET_BIO_write_open (fn); + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, + "STATISTICS", + "DATABASE", + &fn)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "STATISTICS", + "DATABASE"); + return; + } + (void) GNUNET_DISK_directory_create_for_file (fn); + wh = GNUNET_BIO_write_open (fn); total = 0; while (NULL != (pos = start)) { @@ -397,9 +425,8 @@ make_client_entry (struct GNUNET_SERVER_Client *client) GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return NULL; } - ce = GNUNET_malloc (sizeof (struct ClientEntry)); + ce = GNUNET_new (struct ClientEntry); ce->client = client; - GNUNET_SERVER_client_keep (client); GNUNET_CONTAINER_DLL_insert (client_head, client_tail, ce); GNUNET_SERVER_notification_context_add (nc, client); return ce; @@ -463,8 +490,15 @@ notify_change (struct StatsEntry *se) for (pos = se->we_head; NULL != pos; pos = pos->next) { - if (pos->last_value == se->value) - continue; + if (GNUNET_YES == pos->last_value_set) + { + if (pos->last_value == se->value) + continue; + } + else + { + pos->last_value_set = GNUNET_YES; + } wvm.header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE); wvm.header.size = htons (sizeof (struct GNUNET_STATISTICS_WatchValueMessage)); @@ -478,6 +512,7 @@ notify_change (struct StatsEntry *se) } } + /** * Handle SET-message. * @@ -500,6 +535,7 @@ handle_set (void *cls, struct GNUNET_SERVER_Client *client, uint64_t value; int64_t delta; int changed; + int initial_set; if ( (NULL != client) && (NULL == make_client_entry (client)) ) @@ -533,6 +569,7 @@ handle_set (void *cls, struct GNUNET_SERVER_Client *client, { if (matches (pos, service, name)) { + initial_set = 0; if ((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0) { changed = (pos->value != value); @@ -553,6 +590,11 @@ handle_set (void *cls, struct GNUNET_SERVER_Client *client, pos->value += delta; } } + if (GNUNET_NO == pos->set) + { + pos->set = GNUNET_YES; + initial_set = 1; + } pos->msg->value = GNUNET_htonll (pos->value); pos->msg->flags = msg->flags; pos->persistent = (0 != (flags & GNUNET_STATISTICS_SETFLAG_PERSISTENT)); @@ -566,7 +608,7 @@ handle_set (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Statistic `%s:%s' updated to value %llu.\n", service, name, pos->value); - if (changed) + if ((changed) || (1 == initial_set)) notify_change (pos); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; @@ -578,7 +620,14 @@ handle_set (void *cls, struct GNUNET_SERVER_Client *client, pos->next = start; if (((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0) || (0 < (int64_t) GNUNET_ntohll (msg->value))) + { pos->value = GNUNET_ntohll (msg->value); + pos->set = GNUNET_YES; + } + else + { + pos->set = GNUNET_NO; + } pos->uid = uidgen++; pos->persistent = (0 != (flags & GNUNET_STATISTICS_SETFLAG_PERSISTENT)); pos->msg = (void *) &pos[1]; @@ -619,6 +668,7 @@ handle_watch (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } + GNUNET_SERVER_client_mark_monitor (client); ce = make_client_entry (client); msize = ntohs (message->size); if (msize < sizeof (struct GNUNET_MessageHeader)) @@ -653,6 +703,7 @@ handle_watch (void *cls, struct GNUNET_SERVER_Client *client, sizeof (struct GNUNET_STATISTICS_SetMessage) + size); pos->next = start; pos->uid = uidgen++; + pos->set = GNUNET_NO; pos->msg = (void *) &pos[1]; pos->msg->header.size = htons (sizeof (struct GNUNET_STATISTICS_SetMessage) + size); @@ -663,10 +714,13 @@ handle_watch (void *cls, struct GNUNET_SERVER_Client *client, pos->name = &pos->service[slen]; memcpy ((void *) pos->name, name, strlen (name) + 1); start = pos; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "New statistic on `%s:%s' with value %llu created.\n", service, + name, pos->value); } - we = GNUNET_malloc (sizeof (struct WatchEntry)); + we = GNUNET_new (struct WatchEntry); we->client = client; - GNUNET_SERVER_client_keep (client); + we->last_value_set = GNUNET_NO; we->wid = ce->max_wid++; GNUNET_CONTAINER_DLL_insert (pos->we_head, pos->we_tail, we); if (pos->value != 0) @@ -678,7 +732,7 @@ handle_watch (void *cls, struct GNUNET_SERVER_Client *client, /** * Actually perform the shutdown. */ -static void +static void do_shutdown () { struct WatchEntry *we; @@ -688,14 +742,13 @@ do_shutdown () return; save (); GNUNET_SERVER_notification_context_destroy (nc); - nc = NULL; + nc = NULL; GNUNET_assert (NULL == client_head); while (NULL != (se = start)) { start = se->next; while (NULL != (we = se->we_head)) { - GNUNET_SERVER_client_drop (we->client); GNUNET_CONTAINER_DLL_remove (se->we_head, se->we_tail, we); GNUNET_free (we); } @@ -739,7 +792,6 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { if (ce->client == client) { - GNUNET_SERVER_client_drop (ce->client); GNUNET_CONTAINER_DLL_remove (client_head, client_tail, ce); GNUNET_free (ce); break; @@ -755,7 +807,6 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) wen = we->next; if (we->client != client) continue; - GNUNET_SERVER_client_drop (we->client); GNUNET_CONTAINER_DLL_remove (se->we_head, se->we_tail, we); GNUNET_free (we); } @@ -787,7 +838,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, cfg = c; srv = server; GNUNET_SERVER_add_handlers (server, handlers); - GNUNET_SERVER_ignore_shutdown (server, GNUNET_YES); nc = GNUNET_SERVER_notification_context_create (server, 16); GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); load (server); @@ -808,7 +858,22 @@ main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "statistics", - GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; + GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, &run, NULL)) ? 0 : 1; +} + +#ifdef LINUX +#include + +/** + * MINIMIZE heap size (way below 128k) since this process doesn't need much. + */ +void __attribute__ ((constructor)) GNUNET_ARM_memory_init () +{ + mallopt (M_TRIM_THRESHOLD, 4 * 1024); + mallopt (M_TOP_PAD, 1 * 1024); + malloc_trim (0); } +#endif + /* end of gnunet-service-statistics.c */