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


      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 "taler/platform.h"
     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 (GNUNET_CRYPTO_QUALITY_WEAK, 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_connect_with_cfg (cfg,
    310                                      "bench-db-postgres",
    311                                      "benchmark-",
    312                                      NULL,
    313                                      NULL);
    314   if (NULL == conn)
    315   {
    316     result = EXIT_FAILURE;
    317     GNUNET_break (0);
    318     return;
    319   }
    320   conn2 = GNUNET_PQ_connect_with_cfg (cfg,
    321                                       "bench-db-postgres",
    322                                       NULL,
    323                                       NULL,
    324                                       NULL);
    325   if (! prepare (conn))
    326   {
    327     GNUNET_PQ_disconnect (conn);
    328     GNUNET_PQ_disconnect (conn2);
    329     result = EXIT_FAILURE;
    330     GNUNET_break (0);
    331     return;
    332   }
    333   if (! prepare (conn2))
    334   {
    335     GNUNET_PQ_disconnect (conn);
    336     GNUNET_PQ_disconnect (conn2);
    337     result = EXIT_FAILURE;
    338     GNUNET_break (0);
    339     return;
    340   }
    341   {
    342     struct GNUNET_PQ_ExecuteStatement es[] = {
    343       GNUNET_PQ_make_try_execute ("DELETE FROM benchmap;"),
    344       GNUNET_PQ_make_try_execute ("DELETE FROM benchemap;"),
    345       GNUNET_PQ_make_try_execute ("DELETE FROM benchhmap;"),
    346       GNUNET_PQ_EXECUTE_STATEMENT_END
    347     };
    348 
    349     GNUNET_assert (GNUNET_OK ==
    350                    GNUNET_PQ_exec_statements (conn,
    351                                               es));
    352   }
    353   now = GNUNET_TIME_absolute_get ();
    354   for (unsigned int i = 0; i<TOTAL; i++)
    355     if (! bm_insert (conn,
    356                      i))
    357     {
    358       GNUNET_PQ_disconnect (conn);
    359       result = EXIT_FAILURE;
    360       GNUNET_break (0);
    361       return;
    362     }
    363   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    364               "Insertion of %u elements took %s\n",
    365               (unsigned int) TOTAL,
    366               GNUNET_STRINGS_relative_time_to_string (
    367                 GNUNET_TIME_absolute_get_duration (now),
    368                 GNUNET_YES));
    369   now = GNUNET_TIME_absolute_get ();
    370   f = fork ();
    371   for (unsigned int i = 0; i<TOTAL; i++)
    372   {
    373     uint32_t j;
    374 
    375     j = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
    376                                   TOTAL);
    377     if (! bm_select ((0 == f) ? conn2 : conn,
    378                      j))
    379     {
    380       GNUNET_PQ_disconnect (conn);
    381       result = EXIT_FAILURE;
    382       GNUNET_break (0);
    383       return;
    384     }
    385   }
    386   if (0 == f)
    387     exit (0);
    388   waitpid (f, &status, 0);
    389   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    390               "Selection of 2x%u elements took %s\n",
    391               (unsigned int) TOTAL,
    392               GNUNET_STRINGS_relative_time_to_string (
    393                 GNUNET_TIME_absolute_get_duration (now),
    394                 GNUNET_YES));
    395 
    396   now = GNUNET_TIME_absolute_get ();
    397   for (unsigned int i = 0; i<TOTAL; i++)
    398     if (! bhm_insert (conn,
    399                       i))
    400     {
    401       GNUNET_PQ_disconnect (conn);
    402       result = EXIT_FAILURE;
    403       GNUNET_break (0);
    404       return;
    405     }
    406   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    407               "Insertion of %u elements with hash index took %s\n",
    408               (unsigned int) TOTAL,
    409               GNUNET_STRINGS_relative_time_to_string (
    410                 GNUNET_TIME_absolute_get_duration (now),
    411                 GNUNET_YES));
    412   now = GNUNET_TIME_absolute_get ();
    413   f = fork ();
    414   for (unsigned int i = 0; i<TOTAL; i++)
    415   {
    416     uint32_t j;
    417 
    418     j = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
    419                                   TOTAL);
    420     if (! bhm_select ((0 == f) ? conn2 : conn,
    421                       j))
    422     {
    423       GNUNET_PQ_disconnect (conn);
    424       result = EXIT_FAILURE;
    425       GNUNET_break (0);
    426       return;
    427     }
    428   }
    429   if (0 == f)
    430     exit (0);
    431   waitpid (f, &status, 0);
    432   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    433               "Selection of 2x%u elements with hash index took %s\n",
    434               (unsigned int) TOTAL,
    435               GNUNET_STRINGS_relative_time_to_string (
    436                 GNUNET_TIME_absolute_get_duration (now),
    437                 GNUNET_YES));
    438 
    439   now = GNUNET_TIME_absolute_get ();
    440   for (unsigned int i = 0; i<TOTAL; i++)
    441     if (! bem_insert (conn,
    442                       i))
    443     {
    444       GNUNET_PQ_disconnect (conn);
    445       result = EXIT_FAILURE;
    446       GNUNET_break (0);
    447       return;
    448     }
    449   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    450               "Insertion of %u elements with short element took %s\n",
    451               (unsigned int) TOTAL,
    452               GNUNET_STRINGS_relative_time_to_string (
    453                 GNUNET_TIME_absolute_get_duration (now),
    454                 GNUNET_YES));
    455   now = GNUNET_TIME_absolute_get ();
    456   f = fork ();
    457   for (unsigned int i = 0; i<TOTAL; i++)
    458   {
    459     uint32_t j;
    460 
    461     j = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
    462                                   TOTAL);
    463     if (! bem_select ((0 == f) ? conn2 : conn,
    464                       j))
    465     {
    466       GNUNET_PQ_disconnect (conn);
    467       result = EXIT_FAILURE;
    468       GNUNET_break (0);
    469       return;
    470     }
    471   }
    472   if (0 == f)
    473     exit (0);
    474   waitpid (f, &status, 0);
    475   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    476               "Selection of 2x%u elements with short element took %s\n",
    477               (unsigned int) TOTAL,
    478               GNUNET_STRINGS_relative_time_to_string (
    479                 GNUNET_TIME_absolute_get_duration (now),
    480                 GNUNET_YES));
    481 
    482   GNUNET_PQ_disconnect (conn);
    483 }
    484 
    485 
    486 int
    487 main (int argc,
    488       char *const argv[])
    489 {
    490   const char *plugin_name;
    491   char *config_filename;
    492   char *testname;
    493   struct GNUNET_CONFIGURATION_Handle *cfg;
    494 
    495   (void) argc;
    496   result = -1;
    497   if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
    498   {
    499     GNUNET_break (0);
    500     return -1;
    501   }
    502   GNUNET_log_setup (argv[0],
    503                     "INFO",
    504                     NULL);
    505   plugin_name++;
    506   (void) GNUNET_asprintf (&testname,
    507                           "bench-db-%s",
    508                           plugin_name);
    509   (void) GNUNET_asprintf (&config_filename,
    510                           "%s.conf",
    511                           testname);
    512   cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ());
    513   if (GNUNET_OK !=
    514       GNUNET_CONFIGURATION_parse (cfg,
    515                                   config_filename))
    516   {
    517     GNUNET_break (0);
    518     GNUNET_free (config_filename);
    519     GNUNET_free (testname);
    520     return 2;
    521   }
    522   GNUNET_SCHEDULER_run (&run,
    523                         cfg);
    524   GNUNET_CONFIGURATION_destroy (cfg);
    525   GNUNET_free (config_filename);
    526   GNUNET_free (testname);
    527   return result;
    528 }
    529 
    530 
    531 /* end of bench_db.c */