- switch (ntohs (msg->type))
- {
- case GNUNET_MESSAGE_TYPE_STATISTICS_END:
-#if DEBUG_STATISTICS
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received end of statistics marker\n");
-#endif
- h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
- if (h->watches_size > 0)
- {
- GNUNET_CLIENT_receive (h->client,
- &receive_stats,
- h,
- GNUNET_TIME_UNIT_FOREVER_REL);
- }
- else
- {
- h->receiving = GNUNET_NO;
- }
- finish (h, GNUNET_OK);
- return;
- case GNUNET_MESSAGE_TYPE_STATISTICS_VALUE:
- if (GNUNET_OK == process_message (h, msg))
- {
- /* finally, look for more! */
-#if DEBUG_STATISTICS
- GNUNET_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));
- h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
- return;
- }
- GNUNET_break (0);
- break;
- case GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE:
- if (GNUNET_OK ==
- process_watch_value (h,
- msg))
- {
- h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
- GNUNET_assert (h->watches_size > 0);
- GNUNET_CLIENT_receive (h->client,
- &receive_stats,
- h,
- GNUNET_TIME_UNIT_FOREVER_REL);
- return;
- }
- GNUNET_break (0);
- break;
- default:
- GNUNET_break (0);
- break;
- }
- if (NULL != h->client)
+ GNUNET_STATISTICS_destroy (h,
+ GNUNET_NO);
+ return;
+ }
+ do_disconnect (h);
+ reconnect_later (h);
+}
+
+
+/**
+ * Task used to destroy the statistics handle.
+ *
+ * @param cls the `struct GNUNET_STATISTICS_Handle`
+ */
+static void
+do_destroy (void *cls)
+{
+ struct GNUNET_STATISTICS_Handle *h = cls;
+
+ h->destroy_task = NULL;
+ h->do_destroy = GNUNET_NO;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Running final destruction\n");
+ GNUNET_STATISTICS_destroy (h,
+ GNUNET_NO);
+}
+
+
+/**
+ * Handle a #GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM
+ * message. We receive this message at the end of the shutdown when
+ * the service confirms that all data has been written to disk.
+ *
+ * @param cls our `struct GNUNET_STATISTICS_Handle *`
+ * @param msg the message
+ */
+static void
+handle_disconnect_confirm (void *cls,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_STATISTICS_Handle *h = cls;
+
+ if (GNUNET_SYSERR != h->do_destroy)
+ {
+ /* not in shutdown, why do we get 'TEST'? */
+ GNUNET_break (0);
+ do_disconnect (h);
+ reconnect_later (h);
+ return;
+ }
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received DISCONNNECT_CONFIRM message from statistics, can complete disconnect\n");
+ if (NULL != h->destroy_task)
+ GNUNET_SCHEDULER_cancel (h->destroy_task);
+ h->destroy_task = GNUNET_SCHEDULER_add_now (&do_destroy,
+ h);
+}
+
+
+/**
+ * Handle a #GNUNET_MESSAGE_TYPE_STATISTICS_END message. We receive
+ * this message in response to a query to indicate that there are no
+ * further matching results.
+ *
+ * @param cls our `struct GNUNET_STATISTICS_Handle *`
+ * @param msg the message
+ */
+static void
+handle_statistics_end (void *cls,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_STATISTICS_Handle *h = cls;
+ struct GNUNET_STATISTICS_GetHandle *c;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received end of statistics marker\n");
+ if (NULL == (c = h->current))
+ {
+ GNUNET_break (0);
+ do_disconnect (h);
+ reconnect_later (h);
+ return;
+ }
+ h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
+ h->current = NULL;
+ schedule_action (h);
+ if (NULL != c->cont)
+ {
+ c->cont (c->cls,
+ GNUNET_OK);
+ c->cont = NULL;
+ }
+ free_action_item (c);
+}
+
+
+/**
+ * Try to (re)connect to the statistics service.
+ *
+ * @param h statistics handle to reconnect
+ * @return #GNUNET_YES on success, #GNUNET_NO on failure.
+ */
+static int
+try_connect (struct GNUNET_STATISTICS_Handle *h)
+{
+ struct GNUNET_MQ_MessageHandler handlers[] = {
+ GNUNET_MQ_hd_fixed_size (disconnect_confirm,
+ GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM,
+ struct GNUNET_MessageHeader,
+ h),
+ GNUNET_MQ_hd_fixed_size (statistics_end,
+ GNUNET_MESSAGE_TYPE_STATISTICS_END,
+ struct GNUNET_MessageHeader,
+ h),
+ GNUNET_MQ_hd_var_size (statistics_value,
+ GNUNET_MESSAGE_TYPE_STATISTICS_VALUE,
+ struct GNUNET_STATISTICS_ReplyMessage,
+ h),
+ GNUNET_MQ_hd_fixed_size (statistics_watch_value,
+ GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE,
+ struct GNUNET_STATISTICS_WatchValueMessage,
+ h),
+ GNUNET_MQ_handler_end ()
+ };
+ struct GNUNET_STATISTICS_GetHandle *gh;
+ struct GNUNET_STATISTICS_GetHandle *gn;
+
+ if (NULL != h->backoff_task)
+ return GNUNET_NO;
+ if (NULL != h->mq)
+ return GNUNET_YES;
+ h->mq = GNUNET_CLIENT_connect (h->cfg,
+ "statistics",
+ handlers,
+ &mq_error_handler,
+ h);
+ if (NULL == h->mq)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Failed to connect to statistics service!\n");
+ return GNUNET_NO;
+ }
+ gn = h->action_head;
+ while (NULL != (gh = gn))
+ {
+ gn = gh->next;
+ if (gh->type == ACTION_WATCH)