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 (8762B)


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