Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * sqlite.cpp - Fawkes configuration stored in a SQLite database 00004 * 00005 * Created: Wed Dec 06 17:23:00 2006 00006 * Copyright 2006-2009 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <config/sqlite.h> 00025 #include <core/threading/mutex.h> 00026 #include <core/exceptions/system.h> 00027 00028 #include <sqlite3.h> 00029 00030 #ifndef _GNU_SOURCE 00031 #define _GNU_SOURCE 00032 #endif 00033 #include <cstdio> 00034 #include <cstdlib> 00035 #include <cstring> 00036 #include <cerrno> 00037 #include <unistd.h> 00038 #include <fnmatch.h> 00039 00040 namespace fawkes { 00041 00042 /* SQLite statements */ 00043 00044 #define TABLE_HOST_CONFIG "config" 00045 #define TABLE_DEFAULT_CONFIG "defaults.config" 00046 #define TABLE_HOST_TAGGED "tagged_config" 00047 00048 #define SQL_CREATE_TABLE_HOST_CONFIG \ 00049 "CREATE TABLE IF NOT EXISTS config (\n" \ 00050 " path TEXT NOT NULL,\n" \ 00051 " type TEXT NOT NULL,\n" \ 00052 " value NOT NULL,\n" \ 00053 " comment TEXT,\n" \ 00054 " PRIMARY KEY (path)\n" \ 00055 ")" 00056 00057 #define SQL_CREATE_TABLE_DEFAULT_CONFIG \ 00058 "CREATE TABLE IF NOT EXISTS defaults.config (\n" \ 00059 " path TEXT NOT NULL,\n" \ 00060 " type TEXT NOT NULL,\n" \ 00061 " value NOT NULL,\n" \ 00062 " comment TEXT,\n" \ 00063 " PRIMARY KEY (path)\n" \ 00064 ")" 00065 00066 #define SQL_CREATE_TABLE_TAGGED_CONFIG \ 00067 "CREATE TABLE IF NOT EXISTS tagged_config (\n" \ 00068 " tag TEXT NOT NULL,\n" \ 00069 " path TEXT NOT NULL,\n" \ 00070 " type TEXT NOT NULL,\n" \ 00071 " value NOT NULL,\n" \ 00072 " comment TEXT,\n" \ 00073 " PRIMARY KEY (tag, path)\n" \ 00074 ")" 00075 00076 #define SQL_CREATE_TABLE_MODIFIED_CONFIG \ 00077 "CREATE TABLE IF NOT EXISTS modified.config (\n" \ 00078 " path TEXT NOT NULL,\n" \ 00079 " type TEXT NOT NULL,\n" \ 00080 " value NOT NULL,\n" \ 00081 " comment TEXT,\n" \ 00082 " modtype TEXT NOT NULL,\n" \ 00083 " oldvalue NOT NULL,\n" \ 00084 " PRIMARY KEY (path)\n" \ 00085 ")" 00086 00087 #define SQL_ATTACH_DEFAULTS \ 00088 "ATTACH DATABASE '%s' AS defaults" 00089 00090 #define SQL_ATTACH_MODIFIED \ 00091 "ATTACH DATABASE ':memory:' AS modified" 00092 00093 #define SQL_ATTACH_DUMPED \ 00094 "ATTACH DATABASE '%s' AS dumped" 00095 00096 #define SQL_DETACH_DUMPED \ 00097 "DETACH DATABASE dumped" 00098 00099 #define SQL_SELECT_VALUE_TYPE \ 00100 "SELECT type, value, 0 AS is_default FROM config WHERE path=? UNION " \ 00101 "SELECT type, value, 1 AS is_default FROM defaults.config AS dc " \ 00102 "WHERE path=? AND NOT EXISTS " \ 00103 "(SELECT path FROM config WHERE dc.path=path)" 00104 00105 #define SQL_SELECT_COMPLETE \ 00106 "SELECT *, 0 AS is_default FROM config WHERE path LIKE ? UNION " \ 00107 "SELECT *, 1 AS is_default FROM defaults.config AS dc " \ 00108 "WHERE path LIKE ? AND NOT EXISTS " \ 00109 "(SELECT path FROM config WHERE dc.path = path) " \ 00110 "ORDER BY path" 00111 00112 #define SQL_SELECT_TYPE \ 00113 "SELECT type, 0 AS is_default FROM config WHERE path=? UNION " \ 00114 "SELECT type, 1 AS is_default FROM defaults.config AS dc " \ 00115 "WHERE path=? AND NOT EXISTS " \ 00116 "(SELECT path FROM config WHERE dc.path = path)" 00117 00118 #define SQL_SELECT_COMMENT \ 00119 "SELECT comment, 0 AS is_default FROM config WHERE path=?" 00120 00121 #define SQL_SELECT_DEFAULT_COMMENT \ 00122 "SELECT comment, 1 AS is_default FROM defaults.config AS dc " \ 00123 "WHERE dc.path=?" 00124 00125 #define SQL_UPDATE_VALUE \ 00126 "UPDATE config SET value=? WHERE path=?" 00127 00128 #define SQL_UPDATE_DEFAULT_VALUE \ 00129 "UPDATE defaults.config SET value=? WHERE path=?" 00130 00131 #define SQL_UPDATE_COMMENT \ 00132 "UPDATE config SET comment=? WHERE path=?" 00133 00134 #define SQL_UPDATE_DEFAULT_COMMENT \ 00135 "UPDATE defaults.config SET comment=? WHERE path=?" 00136 00137 #define SQL_INSERT_VALUE \ 00138 "INSERT INTO config (path, type, value) VALUES (?, ?, ?)" 00139 00140 #define SQL_INSERT_DEFAULT_VALUE \ 00141 "INSERT INTO defaults.config (path, type, value) VALUES (?, ?, ?)" 00142 00143 #define SQL_SELECT_TAGS \ 00144 "SELECT tag FROM tagged_config GROUP BY tag" 00145 00146 #define SQL_INSERT_TAG \ 00147 "INSERT INTO tagged_config " \ 00148 "(tag, path, type, value, comment) " \ 00149 "SELECT \"%s\",* FROM config" 00150 00151 #define SQL_SELECT_ALL \ 00152 "SELECT *, 0 AS is_default FROM config UNION " \ 00153 "SELECT *, 1 AS is_default FROM defaults.config AS dc " \ 00154 "WHERE NOT EXISTS " \ 00155 "(SELECT path FROM config WHERE dc.path = path) " \ 00156 "ORDER BY path" 00157 00158 #define SQL_SELECT_ALL_DEFAULT \ 00159 "SELECT *, 1 AS is_default FROM defaults.config" 00160 00161 #define SQL_SELECT_ALL_HOSTSPECIFIC \ 00162 "SELECT *, 0 AS is_default FROM config" 00163 00164 #define SQL_DELETE_VALUE \ 00165 "DELETE FROM config WHERE path=?" 00166 00167 #define SQL_DELETE_DEFAULT_VALUE \ 00168 "DELETE FROM defaults.config WHERE path=?" 00169 00170 #define SQL_UPDATE_DEFAULT_DB \ 00171 "INSERT INTO config SELECT * FROM defaults.config AS dc " \ 00172 "WHERE NOT EXISTS (SELECT path from config WHERE path = dc.path)" 00173 00174 #define SQL_UPDATE_MODIFIED_DB_ADDED \ 00175 "INSERT INTO modified.config " \ 00176 " SELECT duc.*,'added' AS modtype, duc.value " \ 00177 " FROM dumped.config AS duc " \ 00178 " WHERE NOT EXISTS (SELECT dc.path FROM defaults.config AS dc " \ 00179 " WHERE dc.path=duc.path) " \ 00180 " ORDER BY path" 00181 00182 #define SQL_UPDATE_MODIFIED_DB_ERASED \ 00183 "INSERT INTO modified.config " \ 00184 " SELECT dc.*,'erased' AS modtype, dc.value " \ 00185 " FROM defaults.config AS dc " \ 00186 " WHERE NOT EXISTS (SELECT duc.path FROM dumped.config AS duc " \ 00187 " WHERE duc.path=dc.path) " \ 00188 " ORDER BY path" 00189 00190 #define SQL_UPDATE_MODIFIED_DB_CHANGED \ 00191 "INSERT INTO modified.config " \ 00192 " SELECT duc.*,'changed' AS modtype, dc.value " \ 00193 " FROM dumped.config AS duc, defaults.config AS dc " \ 00194 " WHERE duc.path = dc.path " \ 00195 " AND (dc.type != duc.type OR dc.value != duc.value) " \ 00196 " ORDER BY duc.path" 00197 00198 #define SQL_COPY_DUMP \ 00199 "DELETE FROM defaults.config; " \ 00200 "INSERT INTO defaults.config SELECT * FROM dumped.config" 00201 00202 #define SQL_SELECT_MODIFIED_ALL \ 00203 "SELECT * FROM modified.config" 00204 00205 /** @class SQLiteConfiguration <config/sqlite.h> 00206 * Configuration storage using SQLite. 00207 * This implementation of the Configuration interface uses SQLite to store the 00208 * configuration. 00209 * 00210 * The configuration uses two databases, one is used to store the host-specific 00211 * configuration and the other one is used to store the default values. Only the 00212 * default database is meant to reside under version control. 00213 * 00214 * See init() for the structure of the databases. This class strictly serializes 00215 * all accesses to the database such that only one thread at a time can modify the 00216 * database. 00217 */ 00218 00219 00220 /** Constructor. */ 00221 SQLiteConfiguration::SQLiteConfiguration() 00222 { 00223 opened = false; 00224 mutex = new Mutex(); 00225 00226 __sysconfdir = NULL; 00227 __userconfdir = NULL; 00228 __default_file = NULL; 00229 __default_sql = NULL; 00230 00231 } 00232 00233 /** Constructor. 00234 * @param sysconfdir system configuration directory, will be searched for 00235 * default configuration file, and system will try to create host-specific 00236 * database if writable 00237 * @param userconfdir user configuration directory, will be searched preferably 00238 * for default configuration file, and will be used to create host-specific 00239 * database if sysconfdir is not writable. This directory will be created 00240 * if it does not exist during load(). 00241 */ 00242 SQLiteConfiguration::SQLiteConfiguration(const char *sysconfdir, 00243 const char *userconfdir) 00244 { 00245 opened = false; 00246 mutex = new Mutex(); 00247 00248 __sysconfdir = strdup(sysconfdir); 00249 __default_file = NULL; 00250 __default_sql = NULL; 00251 00252 if (userconfdir != NULL) { 00253 __userconfdir = strdup(userconfdir); 00254 } else { 00255 const char *homedir = getenv("HOME"); 00256 if (homedir == NULL) { 00257 __userconfdir = strdup(sysconfdir); 00258 } else { 00259 if (asprintf(&__userconfdir, "%s/%s", homedir, USERDIR) == -1) { 00260 __userconfdir = strdup(sysconfdir); 00261 } 00262 } 00263 } 00264 } 00265 00266 /** Destructor. */ 00267 SQLiteConfiguration::~SQLiteConfiguration() 00268 { 00269 if (opened) { 00270 opened = false; 00271 if ( sqlite3_close(db) == SQLITE_BUSY ) { 00272 printf("Boom, we are dead, database cannot be closed " 00273 "because there are open handles\n"); 00274 } 00275 } 00276 00277 if (__host_file) free(__host_file); 00278 if (__default_file) free(__default_file); 00279 if (__default_sql) free(__default_sql); 00280 if (__sysconfdir) free(__sysconfdir); 00281 if (__userconfdir) free(__userconfdir); 00282 delete mutex; 00283 } 00284 00285 00286 /** Initialize the configuration database(s). 00287 * Initialize databases. If the host-specific database already exists 00288 * an exception is thrown. You have to delete it before calling init(). 00289 * First the host-specific database is created. It will contain two tables, 00290 * on is named 'config' and the other one is named 'tagged'. The 'config' 00291 * table will hold the current configuration for this machine. The 'tagged' 00292 * table contains the same fields as config with an additional "tag" field. 00293 * To tag a given revision of the config you give it a name, copy all values 00294 * over to the 'tagged' table with "tag" set to the desired name. 00295 * 00296 * The 'config' table is created with the following schema: 00297 * @code 00298 * CREATE TABLE IF NOT EXISTS config ( 00299 * path TEXT NOT NULL, 00300 * type TEXT NOT NULL, 00301 * value NOT NULL, 00302 * comment TEXT, 00303 * PRIMARY KEY (path) 00304 * ) 00305 * @endcode 00306 * If a default database is found the values from this database are copied 00307 * to the config table. 00308 * The defaults config database is created with the following structure: 00309 * @code 00310 * CREATE TABLE IF NOT EXISTS defaults.config ( 00311 * path TEXT NOT NULL, 00312 * type TEXT NOT NULL, 00313 * value NOT NULL, 00314 * comment TEXT, 00315 * PRIMARY KEY (path) 00316 * ) 00317 * @endcode 00318 * 00319 * After this the 'tagged' table is created with the following schema: 00320 * @code 00321 * CREATE TABLE IF NOT EXISTS tagged_config ( 00322 * tag TEXT NOT NULL, 00323 * path TEXT NOT NULL, 00324 * type TEXT NOT NULL, 00325 * value NOT NULL, 00326 * comment TEXT 00327 * PRIMARY KEY (tag, path) 00328 * ) 00329 * @endcode 00330 * 00331 * If no default database exists it is created. The database is kept in a file 00332 * called default.db. It contains a single table called 'config' with the same 00333 * structure as the 'config' table in the host-specific database. 00334 */ 00335 void 00336 SQLiteConfiguration::init_dbs() 00337 { 00338 char *errmsg; 00339 if ( (sqlite3_exec(db, SQL_CREATE_TABLE_HOST_CONFIG, NULL, NULL, &errmsg) != SQLITE_OK) || 00340 (sqlite3_exec(db, SQL_CREATE_TABLE_DEFAULT_CONFIG, NULL, NULL, &errmsg) != SQLITE_OK) || 00341 (sqlite3_exec(db, SQL_CREATE_TABLE_TAGGED_CONFIG, NULL, NULL, &errmsg) != SQLITE_OK) ) { 00342 CouldNotOpenConfigException ce(sqlite3_errmsg(db)); 00343 sqlite3_close(db); 00344 throw ce; 00345 } 00346 } 00347 00348 00349 /** Dump table. 00350 * Dumps a table to the given file. 00351 * @param f file to write to 00352 * @param tdb SQLite3 database to read from 00353 * @param table_name Name of the table to dump 00354 */ 00355 static void 00356 dump_table(FILE *f, ::sqlite3 *tdb, const char *table_name) 00357 { 00358 std::string tisql = "PRAGMA table_info(\""; 00359 tisql += table_name; 00360 tisql += "\");"; 00361 00362 sqlite3_stmt *stmt; 00363 if ( sqlite3_prepare(tdb, tisql.c_str(), -1, &stmt, 0) != SQLITE_OK ) { 00364 throw ConfigurationException("dump_table/prepare", sqlite3_errmsg(tdb)); 00365 } 00366 std::string value_query = "SELECT 'INSERT INTO ' || '\""; 00367 value_query += table_name; 00368 value_query += "\"' || ' VALUES(' || "; 00369 int rv = sqlite3_step(stmt); 00370 while ( rv == SQLITE_ROW ) { 00371 value_query += "quote(\""; 00372 value_query += (const char *)sqlite3_column_text(stmt, 1); 00373 value_query += "\") || "; 00374 rv = sqlite3_step(stmt); 00375 if ( rv == SQLITE_ROW ) { 00376 value_query += " ',' || "; 00377 } 00378 } 00379 value_query += "')' FROM "; 00380 value_query += table_name; 00381 sqlite3_finalize(stmt); 00382 00383 sqlite3_stmt *vstmt; 00384 if ( sqlite3_prepare(tdb, value_query.c_str(), -1, &vstmt, 0) != SQLITE_OK ) { 00385 throw ConfigurationException("dump_table/prepare 2", sqlite3_errmsg(tdb)); 00386 } 00387 while ( sqlite3_step(vstmt) == SQLITE_ROW ) { 00388 fprintf(f, "%s;\n", sqlite3_column_text(vstmt, 0)); 00389 } 00390 sqlite3_finalize(vstmt); 00391 } 00392 00393 void 00394 SQLiteConfiguration::dump(::sqlite3 *tdb, const char *dumpfile) 00395 { 00396 FILE *f = fopen(dumpfile, "w"); 00397 if ( ! f ) { 00398 throw CouldNotOpenFileException(dumpfile, errno, "Could not open dump file"); 00399 } 00400 00401 fprintf(f, "BEGIN TRANSACTION;\n"); 00402 00403 const char *sql = "SELECT name, sql FROM sqlite_master " 00404 "WHERE sql NOT NULL AND type=='table'"; 00405 sqlite3_stmt *stmt; 00406 if ( (sqlite3_prepare(tdb, sql, -1, &stmt, 0) != SQLITE_OK) || ! stmt ) { 00407 throw ConfigurationException("dump_query/prepare", sqlite3_errmsg(tdb)); 00408 } 00409 while ( sqlite3_step(stmt) == SQLITE_ROW ) { 00410 fprintf(f, "%s;\n", sqlite3_column_text(stmt, 1)); 00411 dump_table(f, tdb, (const char *)sqlite3_column_text(stmt, 0)); 00412 } 00413 sqlite3_finalize(stmt); 00414 00415 fprintf(f, "COMMIT;\n"); 00416 fclose(f); 00417 } 00418 00419 00420 /** Try to dump default configuration. 00421 * This method will try to open the SQL dump file for writing and dump 00422 * the current content of the default database into the file. 00423 * @exception Exception thrown if dumping fails 00424 */ 00425 void 00426 SQLiteConfiguration::try_dump() 00427 { 00428 if ( __default_sql ) { 00429 sqlite3 *tdb; 00430 if ( sqlite3_open(__default_file, &tdb) == SQLITE_OK ) { 00431 try { 00432 dump(tdb, __default_sql); 00433 sqlite3_close(tdb); 00434 } catch (Exception &e) { 00435 sqlite3_close(tdb); 00436 throw; 00437 } 00438 } 00439 } 00440 } 00441 00442 void 00443 SQLiteConfiguration::import(::sqlite3 *tdb, const char *dumpfile) 00444 { 00445 FILE *f = fopen(dumpfile, "r"); 00446 00447 if (! f) { 00448 throw CouldNotOpenConfigException("Import failed, could not open dump file"); 00449 } 00450 00451 char line[4096]; 00452 char *errmsg; 00453 while (! feof(f) ) { 00454 line[0] = 0; 00455 unsigned int i = 0; 00456 while (! feof(f) && (i < sizeof(line) - 1)) { 00457 if (fread(&(line[i]), 1, 1, f) == 1) { 00458 ++i; 00459 if ( (i > 2) && (line[i-1] == '\n') && (line[i-2] == ';') ) { 00460 break; 00461 } 00462 } else { 00463 break; 00464 } 00465 } 00466 line[i] = 0; 00467 if ( line[0] != 0 ) { 00468 if ( sqlite3_exec(tdb, line, 0, 0, &errmsg) != SQLITE_OK ) { 00469 ConfigurationException e(errmsg, line); 00470 sqlite3_free(errmsg); 00471 throw e; 00472 } 00473 } 00474 } 00475 00476 fclose(f); 00477 } 00478 00479 00480 void 00481 SQLiteConfiguration::import_default(const char *default_sql) 00482 { 00483 char *tmpfile = strdup(TMPDIR"/tmp_default_XXXXXX"); 00484 tmpfile = mktemp(tmpfile); 00485 if ( tmpfile[0] == 0 ) { 00486 throw CouldNotOpenConfigException("Failed to create temp file for default DB import"); 00487 } 00488 00489 // Import .sql file into dump database (temporary file) 00490 sqlite3 *dump_db; 00491 if ( sqlite3_open(tmpfile, &dump_db) == SQLITE_OK ) { 00492 import(dump_db, default_sql); 00493 sqlite3_close(dump_db); 00494 } else { 00495 throw CouldNotOpenConfigException("Failed to import dump file into temp DB"); 00496 } 00497 00498 // Attach dump database as "dumped" 00499 char *attach_sql; 00500 char *errmsg; 00501 if ( asprintf(&attach_sql, SQL_ATTACH_DUMPED, tmpfile) == -1 ) { 00502 throw CouldNotOpenConfigException("Could not create attachment SQL in merge"); 00503 } 00504 if ( sqlite3_exec(db, attach_sql, NULL, NULL, &errmsg) != SQLITE_OK ) { 00505 free(attach_sql); 00506 CouldNotOpenConfigException e("Could not attach dump DB in merge: %s", errmsg); 00507 sqlite3_free(errmsg); 00508 throw e; 00509 } 00510 free(attach_sql); 00511 00512 // Create "modified" database for a list of modified values, only stored in RAM 00513 if ( (sqlite3_exec(db, SQL_ATTACH_MODIFIED, NULL, NULL, &errmsg) != SQLITE_OK) || 00514 (sqlite3_exec(db, SQL_CREATE_TABLE_MODIFIED_CONFIG, NULL, NULL, &errmsg) != SQLITE_OK) ) { 00515 CouldNotOpenConfigException ce("Could not create or attach modified memory database: %s", errmsg); 00516 sqlite3_free(errmsg); 00517 throw ce; 00518 } 00519 00520 // Compare old and new database, copying modifications to "modified" database 00521 if ( (sqlite3_exec(db, SQL_UPDATE_MODIFIED_DB_ADDED, NULL, NULL, &errmsg) != SQLITE_OK) || 00522 (sqlite3_exec(db, SQL_UPDATE_MODIFIED_DB_ERASED, NULL, NULL, &errmsg) != SQLITE_OK) || 00523 (sqlite3_exec(db, SQL_UPDATE_MODIFIED_DB_CHANGED, NULL, NULL, &errmsg) != SQLITE_OK) ) { 00524 CouldNotOpenConfigException ce("Could not update modified memory database: %s", errmsg); 00525 sqlite3_free(errmsg); 00526 throw ce; 00527 } 00528 00529 // Copy dump to defaults DB, overwriting everything 00530 if ( (sqlite3_exec(db, SQL_COPY_DUMP, NULL, NULL, &errmsg) != SQLITE_OK) ) { 00531 CouldNotOpenConfigException ce("Could not copy dump to default: %s", errmsg); 00532 sqlite3_free(errmsg); 00533 throw ce; 00534 } 00535 00536 // Detach dumped DB, no longer required 00537 if ( sqlite3_exec(db, SQL_DETACH_DUMPED, NULL, NULL, &errmsg) != SQLITE_OK ) { 00538 CouldNotOpenConfigException e("Could not detach dump DB in import: %s", errmsg); 00539 sqlite3_free(errmsg); 00540 throw e; 00541 } 00542 00543 unlink(tmpfile); 00544 free(tmpfile); 00545 } 00546 00547 00548 /** Begin SQL Transaction. 00549 * @param ttype transaction type 00550 */ 00551 void 00552 SQLiteConfiguration::transaction_begin(transaction_type_t ttype) 00553 { 00554 const char *sql = "BEGIN DEFERRED TRANSACTION;"; 00555 if (ttype == TRANSACTION_IMMEDIATE) { 00556 sql = "BEGIN IMMEDIATE TRANSACTION;"; 00557 } else if (ttype == TRANSACTION_EXCLUSIVE) { 00558 sql = "BEGIN EXCLUSIVE TRANSACTION;"; 00559 } 00560 00561 char *errmsg; 00562 if ( (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK) ) { 00563 throw ConfigurationException("Could not begin transaction (%s)", errmsg); 00564 } 00565 } 00566 00567 /** Commit SQL Transaction. */ 00568 void 00569 SQLiteConfiguration::transaction_commit() 00570 { 00571 const char *sql = "COMMIT TRANSACTION;"; 00572 00573 char *errmsg; 00574 if ( (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK) ) { 00575 throw ConfigurationException("Could not commit transaction (%s)", errmsg); 00576 } 00577 } 00578 00579 00580 /** Rollback SQL Transaction. */ 00581 void 00582 SQLiteConfiguration::transaction_rollback() 00583 { 00584 const char *sql = "ROLLBACK TRANSACTION;"; 00585 00586 char *errmsg; 00587 if ( (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK) ) { 00588 throw ConfigurationException("Could not rollback transaction (%s)", errmsg); 00589 } 00590 } 00591 00592 void 00593 SQLiteConfiguration::attach_default(const char *db_file) 00594 { 00595 char *errmsg; 00596 char *attach_sql; 00597 if ( asprintf(&attach_sql, SQL_ATTACH_DEFAULTS, db_file) == -1 ) { 00598 throw CouldNotOpenConfigException("Could not create attachment SQL"); 00599 } 00600 if (sqlite3_exec(db, attach_sql, NULL, NULL, &errmsg) != SQLITE_OK) { 00601 CouldNotOpenConfigException ce(sqlite3_errmsg(db)); 00602 ce.append("Failed to attach default file (%s)", db_file); 00603 free(attach_sql); 00604 throw ce; 00605 } 00606 free(attach_sql); 00607 } 00608 00609 00610 void 00611 SQLiteConfiguration::load(const char *name, const char *defaults_name, 00612 const char *tag) 00613 { 00614 mutex->lock(); 00615 00616 if (__default_file) free(__default_file); 00617 if (__default_sql) free(__default_sql); 00618 __default_file = NULL; 00619 __default_sql = NULL; 00620 00621 const char *try_paths[] = {__sysconfdir, __userconfdir}; 00622 int try_paths_len = 2; 00623 00624 char *host_name; 00625 00626 if (name == NULL) { 00627 HostInfo hostinfo; 00628 if ( asprintf(&host_name, "%s.db", hostinfo.short_name()) == -1 ) { 00629 host_name = strdup(hostinfo.short_name()); 00630 } 00631 } else { 00632 host_name = strdup(name); 00633 } 00634 00635 // determine host file 00636 if (strcmp(host_name, ":memory:") == 0) { 00637 if (sqlite3_open(host_name, &db) != SQLITE_OK) { 00638 CouldNotOpenConfigException ce(sqlite3_errmsg(db)); 00639 ce.append("Failed to open host db (memory)"); 00640 throw ce; 00641 } 00642 } else if (host_name[0] == '/') { 00643 // absolute path, take as is 00644 if (sqlite3_open(host_name, &db) == SQLITE_OK) { 00645 __host_file = strdup(host_name); 00646 } else { 00647 CouldNotOpenConfigException ce(sqlite3_errmsg(db)); 00648 ce.append("Failed to open host db (absolute)"); 00649 throw ce; 00650 } 00651 } else { 00652 // try sysconfdir and userconfdir 00653 for (int i = 0; i < try_paths_len; ++i) { 00654 char *path; 00655 if (asprintf(&path, "%s/%s", try_paths[i], host_name) != -1) { 00656 if (sqlite3_open(path, &db) == SQLITE_OK) { 00657 __host_file = path; 00658 break; 00659 } else { 00660 free(path); 00661 } 00662 } 00663 } 00664 if (__host_file == NULL) { 00665 CouldNotOpenConfigException ce(sqlite3_errmsg(db)); 00666 ce.append("Failed to open host db (paths)"); 00667 free(host_name); 00668 throw ce; 00669 } 00670 } 00671 00672 if (defaults_name == NULL) { 00673 defaults_name = "default.sql"; 00674 } 00675 00676 // determine default file 00677 if (strcmp(defaults_name, ":memory:") == 0) { 00678 try { 00679 attach_default(":memory:"); 00680 } catch (...) { 00681 free(host_name); 00682 throw; 00683 } 00684 __default_file = strdup(":memory:"); 00685 } else { 00686 if (defaults_name[0] == '/') { 00687 // absolute path, take as is 00688 __default_sql = strdup(defaults_name); 00689 } else { 00690 // try sysconfdir and userconfdir 00691 for (int i = 0; i < try_paths_len; ++i) { 00692 char *path; 00693 if (asprintf(&path, "%s/%s", try_paths[i], defaults_name) != -1) { 00694 if (access(path, F_OK | R_OK) == 0) { 00695 __default_sql = path; 00696 break; 00697 } else { 00698 free(path); 00699 } 00700 } 00701 } 00702 } 00703 00704 // Now go for the .db filename 00705 00706 // generate filename 00707 char *defaults_db; 00708 size_t len = strlen(defaults_name); 00709 if (fnmatch("*.sql", defaults_name, FNM_PATHNAME) == 0) { 00710 defaults_db = (char *)calloc(1, len); // yes, that's one byte less! 00711 strncpy(defaults_db, defaults_name, len - 3); 00712 strcat(defaults_db, "db"); 00713 } else { 00714 defaults_db = (char *)calloc(1, len + 4); 00715 strcpy(defaults_db, defaults_name); 00716 strcat(defaults_db, ".db"); 00717 } 00718 00719 if (defaults_db[0] == '/') { 00720 try { 00721 attach_default(defaults_db); 00722 __default_file = defaults_db; 00723 } catch (...) { 00724 free(host_name); 00725 free(defaults_db); 00726 throw; 00727 } 00728 } else { 00729 // check directories 00730 for (int i = 0; i < try_paths_len; ++i) { 00731 char *path; 00732 if (asprintf(&path, "%s/%s", try_paths[i], defaults_db) != -1) { 00733 try { 00734 attach_default(path); 00735 __default_file = path; 00736 break; 00737 } catch (CouldNotOpenConfigException &e) { 00738 free(path); 00739 } 00740 } 00741 } 00742 } 00743 free(defaults_db); 00744 00745 if (__default_file == NULL) { 00746 free(host_name); 00747 throw CouldNotOpenConfigException("Could not create default filename"); 00748 } 00749 } 00750 00751 init_dbs(); 00752 00753 if ( __default_sql ) import_default(__default_sql); 00754 free(host_name); 00755 00756 opened = true; 00757 00758 mutex->unlock(); 00759 } 00760 00761 00762 /** Load config from default files. 00763 * Default file is "shorthostname.db" (shorthostname replaced by the 00764 * short host name returned by uname) and default.db). 00765 * @param tag optional tag to restore 00766 */ 00767 void 00768 SQLiteConfiguration::load(const char *tag) 00769 { 00770 load(NULL, NULL, tag); 00771 } 00772 00773 00774 /** Copy all values from the given configuration. 00775 * All values from the given configuration are copied. Old values are not erased 00776 * so that the copied values will overwrite existing values, new values are 00777 * created, but values existent in current config but not in the copie config 00778 * will remain unchanged. 00779 * @param copyconf configuration to copy 00780 */ 00781 void 00782 SQLiteConfiguration::copy(Configuration *copyconf) 00783 { 00784 copyconf->lock(); 00785 transaction_begin(); 00786 Configuration::ValueIterator *i = copyconf->iterator(); 00787 while ( i->next() ) { 00788 if ( i->is_float() ) { 00789 set_float(i->path(), i->get_float()); 00790 } else if ( i->is_int() ) { 00791 set_int(i->path(), i->get_int()); 00792 } else if ( i->is_uint() ) { 00793 set_uint(i->path(), i->get_uint()); 00794 } else if ( i->is_bool() ) { 00795 set_bool(i->path(), i->get_bool()); 00796 } else if ( i->is_string() ) { 00797 std::string s = i->get_string(); 00798 set_string(i->path(), s); 00799 } 00800 } 00801 delete i; 00802 transaction_commit(); 00803 copyconf->unlock(); 00804 } 00805 00806 00807 /** Tag this configuration version. 00808 * This creates a new tagged version of the current config. The tagged config can be 00809 * accessed via load(). 00810 * @param tag tag for this version 00811 */ 00812 void 00813 SQLiteConfiguration::tag(const char *tag) 00814 { 00815 char *insert_sql; 00816 char *errmsg; 00817 00818 mutex->lock(); 00819 00820 if ( asprintf(&insert_sql, SQL_INSERT_TAG, tag) == -1 ) { 00821 mutex->unlock(); 00822 throw ConfigurationException("Could not create insert statement for tagging"); 00823 } 00824 00825 if (sqlite3_exec(db, insert_sql, NULL, NULL, &errmsg) != SQLITE_OK) { 00826 ConfigurationException ce("Could not insert tag", sqlite3_errmsg(db)); 00827 free(insert_sql); 00828 mutex->unlock(); 00829 throw ce; 00830 } 00831 00832 free(insert_sql); 00833 mutex->unlock(); 00834 } 00835 00836 00837 std::list<std::string> 00838 SQLiteConfiguration::tags() 00839 { 00840 mutex->lock(); 00841 std::list<std::string> l; 00842 sqlite3_stmt *stmt; 00843 const char *tail; 00844 if ( sqlite3_prepare(db, SQL_SELECT_TAGS, -1, &stmt, &tail) != SQLITE_OK ) { 00845 mutex->unlock(); 00846 throw ConfigurationException("get_type: Preparation SQL failed"); 00847 } 00848 while ( sqlite3_step(stmt) == SQLITE_ROW ) { 00849 l.push_back((char *)sqlite3_column_text(stmt, 0)); 00850 } 00851 sqlite3_finalize(stmt); 00852 mutex->unlock(); 00853 return l; 00854 } 00855 00856 00857 bool 00858 SQLiteConfiguration::exists(const char *path) 00859 { 00860 mutex->lock(); 00861 sqlite3_stmt *stmt; 00862 const char *tail; 00863 bool e; 00864 00865 if ( sqlite3_prepare(db, SQL_SELECT_TYPE, -1, &stmt, &tail) != SQLITE_OK ) { 00866 mutex->unlock(); 00867 throw ConfigurationException("exists/prepare", sqlite3_errmsg(db)); 00868 } 00869 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) { 00870 mutex->unlock(); 00871 throw ConfigurationException("exists/bind/path", sqlite3_errmsg(db)); 00872 } 00873 if ( sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK ) { 00874 mutex->unlock(); 00875 throw ConfigurationException("exists/bind/path", sqlite3_errmsg(db)); 00876 } 00877 e = ( sqlite3_step(stmt) == SQLITE_ROW ); 00878 sqlite3_finalize(stmt); 00879 00880 mutex->unlock(); 00881 return e; 00882 } 00883 00884 00885 std::string 00886 SQLiteConfiguration::get_type(const char *path) 00887 { 00888 sqlite3_stmt *stmt; 00889 const char *tail; 00890 std::string s = ""; 00891 00892 mutex->lock(); 00893 00894 if ( sqlite3_prepare(db, SQL_SELECT_TYPE, -1, &stmt, &tail) != SQLITE_OK ) { 00895 mutex->unlock(); 00896 throw ConfigurationException("get_type: Preparation SQL failed"); 00897 } 00898 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) { 00899 mutex->unlock(); 00900 throw ConfigurationException("get_type: Binding text for path failed (1)"); 00901 } 00902 if ( sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK ) { 00903 mutex->unlock(); 00904 throw ConfigurationException("get_type: Binding text for path failed (2)"); 00905 } 00906 if ( sqlite3_step(stmt) == SQLITE_ROW ) { 00907 s = (char *)sqlite3_column_text(stmt, 0); 00908 sqlite3_finalize(stmt); 00909 mutex->unlock(); 00910 return s; 00911 } else { 00912 sqlite3_finalize(stmt); 00913 mutex->unlock(); 00914 throw ConfigEntryNotFoundException(path); 00915 } 00916 } 00917 00918 00919 std::string 00920 SQLiteConfiguration::get_comment(const char *path) 00921 { 00922 sqlite3_stmt *stmt; 00923 const char *tail; 00924 std::string s = ""; 00925 00926 mutex->lock(); 00927 00928 if ( sqlite3_prepare(db, SQL_SELECT_COMMENT, -1, &stmt, &tail) != SQLITE_OK ) { 00929 mutex->unlock(); 00930 throw ConfigurationException("get_comment: Preparation SQL failed"); 00931 } 00932 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) { 00933 mutex->unlock(); 00934 throw ConfigurationException("get_comment: Binding text for path failed (1)"); 00935 } 00936 if ( sqlite3_step(stmt) == SQLITE_ROW ) { 00937 s = (char *)sqlite3_column_text(stmt, 0); 00938 sqlite3_finalize(stmt); 00939 mutex->unlock(); 00940 return s; 00941 } else { 00942 sqlite3_finalize(stmt); 00943 mutex->unlock(); 00944 throw ConfigEntryNotFoundException(path); 00945 } 00946 } 00947 00948 00949 std::string 00950 SQLiteConfiguration::get_default_comment(const char *path) 00951 { 00952 sqlite3_stmt *stmt; 00953 const char *tail; 00954 std::string s = ""; 00955 00956 mutex->lock(); 00957 00958 if ( sqlite3_prepare(db, SQL_SELECT_DEFAULT_COMMENT, -1, &stmt, &tail) != SQLITE_OK ) { 00959 mutex->unlock(); 00960 throw ConfigurationException("get_default_comment: Preparation SQL failed"); 00961 } 00962 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) { 00963 mutex->unlock(); 00964 throw ConfigurationException("get_default_comment: Binding text for path failed (1)"); 00965 } 00966 if ( sqlite3_step(stmt) == SQLITE_ROW ) { 00967 s = (char *)sqlite3_column_text(stmt, 0); 00968 sqlite3_finalize(stmt); 00969 mutex->unlock(); 00970 return s; 00971 } else { 00972 sqlite3_finalize(stmt); 00973 mutex->unlock(); 00974 throw ConfigEntryNotFoundException(path); 00975 } 00976 } 00977 00978 00979 bool 00980 SQLiteConfiguration::is_float(const char *path) 00981 { 00982 return (get_type(path) == "float"); 00983 } 00984 00985 00986 bool 00987 SQLiteConfiguration::is_uint(const char *path) 00988 { 00989 return (get_type(path) == "unsigned int"); 00990 } 00991 00992 00993 bool 00994 SQLiteConfiguration::is_int(const char *path) 00995 { 00996 return (get_type(path) == "int"); 00997 } 00998 00999 01000 bool 01001 SQLiteConfiguration::is_bool(const char *path) 01002 { 01003 return (get_type(path) == "bool"); 01004 } 01005 01006 01007 bool 01008 SQLiteConfiguration::is_string(const char *path) 01009 { 01010 return (get_type(path) == "string"); 01011 } 01012 01013 01014 bool 01015 SQLiteConfiguration::is_default(const char *path) 01016 { 01017 mutex->lock(); 01018 sqlite3_stmt *stmt; 01019 const char *tail; 01020 bool e; 01021 01022 if ( sqlite3_prepare(db, SQL_SELECT_TYPE, -1, &stmt, &tail) != SQLITE_OK ) { 01023 mutex->unlock(); 01024 throw ConfigurationException("is_default/prepare", sqlite3_errmsg(db)); 01025 } 01026 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) { 01027 mutex->unlock(); 01028 throw ConfigurationException("is_default/bind/path", sqlite3_errmsg(db)); 01029 } 01030 if ( sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK ) { 01031 mutex->unlock(); 01032 throw ConfigurationException("is_default/bind/path", sqlite3_errmsg(db)); 01033 } 01034 e = ( (sqlite3_step(stmt) == SQLITE_ROW) && (sqlite3_column_int(stmt, 1) == 1 )); 01035 sqlite3_finalize(stmt); 01036 01037 mutex->unlock(); 01038 return e; 01039 } 01040 01041 01042 /** Get value. 01043 * Get a value from the database. 01044 * @param path path 01045 * @param type desired value, NULL to omit type check 01046 */ 01047 sqlite3_stmt * 01048 SQLiteConfiguration::get_value(const char *path, 01049 const char *type) 01050 { 01051 sqlite3_stmt *stmt; 01052 const char *tail; 01053 01054 if ( sqlite3_prepare(db, SQL_SELECT_VALUE_TYPE, -1, &stmt, &tail) != SQLITE_OK ) { 01055 throw ConfigurationException("get_value/prepare", sqlite3_errmsg(db)); 01056 } 01057 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) { 01058 throw ConfigurationException("get_value/bind/path (1)", sqlite3_errmsg(db)); 01059 } 01060 if ( sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK ) { 01061 throw ConfigurationException("get_value/bind/path (2)", sqlite3_errmsg(db)); 01062 } 01063 01064 if ( sqlite3_step(stmt) == SQLITE_ROW ) { 01065 if ( type == NULL ) { 01066 // type check omitted 01067 return stmt; 01068 } else { 01069 if (strcmp((char *)sqlite3_column_text(stmt, 0), type) != 0) { 01070 ConfigTypeMismatchException ce(path, (char *)sqlite3_column_text(stmt, 0), type); 01071 sqlite3_finalize(stmt); 01072 throw ce; 01073 } else { 01074 return stmt; 01075 } 01076 } 01077 } else { 01078 sqlite3_finalize(stmt); 01079 throw ConfigEntryNotFoundException(path); 01080 } 01081 } 01082 01083 01084 float 01085 SQLiteConfiguration::get_float(const char *path) 01086 { 01087 sqlite3_stmt *stmt; 01088 mutex->lock(); 01089 try { 01090 stmt = get_value(path, "float"); 01091 float f = (float)sqlite3_column_double(stmt, 1); 01092 sqlite3_finalize(stmt); 01093 mutex->unlock(); 01094 return f; 01095 } catch (Exception &e) { 01096 // we can't handle 01097 mutex->unlock(); 01098 throw; 01099 } 01100 } 01101 01102 01103 unsigned int 01104 SQLiteConfiguration::get_uint(const char *path) 01105 { 01106 sqlite3_stmt *stmt; 01107 mutex->lock(); 01108 try { 01109 stmt = get_value(path, "unsigned int"); 01110 int i = sqlite3_column_int(stmt, 1); 01111 sqlite3_finalize(stmt); 01112 if ( i < 0 ) { 01113 mutex->unlock(); 01114 throw ConfigTypeMismatchException(path, "int", "unsigned int"); 01115 } 01116 mutex->unlock(); 01117 return i; 01118 } catch (Exception &e) { 01119 // we can't handle 01120 mutex->unlock(); 01121 throw; 01122 } 01123 } 01124 01125 01126 int 01127 SQLiteConfiguration::get_int(const char *path) 01128 { 01129 sqlite3_stmt *stmt; 01130 mutex->lock(); 01131 try { 01132 stmt = get_value(path, "int"); 01133 int i = sqlite3_column_int(stmt, 1); 01134 sqlite3_finalize(stmt); 01135 mutex->unlock(); 01136 return i; 01137 } catch (Exception &e) { 01138 // we can't handle 01139 mutex->unlock(); 01140 throw; 01141 } 01142 } 01143 01144 01145 bool 01146 SQLiteConfiguration::get_bool(const char *path) 01147 { 01148 sqlite3_stmt *stmt; 01149 mutex->lock(); 01150 try { 01151 stmt = get_value(path, "bool"); 01152 int i = sqlite3_column_int(stmt, 1); 01153 sqlite3_finalize(stmt); 01154 mutex->unlock(); 01155 return (i != 0); 01156 } catch (Exception &e) { 01157 // we can't handle 01158 mutex->unlock(); 01159 throw; 01160 } 01161 } 01162 01163 std::string 01164 SQLiteConfiguration::get_string(const char *path) 01165 { 01166 sqlite3_stmt *stmt; 01167 mutex->lock(); 01168 try { 01169 stmt = get_value(path, "string"); 01170 const char *c = (char *)sqlite3_column_text(stmt, 1); 01171 std::string rv = c; 01172 sqlite3_finalize(stmt); 01173 mutex->unlock(); 01174 return rv; 01175 } catch (Exception &e) { 01176 // we can't handle 01177 e.append("SQLiteConfiguration::get_string: Fetching %s failed.", path); 01178 mutex->unlock(); 01179 throw; 01180 } 01181 } 01182 01183 01184 Configuration::ValueIterator * 01185 SQLiteConfiguration::get_value(const char *path) 01186 { 01187 sqlite3_stmt *stmt; 01188 const char *tail; 01189 01190 if ( sqlite3_prepare(db, SQL_SELECT_COMPLETE, -1, &stmt, &tail) != SQLITE_OK ) { 01191 throw ConfigurationException("get_value/prepare", sqlite3_errmsg(db)); 01192 } 01193 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) { 01194 throw ConfigurationException("get_value/bind/path (1)", sqlite3_errmsg(db)); 01195 } 01196 if ( sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK ) { 01197 throw ConfigurationException("get_value/bind/path (2)", sqlite3_errmsg(db)); 01198 } 01199 01200 return new SQLiteValueIterator(stmt); 01201 } 01202 01203 01204 sqlite3_stmt * 01205 SQLiteConfiguration::prepare_update(const char *sql, 01206 const char *path) 01207 { 01208 sqlite3_stmt *stmt; 01209 const char *tail; 01210 01211 if ( sqlite3_prepare(db, sql, -1, &stmt, &tail) != SQLITE_OK ) { 01212 throw ConfigurationException("prepare_update/prepare", sqlite3_errmsg(db)); 01213 } 01214 if ( sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK ) { 01215 ConfigurationException ce("prepare_update/bind", sqlite3_errmsg(db)); 01216 sqlite3_finalize(stmt); 01217 throw ce; 01218 } 01219 01220 return stmt; 01221 } 01222 01223 01224 sqlite3_stmt * 01225 SQLiteConfiguration::prepare_insert_value(const char *sql, const char *type, 01226 const char *path) 01227 { 01228 sqlite3_stmt *stmt; 01229 const char *tail; 01230 01231 if ( sqlite3_prepare(db, sql, -1, &stmt, &tail) != SQLITE_OK ) { 01232 throw ConfigurationException("prepare_insert_value/prepare", sqlite3_errmsg(db)); 01233 } 01234 if ( (sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK) || 01235 (sqlite3_bind_text(stmt, 2, type, -1, NULL) != SQLITE_OK) ) { 01236 ConfigurationException ce("prepare_insert_value/bind", sqlite3_errmsg(db)); 01237 sqlite3_finalize(stmt); 01238 throw ce; 01239 } 01240 01241 return stmt; 01242 } 01243 01244 01245 void 01246 SQLiteConfiguration::execute_insert_or_update(sqlite3_stmt *stmt) 01247 { 01248 if ( sqlite3_step(stmt) != SQLITE_DONE ) { 01249 ConfigurationException ce("execute_insert_or_update", sqlite3_errmsg(db)); 01250 sqlite3_finalize(stmt); 01251 throw ce; 01252 } 01253 } 01254 01255 01256 void 01257 SQLiteConfiguration::set_float(const char *path, float f) 01258 { 01259 sqlite3_stmt *stmt = NULL; 01260 01261 mutex->lock(); 01262 01263 try { 01264 stmt = prepare_update(SQL_UPDATE_VALUE, path); 01265 if ( (sqlite3_bind_double(stmt, 1, f) != SQLITE_OK) ) { 01266 ConfigurationException ce("set_float/update/bind", sqlite3_errmsg(db)); 01267 sqlite3_finalize(stmt); 01268 mutex->unlock(); 01269 throw ce; 01270 } 01271 execute_insert_or_update(stmt); 01272 sqlite3_finalize(stmt); 01273 } catch (Exception &e) { 01274 if ( stmt != NULL ) sqlite3_finalize(stmt); 01275 mutex->unlock(); 01276 throw; 01277 } 01278 01279 if ( sqlite3_changes(db) == 0 ) { 01280 // value did not exist, insert 01281 01282 try { 01283 stmt = prepare_insert_value(SQL_INSERT_VALUE, "float", path); 01284 if ( (sqlite3_bind_double(stmt, 3, f) != SQLITE_OK) ) { 01285 ConfigurationException ce("set_float/insert/bind", sqlite3_errmsg(db)); 01286 sqlite3_finalize(stmt); 01287 mutex->unlock(); 01288 throw ce; 01289 } 01290 execute_insert_or_update(stmt); 01291 sqlite3_finalize(stmt); 01292 } catch (Exception &e) { 01293 if ( stmt != NULL ) sqlite3_finalize(stmt); 01294 mutex->unlock(); 01295 throw; 01296 } 01297 } 01298 01299 mutex->unlock(); 01300 01301 notify_handlers(path); 01302 } 01303 01304 01305 void 01306 SQLiteConfiguration::set_uint(const char *path, unsigned int uint) 01307 { 01308 sqlite3_stmt *stmt = NULL; 01309 01310 mutex->lock(); 01311 01312 try { 01313 stmt = prepare_update(SQL_UPDATE_VALUE, path); 01314 if ( (sqlite3_bind_int(stmt, 1, uint) != SQLITE_OK) ) { 01315 ConfigurationException ce("set_uint/update/bind", sqlite3_errmsg(db)); 01316 sqlite3_finalize(stmt); 01317 mutex->unlock(); 01318 throw ce; 01319 } 01320 execute_insert_or_update(stmt); 01321 sqlite3_finalize(stmt); 01322 } catch (Exception &e) { 01323 if ( stmt != NULL ) sqlite3_finalize(stmt); 01324 mutex->unlock(); 01325 throw; 01326 } 01327 01328 if ( sqlite3_changes(db) == 0 ) { 01329 // value did not exist, insert 01330 01331 try { 01332 stmt = prepare_insert_value(SQL_INSERT_VALUE, "unsigned int", path); 01333 if ( (sqlite3_bind_int(stmt, 3, uint) != SQLITE_OK) ) { 01334 ConfigurationException ce("set_uint/insert/bind", sqlite3_errmsg(db)); 01335 sqlite3_finalize(stmt); 01336 mutex->unlock(); 01337 throw ce; 01338 } 01339 execute_insert_or_update(stmt); 01340 sqlite3_finalize(stmt); 01341 } catch (Exception &e) { 01342 if ( stmt != NULL ) sqlite3_finalize(stmt); 01343 mutex->unlock(); 01344 throw; 01345 } 01346 } 01347 mutex->unlock(); 01348 01349 notify_handlers(path); 01350 } 01351 01352 01353 void 01354 SQLiteConfiguration::set_int(const char *path, int i) 01355 { 01356 sqlite3_stmt *stmt = NULL; 01357 01358 mutex->lock(); 01359 01360 try { 01361 stmt = prepare_update(SQL_UPDATE_VALUE, path); 01362 if ( (sqlite3_bind_int(stmt, 1, i) != SQLITE_OK) ) { 01363 ConfigurationException ce("set_int/update/bind", sqlite3_errmsg(db)); 01364 sqlite3_finalize(stmt); 01365 mutex->unlock(); 01366 throw ce; 01367 } 01368 execute_insert_or_update(stmt); 01369 sqlite3_finalize(stmt); 01370 } catch (Exception &e) { 01371 if ( stmt != NULL ) sqlite3_finalize(stmt); 01372 mutex->unlock(); 01373 throw; 01374 } 01375 01376 if ( sqlite3_changes(db) == 0 ) { 01377 // value did not exist, insert 01378 01379 try { 01380 stmt = prepare_insert_value(SQL_INSERT_VALUE, "int", path); 01381 if ( (sqlite3_bind_int(stmt, 3, i) != SQLITE_OK) ) { 01382 ConfigurationException ce("set_int/insert/bind", sqlite3_errmsg(db)); 01383 sqlite3_finalize(stmt); 01384 mutex->unlock(); 01385 throw ce; 01386 } 01387 execute_insert_or_update(stmt); 01388 sqlite3_finalize(stmt); 01389 } catch (Exception &e) { 01390 if ( stmt != NULL ) sqlite3_finalize(stmt); 01391 mutex->unlock(); 01392 throw; 01393 } 01394 } 01395 01396 mutex->unlock(); 01397 01398 notify_handlers(path); 01399 } 01400 01401 01402 void 01403 SQLiteConfiguration::set_bool(const char *path, bool b) 01404 { 01405 sqlite3_stmt *stmt = NULL; 01406 01407 mutex->lock(); 01408 01409 try { 01410 stmt = prepare_update(SQL_UPDATE_VALUE, path); 01411 if ( (sqlite3_bind_int(stmt, 1, (b ? 1 : 0)) != SQLITE_OK) ) { 01412 ConfigurationException ce("set_bool/update/bind", sqlite3_errmsg(db)); 01413 sqlite3_finalize(stmt); 01414 mutex->unlock(); 01415 throw ce; 01416 } 01417 execute_insert_or_update(stmt); 01418 sqlite3_finalize(stmt); 01419 } catch (Exception &e) { 01420 if ( stmt != NULL ) sqlite3_finalize(stmt); 01421 mutex->unlock(); 01422 throw; 01423 } 01424 01425 if ( sqlite3_changes(db) == 0 ) { 01426 // value did not exist, insert 01427 01428 try { 01429 stmt = prepare_insert_value(SQL_INSERT_VALUE, "bool", path); 01430 if ( (sqlite3_bind_int(stmt, 3, (b ? 1 : 0)) != SQLITE_OK) ) { 01431 ConfigurationException ce("set_bool/insert/bind", sqlite3_errmsg(db)); 01432 sqlite3_finalize(stmt); 01433 mutex->unlock(); 01434 throw ce; 01435 } 01436 execute_insert_or_update(stmt); 01437 sqlite3_finalize(stmt); 01438 } catch (Exception &e) { 01439 if ( stmt != NULL ) sqlite3_finalize(stmt); 01440 mutex->unlock(); 01441 throw; 01442 } 01443 } 01444 01445 mutex->unlock(); 01446 01447 notify_handlers(path); 01448 } 01449 01450 01451 void 01452 SQLiteConfiguration::set_string(const char *path, 01453 const char *s) 01454 { 01455 sqlite3_stmt *stmt = NULL; 01456 01457 mutex->lock(); 01458 01459 size_t s_length = strlen(s); 01460 01461 try { 01462 stmt = prepare_update(SQL_UPDATE_VALUE, path); 01463 if ( (sqlite3_bind_text(stmt, 1, s, s_length, SQLITE_STATIC) != SQLITE_OK) ) { 01464 ConfigurationException ce("set_string/update/bind", sqlite3_errmsg(db)); 01465 sqlite3_finalize(stmt); 01466 mutex->unlock(); 01467 throw ce; 01468 } 01469 execute_insert_or_update(stmt); 01470 sqlite3_finalize(stmt); 01471 } catch (Exception &e) { 01472 if ( stmt != NULL ) sqlite3_finalize(stmt); 01473 mutex->unlock(); 01474 throw; 01475 } 01476 01477 if ( sqlite3_changes(db) == 0 ) { 01478 // value did not exist, insert 01479 01480 try { 01481 stmt = prepare_insert_value(SQL_INSERT_VALUE, "string", path); 01482 if ( (sqlite3_bind_text(stmt, 3, s, s_length, SQLITE_STATIC) != SQLITE_OK) ) { 01483 ConfigurationException ce("set_string/insert/bind", sqlite3_errmsg(db)); 01484 sqlite3_finalize(stmt); 01485 mutex->unlock(); 01486 throw ce; 01487 } 01488 execute_insert_or_update(stmt); 01489 sqlite3_finalize(stmt); 01490 } catch (Exception &e) { 01491 if ( stmt != NULL ) sqlite3_finalize(stmt); 01492 mutex->unlock(); 01493 throw; 01494 } 01495 } 01496 01497 mutex->unlock(); 01498 01499 notify_handlers(path); 01500 } 01501 01502 01503 void 01504 SQLiteConfiguration::set_string(const char *path, std::string &s) 01505 { 01506 set_string(path, s.c_str()); 01507 } 01508 01509 01510 void 01511 SQLiteConfiguration::set_comment(const char *path, const char *comment) 01512 { 01513 sqlite3_stmt *stmt = NULL; 01514 01515 mutex->lock(); 01516 01517 size_t s_length = strlen(comment); 01518 01519 try { 01520 stmt = prepare_update(SQL_UPDATE_COMMENT, path); 01521 if ( (sqlite3_bind_text(stmt, 1, comment, s_length, SQLITE_STATIC) != SQLITE_OK) ) { 01522 ConfigurationException ce("set_string/update/bind", sqlite3_errmsg(db)); 01523 sqlite3_finalize(stmt); 01524 mutex->unlock(); 01525 throw ce; 01526 } 01527 execute_insert_or_update(stmt); 01528 sqlite3_finalize(stmt); 01529 } catch (Exception &e) { 01530 if ( stmt != NULL ) sqlite3_finalize(stmt); 01531 mutex->unlock(); 01532 throw; 01533 } 01534 01535 if ( sqlite3_changes(db) == 0 ) { 01536 // value did not exist, insert 01537 mutex->unlock(); 01538 throw ConfigurationException("set_comment", "Cannot set comment for inexistent path"); 01539 } 01540 01541 mutex->unlock(); 01542 01543 notify_handlers(path, true); 01544 } 01545 01546 01547 void 01548 SQLiteConfiguration::set_comment(const char *path, std::string &comment) 01549 { 01550 set_comment(path, comment.c_str()); 01551 } 01552 01553 01554 void 01555 SQLiteConfiguration::erase(const char *path) 01556 { 01557 sqlite3_stmt *stmt; 01558 const char *tail; 01559 01560 if ( sqlite3_prepare(db, SQL_DELETE_VALUE, -1, &stmt, &tail) != SQLITE_OK ) { 01561 throw ConfigurationException("erase/prepare", sqlite3_errmsg(db)); 01562 } 01563 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) { 01564 ConfigurationException ce("erase/bind", sqlite3_errmsg(db)); 01565 sqlite3_finalize(stmt); 01566 throw ce; 01567 } 01568 01569 if ( sqlite3_step(stmt) != SQLITE_DONE ) { 01570 ConfigurationException ce("erase/execute", sqlite3_errmsg(db)); 01571 sqlite3_finalize(stmt); 01572 throw ce; 01573 } 01574 01575 sqlite3_finalize(stmt); 01576 01577 notify_handlers(path); 01578 } 01579 01580 01581 void 01582 SQLiteConfiguration::set_default_float(const char *path, float f) 01583 { 01584 sqlite3_stmt *stmt = NULL; 01585 01586 mutex->lock(); 01587 01588 try { 01589 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path); 01590 if ( (sqlite3_bind_double(stmt, 1, f) != SQLITE_OK) ) { 01591 ConfigurationException ce("set_default_float/update/bind", sqlite3_errmsg(db)); 01592 sqlite3_finalize(stmt); 01593 mutex->unlock(); 01594 throw ce; 01595 } 01596 execute_insert_or_update(stmt); 01597 sqlite3_finalize(stmt); 01598 } catch (Exception &e) { 01599 if ( stmt != NULL ) sqlite3_finalize(stmt); 01600 mutex->unlock(); 01601 throw; 01602 } 01603 01604 if ( sqlite3_changes(db) == 0 ) { 01605 // value did not exist, insert 01606 01607 try { 01608 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "float", path); 01609 if ( (sqlite3_bind_double(stmt, 3, f) != SQLITE_OK) ) { 01610 ConfigurationException ce("set_default_float/insert/bind", sqlite3_errmsg(db)); 01611 sqlite3_finalize(stmt); 01612 mutex->unlock(); 01613 throw ce; 01614 } 01615 execute_insert_or_update(stmt); 01616 sqlite3_finalize(stmt); 01617 } catch (Exception &e) { 01618 if ( stmt != NULL ) sqlite3_finalize(stmt); 01619 mutex->unlock(); 01620 throw; 01621 } 01622 } 01623 01624 mutex->unlock(); 01625 01626 notify_handlers(path); 01627 } 01628 01629 01630 void 01631 SQLiteConfiguration::set_default_uint(const char *path, unsigned int uint) 01632 { 01633 sqlite3_stmt *stmt = NULL; 01634 01635 mutex->lock(); 01636 01637 try { 01638 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path); 01639 if ( (sqlite3_bind_int(stmt, 1, uint) != SQLITE_OK) ) { 01640 ConfigurationException ce("set_default_uint/update/bind", sqlite3_errmsg(db)); 01641 sqlite3_finalize(stmt); 01642 mutex->unlock(); 01643 throw ce; 01644 } 01645 execute_insert_or_update(stmt); 01646 sqlite3_finalize(stmt); 01647 } catch (Exception &e) { 01648 if ( stmt != NULL ) sqlite3_finalize(stmt); 01649 mutex->unlock(); 01650 throw; 01651 } 01652 01653 if ( sqlite3_changes(db) == 0 ) { 01654 // value did not exist, insert 01655 01656 try { 01657 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "unsigned int", path); 01658 if ( (sqlite3_bind_int(stmt, 3, uint) != SQLITE_OK) ) { 01659 ConfigurationException ce("set_default_uint/insert/bind", sqlite3_errmsg(db)); 01660 sqlite3_finalize(stmt); 01661 mutex->unlock(); 01662 throw ce; 01663 } 01664 execute_insert_or_update(stmt); 01665 sqlite3_finalize(stmt); 01666 } catch (Exception &e) { 01667 if ( stmt != NULL ) sqlite3_finalize(stmt); 01668 mutex->unlock(); 01669 throw; 01670 } 01671 } 01672 mutex->unlock(); 01673 01674 notify_handlers(path); 01675 } 01676 01677 01678 void 01679 SQLiteConfiguration::set_default_int(const char *path, int i) 01680 { 01681 sqlite3_stmt *stmt = NULL; 01682 mutex->lock(); 01683 01684 try { 01685 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path); 01686 if ( (sqlite3_bind_int(stmt, 1, i) != SQLITE_OK) ) { 01687 ConfigurationException ce("set_default_int/update/bind", sqlite3_errmsg(db)); 01688 sqlite3_finalize(stmt); 01689 mutex->unlock(); 01690 throw ce; 01691 } 01692 execute_insert_or_update(stmt); 01693 sqlite3_finalize(stmt); 01694 } catch (Exception &e) { 01695 if ( stmt != NULL ) sqlite3_finalize(stmt); 01696 mutex->unlock(); 01697 throw; 01698 } 01699 01700 if ( sqlite3_changes(db) == 0 ) { 01701 // value did not exist, insert 01702 try { 01703 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "int", path); 01704 if ( (sqlite3_bind_int(stmt, 3, i) != SQLITE_OK) ) { 01705 ConfigurationException ce("set_default_int/insert/bind", sqlite3_errmsg(db)); 01706 sqlite3_finalize(stmt); 01707 mutex->unlock(); 01708 throw ce; 01709 } 01710 execute_insert_or_update(stmt); 01711 sqlite3_finalize(stmt); 01712 } catch (Exception &e) { 01713 if ( stmt != NULL ) sqlite3_finalize(stmt); 01714 mutex->unlock(); 01715 throw; 01716 } 01717 } 01718 01719 mutex->unlock(); 01720 01721 notify_handlers(path); 01722 } 01723 01724 01725 void 01726 SQLiteConfiguration::set_default_bool(const char *path, bool b) 01727 { 01728 sqlite3_stmt *stmt = NULL; 01729 01730 mutex->lock(); 01731 01732 try { 01733 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path); 01734 if ( (sqlite3_bind_int(stmt, 1, (b ? 1 : 0)) != SQLITE_OK) ) { 01735 ConfigurationException ce("set_default_bool/update/bind", sqlite3_errmsg(db)); 01736 sqlite3_finalize(stmt); 01737 mutex->unlock(); 01738 throw ce; 01739 } 01740 execute_insert_or_update(stmt); 01741 sqlite3_finalize(stmt); 01742 } catch (Exception &e) { 01743 if ( stmt != NULL ) sqlite3_finalize(stmt); 01744 mutex->unlock(); 01745 throw; 01746 } 01747 01748 if ( sqlite3_changes(db) == 0 ) { 01749 // value did not exist, insert 01750 01751 try { 01752 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "bool", path); 01753 if ( (sqlite3_bind_int(stmt, 3, (b ? 1 : 0)) != SQLITE_OK) ) { 01754 ConfigurationException ce("set_default_bool/insert/bind", sqlite3_errmsg(db)); 01755 sqlite3_finalize(stmt); 01756 mutex->unlock(); 01757 throw ce; 01758 } 01759 execute_insert_or_update(stmt); 01760 sqlite3_finalize(stmt); 01761 } catch (Exception &e) { 01762 if ( stmt != NULL ) sqlite3_finalize(stmt); 01763 mutex->unlock(); 01764 throw; 01765 } 01766 } 01767 01768 mutex->unlock(); 01769 01770 notify_handlers(path); 01771 } 01772 01773 01774 void 01775 SQLiteConfiguration::set_default_string(const char *path, 01776 const char *s) 01777 { 01778 sqlite3_stmt *stmt = NULL; 01779 01780 mutex->lock(); 01781 size_t s_length = strlen(s); 01782 01783 try { 01784 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path); 01785 if ( (sqlite3_bind_text(stmt, 1, s, s_length, SQLITE_STATIC) != SQLITE_OK) ) { 01786 ConfigurationException ce("set_default_string/update/bind", sqlite3_errmsg(db)); 01787 sqlite3_finalize(stmt); 01788 mutex->unlock(); 01789 throw ce; 01790 } 01791 execute_insert_or_update(stmt); 01792 sqlite3_finalize(stmt); 01793 } catch (Exception &e) { 01794 if ( stmt != NULL ) sqlite3_finalize(stmt); 01795 mutex->unlock(); 01796 throw; 01797 } 01798 01799 if ( sqlite3_changes(db) == 0 ) { 01800 // value did not exist, insert 01801 01802 try { 01803 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "string", path); 01804 if ( (sqlite3_bind_text(stmt, 3, s, s_length, SQLITE_STATIC) != SQLITE_OK) ) { 01805 ConfigurationException ce("set_default_string/insert/bind", sqlite3_errmsg(db)); 01806 sqlite3_finalize(stmt); 01807 mutex->unlock(); 01808 throw ce; 01809 } 01810 execute_insert_or_update(stmt); 01811 sqlite3_finalize(stmt); 01812 } catch (Exception &e) { 01813 if ( stmt != NULL ) sqlite3_finalize(stmt); 01814 mutex->unlock(); 01815 throw; 01816 } 01817 } 01818 01819 mutex->unlock(); 01820 01821 notify_handlers(path); 01822 } 01823 01824 01825 void 01826 SQLiteConfiguration::set_default_string(const char *path, std::string &s) 01827 { 01828 set_default_string(path, s.c_str()); 01829 } 01830 01831 01832 void 01833 SQLiteConfiguration::set_default_comment(const char *path, const char *comment) 01834 { 01835 sqlite3_stmt *stmt = NULL; 01836 01837 mutex->lock(); 01838 size_t s_length = strlen(comment); 01839 01840 try { 01841 stmt = prepare_update(SQL_UPDATE_DEFAULT_COMMENT, path); 01842 if ( (sqlite3_bind_text(stmt, 1, comment, s_length, SQLITE_STATIC) != SQLITE_OK) ) { 01843 ConfigurationException ce("set_default_comment/update/bind", sqlite3_errmsg(db)); 01844 sqlite3_finalize(stmt); 01845 mutex->unlock(); 01846 throw ce; 01847 } 01848 execute_insert_or_update(stmt); 01849 sqlite3_finalize(stmt); 01850 } catch (Exception &e) { 01851 if ( stmt != NULL ) sqlite3_finalize(stmt); 01852 mutex->unlock(); 01853 throw; 01854 } 01855 01856 if ( sqlite3_changes(db) == 0 ) { 01857 // value did not exist, insert 01858 mutex->unlock(); 01859 throw ConfigurationException("set_default_comment", "Cannot set comment for inexistent path"); 01860 } 01861 01862 mutex->unlock(); 01863 01864 notify_handlers(path); 01865 } 01866 01867 01868 void 01869 SQLiteConfiguration::set_default_comment(const char *path, std::string &comment) 01870 { 01871 set_default_comment(path, comment.c_str()); 01872 } 01873 01874 01875 void 01876 SQLiteConfiguration::erase_default(const char *path) 01877 { 01878 sqlite3_stmt *stmt; 01879 const char *tail; 01880 01881 if ( sqlite3_prepare(db, SQL_DELETE_DEFAULT_VALUE, -1, &stmt, &tail) != SQLITE_OK ) { 01882 throw ConfigurationException("erase_default/prepare", sqlite3_errmsg(db)); 01883 } 01884 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) { 01885 ConfigurationException ce("erase_default/bind", sqlite3_errmsg(db)); 01886 sqlite3_finalize(stmt); 01887 throw ce; 01888 } 01889 01890 if ( sqlite3_step(stmt) != SQLITE_DONE ) { 01891 ConfigurationException ce("erase_default/execute", sqlite3_errmsg(db)); 01892 sqlite3_finalize(stmt); 01893 throw ce; 01894 } 01895 01896 sqlite3_finalize(stmt); 01897 01898 notify_handlers(path); 01899 } 01900 01901 01902 /** Lock the config. 01903 * No further changes or queries can be executed on the configuration and will block until 01904 * the config is unlocked. 01905 */ 01906 void 01907 SQLiteConfiguration::lock() 01908 { 01909 mutex->lock(); 01910 } 01911 01912 01913 /** Try to lock the config. 01914 * @see Configuration::lock() 01915 * @return true, if the lock has been aquired, false otherwise 01916 */ 01917 bool 01918 SQLiteConfiguration::try_lock() 01919 { 01920 return mutex->try_lock(); 01921 } 01922 01923 /** Unlock the config. 01924 * Modifications and queries are possible again. 01925 */ 01926 void 01927 SQLiteConfiguration::unlock() 01928 { 01929 mutex->unlock(); 01930 } 01931 01932 01933 Configuration::ValueIterator * 01934 SQLiteConfiguration::iterator() 01935 { 01936 sqlite3_stmt *stmt; 01937 const char *tail; 01938 01939 if ( sqlite3_prepare(db, SQL_SELECT_ALL, -1, &stmt, &tail) != SQLITE_OK ) { 01940 throw ConfigurationException("iterator: Preparation SQL failed"); 01941 } 01942 01943 return new SQLiteValueIterator(stmt); 01944 } 01945 01946 01947 Configuration::ValueIterator * 01948 SQLiteConfiguration::iterator_default() 01949 { 01950 sqlite3_stmt *stmt; 01951 const char *tail; 01952 01953 if ( sqlite3_prepare(db, SQL_SELECT_ALL_DEFAULT, -1, &stmt, &tail) != SQLITE_OK ) { 01954 throw ConfigurationException("iterator_default: Preparation SQL failed"); 01955 } 01956 01957 return new SQLiteValueIterator(stmt); 01958 } 01959 01960 Configuration::ValueIterator * 01961 SQLiteConfiguration::iterator_hostspecific() 01962 { 01963 sqlite3_stmt *stmt; 01964 const char *tail; 01965 01966 if ( sqlite3_prepare(db, SQL_SELECT_ALL_HOSTSPECIFIC, -1, &stmt, &tail) != SQLITE_OK ) { 01967 throw ConfigurationException("iterator_hostspecific: Preparation SQL failed"); 01968 } 01969 01970 return new SQLiteValueIterator(stmt); 01971 } 01972 01973 /** Iterator for modified values. 01974 * Returns an iterator that can be used to iterate over all values that have been 01975 * modified in the default database in the last load (added, erased or changed). 01976 * @return iterator over all values 01977 */ 01978 SQLiteConfiguration::SQLiteValueIterator * 01979 SQLiteConfiguration::modified_iterator() 01980 { 01981 sqlite3_stmt *stmt; 01982 const char *tail; 01983 01984 if ( sqlite3_prepare(db, SQL_SELECT_MODIFIED_ALL, -1, &stmt, &tail) != SQLITE_OK ) { 01985 throw ConfigurationException("modified_iterator: Preparation SQL failed"); 01986 } 01987 01988 return new SQLiteValueIterator(stmt); 01989 } 01990 01991 01992 /** Iterator with search results. 01993 * Returns an iterator that can be used to iterate over the search results. All values 01994 * whose component and path start with the given strings are returned. 01995 * A call like 01996 * @code 01997 * config->search(""); 01998 * @endcode 01999 * is effectively the same as a call to iterator(). 02000 * @param path start of path 02001 * @return iterator to search results 02002 */ 02003 Configuration::ValueIterator * 02004 SQLiteConfiguration::search(const char *path) 02005 { 02006 sqlite3_stmt *stmt; 02007 const char *tail; 02008 02009 char *p; 02010 if ( asprintf(&p, "%s%%", path) == -1 ) { 02011 throw ConfigurationException("search: could not allocate component string"); 02012 } 02013 02014 if ( sqlite3_prepare(db, SQL_SELECT_COMPLETE, -1, &stmt, &tail) != SQLITE_OK ) { 02015 free(p); 02016 throw ConfigurationException("begin: Preparation SQL failed"); 02017 } 02018 if ( sqlite3_bind_text(stmt, 1, p, -1, NULL) != SQLITE_OK ) { 02019 free(p); 02020 throw ConfigurationException("begin: Binding text for path failed (1)"); 02021 } 02022 if ( sqlite3_bind_text(stmt, 2, p, -1, NULL) != SQLITE_OK ) { 02023 free(p); 02024 throw ConfigurationException("begin: Binding text for path failed (2)"); 02025 } 02026 02027 return new SQLiteValueIterator(stmt, p); 02028 } 02029 02030 /** @class SQLiteConfiguration::SQLiteValueIterator config/sqlite.h 02031 * SQLite configuration value iterator. 02032 */ 02033 02034 02035 /** Constructor. 02036 * @param stmt compiled SQLite statement 02037 * @param p pointer to arbitrary data that is freed (not deleted!) when the iterator 02038 * is deleted. 02039 */ 02040 SQLiteConfiguration::SQLiteValueIterator::SQLiteValueIterator(::sqlite3_stmt *stmt, void *p) 02041 { 02042 __stmt = stmt; 02043 __p = p; 02044 } 02045 02046 02047 /** Destructor. */ 02048 SQLiteConfiguration::SQLiteValueIterator::~SQLiteValueIterator() 02049 { 02050 if ( __stmt != NULL ) { 02051 sqlite3_finalize(__stmt); 02052 __stmt = NULL; 02053 } 02054 if ( __p != NULL ) { 02055 free(__p); 02056 } 02057 } 02058 02059 02060 /* Check if there is another element and advance to this if possible. 02061 * This advances to the next element, if there is one. 02062 * @return true, if another element has been reached, false otherwise 02063 */ 02064 bool 02065 SQLiteConfiguration::SQLiteValueIterator::next() 02066 { 02067 if ( __stmt == NULL) return false; 02068 02069 if (sqlite3_step(__stmt) == SQLITE_ROW ) { 02070 return true; 02071 } else { 02072 sqlite3_finalize(__stmt); 02073 __stmt = NULL; 02074 return false; 02075 } 02076 } 02077 02078 /** Check if the current element is valid. 02079 * This is much like the classic end element for iterators. If the iterator is 02080 * invalid there all subsequent calls to next() shall fail. 02081 * @return true, if the iterator is still valid, false otherwise 02082 */ 02083 bool 02084 SQLiteConfiguration::SQLiteValueIterator::valid() const 02085 { 02086 return ( __stmt != NULL); 02087 } 02088 02089 02090 /** Path of value. 02091 * @return path of value 02092 */ 02093 const char * 02094 SQLiteConfiguration::SQLiteValueIterator::path() const 02095 { 02096 return (const char *)sqlite3_column_text(__stmt, 0); 02097 } 02098 02099 02100 /** Type of value. 02101 * @return string representation of value type. 02102 */ 02103 const char * 02104 SQLiteConfiguration::SQLiteValueIterator::type() const 02105 { 02106 return (const char *)sqlite3_column_text(__stmt, 1); 02107 } 02108 02109 02110 /** Check if current value is a float. 02111 * @return true, if value is a float, false otherwise 02112 */ 02113 bool 02114 SQLiteConfiguration::SQLiteValueIterator::is_float() const 02115 { 02116 return (strcmp("float", (const char *)sqlite3_column_text(__stmt, 1)) == 0); 02117 } 02118 02119 02120 /** Check if current value is a unsigned int. 02121 * @return true, if value is a unsigned int, false otherwise 02122 */ 02123 bool 02124 SQLiteConfiguration::SQLiteValueIterator::is_uint() const 02125 { 02126 return (strcmp("unsigned int", (const char *)sqlite3_column_text(__stmt, 1)) == 0); 02127 } 02128 02129 /** Check if current value is a int. 02130 * @return true, if value is a int, false otherwise 02131 */ 02132 bool 02133 SQLiteConfiguration::SQLiteValueIterator::is_int() const 02134 { 02135 return (strcmp("int", (const char *)sqlite3_column_text(__stmt, 1)) == 0); 02136 } 02137 02138 02139 /** Check if current value is a bool. 02140 * @return true, if value is a bool, false otherwise 02141 */ 02142 bool 02143 SQLiteConfiguration::SQLiteValueIterator::is_bool() const 02144 { 02145 return (strcmp("bool", (const char *)sqlite3_column_text(__stmt, 1)) == 0); 02146 } 02147 02148 02149 /** Check if current value is a string. 02150 * @return true, if value is a string, false otherwise 02151 */ 02152 bool 02153 SQLiteConfiguration::SQLiteValueIterator::is_string() const 02154 { 02155 return (strcmp("string", (const char *)sqlite3_column_text(__stmt, 1)) == 0); 02156 } 02157 02158 bool 02159 SQLiteConfiguration::SQLiteValueIterator::is_default() const 02160 { 02161 return (sqlite3_column_int(__stmt, 4) == 1); 02162 } 02163 02164 02165 /** Get float value. 02166 * @return value 02167 */ 02168 float 02169 SQLiteConfiguration::SQLiteValueIterator::get_float() const 02170 { 02171 return (float)sqlite3_column_double(__stmt, 2); 02172 } 02173 02174 02175 /** Get unsigned int value. 02176 * @return value 02177 */ 02178 unsigned int 02179 SQLiteConfiguration::SQLiteValueIterator::get_uint() const 02180 { 02181 int i = sqlite3_column_int(__stmt, 2); 02182 if( i < 0 ) { 02183 return 0; 02184 } else { 02185 return i; 02186 } 02187 } 02188 02189 02190 /** Get int value. 02191 * @return value 02192 */ 02193 int 02194 SQLiteConfiguration::SQLiteValueIterator::get_int() const 02195 { 02196 return sqlite3_column_int(__stmt, 2); 02197 } 02198 02199 /** Get bool value. 02200 * @return value 02201 */ 02202 bool 02203 SQLiteConfiguration::SQLiteValueIterator::get_bool() const 02204 { 02205 return (sqlite3_column_int(__stmt, 2) != 0); 02206 } 02207 02208 /** Get string value. 02209 * @return value 02210 */ 02211 std::string 02212 SQLiteConfiguration::SQLiteValueIterator::get_string() const 02213 { 02214 return (const char *)sqlite3_column_text(__stmt, 2); 02215 } 02216 02217 02218 /** Get value as string. 02219 * @return value 02220 */ 02221 std::string 02222 SQLiteConfiguration::SQLiteValueIterator::get_as_string() const 02223 { 02224 return (const char *)sqlite3_column_text(__stmt, 2); 02225 } 02226 02227 /** Get comment. 02228 * @return string comment value 02229 */ 02230 std::string 02231 SQLiteConfiguration::SQLiteValueIterator::get_comment() const 02232 { 02233 const char *c = (const char *)sqlite3_column_text(__stmt, 3); 02234 return c ? c : ""; 02235 } 02236 02237 /** Get modification type. 02238 * This can only be called if the iterator has been retrieved via 02239 * SQLiteConfiguration::modified_iterator(). Otherwise the return value is 02240 * always and empty string. 02241 * @return string modification type 02242 */ 02243 std::string 02244 SQLiteConfiguration::SQLiteValueIterator::get_modtype() const 02245 { 02246 const char *c = (const char *)sqlite3_column_text(__stmt, 4); 02247 return c ? c : ""; 02248 } 02249 02250 02251 02252 /** Get old value (as string). 02253 * This can only be called if the iterator has been retrieved via 02254 * SQLiteConfiguration::modified_iterator(). The value is always returned 02255 * as string, as it is meant for debugging purposes only. Otherwise the 02256 * return value is always and empty string. 02257 * @return string modification type 02258 */ 02259 std::string 02260 SQLiteConfiguration::SQLiteValueIterator::get_oldvalue() const 02261 { 02262 const char *c = (const char *)sqlite3_column_text(__stmt, 5); 02263 return c ? c : ""; 02264 } 02265 02266 02267 } // end namespace fawkes