+
+/**
+ * Callback for informing us about a successful
+ * or unsuccessful churn start call.
+ *
+ * @param cls a ChurnContext
+ * @param id the peer identity of the started peer
+ * @param cfg the handle to the configuration of the peer
+ * @param d handle to the daemon for the peer
+ * @param emsg NULL on success, non-NULL on failure
+ *
+ */
+void
+churn_start_callback (void *cls,
+ const struct GNUNET_PeerIdentity *id,
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ struct GNUNET_TESTING_Daemon *d,
+ const char *emsg)
+{
+ struct ChurnRestartContext *startup_ctx = cls;
+ struct ChurnContext *churn_ctx = startup_ctx->churn_ctx;
+
+ unsigned int total_left;
+ char *error_message;
+
+ error_message = NULL;
+ if (emsg != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Churn stop callback failed with error `%s'\n",
+ emsg);
+ churn_ctx->num_failed_start++;
+ }
+ else
+ {
+ churn_ctx->num_to_start--;
+ }
+
+#if DEBUG_CHURN
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
+ "Started peer, %d left.\n",
+ churn_ctx->num_to_start);
+#endif
+
+ total_left = (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) + (churn_ctx->num_to_start - churn_ctx->num_failed_start);
+
+ if (total_left == 0)
+ {
+ if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0))
+ GNUNET_asprintf(&error_message,
+ "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!",
+ churn_ctx->num_failed_start,
+ churn_ctx->num_failed_stop);
+ churn_ctx->cb(churn_ctx->cb_cls, error_message);
+ GNUNET_free_non_null(error_message);
+ GNUNET_free(churn_ctx);
+ GNUNET_free(startup_ctx);
+ }
+}
+
+
+static void schedule_churn_restart(void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
+{
+ struct PeerRestartContext *peer_restart_ctx = cls;
+ struct ChurnRestartContext *startup_ctx = peer_restart_ctx->churn_restart_ctx;
+
+ if (startup_ctx->outstanding > MAX_CONCURRENT_STARTING)
+ GNUNET_SCHEDULER_add_delayed(peer_restart_ctx->daemon->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 100), &schedule_churn_restart, peer_restart_ctx);
+ else
+ {
+ GNUNET_TESTING_daemon_start_stopped(peer_restart_ctx->daemon,
+ startup_ctx->timeout,
+ &churn_start_callback,
+ startup_ctx);
+ GNUNET_free(peer_restart_ctx);
+ }
+}
+