add: database transactions

This commit is contained in:
Tobias Reisinger 2020-08-15 12:13:03 +02:00
parent 7fa462ef1d
commit 7c6eed8dc2
8 changed files with 119 additions and 30 deletions

View file

@ -1,6 +1,6 @@
cmake_minimum_required (VERSION 3.7) cmake_minimum_required (VERSION 3.7)
project(core project(core
VERSION 0.2.11 VERSION 0.2.12
LANGUAGES C) LANGUAGES C)
add_executable(core src/main.c) add_executable(core src/main.c)

View file

@ -5,7 +5,23 @@
extern sqlite3 *global_database; extern sqlite3 *global_database;
void
database_init();
void
database_free();
int int
database_migrate(); database_migrate();
int
database_transaction_begin();
void
database_transaction_commit();
void
database_transaction_rollback();
#endif /* CORE_DATABASE_H */ #endif /* CORE_DATABASE_H */

View file

@ -7,6 +7,33 @@
#include <sql/migration_0.h> #include <sql/migration_0.h>
sqlite3 *global_database; sqlite3 *global_database;
static int in_transaction;
void
database_init()
{
int rc = sqlite3_open(global_config.database, &global_database);
if(rc)
{
LOGGER_CRIT("can't open database: %s\n", sqlite3_errmsg(global_database));
exit(1);
}
if(database_migrate())
{
exit(1);
}
sqlite3_exec(global_database, "PRAGMA foreign_keys = ON", 0, 0, 0);
in_transaction = 0;
}
void
database_free()
{
sqlite3_close(global_database);
}
int int
database_migrate() database_migrate()
@ -65,3 +92,32 @@ database_migrate()
return rc != SQLITE_DONE; return rc != SQLITE_DONE;
} }
int
database_transaction_begin()
{
if(!in_transaction)
{
LOGGER_DEBUG("beginning transaction\n");
sqlite3_exec(global_database, "BEGIN TRANSACTION;", NULL, NULL, NULL);
in_transaction = 1;
return 1;
}
return 0;
}
void
database_transaction_commit()
{
LOGGER_DEBUG("commiting transaction\n");
sqlite3_exec(global_database, "COMMIT TRANSACTION;", NULL, NULL, NULL);
in_transaction = 0;
}
void
database_transaction_rollback()
{
LOGGER_DEBUG("rolling back transaction\n");
sqlite3_exec(global_database, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
in_transaction = 0;
}

View file

@ -27,8 +27,7 @@ terminate(int signum)
mg_mgr_free(&mgr); mg_mgr_free(&mgr);
sqlite3_close(global_database); database_free();
router_free(); router_free();
status_free(); status_free();
cache_free(); cache_free();
@ -133,26 +132,9 @@ main(int argc, const char** argv)
helper_drop_privileges(); helper_drop_privileges();
/******************** SETUP DATABASE ********************/
int rc = sqlite3_open(global_config.database, &global_database);
if(rc)
{
LOGGER_CRIT("can't open database: %s\n", sqlite3_errmsg(global_database));
return 1;
}
if(database_migrate())
{
terminate(1);
}
sqlite3_exec(global_database, "PRAGMA foreign_keys = ON", 0, 0, 0);
/******************** INIT COMPONENTS ********************/ /******************** INIT COMPONENTS ********************/
database_init();
cache_init(); cache_init();
router_init(); router_init();
status_init(); status_init();

View file

@ -116,6 +116,8 @@ controller_db_select(sqlite3_stmt *stmt)
int int
controller_save(controller_t *controller) controller_save(controller_t *controller)
{ {
int opened_transaction = database_transaction_begin();
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
if(controller->id) if(controller->id)
{ {
@ -138,6 +140,11 @@ controller_save(controller_t *controller)
{ {
LOGGER_ERR("error updating data: %s\n", sqlite3_errmsg(global_database)); LOGGER_ERR("error updating data: %s\n", sqlite3_errmsg(global_database));
} }
if(opened_transaction)
{
database_transaction_rollback();
}
} }
else else
{ {
@ -145,6 +152,11 @@ controller_save(controller_t *controller)
{ {
controller->id = sqlite3_last_insert_rowid(global_database); controller->id = sqlite3_last_insert_rowid(global_database);
} }
if(opened_transaction)
{
database_transaction_commit();
}
} }
cache_invalidate_controller(controller->id); cache_invalidate_controller(controller->id);

View file

@ -126,6 +126,8 @@ relay_db_select(sqlite3_stmt *stmt)
int int
relay_save(relay_t *relay) relay_save(relay_t *relay)
{ {
int opened_transaction = database_transaction_begin();
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
if(relay->id) if(relay->id)
{ {
@ -148,6 +150,11 @@ relay_save(relay_t *relay)
{ {
LOGGER_ERR("error updating data: %s\n", sqlite3_errmsg(global_database)); LOGGER_ERR("error updating data: %s\n", sqlite3_errmsg(global_database));
} }
if(opened_transaction)
{
database_transaction_rollback();
}
} }
else else
{ {
@ -155,16 +162,20 @@ relay_save(relay_t *relay)
{ {
relay->id = sqlite3_last_insert_rowid(global_database); relay->id = sqlite3_last_insert_rowid(global_database);
} }
}
LOGGER_DEBUG("cleaning relay_schedule junction\n");
junction_relay_schedule_remove_for_relay(relay->id);
LOGGER_DEBUG("cleaning relay_schedule junction\n"); LOGGER_DEBUG("rebuilding relay_schedule junction\n");
junction_relay_schedule_remove_for_relay(relay->id); for(int i = 0; i < 7; ++i)
{
junction_relay_schedule_insert(i, relay->id, relay->schedules[i]->id);
}
LOGGER_DEBUG("rebuilding relay_schedule junction\n"); if(opened_transaction)
for(int i = 0; i < 7; ++i) {
{ database_transaction_commit();
junction_relay_schedule_insert(i, relay->id, relay->schedules[i]->id); }
} }
cache_invalidate_relay(relay->id); cache_invalidate_relay(relay->id);

View file

@ -112,6 +112,8 @@ schedule_db_select(sqlite3_stmt *stmt)
int int
schedule_save(schedule_t *schedule) schedule_save(schedule_t *schedule)
{ {
int opened_transaction = database_transaction_begin();
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
if(schedule->id) if(schedule->id)
{ {
@ -134,6 +136,11 @@ schedule_save(schedule_t *schedule)
{ {
LOGGER_ERR("error updating data: %s\n", sqlite3_errmsg(global_database)); LOGGER_ERR("error updating data: %s\n", sqlite3_errmsg(global_database));
} }
if(opened_transaction)
{
database_transaction_rollback();
}
} }
else else
{ {
@ -141,6 +148,11 @@ schedule_save(schedule_t *schedule)
{ {
schedule->id = sqlite3_last_insert_rowid(global_database); schedule->id = sqlite3_last_insert_rowid(global_database);
} }
if(opened_transaction)
{
database_transaction_commit();
}
} }
cache_invalidate_schedule(schedule->id); cache_invalidate_schedule(schedule->id);

View file

@ -8,7 +8,7 @@ alias valgrind_emgauwa="valgrind $2 --log-file=$working_dir/valgrind.log"
rm -rf $working_bak rm -rf $working_bak
mv $working_dir $working_bak [ -d $working_dir ] && mv $working_dir $working_bak
mkdir -p $working_dir mkdir -p $working_dir
cd $working_dir cd $working_dir
@ -53,7 +53,7 @@ core_id=$!
# wait for start # wait for start
sleep 3; sleep 5;
curl -s -o /dev/null --retry 5 --retry-all-errors --retry-connrefused http://localhost:5000/api/v1/tags curl -s -o /dev/null --retry 5 --retry-all-errors --retry-connrefused http://localhost:5000/api/v1/tags