exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

taler-exchange-dbinit.c (8416B)


      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 "platform.h"
     23 #include <gnunet/gnunet_util_lib.h>
     24 #define GNUNET_PQ_RECONNECT_CALLBACK_CLOSURE bool
     25 #include <gnunet/gnunet_pq_lib.h>
     26 #include "exchangedb_lib.h"
     27 
     28 #include "exchange-database/gc.h"
     29 #include "exchange-database/preflight.h"
     30 #include "exchange-database/create_tables.h"
     31 #include "exchange-database/delete_shard_locks.h"
     32 #include "exchange-database/disable_rules.h"
     33 #include "exchange-database/enable_rules.h"
     34 #include "exchange-database/drop_tables.h"
     35 #include "exchange-database/inject_auditor_triggers.h"
     36 
     37 /**
     38  * Return value from main().
     39  */
     40 static int global_ret;
     41 
     42 /**
     43  * -a option: inject auditor triggers
     44  */
     45 static int inject_auditor;
     46 
     47 /**
     48  * -r option: do full DB reset
     49  */
     50 static int reset_db;
     51 
     52 /**
     53  * -e option: enable custom rules
     54  */
     55 static char *enable_rules;
     56 
     57 /**
     58  * -d option: disable custom rules
     59  */
     60 static char *disable_rules;
     61 
     62 /**
     63  * -s option: clear revolving shard locks
     64  */
     65 static int clear_shards;
     66 
     67 /**
     68  * -g option: garbage collect DB
     69  */
     70 static int gc_db;
     71 
     72 /**
     73  * -P option: setup a partitioned database
     74  */
     75 static uint32_t num_partitions;
     76 
     77 /**
     78  * -f option: force partitions to be created when there is only one
     79  */
     80 static int force_create_partitions;
     81 
     82 
     83 /**
     84  * Main function that will be run.
     85  *
     86  * @param cls closure
     87  * @param args remaining command-line arguments
     88  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
     89  * @param cfg configuration
     90  */
     91 static void
     92 run (void *cls,
     93      char *const *args,
     94      const char *cfgfile,
     95      const struct GNUNET_CONFIGURATION_Handle *cfg)
     96 {
     97   struct TALER_EXCHANGEDB_PostgresContext *pg;
     98 
     99   (void) cls;
    100   (void) args;
    101   (void) cfgfile;
    102   pg = TALER_EXCHANGEDB_connect_admin (cfg);
    103   if (NULL == pg)
    104   {
    105     fprintf (stderr,
    106              "Failed to initialize database connection.\n");
    107     global_ret = EXIT_NOTINSTALLED;
    108     return;
    109   }
    110   if (reset_db)
    111   {
    112     if (GNUNET_OK !=
    113         TALER_EXCHANGEDB_drop_tables (pg))
    114     {
    115       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    116                   "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");
    117     }
    118   }
    119   if (GNUNET_OK !=
    120       TALER_EXCHANGEDB_create_tables (pg,
    121                                       force_create_partitions ||
    122                                       (num_partitions > 0),
    123                                       num_partitions))
    124   {
    125     fprintf (stderr,
    126              "Failed to initialize database.\n");
    127     global_ret = EXIT_NOPERMISSION;
    128     goto exit;
    129   }
    130   if (gc_db || clear_shards)
    131   {
    132     if (clear_shards)
    133     {
    134       if (GNUNET_OK !=
    135           TALER_EXCHANGEDB_delete_shard_locks (pg))
    136       {
    137         fprintf (stderr,
    138                  "Clearing revolving shards failed!\n");
    139       }
    140     }
    141     if (gc_db)
    142     {
    143       if (GNUNET_SYSERR ==
    144           TALER_EXCHANGEDB_gc (pg))
    145       {
    146         fprintf (stderr,
    147                  "Garbage collection failed!\n");
    148       }
    149     }
    150   }
    151   if (inject_auditor)
    152   {
    153     if (GNUNET_SYSERR ==
    154         TALER_EXCHANGEDB_inject_auditor_triggers (pg))
    155     {
    156       fprintf (stderr,
    157                "Injecting auditor triggers failed!\n");
    158       global_ret = EXIT_FAILURE;
    159     }
    160   }
    161   if (NULL != disable_rules)
    162   {
    163     if (0 == strcasecmp (disable_rules,
    164                          "exchange"))
    165     {
    166       fprintf (stderr,
    167                "'exchange' is not a customization rule set!\n");
    168       global_ret = EXIT_INVALIDARGUMENT;
    169       goto exit;
    170     }
    171     switch (TALER_EXCHANGEDB_disable_rules (pg,
    172                                             disable_rules))
    173     {
    174     case GNUNET_DB_STATUS_HARD_ERROR:
    175       fprintf (stderr,
    176                "Hard DB error trying to disable customization!\n");
    177       global_ret = EXIT_FAILURE;
    178       goto exit;
    179     case GNUNET_DB_STATUS_SOFT_ERROR:
    180       /* single call, should not be possible */
    181       GNUNET_break (0);
    182       global_ret = EXIT_FAILURE;
    183       goto exit;
    184     case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
    185       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    186                   "Nothing to do to disable customization schema `%s'\n",
    187                   disable_rules);
    188       break;
    189     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
    190       break;
    191     }
    192   }
    193   if (NULL != enable_rules)
    194   {
    195     if (0 == strcasecmp (enable_rules,
    196                          "exchange"))
    197     {
    198       fprintf (stderr,
    199                "'exchange' is not a customization rule set!\n");
    200       global_ret = EXIT_INVALIDARGUMENT;
    201       goto exit;
    202     }
    203     if (GNUNET_OK !=
    204         TALER_EXCHANGEDB_enable_rules (pg,
    205                                        enable_rules))
    206     {
    207       fprintf (stderr,
    208                "Enabling customization `%s' failed!\n",
    209                enable_rules);
    210       global_ret = EXIT_FAILURE;
    211       goto exit;
    212     }
    213   }
    214 exit:
    215   TALER_EXCHANGEDB_disconnect (pg);
    216 }
    217 
    218 
    219 /**
    220  * The main function of the database initialization tool.
    221  * Used to initialize the Taler Exchange's database.
    222  *
    223  * @param argc number of arguments from the command line
    224  * @param argv command line arguments
    225  * @return 0 ok, non-zero on error
    226  */
    227 int
    228 main (int argc,
    229       char *const *argv)
    230 {
    231   const struct GNUNET_GETOPT_CommandLineOption options[] = {
    232     GNUNET_GETOPT_option_flag ('a',
    233                                "inject-auditor",
    234                                "inject auditor triggers",
    235                                &inject_auditor),
    236     GNUNET_GETOPT_option_string ('d',
    237                                  "disable-customization",
    238                                  "SCHEMA",
    239                                  "remove customization rules of SCHEMA",
    240                                  &disable_rules),
    241     GNUNET_GETOPT_option_string ('e',
    242                                  "enable-customization",
    243                                  "SCHEMA",
    244                                  "enable or update (to latest version) the customization rules of SCHEMA",
    245                                  &enable_rules),
    246     GNUNET_GETOPT_option_flag ('g',
    247                                "gc",
    248                                "garbage collect database",
    249                                &gc_db),
    250     GNUNET_GETOPT_option_flag ('r',
    251                                "reset",
    252                                "reset database (DANGEROUS: all existing data is lost!)",
    253                                &reset_db),
    254     GNUNET_GETOPT_option_flag ('s',
    255                                "shardunlock",
    256                                "unlock all revolving shard locks (use after system crash or shard size change while services are not running)",
    257                                &clear_shards),
    258     GNUNET_GETOPT_option_uint ('P',
    259                                "partition",
    260                                "NUMBER",
    261                                "Setup a partitioned database where each table which can be partitioned holds NUMBER partitions on a single DB node",
    262                                &num_partitions),
    263     GNUNET_GETOPT_option_flag ('f',
    264                                "force",
    265                                "Force partitions to be created if there is only one partition",
    266                                &force_create_partitions),
    267     GNUNET_GETOPT_OPTION_END
    268   };
    269   enum GNUNET_GenericReturnValue ret;
    270 
    271   ret = GNUNET_PROGRAM_run (
    272     TALER_EXCHANGE_project_data (),
    273     argc, argv,
    274     "taler-exchange-dbinit",
    275     gettext_noop ("Initialize Taler exchange database"),
    276     options,
    277     &run, NULL);
    278   if (GNUNET_SYSERR == ret)
    279     return EXIT_INVALIDARGUMENT;
    280   if (GNUNET_NO == ret)
    281     return EXIT_SUCCESS;
    282   return global_ret;
    283 }
    284 
    285 
    286 /* end of taler-exchange-dbinit.c */