diff options
author | Tobias Brunner <tobias@strongswan.org> | 2013-09-05 16:50:23 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2013-10-11 15:16:05 +0200 |
commit | fad11d602dc6f969b9d2207a3d3c736fad418812 (patch) | |
tree | 849190dc5347695d739542e04bbfc4d99bbb9938 /src/libstrongswan/plugins/sqlite/sqlite_database.c | |
parent | f3cb889c9b4539ef0669fd080122fb129a5eea67 (diff) | |
download | strongswan-fad11d602dc6f969b9d2207a3d3c736fad418812.tar.bz2 strongswan-fad11d602dc6f969b9d2207a3d3c736fad418812.tar.xz |
sqlite: Implement transaction handling
Diffstat (limited to 'src/libstrongswan/plugins/sqlite/sqlite_database.c')
-rw-r--r-- | src/libstrongswan/plugins/sqlite/sqlite_database.c | 89 |
1 files changed, 83 insertions, 6 deletions
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 <library.h> #include <utils/debug.h> #include <threading/mutex.h> +#include <threading/thread_value.h> typedef struct private_sqlite_database_t private_sqlite_database_t; @@ -40,12 +41,34 @@ 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 */ static sqlite3_stmt* run(private_sqlite_database_t *this, char *sql, @@ -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; } - |