diff options
Diffstat (limited to 'src/stasis/plugin_anastasis_postgres.c')
-rw-r--r-- | src/stasis/plugin_anastasis_postgres.c | 78 |
1 files changed, 73 insertions, 5 deletions
diff --git a/src/stasis/plugin_anastasis_postgres.c b/src/stasis/plugin_anastasis_postgres.c index b78dbdb..b1be081 100644 --- a/src/stasis/plugin_anastasis_postgres.c +++ b/src/stasis/plugin_anastasis_postgres.c | |||
@@ -72,6 +72,10 @@ struct PostgresClosure | |||
72 | */ | 72 | */ |
73 | char *currency; | 73 | char *currency; |
74 | 74 | ||
75 | /** | ||
76 | * Prepared statements have been initialized. | ||
77 | */ | ||
78 | bool init; | ||
75 | }; | 79 | }; |
76 | 80 | ||
77 | 81 | ||
@@ -524,38 +528,102 @@ check_connection (void *cls) | |||
524 | 528 | ||
525 | 529 | ||
526 | /** | 530 | /** |
531 | * Connect to the database if the connection does not exist yet. | ||
532 | * | ||
533 | * @param pg the plugin-specific state | ||
534 | * @param skip_prepare true if we should skip prepared statement setup | ||
535 | * @return #GNUNET_OK on success | ||
536 | */ | ||
537 | static enum GNUNET_GenericReturnValue | ||
538 | internal_setup (struct PostgresClosure *pg, | ||
539 | bool skip_prepare) | ||
540 | { | ||
541 | if (NULL == pg->conn) | ||
542 | { | ||
543 | #if AUTO_EXPLAIN | ||
544 | /* Enable verbose logging to see where queries do not | ||
545 | properly use indices */ | ||
546 | struct GNUNET_PQ_ExecuteStatement es[] = { | ||
547 | GNUNET_PQ_make_try_execute ("LOAD 'auto_explain';"), | ||
548 | GNUNET_PQ_make_try_execute ("SET auto_explain.log_min_duration=50;"), | ||
549 | GNUNET_PQ_make_try_execute ("SET auto_explain.log_timing=TRUE;"), | ||
550 | GNUNET_PQ_make_try_execute ("SET auto_explain.log_analyze=TRUE;"), | ||
551 | /* https://wiki.postgresql.org/wiki/Serializable suggests to really | ||
552 | force the default to 'serializable' if SSI is to be used. */ | ||
553 | GNUNET_PQ_make_try_execute ( | ||
554 | "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"), | ||
555 | GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"), | ||
556 | GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"), | ||
557 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
558 | }; | ||
559 | #else | ||
560 | struct GNUNET_PQ_ExecuteStatement *es = NULL; | ||
561 | #endif | ||
562 | struct GNUNET_PQ_Context *db_conn; | ||
563 | |||
564 | db_conn = GNUNET_PQ_connect_with_cfg (pg->cfg, | ||
565 | "exchangedb-postgres", | ||
566 | NULL, | ||
567 | es, | ||
568 | NULL); | ||
569 | if (NULL == db_conn) | ||
570 | return GNUNET_SYSERR; | ||
571 | pg->conn = db_conn; | ||
572 | } | ||
573 | if (NULL == pg->transaction_name) | ||
574 | GNUNET_PQ_reconnect_if_down (pg->conn); | ||
575 | if (pg->init) | ||
576 | return GNUNET_OK; | ||
577 | if (skip_prepare) | ||
578 | return GNUNET_OK; | ||
579 | return postgres_connect (pg); | ||
580 | } | ||
581 | |||
582 | |||
583 | /** | ||
527 | * Do a pre-flight check that we are not in an uncommitted transaction. | 584 | * Do a pre-flight check that we are not in an uncommitted transaction. |
528 | * If we are, try to commit the previous transaction and output a warning. | 585 | * If we are, try to commit the previous transaction and output a warning. |
529 | * Does not return anything, as we will continue regardless of the outcome. | 586 | * Does not return anything, as we will continue regardless of the outcome. |
530 | * | 587 | * |
531 | * @param cls the `struct PostgresClosure` with the plugin-specific state | 588 | * @param cls the `struct PostgresClosure` with the plugin-specific state |
589 | * @return #GNUNET_OK if everything is fine | ||
590 | * #GNUNET_NO if a transaction was rolled back | ||
591 | * #GNUNET_SYSERR on hard errors | ||
532 | */ | 592 | */ |
533 | static void | 593 | static enum GNUNET_GenericReturnValue |
534 | postgres_preflight (void *cls) | 594 | postgres_preflight (void *cls) |
535 | { | 595 | { |
536 | struct PostgresClosure *pg = cls; | 596 | struct PostgresClosure *pg = cls; |
537 | struct GNUNET_PQ_ExecuteStatement es[] = { | 597 | struct GNUNET_PQ_ExecuteStatement es[] = { |
538 | GNUNET_PQ_make_execute ("COMMIT"), | 598 | GNUNET_PQ_make_execute ("ROLLBACK"), |
539 | GNUNET_PQ_EXECUTE_STATEMENT_END | 599 | GNUNET_PQ_EXECUTE_STATEMENT_END |
540 | }; | 600 | }; |
541 | 601 | ||
602 | if (! pg->init) | ||
603 | { | ||
604 | if (GNUNET_OK != | ||
605 | internal_setup (pg, | ||
606 | false)) | ||
607 | return GNUNET_SYSERR; | ||
608 | } | ||
542 | if (NULL == pg->transaction_name) | 609 | if (NULL == pg->transaction_name) |
543 | return; /* all good */ | 610 | return GNUNET_OK; /* all good */ |
544 | if (GNUNET_OK == | 611 | if (GNUNET_OK == |
545 | GNUNET_PQ_exec_statements (pg->conn, | 612 | GNUNET_PQ_exec_statements (pg->conn, |
546 | es)) | 613 | es)) |
547 | { | 614 | { |
548 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 615 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
549 | "BUG: Preflight check committed transaction `%s'!\n", | 616 | "BUG: Preflight check rolled back transaction `%s'!\n", |
550 | pg->transaction_name); | 617 | pg->transaction_name); |
551 | } | 618 | } |
552 | else | 619 | else |
553 | { | 620 | { |
554 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 621 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
555 | "BUG: Preflight check failed to commit transaction `%s'!\n", | 622 | "BUG: Preflight check failed to rollback transaction `%s'!\n", |
556 | pg->transaction_name); | 623 | pg->transaction_name); |
557 | } | 624 | } |
558 | pg->transaction_name = NULL; | 625 | pg->transaction_name = NULL; |
626 | return GNUNET_NO; | ||
559 | } | 627 | } |
560 | 628 | ||
561 | 629 | ||