From 947b76cda8b28f8b07e30977ca1c902ed8736dbe Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 6 Sep 2013 08:16:39 +0200 Subject: database: Add interface to handle transactions --- src/libstrongswan/plugins/sqlite/sqlite_database.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src/libstrongswan/plugins/sqlite/sqlite_database.c') diff --git a/src/libstrongswan/plugins/sqlite/sqlite_database.c b/src/libstrongswan/plugins/sqlite/sqlite_database.c index 41d45dee7..6c8b48324 100644 --- a/src/libstrongswan/plugins/sqlite/sqlite_database.c +++ b/src/libstrongswan/plugins/sqlite/sqlite_database.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -280,6 +281,24 @@ METHOD(database_t, execute, int, return affected; } +METHOD(database_t, transaction, bool, + private_sqlite_database_t *this) +{ + return FALSE; +} + +METHOD(database_t, commit, bool, + private_sqlite_database_t *this) +{ + return FALSE; +} + +METHOD(database_t, rollback, bool, + private_sqlite_database_t *this) +{ + return FALSE; +} + METHOD(database_t, get_driver, db_driver_t, private_sqlite_database_t *this) { @@ -330,6 +349,9 @@ sqlite_database_t *sqlite_database_create(char *uri) .db = { .query = _query, .execute = _execute, + .transaction = _transaction, + .commit = _commit, + .rollback = _rollback, .get_driver = _get_driver, .destroy = _destroy, }, -- cgit v1.2.3 From fad11d602dc6f969b9d2207a3d3c736fad418812 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 5 Sep 2013 16:50:23 +0200 Subject: sqlite: Implement transaction handling --- src/libstrongswan/plugins/sqlite/sqlite_database.c | 89 ++++++++++++++++++++-- 1 file changed, 83 insertions(+), 6 deletions(-) (limited to 'src/libstrongswan/plugins/sqlite/sqlite_database.c') diff --git a/src/libstrongswan/plugins/sqlite/sqlite_database.c b/src/libstrongswan/plugins/sqlite/sqlite_database.c index 6c8b48324..b5ed7eed2 100644 --- a/src/libstrongswan/plugins/sqlite/sqlite_database.c +++ b/src/libstrongswan/plugins/sqlite/sqlite_database.c @@ -21,6 +21,7 @@ #include #include #include +#include typedef struct private_sqlite_database_t private_sqlite_database_t; @@ -40,11 +41,33 @@ struct private_sqlite_database_t { sqlite3 *db; /** - * mutex used to lock execute() + * thread-specific transaction, as transaction_t + */ + thread_value_t *transaction; + + /** + * mutex used to lock execute(), if necessary */ mutex_t *mutex; }; +/** + * Database transaction + */ +typedef struct { + + /** + * Refcounter if transaction() is called multiple times + */ + refcount_t refs; + + /** + * TRUE if transaction was rolled back + */ + bool rollback; + +} transaction_t; + /** * Create and run a sqlite stmt using a sql string and args */ @@ -284,19 +307,72 @@ METHOD(database_t, execute, int, METHOD(database_t, transaction, bool, private_sqlite_database_t *this) { - return FALSE; + transaction_t *trans; + + trans = this->transaction->get(this->transaction); + if (trans) + { + ref_get(&trans->refs); + return TRUE; + } + if (execute(this, NULL, "BEGIN EXCLUSIVE TRANSACTION") == -1) + { + return FALSE; + } + INIT(trans, + .refs = 1, + ); + this->transaction->set(this->transaction, trans); + return TRUE; +} + +/** + * Finalize a transaction depending on the reference count and if it should be + * rolled back. + */ +static bool finalize_transaction(private_sqlite_database_t *this, + bool rollback) +{ + transaction_t *trans; + char *command = "COMMIT TRANSACTION"; + bool success; + + trans = this->transaction->get(this->transaction); + if (!trans) + { + DBG1(DBG_LIB, "no database transaction found"); + return FALSE; + } + + if (ref_put(&trans->refs)) + { + if (trans->rollback) + { + command = "ROLLBACK TRANSACTION"; + } + success = execute(this, NULL, command) != -1; + + this->transaction->set(this->transaction, NULL); + free(trans); + return success; + } + else + { /* set flag, can't be unset */ + trans->rollback |= rollback; + } + return TRUE; } METHOD(database_t, commit, bool, private_sqlite_database_t *this) { - return FALSE; + return finalize_transaction(this, FALSE); } METHOD(database_t, rollback, bool, private_sqlite_database_t *this) { - return FALSE; + return finalize_transaction(this, TRUE); } METHOD(database_t, get_driver, db_driver_t, @@ -323,6 +399,7 @@ METHOD(database_t, destroy, void, { DBG1(DBG_LIB, "sqlite close failed because database is busy"); } + this->transaction->destroy(this->transaction); this->mutex->destroy(this->mutex); free(this); } @@ -357,13 +434,14 @@ sqlite_database_t *sqlite_database_create(char *uri) }, }, .mutex = mutex_create(MUTEX_TYPE_RECURSIVE), + .transaction = thread_value_create(NULL), ); if (sqlite3_open(file, &this->db) != SQLITE_OK) { DBG1(DBG_LIB, "opening SQLite database '%s' failed: %s", file, sqlite3_errmsg(this->db)); - _destroy(this); + destroy(this); return NULL; } @@ -371,4 +449,3 @@ sqlite_database_t *sqlite_database_create(char *uri) return &this->public; } - -- cgit v1.2.3 From b283a6e9efd2ff16ec5b189435604b0d82d714cd Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 10 Oct 2013 10:58:40 +0200 Subject: database: Add support for serializable transactions --- src/libstrongswan/plugins/sqlite/sqlite_database.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/libstrongswan/plugins/sqlite/sqlite_database.c') diff --git a/src/libstrongswan/plugins/sqlite/sqlite_database.c b/src/libstrongswan/plugins/sqlite/sqlite_database.c index b5ed7eed2..7b4767855 100644 --- a/src/libstrongswan/plugins/sqlite/sqlite_database.c +++ b/src/libstrongswan/plugins/sqlite/sqlite_database.c @@ -305,9 +305,11 @@ METHOD(database_t, execute, int, } METHOD(database_t, transaction, bool, - private_sqlite_database_t *this) + private_sqlite_database_t *this, bool serializable) { transaction_t *trans; + char *cmd = serializable ? "BEGIN EXCLUSIVE TRANSACTION" + : "BEGIN TRANSACTION"; trans = this->transaction->get(this->transaction); if (trans) @@ -315,7 +317,7 @@ METHOD(database_t, transaction, bool, ref_get(&trans->refs); return TRUE; } - if (execute(this, NULL, "BEGIN EXCLUSIVE TRANSACTION") == -1) + if (execute(this, NULL, cmd) == -1) { return FALSE; } -- cgit v1.2.3