db: Track the data_version in the database

This increments the `data_version` upon committing dirty transactions, reads
the last data_version upon startup, and tracks the number in memory in
parallel to the DB (see next commit for rationale).

Changelog-Changed: JSON-RPC: Added a `data_version` field to the `db_write` hook which returns a numeric transaction counter.
This commit is contained in:
Christian Decker 2019-12-18 19:45:24 +01:00 committed by neil saitug
parent 4a4184be70
commit 2c11c54dd2
6 changed files with 43 additions and 0 deletions

View File

@ -175,6 +175,8 @@ void plugin_hook_db_sync(struct db *db)
ph_req->hook = hook;
ph_req->db = db;
json_add_num(req->stream, "data_version", db_data_version_get(db));
json_array_start(req->stream, "writes");
for (size_t i = 0; i < tal_count(changes); i++)
json_add_string(req->stream, NULL, changes[i]);

View File

@ -802,11 +802,27 @@ void db_begin_transaction_(struct db *db, const char *location)
db->in_transaction = location;
}
static void db_data_version_incr(struct db *db)
{
struct db_stmt *stmt = db_prepare_v2(
db, SQL("UPDATE vars "
"SET intval = intval + 1 "
"WHERE name = 'data_version'"));
db_exec_prepared_v2(stmt);
tal_free(stmt);
db->data_version++;
}
void db_commit_transaction(struct db *db)
{
bool ok;
assert(db->in_transaction);
db_assert_no_outstanding_statements(db);
/* Increment before reporting changes to an eventual plugin. */
if (db->dirty)
db_data_version_incr(db);
db_report_changes(db, NULL, 0);
ok = db->config->commit_tx_fn(db);
@ -954,7 +970,18 @@ static void db_migrate(struct lightningd *ld, struct db *db)
db_exec_prepared_v2(stmt);
tal_free(stmt);
}
}
u32 db_data_version_get(struct db *db)
{
struct db_stmt *stmt;
u32 version;
stmt = db_prepare_v2(db, SQL("SELECT intval FROM vars WHERE name = 'data_version'"));
db_query_prepared(stmt);
db_step(stmt);
version = db_column_int(stmt, 0);
tal_free(stmt);
return version;
}
struct db *db_setup(const tal_t *ctx, struct lightningd *ld)
@ -966,6 +993,7 @@ struct db *db_setup(const tal_t *ctx, struct lightningd *ld)
db_migrate(ld, db);
db->data_version = db_data_version_get(db);
db_commit_transaction(db);
return db;
}

View File

@ -229,4 +229,7 @@ struct db_stmt *db_prepare_v2_(const char *location, struct db *db,
*/
const char **db_changes(struct db *db);
/* Get the current data version. */
u32 db_data_version_get(struct db *db);
#endif /* LIGHTNING_WALLET_DB_H */

View File

@ -34,6 +34,10 @@ struct db {
/* Were there any modifying statements in the current transaction?
* Used to bump the data_version in the DB.*/
bool dirty;
/* The current DB version we expect to update if changes are
* committed. */
u32 data_version;
};
struct db_query {

View File

@ -63,6 +63,7 @@ static struct db *create_test_db(void)
dsn = tal_fmt(NULL, "sqlite3://%s", filename);
db = db_open(NULL, dsn);
db->data_version = 0;
tal_free(dsn);
return db;
}
@ -107,6 +108,10 @@ static bool test_primitives(void)
CHECK_MSG(db_err, "Failing SQL command");
tal_free(stmt);
db_err = tal_free(db_err);
/* We didn't migrate the DB, so don't have the vars table. Pretend we
* didn't change anything so we don't bump the data_version. */
db->dirty = false;
db_commit_transaction(db);
CHECK(!db->in_transaction);
tal_free(db);

View File

@ -749,6 +749,7 @@ static struct wallet *create_test_wallet(struct lightningd *ld, const tal_t *ctx
CHECK_MSG(w->db, "Failed opening the db");
db_begin_transaction(w->db);
db_migrate(ld, w->db);
w->db->data_version = 0;
db_commit_transaction(w->db);
CHECK_MSG(!wallet_err, "DB migration failed");
w->max_channel_dbid = 0;