aboutsummaryrefslogtreecommitdiff
path: root/src/stasis/plugin_anastasis_postgres.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stasis/plugin_anastasis_postgres.c')
-rw-r--r--src/stasis/plugin_anastasis_postgres.c78
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 */
537static enum GNUNET_GenericReturnValue
538internal_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 */
533static void 593static enum GNUNET_GenericReturnValue
534postgres_preflight (void *cls) 594postgres_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