diff --git a/CMakeLists.txt b/CMakeLists.txt index 15c8afa..45b8ccb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required (VERSION 3.7) project(core - VERSION 0.2.11 + VERSION 0.2.12 LANGUAGES C) add_executable(core src/main.c) diff --git a/include/database.h b/include/database.h index 225ae47..877e166 100644 --- a/include/database.h +++ b/include/database.h @@ -5,7 +5,23 @@ extern sqlite3 *global_database; +void +database_init(); + +void +database_free(); + int database_migrate(); + +int +database_transaction_begin(); + +void +database_transaction_commit(); + +void +database_transaction_rollback(); + #endif /* CORE_DATABASE_H */ diff --git a/src/database.c b/src/database.c index 50587cf..48335fb 100644 --- a/src/database.c +++ b/src/database.c @@ -7,6 +7,33 @@ #include 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 database_migrate() @@ -65,3 +92,32 @@ database_migrate() 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; +} diff --git a/src/main.c b/src/main.c index 367259e..525c710 100644 --- a/src/main.c +++ b/src/main.c @@ -27,8 +27,7 @@ terminate(int signum) mg_mgr_free(&mgr); - sqlite3_close(global_database); - + database_free(); router_free(); status_free(); cache_free(); @@ -133,26 +132,9 @@ main(int argc, const char** argv) 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 ********************/ + database_init(); cache_init(); router_init(); status_init(); diff --git a/src/models/controller.c b/src/models/controller.c index 2c90e6b..b70184a 100644 --- a/src/models/controller.c +++ b/src/models/controller.c @@ -116,6 +116,8 @@ controller_db_select(sqlite3_stmt *stmt) int controller_save(controller_t *controller) { + int opened_transaction = database_transaction_begin(); + sqlite3_stmt *stmt; if(controller->id) { @@ -138,6 +140,11 @@ controller_save(controller_t *controller) { LOGGER_ERR("error updating data: %s\n", sqlite3_errmsg(global_database)); } + + if(opened_transaction) + { + database_transaction_rollback(); + } } else { @@ -145,6 +152,11 @@ controller_save(controller_t *controller) { controller->id = sqlite3_last_insert_rowid(global_database); } + + if(opened_transaction) + { + database_transaction_commit(); + } } cache_invalidate_controller(controller->id); diff --git a/src/models/relay.c b/src/models/relay.c index d6c1f3b..a5fe564 100644 --- a/src/models/relay.c +++ b/src/models/relay.c @@ -126,6 +126,8 @@ relay_db_select(sqlite3_stmt *stmt) int relay_save(relay_t *relay) { + int opened_transaction = database_transaction_begin(); + sqlite3_stmt *stmt; if(relay->id) { @@ -148,6 +150,11 @@ relay_save(relay_t *relay) { LOGGER_ERR("error updating data: %s\n", sqlite3_errmsg(global_database)); } + + if(opened_transaction) + { + database_transaction_rollback(); + } } else { @@ -155,16 +162,20 @@ relay_save(relay_t *relay) { 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"); - junction_relay_schedule_remove_for_relay(relay->id); + LOGGER_DEBUG("rebuilding relay_schedule junction\n"); + 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"); - for(int i = 0; i < 7; ++i) - { - junction_relay_schedule_insert(i, relay->id, relay->schedules[i]->id); + if(opened_transaction) + { + database_transaction_commit(); + } } cache_invalidate_relay(relay->id); diff --git a/src/models/schedule.c b/src/models/schedule.c index 52ecba2..cd1d783 100644 --- a/src/models/schedule.c +++ b/src/models/schedule.c @@ -112,6 +112,8 @@ schedule_db_select(sqlite3_stmt *stmt) int schedule_save(schedule_t *schedule) { + int opened_transaction = database_transaction_begin(); + sqlite3_stmt *stmt; if(schedule->id) { @@ -134,6 +136,11 @@ schedule_save(schedule_t *schedule) { LOGGER_ERR("error updating data: %s\n", sqlite3_errmsg(global_database)); } + + if(opened_transaction) + { + database_transaction_rollback(); + } } else { @@ -141,6 +148,11 @@ schedule_save(schedule_t *schedule) { schedule->id = sqlite3_last_insert_rowid(global_database); } + + if(opened_transaction) + { + database_transaction_commit(); + } } cache_invalidate_schedule(schedule->id); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 8b259b9..fb43731 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -8,7 +8,7 @@ alias valgrind_emgauwa="valgrind $2 --log-file=$working_dir/valgrind.log" rm -rf $working_bak -mv $working_dir $working_bak +[ -d $working_dir ] && mv $working_dir $working_bak mkdir -p $working_dir cd $working_dir @@ -53,7 +53,7 @@ core_id=$! # 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