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 */