exchange

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

bench_db.c (14551B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2014-2021 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 exchangedb/bench_db.c
     18  * @brief test cases for DB interaction functions
     19  * @author Sree Harsha Totakura
     20  * @author Christian Grothoff
     21  * @author Marcello Stanisci
     22  */
     23 #include "platform.h"  /* UNNECESSARY? */
     24 #include <gnunet/gnunet_pq_lib.h>
     25 #include "taler/taler_util.h"
     26 
     27 /**
     28  * How many elements should we insert?
     29  */
     30 #define TOTAL (1024 * 16)
     31 
     32 /**
     33  * Global result from the testcase.
     34  */
     35 static int result;
     36 
     37 /**
     38  * Initializes @a ptr with random data.
     39  */
     40 #define RND_BLK(ptr)                                                    \
     41         GNUNET_CRYPTO_random_block (ptr, sizeof (* \
     42                                                  ptr))
     43 
     44 
     45 static bool
     46 prepare (struct GNUNET_PQ_Context *conn)
     47 {
     48   struct GNUNET_PQ_PreparedStatement ps[] = {
     49     GNUNET_PQ_make_prepare (
     50       "bm_insert",
     51       "INSERT INTO benchmap "
     52       "(hc"
     53       ",expiration_date"
     54       ") VALUES "
     55       "($1, $2);"),
     56     /* Used in #postgres_iterate_denomination_info() */
     57     GNUNET_PQ_make_prepare (
     58       "bm_select",
     59       "SELECT"
     60       " expiration_date"
     61       " FROM benchmap"
     62       " WHERE hc=$1;"),
     63     GNUNET_PQ_make_prepare (
     64       "bhm_insert",
     65       "INSERT INTO benchhmap "
     66       "(hc"
     67       ",expiration_date"
     68       ") VALUES "
     69       "($1, $2);"),
     70     /* Used in #postgres_iterate_denomination_info() */
     71     GNUNET_PQ_make_prepare (
     72       "bhm_select",
     73       "SELECT"
     74       " expiration_date"
     75       " FROM benchhmap"
     76       " WHERE hc=$1;"),
     77     GNUNET_PQ_make_prepare (
     78       "bem_insert",
     79       "INSERT INTO benchemap "
     80       "(hc"
     81       ",ihc"
     82       ",expiration_date"
     83       ") VALUES "
     84       "($1, $2, $3);"),
     85     /* Used in #postgres_iterate_denomination_info() */
     86     GNUNET_PQ_make_prepare (
     87       "bem_select",
     88       "SELECT"
     89       " expiration_date"
     90       " FROM benchemap"
     91       " WHERE ihc=$1 AND hc=$2;"),
     92     GNUNET_PQ_PREPARED_STATEMENT_END
     93   };
     94   enum GNUNET_GenericReturnValue ret;
     95 
     96   ret = GNUNET_PQ_prepare_statements (conn,
     97                                       ps);
     98   if (GNUNET_OK != ret)
     99     return false;
    100   return true;
    101 }
    102 
    103 
    104 static bool
    105 bm_insert (struct GNUNET_PQ_Context *conn,
    106            unsigned int i)
    107 {
    108   uint32_t b = htonl ((uint32_t) i);
    109   struct GNUNET_HashCode hc;
    110   struct GNUNET_TIME_Absolute now;
    111 
    112   now = GNUNET_TIME_absolute_get ();
    113   GNUNET_CRYPTO_hash (&b,
    114                       sizeof (b),
    115                       &hc);
    116   {
    117     struct GNUNET_PQ_QueryParam params[] = {
    118       GNUNET_PQ_query_param_auto_from_type (&hc),
    119       GNUNET_PQ_query_param_absolute_time (&now),
    120       GNUNET_PQ_query_param_end
    121     };
    122     enum GNUNET_DB_QueryStatus qs;
    123 
    124     qs = GNUNET_PQ_eval_prepared_non_select (conn,
    125                                              "bm_insert",
    126                                              params);
    127     return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
    128   }
    129 }
    130 
    131 
    132 static bool
    133 bhm_insert (struct GNUNET_PQ_Context *conn,
    134             unsigned int i)
    135 {
    136   uint32_t b = htonl ((uint32_t) i);
    137   struct GNUNET_HashCode hc;
    138   struct GNUNET_TIME_Absolute now;
    139 
    140   now = GNUNET_TIME_absolute_get ();
    141   GNUNET_CRYPTO_hash (&b,
    142                       sizeof (b),
    143                       &hc);
    144   {
    145     struct GNUNET_PQ_QueryParam params[] = {
    146       GNUNET_PQ_query_param_auto_from_type (&hc),
    147       GNUNET_PQ_query_param_absolute_time (&now),
    148       GNUNET_PQ_query_param_end
    149     };
    150     enum GNUNET_DB_QueryStatus qs;
    151 
    152     qs = GNUNET_PQ_eval_prepared_non_select (conn,
    153                                              "bhm_insert",
    154                                              params);
    155     return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
    156   }
    157 }
    158 
    159 
    160 static bool
    161 bem_insert (struct GNUNET_PQ_Context *conn,
    162             unsigned int i)
    163 {
    164   uint32_t b = htonl ((uint32_t) i);
    165   struct GNUNET_HashCode hc;
    166   struct GNUNET_TIME_Absolute now;
    167   uint32_t ihc;
    168 
    169   now = GNUNET_TIME_absolute_get ();
    170   GNUNET_CRYPTO_hash (&b,
    171                       sizeof (b),
    172                       &hc);
    173   GNUNET_memcpy (&ihc,
    174                  &hc,
    175                  sizeof (ihc));
    176   {
    177     struct GNUNET_PQ_QueryParam params[] = {
    178       GNUNET_PQ_query_param_auto_from_type (&hc),
    179       GNUNET_PQ_query_param_uint32 (&ihc),
    180       GNUNET_PQ_query_param_absolute_time (&now),
    181       GNUNET_PQ_query_param_end
    182     };
    183     enum GNUNET_DB_QueryStatus qs;
    184 
    185     qs = GNUNET_PQ_eval_prepared_non_select (conn,
    186                                              "bem_insert",
    187                                              params);
    188     return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
    189   }
    190 }
    191 
    192 
    193 static bool
    194 bm_select (struct GNUNET_PQ_Context *conn,
    195            unsigned int i)
    196 {
    197   uint32_t b = htonl ((uint32_t) i);
    198   struct GNUNET_HashCode hc;
    199   struct GNUNET_TIME_Absolute now;
    200 
    201   GNUNET_CRYPTO_hash (&b,
    202                       sizeof (b),
    203                       &hc);
    204   {
    205     struct GNUNET_PQ_QueryParam params[] = {
    206       GNUNET_PQ_query_param_auto_from_type (&hc),
    207       GNUNET_PQ_query_param_end
    208     };
    209     struct GNUNET_PQ_ResultSpec rs[] = {
    210       GNUNET_PQ_result_spec_absolute_time ("expiration_date",
    211                                            &now),
    212       GNUNET_PQ_result_spec_end
    213     };
    214     enum GNUNET_DB_QueryStatus qs;
    215 
    216     qs = GNUNET_PQ_eval_prepared_singleton_select (conn,
    217                                                    "bm_select",
    218                                                    params,
    219                                                    rs);
    220     return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
    221   }
    222 }
    223 
    224 
    225 static bool
    226 bhm_select (struct GNUNET_PQ_Context *conn,
    227             unsigned int i)
    228 {
    229   uint32_t b = htonl ((uint32_t) i);
    230   struct GNUNET_HashCode hc;
    231   struct GNUNET_TIME_Absolute now;
    232 
    233   GNUNET_CRYPTO_hash (&b,
    234                       sizeof (b),
    235                       &hc);
    236   {
    237     struct GNUNET_PQ_QueryParam params[] = {
    238       GNUNET_PQ_query_param_auto_from_type (&hc),
    239       GNUNET_PQ_query_param_end
    240     };
    241     struct GNUNET_PQ_ResultSpec rs[] = {
    242       GNUNET_PQ_result_spec_absolute_time ("expiration_date",
    243                                            &now),
    244       GNUNET_PQ_result_spec_end
    245     };
    246     enum GNUNET_DB_QueryStatus qs;
    247 
    248     qs = GNUNET_PQ_eval_prepared_singleton_select (conn,
    249                                                    "bhm_select",
    250                                                    params,
    251                                                    rs);
    252     return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
    253   }
    254 }
    255 
    256 
    257 static bool
    258 bem_select (struct GNUNET_PQ_Context *conn,
    259             unsigned int i)
    260 {
    261   uint32_t b = htonl ((uint32_t) i);
    262   struct GNUNET_HashCode hc;
    263   struct GNUNET_TIME_Absolute now;
    264   uint32_t ihc;
    265 
    266   GNUNET_CRYPTO_hash (&b,
    267                       sizeof (b),
    268                       &hc);
    269   GNUNET_memcpy (&ihc,
    270                  &hc,
    271                  sizeof (ihc));
    272   {
    273     struct GNUNET_PQ_QueryParam params[] = {
    274       GNUNET_PQ_query_param_uint32 (&ihc),
    275       GNUNET_PQ_query_param_auto_from_type (&hc),
    276       GNUNET_PQ_query_param_end
    277     };
    278     struct GNUNET_PQ_ResultSpec rs[] = {
    279       GNUNET_PQ_result_spec_absolute_time ("expiration_date",
    280                                            &now),
    281       GNUNET_PQ_result_spec_end
    282     };
    283     enum GNUNET_DB_QueryStatus qs;
    284 
    285     qs = GNUNET_PQ_eval_prepared_singleton_select (conn,
    286                                                    "bem_select",
    287                                                    params,
    288                                                    rs);
    289     return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
    290   }
    291 }
    292 
    293 
    294 /**
    295  * Main function that will be run by the scheduler.
    296  *
    297  * @param cls closure with config
    298  */
    299 static void
    300 run (void *cls)
    301 {
    302   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
    303   struct GNUNET_PQ_Context *conn;
    304   struct GNUNET_PQ_Context *conn2;
    305   struct GNUNET_TIME_Absolute now;
    306   pid_t f;
    307   int status;
    308 
    309   conn = GNUNET_PQ_init (cfg,
    310                          "bench-db-postgres",
    311                          NULL,
    312                          NULL);
    313   if (NULL == conn)
    314   {
    315     result = EXIT_FAILURE;
    316     GNUNET_break (0);
    317     return;
    318   }
    319   if (GNUNET_OK !=
    320       GNUNET_PQ_exec_sql (conn,
    321                           "benchmark-"))
    322   {
    323     result = EXIT_FAILURE;
    324     GNUNET_break (0);
    325     GNUNET_PQ_disconnect (conn);
    326     return;
    327   }
    328   conn2 = GNUNET_PQ_init (cfg,
    329                           "bench-db-postgres",
    330                           NULL,
    331                           NULL);
    332   if (! prepare (conn))
    333   {
    334     GNUNET_PQ_disconnect (conn);
    335     GNUNET_PQ_disconnect (conn2);
    336     result = EXIT_FAILURE;
    337     GNUNET_break (0);
    338     return;
    339   }
    340   if (! prepare (conn2))
    341   {
    342     GNUNET_PQ_disconnect (conn);
    343     GNUNET_PQ_disconnect (conn2);
    344     result = EXIT_FAILURE;
    345     GNUNET_break (0);
    346     return;
    347   }
    348   {
    349     struct GNUNET_PQ_ExecuteStatement es[] = {
    350       GNUNET_PQ_make_try_execute ("DELETE FROM benchmap;"),
    351       GNUNET_PQ_make_try_execute ("DELETE FROM benchemap;"),
    352       GNUNET_PQ_make_try_execute ("DELETE FROM benchhmap;"),
    353       GNUNET_PQ_EXECUTE_STATEMENT_END
    354     };
    355 
    356     GNUNET_assert (GNUNET_OK ==
    357                    GNUNET_PQ_exec_statements (conn,
    358                                               es));
    359   }
    360   now = GNUNET_TIME_absolute_get ();
    361   for (unsigned int i = 0; i<TOTAL; i++)
    362     if (! bm_insert (conn,
    363                      i))
    364     {
    365       GNUNET_PQ_disconnect (conn);
    366       result = EXIT_FAILURE;
    367       GNUNET_break (0);
    368       return;
    369     }
    370   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    371               "Insertion of %u elements took %s\n",
    372               (unsigned int) TOTAL,
    373               GNUNET_STRINGS_relative_time_to_string (
    374                 GNUNET_TIME_absolute_get_duration (now),
    375                 GNUNET_YES));
    376   now = GNUNET_TIME_absolute_get ();
    377   f = fork ();
    378   for (unsigned int i = 0; i<TOTAL; i++)
    379   {
    380     uint32_t j;
    381 
    382     j = GNUNET_CRYPTO_random_u32 (TOTAL);
    383     if (! bm_select ((0 == f) ? conn2 : conn,
    384                      j))
    385     {
    386       GNUNET_PQ_disconnect (conn);
    387       result = EXIT_FAILURE;
    388       GNUNET_break (0);
    389       return;
    390     }
    391   }
    392   if (0 == f)
    393     exit (0);
    394   waitpid (f, &status, 0);
    395   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    396               "Selection of 2x%u elements took %s\n",
    397               (unsigned int) TOTAL,
    398               GNUNET_STRINGS_relative_time_to_string (
    399                 GNUNET_TIME_absolute_get_duration (now),
    400                 GNUNET_YES));
    401 
    402   now = GNUNET_TIME_absolute_get ();
    403   for (unsigned int i = 0; i<TOTAL; i++)
    404     if (! bhm_insert (conn,
    405                       i))
    406     {
    407       GNUNET_PQ_disconnect (conn);
    408       result = EXIT_FAILURE;
    409       GNUNET_break (0);
    410       return;
    411     }
    412   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    413               "Insertion of %u elements with hash index took %s\n",
    414               (unsigned int) TOTAL,
    415               GNUNET_STRINGS_relative_time_to_string (
    416                 GNUNET_TIME_absolute_get_duration (now),
    417                 GNUNET_YES));
    418   now = GNUNET_TIME_absolute_get ();
    419   f = fork ();
    420   for (unsigned int i = 0; i<TOTAL; i++)
    421   {
    422     uint32_t j;
    423 
    424     j = GNUNET_CRYPTO_random_u32 (TOTAL);
    425     if (! bhm_select ((0 == f) ? conn2 : conn,
    426                       j))
    427     {
    428       GNUNET_PQ_disconnect (conn);
    429       result = EXIT_FAILURE;
    430       GNUNET_break (0);
    431       return;
    432     }
    433   }
    434   if (0 == f)
    435     exit (0);
    436   waitpid (f, &status, 0);
    437   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    438               "Selection of 2x%u elements with hash index took %s\n",
    439               (unsigned int) TOTAL,
    440               GNUNET_STRINGS_relative_time_to_string (
    441                 GNUNET_TIME_absolute_get_duration (now),
    442                 GNUNET_YES));
    443 
    444   now = GNUNET_TIME_absolute_get ();
    445   for (unsigned int i = 0; i<TOTAL; i++)
    446     if (! bem_insert (conn,
    447                       i))
    448     {
    449       GNUNET_PQ_disconnect (conn);
    450       result = EXIT_FAILURE;
    451       GNUNET_break (0);
    452       return;
    453     }
    454   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    455               "Insertion of %u elements with short element took %s\n",
    456               (unsigned int) TOTAL,
    457               GNUNET_STRINGS_relative_time_to_string (
    458                 GNUNET_TIME_absolute_get_duration (now),
    459                 GNUNET_YES));
    460   now = GNUNET_TIME_absolute_get ();
    461   f = fork ();
    462   for (unsigned int i = 0; i<TOTAL; i++)
    463   {
    464     uint32_t j;
    465 
    466     j = GNUNET_CRYPTO_random_u32 (TOTAL);
    467     if (! bem_select ((0 == f) ? conn2 : conn,
    468                       j))
    469     {
    470       GNUNET_PQ_disconnect (conn);
    471       result = EXIT_FAILURE;
    472       GNUNET_break (0);
    473       return;
    474     }
    475   }
    476   if (0 == f)
    477     exit (0);
    478   waitpid (f, &status, 0);
    479   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    480               "Selection of 2x%u elements with short element took %s\n",
    481               (unsigned int) TOTAL,
    482               GNUNET_STRINGS_relative_time_to_string (
    483                 GNUNET_TIME_absolute_get_duration (now),
    484                 GNUNET_YES));
    485 
    486   GNUNET_PQ_disconnect (conn);
    487 }
    488 
    489 
    490 int
    491 main (int argc,
    492       char *const argv[])
    493 {
    494   const char *plugin_name;
    495   char *config_filename;
    496   char *testname;
    497   struct GNUNET_CONFIGURATION_Handle *cfg;
    498 
    499   (void) argc;
    500   result = -1;
    501   if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
    502   {
    503     GNUNET_break (0);
    504     return -1;
    505   }
    506   GNUNET_log_setup (argv[0],
    507                     "INFO",
    508                     NULL);
    509   plugin_name++;
    510   (void) GNUNET_asprintf (&testname,
    511                           "bench-db-%s",
    512                           plugin_name);
    513   (void) GNUNET_asprintf (&config_filename,
    514                           "%s.conf",
    515                           testname);
    516   cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ());
    517   if (GNUNET_OK !=
    518       GNUNET_CONFIGURATION_parse (cfg,
    519                                   config_filename))
    520   {
    521     GNUNET_break (0);
    522     GNUNET_free (config_filename);
    523     GNUNET_free (testname);
    524     return 2;
    525   }
    526   GNUNET_SCHEDULER_run (&run,
    527                         cfg);
    528   GNUNET_CONFIGURATION_destroy (cfg);
    529   GNUNET_free (config_filename);
    530   GNUNET_free (testname);
    531   return result;
    532 }
    533 
    534 
    535 /* end of bench_db.c */