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 "taler/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_connect_with_cfg (cfg,
310 : "bench-db-postgres",
311 : "benchmark-",
312 : NULL,
313 : NULL);
314 0 : if (NULL == conn)
315 : {
316 0 : result = EXIT_FAILURE;
317 0 : GNUNET_break (0);
318 0 : return;
319 : }
320 0 : conn2 = GNUNET_PQ_connect_with_cfg (cfg,
321 : "bench-db-postgres",
322 : NULL,
323 : NULL,
324 : NULL);
325 0 : if (! prepare (conn))
326 : {
327 0 : GNUNET_PQ_disconnect (conn);
328 0 : GNUNET_PQ_disconnect (conn2);
329 0 : result = EXIT_FAILURE;
330 0 : GNUNET_break (0);
331 0 : return;
332 : }
333 0 : if (! prepare (conn2))
334 : {
335 0 : GNUNET_PQ_disconnect (conn);
336 0 : GNUNET_PQ_disconnect (conn2);
337 0 : result = EXIT_FAILURE;
338 0 : GNUNET_break (0);
339 0 : return;
340 : }
341 : {
342 0 : struct GNUNET_PQ_ExecuteStatement es[] = {
343 0 : GNUNET_PQ_make_try_execute ("DELETE FROM benchmap;"),
344 0 : GNUNET_PQ_make_try_execute ("DELETE FROM benchemap;"),
345 0 : GNUNET_PQ_make_try_execute ("DELETE FROM benchhmap;"),
346 : GNUNET_PQ_EXECUTE_STATEMENT_END
347 : };
348 :
349 0 : GNUNET_assert (GNUNET_OK ==
350 : GNUNET_PQ_exec_statements (conn,
351 : es));
352 : }
353 0 : now = GNUNET_TIME_absolute_get ();
354 0 : for (unsigned int i = 0; i<TOTAL; i++)
355 0 : if (! bm_insert (conn,
356 : i))
357 : {
358 0 : GNUNET_PQ_disconnect (conn);
359 0 : result = EXIT_FAILURE;
360 0 : GNUNET_break (0);
361 0 : return;
362 : }
363 0 : 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 0 : now = GNUNET_TIME_absolute_get ();
370 0 : f = fork ();
371 0 : for (unsigned int i = 0; i<TOTAL; i++)
372 : {
373 : uint32_t j;
374 :
375 0 : j = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
376 : TOTAL);
377 0 : if (! bm_select ((0 == f) ? conn2 : conn,
378 : j))
379 : {
380 0 : GNUNET_PQ_disconnect (conn);
381 0 : result = EXIT_FAILURE;
382 0 : GNUNET_break (0);
383 0 : return;
384 : }
385 : }
386 0 : if (0 == f)
387 0 : exit (0);
388 0 : waitpid (f, &status, 0);
389 0 : 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 0 : now = GNUNET_TIME_absolute_get ();
397 0 : for (unsigned int i = 0; i<TOTAL; i++)
398 0 : if (! bhm_insert (conn,
399 : i))
400 : {
401 0 : GNUNET_PQ_disconnect (conn);
402 0 : result = EXIT_FAILURE;
403 0 : GNUNET_break (0);
404 0 : return;
405 : }
406 0 : 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 0 : now = GNUNET_TIME_absolute_get ();
413 0 : f = fork ();
414 0 : for (unsigned int i = 0; i<TOTAL; i++)
415 : {
416 : uint32_t j;
417 :
418 0 : j = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
419 : TOTAL);
420 0 : if (! bhm_select ((0 == f) ? conn2 : conn,
421 : j))
422 : {
423 0 : GNUNET_PQ_disconnect (conn);
424 0 : result = EXIT_FAILURE;
425 0 : GNUNET_break (0);
426 0 : return;
427 : }
428 : }
429 0 : if (0 == f)
430 0 : exit (0);
431 0 : waitpid (f, &status, 0);
432 0 : 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 0 : now = GNUNET_TIME_absolute_get ();
440 0 : for (unsigned int i = 0; i<TOTAL; i++)
441 0 : if (! bem_insert (conn,
442 : i))
443 : {
444 0 : GNUNET_PQ_disconnect (conn);
445 0 : result = EXIT_FAILURE;
446 0 : GNUNET_break (0);
447 0 : return;
448 : }
449 0 : 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 0 : now = GNUNET_TIME_absolute_get ();
456 0 : f = fork ();
457 0 : for (unsigned int i = 0; i<TOTAL; i++)
458 : {
459 : uint32_t j;
460 :
461 0 : j = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
462 : TOTAL);
463 0 : if (! bem_select ((0 == f) ? conn2 : conn,
464 : j))
465 : {
466 0 : GNUNET_PQ_disconnect (conn);
467 0 : result = EXIT_FAILURE;
468 0 : GNUNET_break (0);
469 0 : return;
470 : }
471 : }
472 0 : if (0 == f)
473 0 : exit (0);
474 0 : waitpid (f, &status, 0);
475 0 : 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 0 : GNUNET_PQ_disconnect (conn);
483 : }
484 :
485 :
486 : int
487 0 : 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 0 : result = -1;
497 0 : if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
498 : {
499 0 : GNUNET_break (0);
500 0 : return -1;
501 : }
502 0 : GNUNET_log_setup (argv[0],
503 : "INFO",
504 : NULL);
505 0 : plugin_name++;
506 0 : (void) GNUNET_asprintf (&testname,
507 : "bench-db-%s",
508 : plugin_name);
509 0 : (void) GNUNET_asprintf (&config_filename,
510 : "%s.conf",
511 : testname);
512 0 : cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ());
513 0 : if (GNUNET_OK !=
514 0 : GNUNET_CONFIGURATION_parse (cfg,
515 : config_filename))
516 : {
517 0 : GNUNET_break (0);
518 0 : GNUNET_free (config_filename);
519 0 : GNUNET_free (testname);
520 0 : return 2;
521 : }
522 0 : GNUNET_SCHEDULER_run (&run,
523 : cfg);
524 0 : GNUNET_CONFIGURATION_destroy (cfg);
525 0 : GNUNET_free (config_filename);
526 0 : GNUNET_free (testname);
527 0 : return result;
528 : }
529 :
530 :
531 : /* end of bench_db.c */
|