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