Line data Source code
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 (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (* \
42 : ptr))
43 :
44 :
45 : static bool
46 0 : prepare (struct GNUNET_PQ_Context *conn)
47 : {
48 0 : struct GNUNET_PQ_PreparedStatement ps[] = {
49 0 : 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 0 : GNUNET_PQ_make_prepare (
58 : "bm_select",
59 : "SELECT"
60 : " expiration_date"
61 : " FROM benchmap"
62 : " WHERE hc=$1;"),
63 0 : 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 0 : GNUNET_PQ_make_prepare (
72 : "bhm_select",
73 : "SELECT"
74 : " expiration_date"
75 : " FROM benchhmap"
76 : " WHERE hc=$1;"),
77 0 : 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 0 : 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 0 : ret = GNUNET_PQ_prepare_statements (conn,
97 : ps);
98 0 : if (GNUNET_OK != ret)
99 0 : return false;
100 0 : return true;
101 : }
102 :
103 :
104 : static bool
105 0 : bm_insert (struct GNUNET_PQ_Context *conn,
106 : unsigned int i)
107 : {
108 0 : uint32_t b = htonl ((uint32_t) i);
109 : struct GNUNET_HashCode hc;
110 : struct GNUNET_TIME_Absolute now;
111 :
112 0 : now = GNUNET_TIME_absolute_get ();
113 0 : GNUNET_CRYPTO_hash (&b,
114 : sizeof (b),
115 : &hc);
116 : {
117 0 : struct GNUNET_PQ_QueryParam params[] = {
118 0 : GNUNET_PQ_query_param_auto_from_type (&hc),
119 0 : GNUNET_PQ_query_param_absolute_time (&now),
120 : GNUNET_PQ_query_param_end
121 : };
122 : enum GNUNET_DB_QueryStatus qs;
123 :
124 0 : qs = GNUNET_PQ_eval_prepared_non_select (conn,
125 : "bm_insert",
126 : params);
127 0 : return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
128 : }
129 : }
130 :
131 :
132 : static bool
133 0 : bhm_insert (struct GNUNET_PQ_Context *conn,
134 : unsigned int i)
135 : {
136 0 : uint32_t b = htonl ((uint32_t) i);
137 : struct GNUNET_HashCode hc;
138 : struct GNUNET_TIME_Absolute now;
139 :
140 0 : now = GNUNET_TIME_absolute_get ();
141 0 : GNUNET_CRYPTO_hash (&b,
142 : sizeof (b),
143 : &hc);
144 : {
145 0 : struct GNUNET_PQ_QueryParam params[] = {
146 0 : GNUNET_PQ_query_param_auto_from_type (&hc),
147 0 : GNUNET_PQ_query_param_absolute_time (&now),
148 : GNUNET_PQ_query_param_end
149 : };
150 : enum GNUNET_DB_QueryStatus qs;
151 :
152 0 : qs = GNUNET_PQ_eval_prepared_non_select (conn,
153 : "bhm_insert",
154 : params);
155 0 : return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
156 : }
157 : }
158 :
159 :
160 : static bool
161 0 : bem_insert (struct GNUNET_PQ_Context *conn,
162 : unsigned int i)
163 : {
164 0 : uint32_t b = htonl ((uint32_t) i);
165 : struct GNUNET_HashCode hc;
166 : struct GNUNET_TIME_Absolute now;
167 : uint32_t ihc;
168 :
169 0 : now = GNUNET_TIME_absolute_get ();
170 0 : GNUNET_CRYPTO_hash (&b,
171 : sizeof (b),
172 : &hc);
173 0 : GNUNET_memcpy (&ihc,
174 : &hc,
175 : sizeof (ihc));
176 : {
177 0 : struct GNUNET_PQ_QueryParam params[] = {
178 0 : GNUNET_PQ_query_param_auto_from_type (&hc),
179 0 : GNUNET_PQ_query_param_uint32 (&ihc),
180 0 : GNUNET_PQ_query_param_absolute_time (&now),
181 : GNUNET_PQ_query_param_end
182 : };
183 : enum GNUNET_DB_QueryStatus qs;
184 :
185 0 : qs = GNUNET_PQ_eval_prepared_non_select (conn,
186 : "bem_insert",
187 : params);
188 0 : return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
189 : }
190 : }
191 :
192 :
193 : static bool
194 0 : bm_select (struct GNUNET_PQ_Context *conn,
195 : unsigned int i)
196 : {
197 0 : uint32_t b = htonl ((uint32_t) i);
198 : struct GNUNET_HashCode hc;
199 : struct GNUNET_TIME_Absolute now;
200 :
201 0 : GNUNET_CRYPTO_hash (&b,
202 : sizeof (b),
203 : &hc);
204 : {
205 0 : struct GNUNET_PQ_QueryParam params[] = {
206 0 : GNUNET_PQ_query_param_auto_from_type (&hc),
207 : GNUNET_PQ_query_param_end
208 : };
209 0 : struct GNUNET_PQ_ResultSpec rs[] = {
210 0 : 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 0 : qs = GNUNET_PQ_eval_prepared_singleton_select (conn,
217 : "bm_select",
218 : params,
219 : rs);
220 0 : return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
221 : }
222 : }
223 :
224 :
225 : static bool
226 0 : bhm_select (struct GNUNET_PQ_Context *conn,
227 : unsigned int i)
228 : {
229 0 : uint32_t b = htonl ((uint32_t) i);
230 : struct GNUNET_HashCode hc;
231 : struct GNUNET_TIME_Absolute now;
232 :
233 0 : GNUNET_CRYPTO_hash (&b,
234 : sizeof (b),
235 : &hc);
236 : {
237 0 : struct GNUNET_PQ_QueryParam params[] = {
238 0 : GNUNET_PQ_query_param_auto_from_type (&hc),
239 : GNUNET_PQ_query_param_end
240 : };
241 0 : struct GNUNET_PQ_ResultSpec rs[] = {
242 0 : 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 0 : qs = GNUNET_PQ_eval_prepared_singleton_select (conn,
249 : "bhm_select",
250 : params,
251 : rs);
252 0 : return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
253 : }
254 : }
255 :
256 :
257 : static bool
258 0 : bem_select (struct GNUNET_PQ_Context *conn,
259 : unsigned int i)
260 : {
261 0 : uint32_t b = htonl ((uint32_t) i);
262 : struct GNUNET_HashCode hc;
263 : struct GNUNET_TIME_Absolute now;
264 : uint32_t ihc;
265 :
266 0 : GNUNET_CRYPTO_hash (&b,
267 : sizeof (b),
268 : &hc);
269 0 : GNUNET_memcpy (&ihc,
270 : &hc,
271 : sizeof (ihc));
272 : {
273 0 : struct GNUNET_PQ_QueryParam params[] = {
274 0 : GNUNET_PQ_query_param_uint32 (&ihc),
275 0 : GNUNET_PQ_query_param_auto_from_type (&hc),
276 : GNUNET_PQ_query_param_end
277 : };
278 0 : struct GNUNET_PQ_ResultSpec rs[] = {
279 0 : 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 0 : qs = GNUNET_PQ_eval_prepared_singleton_select (conn,
286 : "bem_select",
287 : params,
288 : rs);
289 0 : 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 0 : run (void *cls)
301 : {
302 0 : 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 0 : conn = GNUNET_PQ_init (cfg,
310 : "bench-db-postgres",
311 : NULL,
312 : NULL);
313 0 : if (NULL == conn)
314 : {
315 0 : result = EXIT_FAILURE;
316 0 : GNUNET_break (0);
317 0 : return;
318 : }
319 0 : if (GNUNET_OK !=
320 0 : GNUNET_PQ_exec_sql (conn,
321 : "benchmark-"))
322 : {
323 0 : result = EXIT_FAILURE;
324 0 : GNUNET_break (0);
325 0 : GNUNET_PQ_disconnect (conn);
326 0 : return;
327 : }
328 0 : conn2 = GNUNET_PQ_init (cfg,
329 : "bench-db-postgres",
330 : NULL,
331 : NULL);
332 0 : if (! prepare (conn))
333 : {
334 0 : GNUNET_PQ_disconnect (conn);
335 0 : GNUNET_PQ_disconnect (conn2);
336 0 : result = EXIT_FAILURE;
337 0 : GNUNET_break (0);
338 0 : return;
339 : }
340 0 : if (! prepare (conn2))
341 : {
342 0 : GNUNET_PQ_disconnect (conn);
343 0 : GNUNET_PQ_disconnect (conn2);
344 0 : result = EXIT_FAILURE;
345 0 : GNUNET_break (0);
346 0 : return;
347 : }
348 : {
349 0 : struct GNUNET_PQ_ExecuteStatement es[] = {
350 0 : GNUNET_PQ_make_try_execute ("DELETE FROM benchmap;"),
351 0 : GNUNET_PQ_make_try_execute ("DELETE FROM benchemap;"),
352 0 : GNUNET_PQ_make_try_execute ("DELETE FROM benchhmap;"),
353 : GNUNET_PQ_EXECUTE_STATEMENT_END
354 : };
355 :
356 0 : GNUNET_assert (GNUNET_OK ==
357 : GNUNET_PQ_exec_statements (conn,
358 : es));
359 : }
360 0 : now = GNUNET_TIME_absolute_get ();
361 0 : for (unsigned int i = 0; i<TOTAL; i++)
362 0 : if (! bm_insert (conn,
363 : i))
364 : {
365 0 : GNUNET_PQ_disconnect (conn);
366 0 : result = EXIT_FAILURE;
367 0 : GNUNET_break (0);
368 0 : return;
369 : }
370 0 : 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 0 : now = GNUNET_TIME_absolute_get ();
377 0 : f = fork ();
378 0 : for (unsigned int i = 0; i<TOTAL; i++)
379 : {
380 : uint32_t j;
381 :
382 0 : j = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
383 : TOTAL);
384 0 : if (! bm_select ((0 == f) ? conn2 : conn,
385 : j))
386 : {
387 0 : GNUNET_PQ_disconnect (conn);
388 0 : result = EXIT_FAILURE;
389 0 : GNUNET_break (0);
390 0 : return;
391 : }
392 : }
393 0 : if (0 == f)
394 0 : exit (0);
395 0 : waitpid (f, &status, 0);
396 0 : GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
397 : "Selection of 2x%u elements took %s\n",
398 : (unsigned int) TOTAL,
399 : GNUNET_STRINGS_relative_time_to_string (
400 : GNUNET_TIME_absolute_get_duration (now),
401 : GNUNET_YES));
402 :
403 0 : now = GNUNET_TIME_absolute_get ();
404 0 : for (unsigned int i = 0; i<TOTAL; i++)
405 0 : if (! bhm_insert (conn,
406 : i))
407 : {
408 0 : GNUNET_PQ_disconnect (conn);
409 0 : result = EXIT_FAILURE;
410 0 : GNUNET_break (0);
411 0 : return;
412 : }
413 0 : GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
414 : "Insertion of %u elements with hash index took %s\n",
415 : (unsigned int) TOTAL,
416 : GNUNET_STRINGS_relative_time_to_string (
417 : GNUNET_TIME_absolute_get_duration (now),
418 : GNUNET_YES));
419 0 : now = GNUNET_TIME_absolute_get ();
420 0 : f = fork ();
421 0 : for (unsigned int i = 0; i<TOTAL; i++)
422 : {
423 : uint32_t j;
424 :
425 0 : j = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
426 : TOTAL);
427 0 : if (! bhm_select ((0 == f) ? conn2 : conn,
428 : j))
429 : {
430 0 : GNUNET_PQ_disconnect (conn);
431 0 : result = EXIT_FAILURE;
432 0 : GNUNET_break (0);
433 0 : return;
434 : }
435 : }
436 0 : if (0 == f)
437 0 : exit (0);
438 0 : waitpid (f, &status, 0);
439 0 : GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
440 : "Selection of 2x%u elements with hash index took %s\n",
441 : (unsigned int) TOTAL,
442 : GNUNET_STRINGS_relative_time_to_string (
443 : GNUNET_TIME_absolute_get_duration (now),
444 : GNUNET_YES));
445 :
446 0 : now = GNUNET_TIME_absolute_get ();
447 0 : for (unsigned int i = 0; i<TOTAL; i++)
448 0 : if (! bem_insert (conn,
449 : i))
450 : {
451 0 : GNUNET_PQ_disconnect (conn);
452 0 : result = EXIT_FAILURE;
453 0 : GNUNET_break (0);
454 0 : return;
455 : }
456 0 : GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
457 : "Insertion of %u elements with short element took %s\n",
458 : (unsigned int) TOTAL,
459 : GNUNET_STRINGS_relative_time_to_string (
460 : GNUNET_TIME_absolute_get_duration (now),
461 : GNUNET_YES));
462 0 : now = GNUNET_TIME_absolute_get ();
463 0 : f = fork ();
464 0 : for (unsigned int i = 0; i<TOTAL; i++)
465 : {
466 : uint32_t j;
467 :
468 0 : j = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
469 : TOTAL);
470 0 : if (! bem_select ((0 == f) ? conn2 : conn,
471 : j))
472 : {
473 0 : GNUNET_PQ_disconnect (conn);
474 0 : result = EXIT_FAILURE;
475 0 : GNUNET_break (0);
476 0 : return;
477 : }
478 : }
479 0 : if (0 == f)
480 0 : exit (0);
481 0 : waitpid (f, &status, 0);
482 0 : GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
483 : "Selection of 2x%u elements with short element took %s\n",
484 : (unsigned int) TOTAL,
485 : GNUNET_STRINGS_relative_time_to_string (
486 : GNUNET_TIME_absolute_get_duration (now),
487 : GNUNET_YES));
488 :
489 0 : GNUNET_PQ_disconnect (conn);
490 : }
491 :
492 :
493 : int
494 0 : main (int argc,
495 : char *const argv[])
496 : {
497 : const char *plugin_name;
498 : char *config_filename;
499 : char *testname;
500 : struct GNUNET_CONFIGURATION_Handle *cfg;
501 :
502 : (void) argc;
503 0 : result = -1;
504 0 : if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
505 : {
506 0 : GNUNET_break (0);
507 0 : return -1;
508 : }
509 0 : GNUNET_log_setup (argv[0],
510 : "INFO",
511 : NULL);
512 0 : plugin_name++;
513 0 : (void) GNUNET_asprintf (&testname,
514 : "bench-db-%s",
515 : plugin_name);
516 0 : (void) GNUNET_asprintf (&config_filename,
517 : "%s.conf",
518 : testname);
519 0 : cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ());
520 0 : if (GNUNET_OK !=
521 0 : GNUNET_CONFIGURATION_parse (cfg,
522 : config_filename))
523 : {
524 0 : GNUNET_break (0);
525 0 : GNUNET_free (config_filename);
526 0 : GNUNET_free (testname);
527 0 : return 2;
528 : }
529 0 : GNUNET_SCHEDULER_run (&run,
530 : cfg);
531 0 : GNUNET_CONFIGURATION_destroy (cfg);
532 0 : GNUNET_free (config_filename);
533 0 : GNUNET_free (testname);
534 0 : return result;
535 : }
536 :
537 :
538 : /* end of bench_db.c */
|