diff options
Diffstat (limited to 'src/statistics')
-rw-r--r-- | src/statistics/Makefile.am | 11 | ||||
-rw-r--r-- | src/statistics/Makefile.in | 31 | ||||
-rw-r--r-- | src/statistics/gnunet-service-statistics.c | 233 | ||||
-rw-r--r-- | src/statistics/gnunet-statistics.c | 78 | ||||
-rw-r--r-- | src/statistics/statistics.conf.in | 2 | ||||
-rw-r--r-- | src/statistics/statistics.h | 1 | ||||
-rw-r--r-- | src/statistics/statistics_api.c | 244 | ||||
-rw-r--r-- | src/statistics/test_statistics_api.c | 19 | ||||
-rw-r--r-- | src/statistics/test_statistics_api_data.conf | 15 | ||||
-rw-r--r-- | src/statistics/test_statistics_api_loop.c | 2 | ||||
-rw-r--r-- | src/statistics/test_statistics_api_watch.c | 2 | ||||
-rw-r--r-- | src/statistics/test_statistics_api_watch_zero_value.c | 201 |
12 files changed, 664 insertions, 175 deletions
diff --git a/src/statistics/Makefile.am b/src/statistics/Makefile.am index 2d1daf8..ddf5fda 100644 --- a/src/statistics/Makefile.am +++ b/src/statistics/Makefile.am @@ -23,7 +23,7 @@ libgnunetstatistics_la_LIBADD = \ $(GN_LIBINTL) $(XLIB) libgnunetstatistics_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 1:0:1 + -version-info 1:1:1 bin_PROGRAMS = \ @@ -51,7 +51,8 @@ gnunet_service_statistics_DEPENDENCIES = \ check_PROGRAMS = \ test_statistics_api \ test_statistics_api_loop \ - test_statistics_api_watch + test_statistics_api_watch \ + test_statistics_api_watch_zero_value if ENABLE_TEST_RUN TESTS = $(check_PROGRAMS) $(check_SCRIPTS) @@ -75,6 +76,12 @@ test_statistics_api_watch_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la +test_statistics_api_watch_zero_value_SOURCES = \ + test_statistics_api_watch_zero_value.c +test_statistics_api_watch_zero_value_LDADD = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la + check_SCRIPTS = \ test_gnunet_statistics.sh diff --git a/src/statistics/Makefile.in b/src/statistics/Makefile.in index 1930c3a..a81ae4a 100644 --- a/src/statistics/Makefile.in +++ b/src/statistics/Makefile.in @@ -41,7 +41,8 @@ bin_PROGRAMS = gnunet-statistics$(EXEEXT) \ gnunet-service-statistics$(EXEEXT) check_PROGRAMS = test_statistics_api$(EXEEXT) \ test_statistics_api_loop$(EXEEXT) \ - test_statistics_api_watch$(EXEEXT) + test_statistics_api_watch$(EXEEXT) \ + test_statistics_api_watch_zero_value$(EXEEXT) subdir = src/statistics DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/statistics.conf.in @@ -127,6 +128,13 @@ test_statistics_api_watch_OBJECTS = \ test_statistics_api_watch_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la +am_test_statistics_api_watch_zero_value_OBJECTS = \ + test_statistics_api_watch_zero_value.$(OBJEXT) +test_statistics_api_watch_zero_value_OBJECTS = \ + $(am_test_statistics_api_watch_zero_value_OBJECTS) +test_statistics_api_watch_zero_value_DEPENDENCIES = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -157,12 +165,14 @@ SOURCES = $(libgnunetstatistics_la_SOURCES) \ $(gnunet_service_statistics_SOURCES) \ $(gnunet_statistics_SOURCES) $(test_statistics_api_SOURCES) \ $(test_statistics_api_loop_SOURCES) \ - $(test_statistics_api_watch_SOURCES) + $(test_statistics_api_watch_SOURCES) \ + $(test_statistics_api_watch_zero_value_SOURCES) DIST_SOURCES = $(libgnunetstatistics_la_SOURCES) \ $(gnunet_service_statistics_SOURCES) \ $(gnunet_statistics_SOURCES) $(test_statistics_api_SOURCES) \ $(test_statistics_api_loop_SOURCES) \ - $(test_statistics_api_watch_SOURCES) + $(test_statistics_api_watch_SOURCES) \ + $(test_statistics_api_watch_zero_value_SOURCES) DATA = $(pkgcfg_DATA) ETAGS = etags CTAGS = ctags @@ -224,6 +234,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBADD_DL = @LIBADD_DL@ @@ -257,6 +268,7 @@ LT_DLLOADERS = @LT_DLLOADERS@ LT_DLPREOPEN = @LT_DLPREOPEN@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ +MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ @@ -391,7 +403,7 @@ libgnunetstatistics_la_LIBADD = \ libgnunetstatistics_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 1:0:1 + -version-info 1:1:1 gnunet_statistics_SOURCES = \ gnunet-statistics.c @@ -437,6 +449,13 @@ test_statistics_api_watch_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la +test_statistics_api_watch_zero_value_SOURCES = \ + test_statistics_api_watch_zero_value.c + +test_statistics_api_watch_zero_value_LDADD = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la + check_SCRIPTS = \ test_gnunet_statistics.sh @@ -580,6 +599,9 @@ test_statistics_api_loop$(EXEEXT): $(test_statistics_api_loop_OBJECTS) $(test_st test_statistics_api_watch$(EXEEXT): $(test_statistics_api_watch_OBJECTS) $(test_statistics_api_watch_DEPENDENCIES) @rm -f test_statistics_api_watch$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_statistics_api_watch_OBJECTS) $(test_statistics_api_watch_LDADD) $(LIBS) +test_statistics_api_watch_zero_value$(EXEEXT): $(test_statistics_api_watch_zero_value_OBJECTS) $(test_statistics_api_watch_zero_value_DEPENDENCIES) + @rm -f test_statistics_api_watch_zero_value$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_statistics_api_watch_zero_value_OBJECTS) $(test_statistics_api_watch_zero_value_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -593,6 +615,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_statistics_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_statistics_api_loop.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_statistics_api_watch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_statistics_api_watch_zero_value.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/src/statistics/gnunet-service-statistics.c b/src/statistics/gnunet-service-statistics.c index a890d6d..efd8346 100644 --- a/src/statistics/gnunet-service-statistics.c +++ b/src/statistics/gnunet-service-statistics.c @@ -41,16 +41,37 @@ struct WatchEntry { + /** + * Watch entries are kept in a linked list. + */ struct WatchEntry *next; + /** + * Watch entries are kept in a linked list. + */ struct WatchEntry *prev; + /** + * For which client is this watch entry? + */ struct GNUNET_SERVER_Client *client; + /** + * Last value we communicated to the client for this watch entry. + */ uint64_t last_value; + /** + * Unique watch number for this client and this watched value. + */ uint32_t wid; + /** + * Is last_value valid + * GNUNET_NO : last_value is n/a, GNUNET_YES: last_value is valid + */ + int last_value_set; + }; @@ -59,13 +80,24 @@ struct WatchEntry */ struct ClientEntry { - + /** + * Clients are kept in a linked list. + */ struct ClientEntry *next; + /** + * Clients are kept in a linked list. + */ struct ClientEntry *prev; + /** + * Corresponding server handle. + */ struct GNUNET_SERVER_Client *client; + /** + * Maximum watch ID used by this client so far. + */ uint32_t max_wid; }; @@ -126,6 +158,12 @@ struct StatsEntry */ int persistent; + /** + * Is this value set? + * GNUNET_NO : value is n/a, GNUNET_YES: value is valid + */ + int set; + }; /** @@ -138,11 +176,22 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg; */ static struct StatsEntry *start; +/** + * Head of linked list of connected clients. + */ static struct ClientEntry *client_head; +/** + * Tail of linked list of connected clients. + */ static struct ClientEntry *client_tail; /** + * Handle to our server. + */ +static struct GNUNET_SERVER_Handle *srv; + +/** * Our notification context. */ static struct GNUNET_SERVER_NotificationContext *nc; @@ -152,13 +201,26 @@ static struct GNUNET_SERVER_NotificationContext *nc; */ static uint32_t uidgen; +/** + * Set to YES if we are shutting down as soon as possible. + */ +static int in_shutdown; + -static void +/** + * Inject a message to our server with a client of 'NULL'. + * + * @param cls the 'struct GNUNET_SERVER_Handle' + * @param client unused + * @param msg message to inject + */ +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; } @@ -174,7 +236,7 @@ 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; @@ -183,12 +245,12 @@ load (struct GNUNET_SERVER_Handle *server) NULL); if (fn == NULL) return; - if ((0 != stat (fn, &sb)) || (sb.st_size == 0)) + if ((GNUNET_OK != GNUNET_DISK_file_size (fn, &fsize, GNUNET_NO, GNUNET_YES)) || (fsize == 0)) { GNUNET_free (fn); return; } - buf = GNUNET_malloc (sb.st_size); + buf = GNUNET_malloc (fsize); rh = GNUNET_BIO_read_open (fn); if (!rh) { @@ -196,7 +258,7 @@ load (struct GNUNET_SERVER_Handle *server) GNUNET_free (fn); return; } - if (GNUNET_OK != GNUNET_BIO_read (rh, fn, buf, sb.st_size)) + if (GNUNET_OK != GNUNET_BIO_read (rh, fn, buf, fsize)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "read", fn); GNUNET_break (GNUNET_OK == GNUNET_BIO_read_close (rh, &emsg)); @@ -207,10 +269,10 @@ load (struct GNUNET_SERVER_Handle *server) } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading %llu bytes of statistics from `%s'\n"), - (unsigned long long) sb.st_size, fn); + fsize, fn); mst = GNUNET_SERVER_mst_create (&inject_message, server); GNUNET_break (GNUNET_OK == - GNUNET_SERVER_mst_receive (mst, NULL, buf, sb.st_size, + GNUNET_SERVER_mst_receive (mst, NULL, buf, fsize, GNUNET_YES, GNUNET_NO)); GNUNET_SERVER_mst_destroy (mst); GNUNET_free (buf); @@ -219,6 +281,7 @@ load (struct GNUNET_SERVER_Handle *server) GNUNET_free (fn); } + /** * Write persistent statistics to disk. */ @@ -272,6 +335,9 @@ save () /** * Transmit the given stats value. + * + * @param client receiver of the value + * @param e value to transmit */ static void transmit (struct GNUNET_SERVER_Client *client, const struct StatsEntry *e) @@ -294,11 +360,9 @@ transmit (struct GNUNET_SERVER_Client *client, const struct StatsEntry *e) GNUNET_assert (size == GNUNET_STRINGS_buffer_fill ((char *) &m[1], size, 2, e->service, e->name)); -#if DEBUG_STATISTICS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting value for `%s:%s' (%d): %llu\n", e->service, e->name, e->persistent, e->value); -#endif GNUNET_SERVER_notification_context_unicast (nc, client, &m->header, GNUNET_NO); GNUNET_free (m); @@ -307,6 +371,11 @@ transmit (struct GNUNET_SERVER_Client *client, const struct StatsEntry *e) /** * Does this entry match the request? + * + * @param e an entry + * @param service name of service to match + * @param name value to match + * @return 1 if they match, 0 if not */ static int matches (const struct StatsEntry *e, const char *service, const char *name) @@ -316,6 +385,12 @@ matches (const struct StatsEntry *e, const char *service, const char *name) } +/** + * Find a client entry for the given client handle, or create one. + * + * @param client handle to match + * @return corresponding client entry struct + */ static struct ClientEntry * make_client_entry (struct GNUNET_SERVER_Client *client) { @@ -329,6 +404,11 @@ make_client_entry (struct GNUNET_SERVER_Client *client) return ce; ce = ce->next; } + if (NULL == nc) + { + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return NULL; + } ce = GNUNET_malloc (sizeof (struct ClientEntry)); ce->client = client; GNUNET_SERVER_client_keep (client); @@ -357,8 +437,9 @@ handle_get (void *cls, struct GNUNET_SERVER_Client *client, struct StatsEntry *pos; size_t size; - if (client != NULL) - make_client_entry (client); + if ( (NULL != client) && + (NULL == make_client_entry (client)) ) + return; /* new client during shutdown */ size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], size, 2, @@ -368,18 +449,12 @@ handle_get (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } -#if DEBUG_STATISTICS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received request for statistics on `%s:%s'\n", strlen (service) ? service : "*", strlen (name) ? name : "*"); -#endif - pos = start; - while (pos != NULL) - { + for (pos = start; NULL != pos; pos = pos->next) if (matches (pos, service, name)) transmit (client, pos); - pos = pos->next; - } end.size = htons (sizeof (struct GNUNET_MessageHeader)); end.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_END); GNUNET_SERVER_notification_context_unicast (nc, client, &end, GNUNET_NO); @@ -387,29 +462,38 @@ handle_get (void *cls, struct GNUNET_SERVER_Client *client, } +/** + * Notify all clients listening about a change to a value. + * + * @param se value that changed + */ static void notify_change (struct StatsEntry *se) { struct GNUNET_STATISTICS_WatchValueMessage wvm; struct WatchEntry *pos; - pos = se->we_head; - while (pos != NULL) + for (pos = se->we_head; NULL != pos; pos = pos->next) { - if (pos->last_value != se->value) + if (GNUNET_YES == pos->last_value_set) { - wvm.header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE); - wvm.header.size = - htons (sizeof (struct GNUNET_STATISTICS_WatchValueMessage)); - wvm.flags = htonl (se->persistent ? GNUNET_STATISTICS_PERSIST_BIT : 0); - wvm.wid = htonl (pos->wid); - wvm.reserved = htonl (0); - wvm.value = GNUNET_htonll (se->value); - GNUNET_SERVER_notification_context_unicast (nc, pos->client, &wvm.header, - GNUNET_NO); - pos->last_value = se->value; + if (pos->last_value == se->value) + continue; } - pos = pos->next; + 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)); + wvm.flags = htonl (se->persistent ? GNUNET_STATISTICS_PERSIST_BIT : 0); + wvm.wid = htonl (pos->wid); + wvm.reserved = htonl (0); + wvm.value = GNUNET_htonll (se->value); + GNUNET_SERVER_notification_context_unicast (nc, pos->client, &wvm.header, + GNUNET_NO); + pos->last_value = se->value; } } @@ -435,9 +519,11 @@ handle_set (void *cls, struct GNUNET_SERVER_Client *client, uint64_t value; int64_t delta; int changed; + int initial_set; - if (client != NULL) - make_client_entry (client); + if ( (NULL != client) && + (NULL == make_client_entry (client)) ) + return; /* new client during shutdown */ msize = ntohs (message->size); if (msize < sizeof (struct GNUNET_STATISTICS_SetMessage)) { @@ -458,17 +544,16 @@ handle_set (void *cls, struct GNUNET_SERVER_Client *client, } flags = ntohl (msg->flags); value = GNUNET_ntohll (msg->value); -#if DEBUG_STATISTICS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received request to update statistic on `%s:%s' (%u) to/by %llu\n", service, name, (unsigned int) flags, (unsigned long long) value); -#endif pos = start; prev = NULL; while (pos != NULL) { if (matches (pos, service, name)) { + initial_set = 0; if ((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0) { changed = (pos->value != value); @@ -489,6 +574,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)); @@ -499,12 +589,10 @@ handle_set (void *cls, struct GNUNET_SERVER_Client *client, pos->next = start; start = pos; } -#if DEBUG_STATISTICS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Statistic `%s:%s' updated to value %llu.\n", service, name, pos->value); -#endif - if (changed) + if ((changed) || (1 == initial_set)) notify_change (pos); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; @@ -516,7 +604,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]; @@ -525,11 +620,9 @@ handle_set (void *cls, struct GNUNET_SERVER_Client *client, pos->name = &pos->service[strlen (pos->service) + 1]; start = pos; -#if DEBUG_STATISTICS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New statistic on `%s:%s' with value %llu created.\n", service, name, pos->value); -#endif GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -554,6 +647,12 @@ handle_watch (void *cls, struct GNUNET_SERVER_Client *client, struct WatchEntry *we; size_t slen; + if (NULL == nc) + { + 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)) @@ -571,11 +670,9 @@ handle_watch (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } -#if DEBUG_STATISTICS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received request to watch statistic on `%s:%s'\n", service, name); -#endif pos = start; while (pos != NULL) { @@ -590,6 +687,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); @@ -600,9 +698,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->client = client; + we->last_value_set = GNUNET_NO; GNUNET_SERVER_client_keep (client); we->wid = ce->max_wid++; GNUNET_CONTAINER_DLL_insert (pos->we_head, pos->we_tail, we); @@ -613,27 +715,20 @@ handle_watch (void *cls, struct GNUNET_SERVER_Client *client, /** - * Task run during shutdown. - * - * @param cls unused - * @param tc unused + * Actually perform the shutdown. */ -static void -shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +static void +do_shutdown () { - struct ClientEntry *ce; struct WatchEntry *we; struct StatsEntry *se; + if (NULL == nc) + return; save (); GNUNET_SERVER_notification_context_destroy (nc); - nc = NULL; - while (NULL != (ce = client_head)) - { - GNUNET_SERVER_client_drop (ce->client); - GNUNET_CONTAINER_DLL_remove (client_head, client_tail, ce); - GNUNET_free (ce); - } + nc = NULL; + GNUNET_assert (NULL == client_head); while (NULL != (se = start)) { start = se->next; @@ -649,6 +744,22 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** + * Task run during shutdown. + * + * @param cls unused + * @param tc unused + */ +static void +shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + in_shutdown = GNUNET_YES; + if (NULL != client_head) + return; + do_shutdown (); +} + + +/** * A client disconnected. Remove all of its data structure entries. * * @param cls closure, NULL @@ -689,6 +800,9 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) } se = se->next; } + if ( (NULL == client_head) && + (GNUNET_YES == in_shutdown) ) + do_shutdown (); } @@ -710,6 +824,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, {NULL, NULL, 0, 0} }; cfg = c; + srv = server; GNUNET_SERVER_add_handlers (server, handlers); nc = GNUNET_SERVER_notification_context_create (server, 16); GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); @@ -731,7 +846,7 @@ 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; } /* end of gnunet-service-statistics.c */ diff --git a/src/statistics/gnunet-statistics.c b/src/statistics/gnunet-statistics.c index ce91572..3eef887 100644 --- a/src/statistics/gnunet-statistics.c +++ b/src/statistics/gnunet-statistics.c @@ -27,6 +27,7 @@ #include "platform.h" #include "gnunet_getopt_lib.h" #include "gnunet_program_lib.h" +#include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "statistics.h" @@ -53,10 +54,16 @@ static char *name; static int persistent; /** + * Watch value continuously + */ +static int watch; + +/** * Quiet mode */ static int quiet; + /** * Callback function to process statistic values. * @@ -71,9 +78,26 @@ static int printer (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { + struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get(); + char * now_str; if (quiet == GNUNET_NO) - FPRINTF (stdout, "%s%-12s %-50s: %16llu\n", is_persistent ? "!" : " ", - subsystem, _(name), (unsigned long long) value); + { + if (GNUNET_YES == watch) + { + now_str = GNUNET_STRINGS_absolute_time_to_string(now); + FPRINTF (stdout, "%24s %s%12s %50s: %16llu \n", + now_str, + is_persistent ? "!" : " ", + subsystem, _(name), (unsigned long long) value); + GNUNET_free (now_str); + } + else + { + FPRINTF (stdout, "%s%12s %50s: %16llu \n", + is_persistent ? "!" : " ", + subsystem, _(name), (unsigned long long) value); + } + } else FPRINTF (stdout, "%llu\n", (unsigned long long) value); @@ -98,8 +122,25 @@ cleanup (void *cls, int success) FPRINTF (stderr, "%s", _("Failed to obtain statistics.\n")); ret = 1; } - if (h != NULL) + if (NULL != h) + { + GNUNET_STATISTICS_destroy (h, GNUNET_NO); + h = NULL; + } +} + + +static void +shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_STATISTICS_Handle *h = cls; + + GNUNET_STATISTICS_watch_cancel (h, subsystem, name, &printer, h); + if (NULL != h) + { GNUNET_STATISTICS_destroy (h, GNUNET_NO); + h = NULL; + } } @@ -128,25 +169,47 @@ run (void *cls, char *const *args, const char *cfgfile, return; } h = GNUNET_STATISTICS_create (subsystem, cfg); - if (h == NULL) + if (NULL == h) { ret = 1; return; } GNUNET_STATISTICS_set (h, name, (uint64_t) val, persistent); GNUNET_STATISTICS_destroy (h, GNUNET_YES); + h = NULL; return; } h = GNUNET_STATISTICS_create ("gnunet-statistics", cfg); - if (h == NULL) + if (NULL == h) { ret = 1; return; } - if (NULL == + if (GNUNET_NO == watch) + { + if (NULL == GNUNET_STATISTICS_get (h, subsystem, name, GET_TIMEOUT, &cleanup, &printer, h)) cleanup (h, GNUNET_SYSERR); + } + else + { + if ((NULL == subsystem) || (NULL == name)) + { + printf (_("No subsystem or name given\n")); + if (h != NULL) + GNUNET_STATISTICS_destroy (h, GNUNET_NO); + ret = 1; + return; + } + if (GNUNET_OK != GNUNET_STATISTICS_watch (h, subsystem, name, &printer, h)) + { + fprintf (stderr, _("Failed to initialize watch routine\n")); + GNUNET_SCHEDULER_add_now (&shutdown_task, h); + return; + } + GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, h); + } } /** @@ -172,6 +235,9 @@ main (int argc, char *const *argv) {'q', "quiet", NULL, gettext_noop ("just print the statistics value"), 0, &GNUNET_GETOPT_set_one, &quiet}, + {'w', "watch", NULL, + gettext_noop ("watch value continously"), 0, + &GNUNET_GETOPT_set_one, &watch}, GNUNET_GETOPT_OPTION_END }; return (GNUNET_OK == diff --git a/src/statistics/statistics.conf.in b/src/statistics/statistics.conf.in index 4482b0f..5de9ded 100644 --- a/src/statistics/statistics.conf.in +++ b/src/statistics/statistics.conf.in @@ -1,6 +1,6 @@ [statistics] AUTOSTART = YES -@UNIXONLY@ PORT = 2088 +@JAVAPORT@PORT = 2088 HOSTNAME = localhost HOME = $SERVICEHOME CONFIG = $DEFAULTCONFIG diff --git a/src/statistics/statistics.h b/src/statistics/statistics.h index 3fcac27..d5f662c 100644 --- a/src/statistics/statistics.h +++ b/src/statistics/statistics.h @@ -27,7 +27,6 @@ #include "gnunet_common.h" -#define DEBUG_STATISTICS GNUNET_EXTRA_LOGGING GNUNET_NETWORK_STRUCT_BEGIN diff --git a/src/statistics/statistics_api.c b/src/statistics/statistics_api.c index 2838b70..e1b3698 100644 --- a/src/statistics/statistics_api.c +++ b/src/statistics/statistics_api.c @@ -280,7 +280,9 @@ schedule_watch_request (struct GNUNET_STATISTICS_Handle *h, size_t nlen; size_t nsize; - GNUNET_assert (h != NULL); + GNUNET_assert (NULL != h); + GNUNET_assert (NULL != watch); + slen = strlen (watch->subsystem) + 1; nlen = strlen (watch->name) + 1; nsize = sizeof (struct GNUNET_MessageHeader) + slen + nlen; @@ -335,14 +337,14 @@ do_disconnect (struct GNUNET_STATISTICS_Handle *h) } if (NULL != h->client) { - GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } h->receiving = GNUNET_NO; if (NULL != (c = h->current)) { h->current = NULL; - if (c->cont != NULL) + if (NULL != c->cont) c->cont (c->cls, GNUNET_SYSERR); free_action_item (c); } @@ -362,12 +364,12 @@ try_connect (struct GNUNET_STATISTICS_Handle *h) struct GNUNET_STATISTICS_GetHandle *gn; unsigned int i; - if (h->backoff_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != h->backoff_task) return GNUNET_NO; - if (h->client != NULL) + if (NULL != h->client) return GNUNET_YES; h->client = GNUNET_CLIENT_connect ("statistics", h->cfg); - if (h->client != NULL) + if (NULL != h->client) { gn = h->action_head; while (NULL != (gh = gn)) @@ -382,13 +384,14 @@ try_connect (struct GNUNET_STATISTICS_Handle *h) } } for (i = 0; i < h->watches_size; i++) - schedule_watch_request (h, h->watches[i]); + { + if (NULL != h->watches[i]) + schedule_watch_request (h, h->watches[i]); + } return GNUNET_YES; } -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG, - _("Failed to connect to statistics service!\n")); -#endif + "Failed to connect to statistics service!\n"); return GNUNET_NO; } @@ -410,6 +413,22 @@ reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** + * Task used by 'reconnect_later' to shutdown the handle + * + * @param cls the statistics handle + * @param tc scheduler context + */ +static void +do_destroy (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_STATISTICS_Handle *h = cls; + + GNUNET_STATISTICS_destroy (h, GNUNET_NO); +} + + +/** * Reconnect at a later time, respecting back-off. * * @param h statistics handle @@ -417,7 +436,29 @@ reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void reconnect_later (struct GNUNET_STATISTICS_Handle *h) { + int loss; + struct GNUNET_STATISTICS_GetHandle *gh; + GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->backoff_task); + if (GNUNET_YES == h->do_destroy) + { + /* So we are shutting down and the service is not reachable. + * Chances are that it's down for good and we are not going to connect to + * it anymore. + * Give up and don't sync the rest of the data. + */ + loss = GNUNET_NO; + for (gh = h->action_head; NULL != gh; gh = gh->next) + 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_continuation (&do_destroy, h, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + return; + } h->backoff_task = GNUNET_SCHEDULER_add_delayed (h->backoff, &reconnect_task, h); h->backoff = GNUNET_TIME_relative_multiply (h->backoff, 2); @@ -444,9 +485,7 @@ process_statistics_value_message (struct GNUNET_STATISTICS_Handle *h, if (h->current->aborted) { -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG, "Iteration was aborted, ignoring VALUE\n"); -#endif return GNUNET_OK; /* don't bother */ } size = ntohs (msg->size); @@ -464,25 +503,19 @@ process_statistics_value_message (struct GNUNET_STATISTICS_Handle *h, GNUNET_break (0); return GNUNET_SYSERR; } -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG, "Received valid statistic on `%s:%s': %llu\n", service, name, GNUNET_ntohll (smsg->value)); -#endif if (GNUNET_OK != h->current->proc (h->current->cls, service, name, GNUNET_ntohll (smsg->value), 0 != (ntohl (smsg->uid) & GNUNET_STATISTICS_PERSIST_BIT))) { -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing of remaining statistics aborted by client.\n"); -#endif h->current->aborted = GNUNET_YES; } -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG, "VALUE processed successfully\n"); -#endif return GNUNET_OK; } @@ -526,6 +559,16 @@ process_watch_value (struct GNUNET_STATISTICS_Handle *h, } +static void +destroy_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_STATISTICS_Handle *h = cls; + + GNUNET_STATISTICS_destroy (h, GNUNET_NO); +} + + /** * Function called with messages from stats service. * @@ -539,22 +582,31 @@ receive_stats (void *cls, const struct GNUNET_MessageHeader *msg) struct GNUNET_STATISTICS_GetHandle *c; int ret; - if (msg == NULL) + if (NULL == msg) { -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Error receiving statistics from service, is the service running?\n"); -#endif do_disconnect (h); reconnect_later (h); return; } switch (ntohs (msg->type)) { + case GNUNET_MESSAGE_TYPE_TEST: + if (GNUNET_SYSERR != h->do_destroy) + { + /* not in shutdown, why do we get 'TEST'? */ + GNUNET_break (0); + do_disconnect (h); + reconnect_later (h); + return; + } + h->do_destroy = GNUNET_NO; + GNUNET_SCHEDULER_add_continuation (&destroy_task, h, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + break; case GNUNET_MESSAGE_TYPE_STATISTICS_END: -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG, "Received end of statistics marker\n"); -#endif if (NULL == (c = h->current)) { GNUNET_break (0); @@ -574,7 +626,7 @@ receive_stats (void *cls, const struct GNUNET_MessageHeader *msg) } h->current = NULL; schedule_action (h); - if (c->cont != NULL) + if (NULL != c->cont) c->cont (c->cls, GNUNET_OK); free_action_item (c); return; @@ -586,10 +638,8 @@ receive_stats (void *cls, const struct GNUNET_MessageHeader *msg) return; } /* finally, look for more! */ -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing VALUE done, now reading more\n"); -#endif GNUNET_CLIENT_receive (h->client, &receive_stats, h, GNUNET_TIME_absolute_get_remaining (h-> current->timeout)); @@ -638,13 +688,11 @@ transmit_get (struct GNUNET_STATISTICS_Handle *handle, size_t size, void *buf) uint16_t msize; GNUNET_assert (NULL != (c = handle->current)); - if (buf == NULL) + if (NULL == buf) { /* timeout / error */ -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission of request for statistics failed!\n"); -#endif do_disconnect (handle); reconnect_later (handle); return 0; @@ -662,10 +710,8 @@ transmit_get (struct GNUNET_STATISTICS_Handle *handle, size_t size, void *buf) c->name)); if (GNUNET_YES != handle->receiving) { -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission of GET done, now reading response\n"); -#endif handle->receiving = GNUNET_YES; GNUNET_CLIENT_receive (handle->client, &receive_stats, handle, GNUNET_TIME_absolute_get_remaining (c->timeout)); @@ -691,21 +737,17 @@ transmit_watch (struct GNUNET_STATISTICS_Handle *handle, size_t size, void *buf) size_t slen2; uint16_t msize; - if (buf == NULL) + if (NULL == buf) { /* timeout / error */ -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission of request for statistics failed!\n"); -#endif do_disconnect (handle); reconnect_later (handle); return 0; } -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting watch request for `%s'\n", handle->current->name); -#endif slen1 = strlen (handle->current->subsystem) + 1; slen2 = strlen (handle->current->name) + 1; msize = slen1 + slen2 + sizeof (struct GNUNET_MessageHeader); @@ -833,8 +875,8 @@ GNUNET_STATISTICS_create (const char *subsystem, { struct GNUNET_STATISTICS_Handle *ret; - GNUNET_assert (subsystem != NULL); - GNUNET_assert (cfg != NULL); + GNUNET_assert (NULL != subsystem); + GNUNET_assert (NULL != cfg); ret = GNUNET_malloc (sizeof (struct GNUNET_STATISTICS_Handle)); ret->cfg = cfg; ret->subsystem = GNUNET_strdup (subsystem); @@ -859,8 +901,9 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, int sync_first) struct GNUNET_TIME_Relative timeout; int i; - if (h == NULL) + if (NULL == h) return; + GNUNET_assert (GNUNET_NO == h->do_destroy); // Don't call twice. if (GNUNET_SCHEDULER_NO_TASK != h->backoff_task) { GNUNET_SCHEDULER_cancel (h->backoff_task); @@ -868,9 +911,9 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, int sync_first) } if (sync_first) { - if (h->current != NULL) + if (NULL != h->current) { - if (h->current->type == ACTION_GET) + if (ACTION_GET == h->current->type) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; @@ -882,7 +925,7 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, int sync_first) while (NULL != (pos = next)) { next = pos->next; - if (pos->type == ACTION_GET) + if (ACTION_GET == pos->type) { GNUNET_CONTAINER_DLL_remove (h->action_head, h->action_tail, @@ -896,24 +939,17 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, int sync_first) h->action_tail, h->current); h->do_destroy = GNUNET_YES; - if ((h->current != NULL) && (h->th == NULL)) + if ((NULL != h->current) && (NULL == h->th) && + (NULL != h->client)) { - if (NULL == h->client) - { - /* instant-connect (regardless of back-off) to submit final value */ - h->client = GNUNET_CLIENT_connect ("statistics", h->cfg); - } - if (NULL != h->client) - { - 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); - } + 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); } - if (h->th != NULL) + if (NULL != h->th) return; /* do not finish destruction just yet */ } while (NULL != (pos = h->action_head)) @@ -939,6 +975,47 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, int sync_first) /** + * Function called to transmit TEST message to service to + * confirm that the service has received all of our 'SET' + * messages (during statistics disconnect/shutdown). + * + * @param cls the 'struct GNUNET_STATISTICS_Handle' + * @param size how many bytes can we write to buf + * @param buf where to write requests to the service + * @return number of bytes written to buf + */ +static size_t +transmit_test_on_shutdown (void *cls, + size_t size, + void *buf) +{ + struct GNUNET_STATISTICS_Handle *h = cls; + struct GNUNET_MessageHeader hdr; + + h->th = NULL; + if (NULL == buf) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Failed to receive acknowledgement from statistics service, some statistics might have been lost!\n")); + h->do_destroy = GNUNET_NO; + GNUNET_SCHEDULER_add_continuation (&destroy_task, h, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + return 0; + } + hdr.type = htons (GNUNET_MESSAGE_TYPE_TEST); + hdr.size = htons (sizeof (struct GNUNET_MessageHeader)); + memcpy (buf, &hdr, sizeof (hdr)); + if (GNUNET_YES != h->receiving) + { + h->receiving = GNUNET_YES; + GNUNET_CLIENT_receive (h->client, &receive_stats, h, + GNUNET_TIME_UNIT_FOREVER_REL); + } + return sizeof (struct GNUNET_MessageHeader); +} + + +/** * Schedule the next action to be performed. * * @param h statistics handle @@ -948,8 +1025,8 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h) { struct GNUNET_TIME_Relative timeout; - if ( (h->th != NULL) || - (h->backoff_task != GNUNET_SCHEDULER_NO_TASK) ) + if ( (NULL != h->th) || + (GNUNET_SCHEDULER_NO_TASK != h->backoff_task) ) return; /* action already pending */ if (GNUNET_YES != try_connect (h)) { @@ -962,10 +1039,14 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h) h->current = h->action_head; if (NULL == h->current) { - if (h->do_destroy) + if (GNUNET_YES == h->do_destroy) { - h->do_destroy = GNUNET_NO; - GNUNET_STATISTICS_destroy (h, GNUNET_YES); + h->do_destroy = GNUNET_SYSERR; /* in 'TEST' mode */ + h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, + sizeof (struct GNUNET_MessageHeader), + SET_TRANSMIT_TIMEOUT, + GNUNET_NO, + &transmit_test_on_shutdown, h); } return; } @@ -977,10 +1058,8 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h) timeout, GNUNET_YES, &transmit_action, h))) { -#if DEBUG_STATISTICS LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit request to statistics service.\n"); -#endif do_disconnect (h); reconnect_later (h); } @@ -996,6 +1075,7 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h) * @param timeout after how long should we give up (and call * cont with an error code)? * @param cont continuation to call when done (can be NULL) + * This callback CANNOT destroy the statistics handle in the same call. * @param proc function to call on each value * @param cls closure for cont and proc * @return NULL on error @@ -1013,11 +1093,11 @@ GNUNET_STATISTICS_get (struct GNUNET_STATISTICS_Handle *handle, if (NULL == handle) return NULL; - GNUNET_assert (proc != NULL); + GNUNET_assert (NULL != proc); GNUNET_assert (GNUNET_NO == handle->do_destroy); - if (subsystem == NULL) + if (NULL == subsystem) subsystem = ""; - if (name == NULL) + if (NULL == name) name = ""; slen1 = strlen (subsystem) + 1; slen2 = strlen (name) + 1; @@ -1082,7 +1162,7 @@ GNUNET_STATISTICS_watch (struct GNUNET_STATISTICS_Handle *handle, { struct GNUNET_STATISTICS_WatchEntry *w; - if (handle == NULL) + if (NULL == handle) return GNUNET_SYSERR; w = GNUNET_malloc (sizeof (struct GNUNET_STATISTICS_WatchEntry)); w->subsystem = GNUNET_strdup (subsystem); @@ -1113,11 +1193,13 @@ GNUNET_STATISTICS_watch_cancel (struct GNUNET_STATISTICS_Handle *handle, struct GNUNET_STATISTICS_WatchEntry *w; unsigned int i; - if (handle == NULL) + if (NULL == handle) return GNUNET_SYSERR; for (i=0;i<handle->watches_size;i++) { w = handle->watches[i]; + if (NULL == w) + continue; if ( (w->proc == proc) && (w->proc_cls == proc_cls) && (0 == strcmp (w->name, name)) && @@ -1154,8 +1236,8 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h, const char *name, size_t nsize; int64_t delta; - GNUNET_assert (h != NULL); - GNUNET_assert (name != NULL); + GNUNET_assert (NULL != h); + GNUNET_assert (NULL != name); slen = strlen (h->subsystem) + 1; nlen = strlen (name) + 1; nsize = sizeof (struct GNUNET_STATISTICS_SetMessage) + slen + nlen; @@ -1164,16 +1246,16 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h, const char *name, GNUNET_break (0); return; } - for (ai = h->action_head; ai != NULL; ai = ai->next) + for (ai = h->action_head; NULL != ai; ai = ai->next) { if (! ( (0 == strcmp (ai->subsystem, h->subsystem)) && (0 == strcmp (ai->name, name)) && - ( (ai->type == ACTION_UPDATE) || - (ai->type == ACTION_SET) ) ) ) + ( (ACTION_UPDATE == ai->type) || + (ACTION_SET == ai->type) ) ) ) continue; - if (ai->type == ACTION_SET) + if (ACTION_SET == ai->type) { - if (type == ACTION_UPDATE) + if (ACTION_UPDATE == type) { delta = (int64_t) value; if (delta > 0) @@ -1198,7 +1280,7 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h, const char *name, } else { - if (type == ACTION_UPDATE) + if (ACTION_UPDATE == type) { /* make delta cummulative */ delta = (int64_t) value; @@ -1244,7 +1326,7 @@ void GNUNET_STATISTICS_set (struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent) { - if (handle == NULL) + if (NULL == handle) return; GNUNET_assert (GNUNET_NO == handle->do_destroy); add_setter_action (handle, name, make_persistent, value, ACTION_SET); @@ -1264,9 +1346,9 @@ void GNUNET_STATISTICS_update (struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent) { - if (handle == NULL) + if (NULL == handle) return; - if (delta == 0) + if (0 == delta) return; GNUNET_assert (GNUNET_NO == handle->do_destroy); add_setter_action (handle, name, make_persistent, (uint64_t) delta, diff --git a/src/statistics/test_statistics_api.c b/src/statistics/test_statistics_api.c index 0647a49..11f02b8 100644 --- a/src/statistics/test_statistics_api.c +++ b/src/statistics/test_statistics_api.c @@ -29,7 +29,6 @@ #include "gnunet_scheduler_lib.h" #include "gnunet_statistics_service.h" -#define DEBUG_STATISTICS GNUNET_EXTRA_LOGGING #define START_SERVICE GNUNET_YES @@ -130,11 +129,7 @@ check () char *const argv[] = { "test-statistics-api", "-c", "test_statistics_api_data.conf", -#if DEBUG_STATISTICS - "-L", "DEBUG", -#else "-L", "WARNING", -#endif NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { @@ -146,9 +141,6 @@ check () proc = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-statistics", "gnunet-service-statistics", -#if DEBUG_STATISTICS - "-L", "DEBUG", -#endif "-c", "test_statistics_api_data.conf", NULL); #endif GNUNET_assert (NULL != proc); @@ -161,7 +153,7 @@ check () ok = 1; } GNUNET_OS_process_wait (proc); - GNUNET_OS_process_close (proc); + GNUNET_OS_process_destroy (proc); proc = NULL; #endif if (ok != 0) @@ -172,9 +164,6 @@ check () proc = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-statistics", "gnunet-service-statistics", -#if DEBUG_STATISTICS - "-L", "DEBUG", -#endif "-c", "test_statistics_api_data.conf", NULL); #endif GNUNET_PROGRAM_run (5, argv, "test-statistics-api", "nohelp", options, @@ -186,7 +175,7 @@ check () ok = 1; } GNUNET_OS_process_wait (proc); - GNUNET_OS_process_close (proc); + GNUNET_OS_process_destroy (proc); proc = NULL; #endif return ok; @@ -198,11 +187,7 @@ main (int argc, char *argv[]) int ret; GNUNET_log_setup ("test_statistics_api", -#if DEBUG_STATISTICS - "DEBUG", -#else "WARNING", -#endif NULL); ret = check (); diff --git a/src/statistics/test_statistics_api_data.conf b/src/statistics/test_statistics_api_data.conf index 9ccb770..4e229e9 100644 --- a/src/statistics/test_statistics_api_data.conf +++ b/src/statistics/test_statistics_api_data.conf @@ -31,13 +31,24 @@ AUTOSTART = NO [peerinfo] AUTOSTART = NO - [dns] AUTOSTART = NO +[nse] +AUTOSTART = NO +[lockmanager] +AUTOSTART = NO -[nse] +[ats] AUTOSTART = NO +[namestore] +AUTOSTART = NO + +[gns] +AUTOSTART = NO + +[vpn] +AUTOSTART = NO diff --git a/src/statistics/test_statistics_api_loop.c b/src/statistics/test_statistics_api_loop.c index 32b176c..58114f2 100644 --- a/src/statistics/test_statistics_api_loop.c +++ b/src/statistics/test_statistics_api_loop.c @@ -114,7 +114,7 @@ check () ok = 1; } GNUNET_OS_process_wait (proc); - GNUNET_OS_process_close (proc); + GNUNET_OS_process_destroy (proc); proc = NULL; #endif return ok; diff --git a/src/statistics/test_statistics_api_watch.c b/src/statistics/test_statistics_api_watch.c index 979b561..e976bd4 100644 --- a/src/statistics/test_statistics_api_watch.c +++ b/src/statistics/test_statistics_api_watch.c @@ -145,7 +145,7 @@ check () ok = 1; } GNUNET_OS_process_wait (proc); - GNUNET_OS_process_close (proc); + GNUNET_OS_process_destroy (proc); proc = NULL; #endif return ok; diff --git a/src/statistics/test_statistics_api_watch_zero_value.c b/src/statistics/test_statistics_api_watch_zero_value.c new file mode 100644 index 0000000..9fadf6a --- /dev/null +++ b/src/statistics/test_statistics_api_watch_zero_value.c @@ -0,0 +1,201 @@ +/* + This file is part of GNUnet. + (C) 2009, 2011 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file statistics/test_statistics_api_watch_zero_value.c + * @brief testcase for statistics_api.c watch functions with initial 0 value + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_getopt_lib.h" +#include "gnunet_os_lib.h" +#include "gnunet_program_lib.h" +#include "gnunet_scheduler_lib.h" +#include "gnunet_statistics_service.h" + +#define VERBOSE GNUNET_NO + +#define START_SERVICE GNUNET_YES + +static int ok; +static int ok2; + +static struct GNUNET_STATISTICS_Handle *h; +static struct GNUNET_STATISTICS_Handle *h2; + +static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; + + +static void +force_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + fprintf (stderr, "Timeout, failed to receive notifications: %d\n", ok); + GNUNET_STATISTICS_destroy (h, GNUNET_NO); + GNUNET_STATISTICS_destroy (h2, GNUNET_NO); + ok = 7; +} + + +static void +normal_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_STATISTICS_destroy (h, GNUNET_NO); + GNUNET_STATISTICS_destroy (h2, GNUNET_NO); +} + + +static int +watch_1 (void *cls, const char *subsystem, const char *name, uint64_t value, + int is_persistent) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received value `%s' `%s' %llu\n", + subsystem, name, value); + GNUNET_assert (0 == strcmp (name, "test-1")); + if ((0 == value) && (3 == ok)) + { + ok--; + GNUNET_STATISTICS_set (h, "test-1", 42, GNUNET_NO); + } + + if ((42 == value) && (2 == ok)) + { + ok--; + GNUNET_STATISTICS_set (h, "test-1", 0, GNUNET_NO); + } + + if ((0 == value) && (1 == ok)) + { + ok--; + } + if ((0 == ok) && (0 == ok2)) + { + GNUNET_SCHEDULER_cancel (shutdown_task); + GNUNET_SCHEDULER_add_now (&normal_shutdown, NULL); + } + + return GNUNET_OK; +} + +static int +watch_2 (void *cls, const char *subsystem, const char *name, uint64_t value, + int is_persistent) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received value `%s' `%s' %llu\n", + subsystem, name, value); + + GNUNET_assert (0 == strcmp (name, "test-2")); + if ((42 == value) && (1 == ok2)) + { + ok2 = 0; + if (0 == ok) + { + GNUNET_SCHEDULER_cancel (shutdown_task); + GNUNET_SCHEDULER_add_now (&normal_shutdown, NULL); + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received unexpected value %llu\n", value); + + GNUNET_break (0); + GNUNET_SCHEDULER_cancel (shutdown_task); + GNUNET_SCHEDULER_add_now (&normal_shutdown, NULL); + } + + return GNUNET_OK; +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + h = GNUNET_STATISTICS_create ("dummy", cfg); + h2 = GNUNET_STATISTICS_create ("dummy-2", cfg); + GNUNET_assert (GNUNET_OK == + GNUNET_STATISTICS_watch (h, "dummy", + "test-1", &watch_1, NULL)); + + GNUNET_assert (GNUNET_OK == + GNUNET_STATISTICS_watch (h2, "dummy-2", + "test-2", &watch_2, NULL)); + + /* Set initial value to 0 */ + GNUNET_STATISTICS_set (h, "test-1", 0, GNUNET_NO); + GNUNET_STATISTICS_set (h2, "test-2", 42, GNUNET_NO); + + shutdown_task = + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &force_shutdown, + NULL); +} + + +static int +check () +{ + char *const argv[] = { "test-statistics-api", + "-c", + "test_statistics_api_data.conf", + NULL + }; + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; +#if START_SERVICE + struct GNUNET_OS_Process *proc; + + proc = + GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-statistics", + "gnunet-service-statistics", +#if VERBOSE + "-L", "DEBUG", +#endif + "-c", "test_statistics_api_data.conf", NULL); +#endif + GNUNET_assert (NULL != proc); + ok = 3; + ok2 = 1; + GNUNET_PROGRAM_run (3, argv, "test-statistics-api", "nohelp", options, &run, + NULL); +#if START_SERVICE + if (0 != GNUNET_OS_process_kill (proc, SIGTERM)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + ok = 1; + } + GNUNET_OS_process_wait (proc); + GNUNET_OS_process_destroy (proc); + proc = NULL; +#endif + if ((0 == ok) && (0 == ok2)) + return 0; + else + return 1; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + + return ret; +} + +/* end of test_statistics_api_watch_zero_value.c */ |