taler-exchange-dbinit.c (8371B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2014-2025 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file exchange-tools/taler-exchange-dbinit.c 18 * @brief Create tables for the exchange database. 19 * @author Florian Dold 20 * @author Christian Grothoff 21 */ 22 #include "taler/platform.h" 23 #include <gnunet/gnunet_util_lib.h> 24 #include "taler/taler_exchangedb_lib.h" 25 26 27 /** 28 * Return value from main(). 29 */ 30 static int global_ret; 31 32 /** 33 * -a option: inject auditor triggers 34 */ 35 static int inject_auditor; 36 37 /** 38 * -r option: do full DB reset 39 */ 40 static int reset_db; 41 42 /** 43 * -e option: enable custom rules 44 */ 45 static char *enable_rules; 46 47 /** 48 * -d option: disable custom rules 49 */ 50 static char *disable_rules; 51 52 /** 53 * -s option: clear revolving shard locks 54 */ 55 static int clear_shards; 56 57 /** 58 * -g option: garbage collect DB 59 */ 60 static int gc_db; 61 62 /** 63 * -P option: setup a partitioned database 64 */ 65 static uint32_t num_partitions; 66 67 /** 68 * -f option: force partitions to be created when there is only one 69 */ 70 static int force_create_partitions; 71 72 /** 73 * Main function that will be run. 74 * 75 * @param cls closure 76 * @param args remaining command-line arguments 77 * @param cfgfile name of the configuration file used (for saving, can be NULL!) 78 * @param cfg configuration 79 */ 80 static void 81 run (void *cls, 82 char *const *args, 83 const char *cfgfile, 84 const struct GNUNET_CONFIGURATION_Handle *cfg) 85 { 86 struct TALER_EXCHANGEDB_Plugin *plugin; 87 88 (void) cls; 89 (void) args; 90 (void) cfgfile; 91 92 if (NULL == 93 (plugin = TALER_EXCHANGEDB_plugin_load (cfg, 94 true))) 95 { 96 fprintf (stderr, 97 "Failed to initialize database plugin.\n"); 98 global_ret = EXIT_NOTINSTALLED; 99 return; 100 } 101 if (reset_db) 102 { 103 if (GNUNET_OK != 104 plugin->drop_tables (plugin->cls)) 105 { 106 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 107 "Could not drop tables as requested. Either database was not yet initialized, or permission denied. Consult the logs. Will still try to create new tables.\n"); 108 } 109 } 110 if (GNUNET_OK != 111 plugin->create_tables (plugin->cls, 112 force_create_partitions || num_partitions > 0, 113 num_partitions)) 114 { 115 fprintf (stderr, 116 "Failed to initialize database.\n"); 117 global_ret = EXIT_NOPERMISSION; 118 goto exit; 119 } 120 if (gc_db || clear_shards) 121 { 122 if (GNUNET_OK != 123 plugin->preflight (plugin->cls)) 124 { 125 fprintf (stderr, 126 "Failed to prepare database.\n"); 127 global_ret = EXIT_NOPERMISSION; 128 goto exit; 129 } 130 if (clear_shards) 131 { 132 if (GNUNET_OK != 133 plugin->delete_shard_locks (plugin->cls)) 134 { 135 fprintf (stderr, 136 "Clearing revolving shards failed!\n"); 137 } 138 } 139 if (gc_db) 140 { 141 if (GNUNET_SYSERR == plugin->gc (plugin->cls)) 142 { 143 fprintf (stderr, 144 "Garbage collection failed!\n"); 145 } 146 } 147 } 148 if (inject_auditor) 149 { 150 if (GNUNET_SYSERR == 151 plugin->inject_auditor_triggers (plugin->cls)) 152 { 153 fprintf (stderr, 154 "Injecting auditor triggers failed!\n"); 155 global_ret = EXIT_FAILURE; 156 } 157 } 158 if (NULL != disable_rules) 159 { 160 if (0 == strcasecmp (disable_rules, 161 "exchange")) 162 { 163 fprintf (stderr, 164 "'exchange' is not a customization rule set!\n"); 165 global_ret = EXIT_INVALIDARGUMENT; 166 goto exit; 167 } 168 if (GNUNET_OK != 169 plugin->preflight (plugin->cls)) 170 { 171 fprintf (stderr, 172 "Preflight check failed!\n"); 173 global_ret = EXIT_FAILURE; 174 goto exit; 175 } 176 switch (plugin->disable_rules (plugin->cls, 177 disable_rules)) 178 { 179 case GNUNET_DB_STATUS_HARD_ERROR: 180 fprintf (stderr, 181 "Hard DB error trying to disable customization!\n"); 182 global_ret = EXIT_FAILURE; 183 goto exit; 184 case GNUNET_DB_STATUS_SOFT_ERROR: 185 /* single call, should not be possible */ 186 GNUNET_break (0); 187 global_ret = EXIT_FAILURE; 188 goto exit; 189 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 190 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 191 "Nothing to do to disable customization schema `%s'\n", 192 disable_rules); 193 break; 194 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 195 break; 196 } 197 } 198 if (NULL != enable_rules) 199 { 200 if (0 == strcasecmp (enable_rules, 201 "exchange")) 202 { 203 fprintf (stderr, 204 "'exchange' is not a customization rule set!\n"); 205 global_ret = EXIT_INVALIDARGUMENT; 206 goto exit; 207 } 208 if (GNUNET_OK != 209 plugin->enable_rules (plugin->cls, 210 enable_rules)) 211 { 212 fprintf (stderr, 213 "Enabling customization `%s' failed!\n", 214 enable_rules); 215 global_ret = EXIT_FAILURE; 216 goto exit; 217 } 218 } 219 exit: 220 TALER_EXCHANGEDB_plugin_unload (plugin); 221 plugin = NULL; 222 } 223 224 225 /** 226 * The main function of the database initialization tool. 227 * Used to initialize the Taler Exchange's database. 228 * 229 * @param argc number of arguments from the command line 230 * @param argv command line arguments 231 * @return 0 ok, non-zero on error 232 */ 233 int 234 main (int argc, 235 char *const *argv) 236 { 237 const struct GNUNET_GETOPT_CommandLineOption options[] = { 238 GNUNET_GETOPT_option_flag ('a', 239 "inject-auditor", 240 "inject auditor triggers", 241 &inject_auditor), 242 GNUNET_GETOPT_option_string ('d', 243 "disable-customization", 244 "SCHEMA", 245 "remove customization rules of SCHEMA", 246 &disable_rules), 247 GNUNET_GETOPT_option_string ('e', 248 "enable-customization", 249 "SCHEMA", 250 "enable or update (to latest version) the customization rules of SCHEMA", 251 &enable_rules), 252 GNUNET_GETOPT_option_flag ('g', 253 "gc", 254 "garbage collect database", 255 &gc_db), 256 GNUNET_GETOPT_option_flag ('r', 257 "reset", 258 "reset database (DANGEROUS: all existing data is lost!)", 259 &reset_db), 260 GNUNET_GETOPT_option_flag ('s', 261 "shardunlock", 262 "unlock all revolving shard locks (use after system crash or shard size change while services are not running)", 263 &clear_shards), 264 GNUNET_GETOPT_option_uint ('P', 265 "partition", 266 "NUMBER", 267 "Setup a partitioned database where each table which can be partitioned holds NUMBER partitions on a single DB node", 268 &num_partitions), 269 GNUNET_GETOPT_option_flag ('f', 270 "force", 271 "Force partitions to be created if there is only one partition", 272 &force_create_partitions), 273 GNUNET_GETOPT_OPTION_END 274 }; 275 enum GNUNET_GenericReturnValue ret; 276 277 ret = GNUNET_PROGRAM_run ( 278 TALER_EXCHANGE_project_data (), 279 argc, argv, 280 "taler-exchange-dbinit", 281 gettext_noop ("Initialize Taler exchange database"), 282 options, 283 &run, NULL); 284 if (GNUNET_SYSERR == ret) 285 return EXIT_INVALIDARGUMENT; 286 if (GNUNET_NO == ret) 287 return EXIT_SUCCESS; 288 return global_ret; 289 } 290 291 292 /* end of taler-exchange-dbinit.c */