From 7e669bcf6b6336ec429da949bcb4aa456971dba2 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 30 Jul 2021 10:38:27 +0200 Subject: folding history in preparation of GNU Anastasis v0.0.0 release --- src/cli/anastasis-cli-redux.c | 366 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 366 insertions(+) create mode 100644 src/cli/anastasis-cli-redux.c (limited to 'src/cli/anastasis-cli-redux.c') diff --git a/src/cli/anastasis-cli-redux.c b/src/cli/anastasis-cli-redux.c new file mode 100644 index 0000000..7b533c2 --- /dev/null +++ b/src/cli/anastasis-cli-redux.c @@ -0,0 +1,366 @@ +/* + This file is part of Anastasis + Copyright (C) 2020,2021 Taler Systems SA + + Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Lesser General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Anastasis 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 + Anastasis; see the file COPYING.GPL. If not, see +*/ +/** + * @file cli/anastasis-cli-redux.c + * @brief command line tool for our reducer + * @author Christian Grothoff + * @author Dennis Neufeld + * @author Dominik Meister + */ + +#include "platform.h" +#include +#include +#include "anastasis_redux.h" +#include +#include +#include +#include "anastasis_util_lib.h" + +/** + * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule(). + */ +static struct GNUNET_CURL_RescheduleContext *rc; + +/** + * Curl context for communication with anastasis backend + */ +static struct GNUNET_CURL_Context *ctx; + +/** + * -b option given. + */ +static int b_flag; + +/** + * -r option given. + */ +static int r_flag; + +/** + * Input to -a option given. + */ +static char *input; + +/** + * Output filename, if given. + */ +static char *output_filename; + +/** + * JSON containing previous state + */ +static json_t *prev_state; + +/** + * JSON containing arguments for action + */ +static json_t *arguments; + +/** + * Handle to an ongoing action. + */ +static struct ANASTASIS_ReduxAction *ra; + +/** + * Return value from main. + */ +static int global_ret; + + +/** + * Persist a json state, report errors. + * + * @param state to persist + * @param filename where to write the state to, NULL for stdout + */ +static void +persist_new_state (json_t *state, + const char *filename) +{ + if (NULL != filename) + { + if (0 != + json_dump_file (state, + filename, + JSON_COMPACT)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not dump state to `%s'\n", + filename); + return; + } + return; + } + { + char *state_str = json_dumps (state, + JSON_COMPACT); + if (-1 >= + fprintf (stdout, + "%s", + state_str)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not dump state to stdout\n"); + GNUNET_free (state_str); + return; + } + GNUNET_free (state_str); + } +} + + +/** + * Function called with the results of #ANASTASIS_backup_action + * or #ANASTASIS_recovery_action. + * + * @param cls closure + * @param error_code Error code + * @param new_state new state as result + */ +static void +action_cb (void *cls, + enum TALER_ErrorCode error_code, + json_t *result_state) +{ + (void) cls; + ra = NULL; + if (NULL != result_state) + persist_new_state (result_state, + output_filename); + if (TALER_EC_NONE != error_code) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Redux failed with error %d: %s\n", + error_code, + TALER_ErrorCode_get_hint (error_code)); + } + GNUNET_SCHEDULER_shutdown (); + global_ret = (TALER_EC_NONE != error_code) ? 1 : 0; +} + + +/** + * @brief Shutdown the application. + * + * @param cls closure + */ +static void +shutdown_task (void *cls) +{ + (void) cls; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Shutdown initiated\n"); + if (NULL != ra) + { + ANASTASIS_redux_action_cancel (ra); + ra = NULL; + } + ANASTASIS_redux_done (); + if (NULL != ctx) + { + GNUNET_CURL_fini (ctx); + ctx = NULL; + } + if (NULL != rc) + { + GNUNET_CURL_gnunet_rc_destroy (rc); + rc = NULL; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Shutdown complete\n"); +} + + +/** + * @brief Start the application + * + * @param cls closure + * @param args arguments left + * @param cfgfile config file name + * @param cfg handle for the configuration file + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + (void) cls; + json_error_t error; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Starting anastasis-reducer\n"); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + NULL); + if (b_flag && r_flag) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "We cannot start backup and recovery at the same time!\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (r_flag) + { + json_t *init_state; + + init_state = ANASTASIS_recovery_start (cfg); + if (NULL == init_state) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Failed to create an initial recovery state!\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + persist_new_state (init_state, + args[0]); + json_decref (init_state); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (b_flag) + { + json_t *init_state; + + init_state = ANASTASIS_backup_start (cfg); + if (NULL == init_state) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Failed to create an initial backup state!\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + persist_new_state (init_state, + args[0]); + json_decref (init_state); + GNUNET_SCHEDULER_shutdown (); + return; + } + + /* action processing */ + { + const char *action = args[0]; + + if (NULL == action) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "You must specify an action as the first argument (or `-b' or `-r')\n"); + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Example: anastasis-reducer back\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + args++; + if (NULL != input) + { + arguments = json_loads (input, + JSON_DECODE_ANY, + &error); + if (NULL == arguments) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Failed to parse arguments on line %u:%u: %s!\n", + error.line, + error.column, + error.text); + GNUNET_SCHEDULER_shutdown (); + return; + } + } + if (NULL != args[0]) + { + prev_state = json_load_file (args[0], + JSON_DECODE_ANY, + &error); + args++; + } + else + { + prev_state = json_loadf (stdin, + JSON_DECODE_ANY, + &error); + } + if (NULL == prev_state) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Failed to parse initial state on line %u:%u: %s!\n", + error.line, + error.column, + error.text); + GNUNET_SCHEDULER_shutdown (); + return; + } + output_filename = args[0]; + /* initialize HTTP client event loop */ + ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &rc); + rc = GNUNET_CURL_gnunet_rc_create (ctx); + ANASTASIS_redux_init (ctx); + ra = ANASTASIS_redux_action (prev_state, + action, + arguments, + &action_cb, + cls); + } +} + + +int +main (int argc, + char *const *argv) +{ + /* the available command line options */ + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_option_flag ('b', + "backup", + "use reducer to handle states for backup process", + &b_flag), + GNUNET_GETOPT_option_flag ('r', + "restore", + "use reducer to handle states for restore process", + &r_flag), + GNUNET_GETOPT_option_string ('a', + "arguments", + "JSON", + "pass a JSON string containing arguments to reducer", + &input), + + GNUNET_GETOPT_OPTION_END + }; + enum GNUNET_GenericReturnValue ret; + + /* FIRST get the libtalerutil initialization out + of the way. Then throw that one away, and force + the SYNC defaults to be used! */ + (void) TALER_project_data_default (); + GNUNET_OS_init (ANASTASIS_project_data_default ()); + ret = GNUNET_PROGRAM_run (argc, + argv, + "anastasis-reducer", + "This is an application for using Anastasis to handle the states.\n", + options, + &run, + NULL); + if (GNUNET_SYSERR == ret) + return 3; + if (GNUNET_NO == ret) + return 0; + return global_ret; +} + + +/* end of anastasis-cli-redux.c */ -- cgit v1.2.3