1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-09 23:39:51 +02:00

g10: Support nested transactions on the TOFU DB.

* g10/gpg.h (struct server_control_s): New field in_transaction.
* g10/tofu.c (struct tofu_dbs_s): Remove fields savepoint_inner and
savepoint_inner_commit.
(begin_transaction): Increment CTRL->TOFU.IN_TRANSACTION.  Name the
savepoint according to the nesting level.
(end_transaction): Name the savepoint according to the nesting level.
Decrement CTRL->TOFU.IN_TRANSACTION.
(rollback_transaction): Likewise.  Only ever rollback a non-batch
transaction.
(opendbs): Assert that there are no outstanding transactions.

--
Signed-off-by: Neal H. Walfield <neal@g10code.com>
This commit is contained in:
Neal H. Walfield 2016-08-29 15:13:45 +02:00
parent 4c2abb221b
commit 33e97813d7
2 changed files with 22 additions and 20 deletions

View File

@ -82,6 +82,7 @@ struct server_control_s
/* Local data for tofu.c */ /* Local data for tofu.c */
struct { struct {
tofu_dbs_t dbs; tofu_dbs_t dbs;
int in_transaction;
int batch_update_ref; int batch_update_ref;
time_t batch_update_started; time_t batch_update_started;
} tofu; } tofu;

View File

@ -70,9 +70,6 @@ struct tofu_dbs_s
sqlite3_stmt *savepoint_batch; sqlite3_stmt *savepoint_batch;
sqlite3_stmt *savepoint_batch_commit; sqlite3_stmt *savepoint_batch_commit;
sqlite3_stmt *savepoint_inner;
sqlite3_stmt *savepoint_inner_commit;
sqlite3_stmt *record_binding_get_old_policy; sqlite3_stmt *record_binding_get_old_policy;
sqlite3_stmt *record_binding_update; sqlite3_stmt *record_binding_update;
sqlite3_stmt *record_binding_update2; sqlite3_stmt *record_binding_update2;
@ -209,9 +206,12 @@ begin_transaction (ctrl_t ctrl, int only_batch)
if (only_batch) if (only_batch)
return 0; return 0;
rc = gpgsql_stepx (dbs->db, &dbs->s.savepoint_inner, log_assert(ctrl->tofu.in_transaction >= 0);
NULL, NULL, &err, ctrl->tofu.in_transaction ++;
"savepoint inner;", SQLITE_ARG_END);
rc = gpgsql_exec_printf (dbs->db, NULL, NULL, &err,
"savepoint inner%d;",
ctrl->tofu.in_transaction);
if (rc) if (rc)
{ {
log_error (_("error beginning transaction on TOFU database: %s\n"), log_error (_("error beginning transaction on TOFU database: %s\n"),
@ -263,9 +263,9 @@ end_transaction (ctrl_t ctrl, int only_batch)
if (only_batch) if (only_batch)
return 0; return 0;
rc = gpgsql_stepx (dbs->db, &dbs->s.savepoint_inner_commit, log_assert (ctrl->tofu.in_transaction > 0);
NULL, NULL, &err, rc = gpgsql_exec_printf (dbs->db, NULL, NULL, &err,
"release inner;", SQLITE_ARG_END); "release inner%d;", ctrl->tofu.in_transaction);
if (rc) if (rc)
{ {
log_error (_("error committing transaction on TOFU database: %s\n"), log_error (_("error committing transaction on TOFU database: %s\n"),
@ -274,6 +274,8 @@ end_transaction (ctrl_t ctrl, int only_batch)
return gpg_error (GPG_ERR_GENERAL); return gpg_error (GPG_ERR_GENERAL);
} }
ctrl->tofu.in_transaction --;
return 0; return 0;
} }
@ -287,18 +289,15 @@ rollback_transaction (ctrl_t ctrl)
if (!dbs) if (!dbs)
return 0; /* Shortcut to allow for easier cleanup code. */ return 0; /* Shortcut to allow for easier cleanup code. */
log_assert (ctrl->tofu.in_transaction > 0);
if (dbs->batch_update) /* Be careful to not any progress made by closed transactions in
{ batch mode. */
/* Just undo the most recent update; don't revert any progress rc = gpgsql_exec_printf (dbs->db, NULL, NULL, &err,
made by the batch transaction. */ "rollback to inner%d;",
rc = sqlite3_exec (dbs->db, "rollback to inner;", NULL, NULL, &err); ctrl->tofu.in_transaction);
}
else ctrl->tofu.in_transaction --;
{
/* Rollback the whole she-bang. */
rc = sqlite3_exec (dbs->db, "rollback;", NULL, NULL, &err);
}
if (rc) if (rc)
{ {
@ -694,6 +693,8 @@ tofu_closedbs (ctrl_t ctrl)
tofu_dbs_t dbs; tofu_dbs_t dbs;
sqlite3_stmt **statements; sqlite3_stmt **statements;
log_assert(ctrl->tofu.in_transaction == 0);
dbs = ctrl->tofu.dbs; dbs = ctrl->tofu.dbs;
if (!dbs) if (!dbs)
return; /* Not initialized. */ return; /* Not initialized. */