Annotation of embedaddon/strongswan/src/libstrongswan/plugins/sqlite/sqlite_database.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2013 Tobias Brunner
3: * Copyright (C) 2007 Martin Willi
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: #include "sqlite_database.h"
18:
19: #include <sqlite3.h>
20: #include <unistd.h>
21: #include <library.h>
22: #include <utils/debug.h>
23: #include <threading/mutex.h>
24: #include <threading/thread_value.h>
25:
26: typedef struct private_sqlite_database_t private_sqlite_database_t;
27:
28: /**
29: * private data of sqlite_database
30: */
31: struct private_sqlite_database_t {
32:
33: /**
34: * public functions
35: */
36: sqlite_database_t public;
37:
38: /**
39: * sqlite database connection
40: */
41: sqlite3 *db;
42:
43: /**
44: * thread-specific transaction, as transaction_t
45: */
46: thread_value_t *transaction;
47:
48: /**
49: * mutex used to lock execute(), if necessary
50: */
51: mutex_t *mutex;
52: };
53:
54: /**
55: * Database transaction
56: */
57: typedef struct {
58:
59: /**
60: * Refcounter if transaction() is called multiple times
61: */
62: refcount_t refs;
63:
64: /**
65: * TRUE if transaction was rolled back
66: */
67: bool rollback;
68:
69: } transaction_t;
70:
71: /**
72: * Check if the SQLite library is thread safe
73: */
74: static bool is_threadsafe()
75: {
76: #if SQLITE_VERSION_NUMBER >= 3005000
77: return sqlite3_threadsafe() > 0;
78: #endif
79: /* sqlite connections prior to 3.5 may be used by a single thread only */
80: return FALSE;
81: }
82:
83: /**
84: * Create and run a sqlite stmt using a sql string and args
85: */
86: static sqlite3_stmt* run(private_sqlite_database_t *this, char *sql,
87: va_list *args)
88: {
89: sqlite3_stmt *stmt = NULL;
90: int params, i, res = SQLITE_OK;
91:
92: #ifdef HAVE_SQLITE3_PREPARE_V2
93: if (sqlite3_prepare_v2(this->db, sql, -1, &stmt, NULL) == SQLITE_OK)
94: #else
95: if (sqlite3_prepare(this->db, sql, -1, &stmt, NULL) == SQLITE_OK)
96: #endif
97: {
98: params = sqlite3_bind_parameter_count(stmt);
99: for (i = 1; i <= params; i++)
100: {
101: switch (va_arg(*args, db_type_t))
102: {
103: case DB_INT:
104: {
105: res = sqlite3_bind_int(stmt, i, va_arg(*args, int));
106: break;
107: }
108: case DB_UINT:
109: {
110: res = sqlite3_bind_int64(stmt, i, va_arg(*args, u_int));
111: break;
112: }
113: case DB_TEXT:
114: {
115: const char *text = va_arg(*args, const char*);
116: res = sqlite3_bind_text(stmt, i, text, -1,
117: SQLITE_TRANSIENT);
118: break;
119: }
120: case DB_BLOB:
121: {
122: chunk_t c = va_arg(*args, chunk_t);
123: res = sqlite3_bind_blob(stmt, i, c.ptr, c.len,
124: SQLITE_TRANSIENT);
125: break;
126: }
127: case DB_DOUBLE:
128: {
129: res = sqlite3_bind_double(stmt, i, va_arg(*args, double));
130: break;
131: }
132: case DB_NULL:
133: {
134: res = sqlite3_bind_null(stmt, i);
135: break;
136: }
137: default:
138: {
139: res = SQLITE_MISUSE;
140: break;
141: }
142: }
143: if (res != SQLITE_OK)
144: {
145: break;
146: }
147: }
148: }
149: else
150: {
151: DBG1(DBG_LIB, "preparing sqlite statement failed: %s",
152: sqlite3_errmsg(this->db));
153: }
154: if (res != SQLITE_OK)
155: {
156: DBG1(DBG_LIB, "binding sqlite statement failed: %s",
157: sqlite3_errmsg(this->db));
158: sqlite3_finalize(stmt);
159: return NULL;
160: }
161: return stmt;
162: }
163:
164: typedef struct {
165: /** implements enumerator_t */
166: enumerator_t public;
167: /** associated sqlite statement */
168: sqlite3_stmt *stmt;
169: /** number of result columns */
170: int count;
171: /** column types */
172: db_type_t *columns;
173: /** back reference to parent */
174: private_sqlite_database_t *database;
175: } sqlite_enumerator_t;
176:
177: METHOD(enumerator_t, sqlite_enumerator_destroy, void,
178: sqlite_enumerator_t *this)
179: {
180: sqlite3_finalize(this->stmt);
181: if (!is_threadsafe())
182: {
183: this->database->mutex->unlock(this->database->mutex);
184: }
185: free(this->columns);
186: free(this);
187: }
188:
189: METHOD(enumerator_t, sqlite_enumerator_enumerate, bool,
190: sqlite_enumerator_t *this, va_list args)
191: {
192: int i;
193:
194: switch (sqlite3_step(this->stmt))
195: {
196: case SQLITE_ROW:
197: break;
198: default:
199: DBG1(DBG_LIB, "stepping sqlite statement failed: %s",
200: sqlite3_errmsg(this->database->db));
201: /* fall */
202: case SQLITE_DONE:
203: return FALSE;
204: }
205:
206: for (i = 0; i < this->count; i++)
207: {
208: switch (this->columns[i])
209: {
210: case DB_INT:
211: {
212: int *value = va_arg(args, int*);
213: *value = sqlite3_column_int(this->stmt, i);
214: break;
215: }
216: case DB_UINT:
217: {
218: u_int *value = va_arg(args, u_int*);
219: *value = (u_int)sqlite3_column_int64(this->stmt, i);
220: break;
221: }
222: case DB_TEXT:
223: {
224: const unsigned char **value = va_arg(args, const unsigned char**);
225: *value = sqlite3_column_text(this->stmt, i);
226: break;
227: }
228: case DB_BLOB:
229: {
230: chunk_t *chunk = va_arg(args, chunk_t*);
231: chunk->len = sqlite3_column_bytes(this->stmt, i);
232: chunk->ptr = (u_char*)sqlite3_column_blob(this->stmt, i);
233: break;
234: }
235: case DB_DOUBLE:
236: {
237: double *value = va_arg(args, double*);
238: *value = sqlite3_column_double(this->stmt, i);
239: break;
240: }
241: default:
242: DBG1(DBG_LIB, "invalid result type supplied");
243: return FALSE;
244: }
245: }
246: return TRUE;
247: }
248:
249: METHOD(database_t, query, enumerator_t*,
250: private_sqlite_database_t *this, char *sql, ...)
251: {
252: sqlite3_stmt *stmt;
253: va_list args;
254: sqlite_enumerator_t *enumerator = NULL;
255: int i;
256:
257: if (!is_threadsafe())
258: {
259: this->mutex->lock(this->mutex);
260: }
261:
262: va_start(args, sql);
263: stmt = run(this, sql, &args);
264: if (stmt)
265: {
266: INIT(enumerator,
267: .public = {
268: .enumerate = enumerator_enumerate_default,
269: .venumerate = _sqlite_enumerator_enumerate,
270: .destroy = _sqlite_enumerator_destroy,
271: },
272: .stmt = stmt,
273: .count = sqlite3_column_count(stmt),
274: .database = this,
275: );
276: enumerator->columns = malloc(sizeof(db_type_t) * enumerator->count);
277: for (i = 0; i < enumerator->count; i++)
278: {
279: enumerator->columns[i] = va_arg(args, db_type_t);
280: }
281: }
282: va_end(args);
283: return (enumerator_t*)enumerator;
284: }
285:
286: METHOD(database_t, execute, int,
287: private_sqlite_database_t *this, int *rowid, char *sql, ...)
288: {
289: sqlite3_stmt *stmt;
290: int affected = -1;
291: va_list args;
292:
293: /* we need a lock to get our rowid/changes correctly */
294: this->mutex->lock(this->mutex);
295: va_start(args, sql);
296: stmt = run(this, sql, &args);
297: va_end(args);
298: if (stmt)
299: {
300: if (sqlite3_step(stmt) == SQLITE_DONE)
301: {
302: if (rowid)
303: {
304: *rowid = sqlite3_last_insert_rowid(this->db);
305: }
306: affected = sqlite3_changes(this->db);
307: }
308: else
309: {
310: DBG1(DBG_LIB, "sqlite execute failed: %s",
311: sqlite3_errmsg(this->db));
312: }
313: sqlite3_finalize(stmt);
314: }
315: this->mutex->unlock(this->mutex);
316: return affected;
317: }
318:
319: METHOD(database_t, transaction, bool,
320: private_sqlite_database_t *this, bool serializable)
321: {
322: transaction_t *trans;
323: char *cmd = serializable ? "BEGIN EXCLUSIVE TRANSACTION"
324: : "BEGIN TRANSACTION";
325:
326: trans = this->transaction->get(this->transaction);
327: if (trans)
328: {
329: ref_get(&trans->refs);
330: return TRUE;
331: }
332: if (execute(this, NULL, cmd) == -1)
333: {
334: return FALSE;
335: }
336: INIT(trans,
337: .refs = 1,
338: );
339: this->transaction->set(this->transaction, trans);
340: return TRUE;
341: }
342:
343: /**
344: * Finalize a transaction depending on the reference count and if it should be
345: * rolled back.
346: */
347: static bool finalize_transaction(private_sqlite_database_t *this,
348: bool rollback)
349: {
350: transaction_t *trans;
351: char *command = "COMMIT TRANSACTION";
352: bool success;
353:
354: trans = this->transaction->get(this->transaction);
355: if (!trans)
356: {
357: DBG1(DBG_LIB, "no database transaction found");
358: return FALSE;
359: }
360:
361: if (ref_put(&trans->refs))
362: {
363: if (trans->rollback)
364: {
365: command = "ROLLBACK TRANSACTION";
366: }
367: success = execute(this, NULL, command) != -1;
368:
369: this->transaction->set(this->transaction, NULL);
370: free(trans);
371: return success;
372: }
373: else
374: { /* set flag, can't be unset */
375: trans->rollback |= rollback;
376: }
377: return TRUE;
378: }
379:
380: METHOD(database_t, commit_, bool,
381: private_sqlite_database_t *this)
382: {
383: return finalize_transaction(this, FALSE);
384: }
385:
386: METHOD(database_t, rollback, bool,
387: private_sqlite_database_t *this)
388: {
389: return finalize_transaction(this, TRUE);
390: }
391:
392: METHOD(database_t, get_driver, db_driver_t,
393: private_sqlite_database_t *this)
394: {
395: return DB_SQLITE;
396: }
397:
398: /**
399: * Busy handler implementation
400: */
401: static int busy_handler(private_sqlite_database_t *this, int count)
402: {
403: /* add a backoff time, quadratically increasing with every try */
404: usleep(count * count * 1000);
405: /* always retry */
406: return 1;
407: }
408:
409: METHOD(database_t, destroy, void,
410: private_sqlite_database_t *this)
411: {
412: if (sqlite3_close(this->db) == SQLITE_BUSY)
413: {
414: DBG1(DBG_LIB, "sqlite close failed because database is busy");
415: }
416: this->transaction->destroy(this->transaction);
417: this->mutex->destroy(this->mutex);
418: free(this);
419: }
420:
421: /*
422: * see header file
423: */
424: sqlite_database_t *sqlite_database_create(char *uri)
425: {
426: char *file;
427: private_sqlite_database_t *this;
428:
429: /**
430: * parse sqlite:///path/to/file.db uri
431: */
432: if (!strpfx(uri, "sqlite://"))
433: {
434: return NULL;
435: }
436: file = uri + 9;
437:
438: INIT(this,
439: .public = {
440: .db = {
441: .query = _query,
442: .execute = _execute,
443: .transaction = _transaction,
444: .commit = _commit_,
445: .rollback = _rollback,
446: .get_driver = _get_driver,
447: .destroy = _destroy,
448: },
449: },
450: .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
451: .transaction = thread_value_create(NULL),
452: );
453:
454: if (sqlite3_open(file, &this->db) != SQLITE_OK)
455: {
456: DBG1(DBG_LIB, "opening SQLite database '%s' failed: %s",
457: file, sqlite3_errmsg(this->db));
458: destroy(this);
459: return NULL;
460: }
461:
462: sqlite3_busy_handler(this->db, (void*)busy_handler, this);
463:
464: return &this->public;
465: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>