aboutsummaryrefslogtreecommitdiff
path: root/src/statistics
diff options
context:
space:
mode:
Diffstat (limited to 'src/statistics')
-rw-r--r--src/statistics/Makefile.am11
-rw-r--r--src/statistics/Makefile.in31
-rw-r--r--src/statistics/gnunet-service-statistics.c233
-rw-r--r--src/statistics/gnunet-statistics.c78
-rw-r--r--src/statistics/statistics.conf.in2
-rw-r--r--src/statistics/statistics.h1
-rw-r--r--src/statistics/statistics_api.c244
-rw-r--r--src/statistics/test_statistics_api.c19
-rw-r--r--src/statistics/test_statistics_api_data.conf15
-rw-r--r--src/statistics/test_statistics_api_loop.c2
-rw-r--r--src/statistics/test_statistics_api_watch.c2
-rw-r--r--src/statistics/test_statistics_api_watch_zero_value.c201
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 */