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 ChangeHandlerList *h = find_handlers(path); 01302 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) { 01303 (*i)->config_value_changed(path, false, f); 01304 } 01305 delete h; 01306 } 01307 01308 01309 void 01310 SQLiteConfiguration::set_uint(const char *path, unsigned int uint) 01311 { 01312 sqlite3_stmt *stmt = NULL; 01313 01314 mutex->lock(); 01315 01316 try { 01317 stmt = prepare_update(SQL_UPDATE_VALUE, path); 01318 if ( (sqlite3_bind_int(stmt, 1, uint) != SQLITE_OK) ) { 01319 ConfigurationException ce("set_uint/update/bind", sqlite3_errmsg(db)); 01320 sqlite3_finalize(stmt); 01321 mutex->unlock(); 01322 throw ce; 01323 } 01324 execute_insert_or_update(stmt); 01325 sqlite3_finalize(stmt); 01326 } catch (Exception &e) { 01327 if ( stmt != NULL ) sqlite3_finalize(stmt); 01328 mutex->unlock(); 01329 throw; 01330 } 01331 01332 if ( sqlite3_changes(db) == 0 ) { 01333 // value did not exist, insert 01334 01335 try { 01336 stmt = prepare_insert_value(SQL_INSERT_VALUE, "unsigned int", path); 01337 if ( (sqlite3_bind_int(stmt, 3, uint) != SQLITE_OK) ) { 01338 ConfigurationException ce("set_uint/insert/bind", sqlite3_errmsg(db)); 01339 sqlite3_finalize(stmt); 01340 mutex->unlock(); 01341 throw ce; 01342 } 01343 execute_insert_or_update(stmt); 01344 sqlite3_finalize(stmt); 01345 } catch (Exception &e) { 01346 if ( stmt != NULL ) sqlite3_finalize(stmt); 01347 mutex->unlock(); 01348 throw; 01349 } 01350 } 01351 mutex->unlock(); 01352 01353 ChangeHandlerList *h = find_handlers(path); 01354 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) { 01355 (*i)->config_value_changed(path, false, uint); 01356 } 01357 delete h; 01358 } 01359 01360 01361 void 01362 SQLiteConfiguration::set_int(const char *path, int i) 01363 { 01364 sqlite3_stmt *stmt = NULL; 01365 01366 mutex->lock(); 01367 01368 try { 01369 stmt = prepare_update(SQL_UPDATE_VALUE, path); 01370 if ( (sqlite3_bind_int(stmt, 1, i) != SQLITE_OK) ) { 01371 ConfigurationException ce("set_int/update/bind", sqlite3_errmsg(db)); 01372 sqlite3_finalize(stmt); 01373 mutex->unlock(); 01374 throw ce; 01375 } 01376 execute_insert_or_update(stmt); 01377 sqlite3_finalize(stmt); 01378 } catch (Exception &e) { 01379 if ( stmt != NULL ) sqlite3_finalize(stmt); 01380 mutex->unlock(); 01381 throw; 01382 } 01383 01384 if ( sqlite3_changes(db) == 0 ) { 01385 // value did not exist, insert 01386 01387 try { 01388 stmt = prepare_insert_value(SQL_INSERT_VALUE, "int", path); 01389 if ( (sqlite3_bind_int(stmt, 3, i) != SQLITE_OK) ) { 01390 ConfigurationException ce("set_int/insert/bind", sqlite3_errmsg(db)); 01391 sqlite3_finalize(stmt); 01392 mutex->unlock(); 01393 throw ce; 01394 } 01395 execute_insert_or_update(stmt); 01396 sqlite3_finalize(stmt); 01397 } catch (Exception &e) { 01398 if ( stmt != NULL ) sqlite3_finalize(stmt); 01399 mutex->unlock(); 01400 throw; 01401 } 01402 } 01403 01404 mutex->unlock(); 01405 01406 ChangeHandlerList *h = find_handlers(path); 01407 for (ChangeHandlerList::const_iterator j = h->begin(); j != h->end(); ++j) { 01408 (*j)->config_value_changed(path, false, i); 01409 } 01410 delete h; 01411 } 01412 01413 01414 void 01415 SQLiteConfiguration::set_bool(const char *path, bool b) 01416 { 01417 sqlite3_stmt *stmt = NULL; 01418 01419 mutex->lock(); 01420 01421 try { 01422 stmt = prepare_update(SQL_UPDATE_VALUE, path); 01423 if ( (sqlite3_bind_int(stmt, 1, (b ? 1 : 0)) != SQLITE_OK) ) { 01424 ConfigurationException ce("set_bool/update/bind", sqlite3_errmsg(db)); 01425 sqlite3_finalize(stmt); 01426 mutex->unlock(); 01427 throw ce; 01428 } 01429 execute_insert_or_update(stmt); 01430 sqlite3_finalize(stmt); 01431 } catch (Exception &e) { 01432 if ( stmt != NULL ) sqlite3_finalize(stmt); 01433 mutex->unlock(); 01434 throw; 01435 } 01436 01437 if ( sqlite3_changes(db) == 0 ) { 01438 // value did not exist, insert 01439 01440 try { 01441 stmt = prepare_insert_value(SQL_INSERT_VALUE, "bool", path); 01442 if ( (sqlite3_bind_int(stmt, 3, (b ? 1 : 0)) != SQLITE_OK) ) { 01443 ConfigurationException ce("set_bool/insert/bind", sqlite3_errmsg(db)); 01444 sqlite3_finalize(stmt); 01445 mutex->unlock(); 01446 throw ce; 01447 } 01448 execute_insert_or_update(stmt); 01449 sqlite3_finalize(stmt); 01450 } catch (Exception &e) { 01451 if ( stmt != NULL ) sqlite3_finalize(stmt); 01452 mutex->unlock(); 01453 throw; 01454 } 01455 } 01456 01457 mutex->unlock(); 01458 01459 ChangeHandlerList *h = find_handlers(path); 01460 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) { 01461 (*i)->config_value_changed(path, false, b); 01462 } 01463 delete h; 01464 } 01465 01466 01467 void 01468 SQLiteConfiguration::set_string(const char *path, 01469 const char *s) 01470 { 01471 sqlite3_stmt *stmt = NULL; 01472 01473 mutex->lock(); 01474 01475 size_t s_length = strlen(s); 01476 01477 try { 01478 stmt = prepare_update(SQL_UPDATE_VALUE, path); 01479 if ( (sqlite3_bind_text(stmt, 1, s, s_length, SQLITE_STATIC) != SQLITE_OK) ) { 01480 ConfigurationException ce("set_string/update/bind", sqlite3_errmsg(db)); 01481 sqlite3_finalize(stmt); 01482 mutex->unlock(); 01483 throw ce; 01484 } 01485 execute_insert_or_update(stmt); 01486 sqlite3_finalize(stmt); 01487 } catch (Exception &e) { 01488 if ( stmt != NULL ) sqlite3_finalize(stmt); 01489 mutex->unlock(); 01490 throw; 01491 } 01492 01493 if ( sqlite3_changes(db) == 0 ) { 01494 // value did not exist, insert 01495 01496 try { 01497 stmt = prepare_insert_value(SQL_INSERT_VALUE, "string", path); 01498 if ( (sqlite3_bind_text(stmt, 3, s, s_length, SQLITE_STATIC) != SQLITE_OK) ) { 01499 ConfigurationException ce("set_string/insert/bind", sqlite3_errmsg(db)); 01500 sqlite3_finalize(stmt); 01501 mutex->unlock(); 01502 throw ce; 01503 } 01504 execute_insert_or_update(stmt); 01505 sqlite3_finalize(stmt); 01506 } catch (Exception &e) { 01507 if ( stmt != NULL ) sqlite3_finalize(stmt); 01508 mutex->unlock(); 01509 throw; 01510 } 01511 } 01512 01513 mutex->unlock(); 01514 01515 ChangeHandlerList *h = find_handlers(path); 01516 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) { 01517 (*i)->config_value_changed(path, false, s); 01518 } 01519 delete h; 01520 } 01521 01522 01523 void 01524 SQLiteConfiguration::set_string(const char *path, std::string &s) 01525 { 01526 set_string(path, s.c_str()); 01527 } 01528 01529 01530 void 01531 SQLiteConfiguration::set_comment(const char *path, const char *comment) 01532 { 01533 sqlite3_stmt *stmt = NULL; 01534 01535 mutex->lock(); 01536 01537 size_t s_length = strlen(comment); 01538 01539 try { 01540 stmt = prepare_update(SQL_UPDATE_COMMENT, path); 01541 if ( (sqlite3_bind_text(stmt, 1, comment, s_length, SQLITE_STATIC) != SQLITE_OK) ) { 01542 ConfigurationException ce("set_string/update/bind", sqlite3_errmsg(db)); 01543 sqlite3_finalize(stmt); 01544 mutex->unlock(); 01545 throw ce; 01546 } 01547 execute_insert_or_update(stmt); 01548 sqlite3_finalize(stmt); 01549 } catch (Exception &e) { 01550 if ( stmt != NULL ) sqlite3_finalize(stmt); 01551 mutex->unlock(); 01552 throw; 01553 } 01554 01555 if ( sqlite3_changes(db) == 0 ) { 01556 // value did not exist, insert 01557 mutex->unlock(); 01558 throw ConfigurationException("set_comment", "Cannot set comment for inexistent path"); 01559 } 01560 01561 mutex->unlock(); 01562 01563 ChangeHandlerList *h = find_handlers(path); 01564 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) { 01565 (*i)->config_comment_changed(path, false, comment); 01566 } 01567 delete h; 01568 } 01569 01570 01571 void 01572 SQLiteConfiguration::set_comment(const char *path, std::string &comment) 01573 { 01574 set_comment(path, comment.c_str()); 01575 } 01576 01577 01578 void 01579 SQLiteConfiguration::erase(const char *path) 01580 { 01581 sqlite3_stmt *stmt; 01582 const char *tail; 01583 01584 if ( sqlite3_prepare(db, SQL_DELETE_VALUE, -1, &stmt, &tail) != SQLITE_OK ) { 01585 throw ConfigurationException("erase/prepare", sqlite3_errmsg(db)); 01586 } 01587 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) { 01588 ConfigurationException ce("erase/bind", sqlite3_errmsg(db)); 01589 sqlite3_finalize(stmt); 01590 throw ce; 01591 } 01592 01593 if ( sqlite3_step(stmt) != SQLITE_DONE ) { 01594 ConfigurationException ce("erase/execute", sqlite3_errmsg(db)); 01595 sqlite3_finalize(stmt); 01596 throw ce; 01597 } 01598 01599 sqlite3_finalize(stmt); 01600 01601 ChangeHandlerList *h = find_handlers(path); 01602 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) { 01603 (*i)->config_value_erased(path, false); 01604 } 01605 delete h; 01606 } 01607 01608 01609 void 01610 SQLiteConfiguration::set_default_float(const char *path, float f) 01611 { 01612 sqlite3_stmt *stmt = NULL; 01613 01614 mutex->lock(); 01615 01616 try { 01617 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path); 01618 if ( (sqlite3_bind_double(stmt, 1, f) != SQLITE_OK) ) { 01619 ConfigurationException ce("set_default_float/update/bind", sqlite3_errmsg(db)); 01620 sqlite3_finalize(stmt); 01621 mutex->unlock(); 01622 throw ce; 01623 } 01624 execute_insert_or_update(stmt); 01625 sqlite3_finalize(stmt); 01626 } catch (Exception &e) { 01627 if ( stmt != NULL ) sqlite3_finalize(stmt); 01628 mutex->unlock(); 01629 throw; 01630 } 01631 01632 if ( sqlite3_changes(db) == 0 ) { 01633 // value did not exist, insert 01634 01635 try { 01636 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "float", path); 01637 if ( (sqlite3_bind_double(stmt, 3, f) != SQLITE_OK) ) { 01638 ConfigurationException ce("set_default_float/insert/bind", sqlite3_errmsg(db)); 01639 sqlite3_finalize(stmt); 01640 mutex->unlock(); 01641 throw ce; 01642 } 01643 execute_insert_or_update(stmt); 01644 sqlite3_finalize(stmt); 01645 } catch (Exception &e) { 01646 if ( stmt != NULL ) sqlite3_finalize(stmt); 01647 mutex->unlock(); 01648 throw; 01649 } 01650 } 01651 01652 mutex->unlock(); 01653 01654 ChangeHandlerList *h = find_handlers(path); 01655 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) { 01656 (*i)->config_value_changed(path, true, f); 01657 } 01658 delete h; 01659 } 01660 01661 01662 void 01663 SQLiteConfiguration::set_default_uint(const char *path, unsigned int uint) 01664 { 01665 sqlite3_stmt *stmt = NULL; 01666 01667 mutex->lock(); 01668 01669 try { 01670 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path); 01671 if ( (sqlite3_bind_int(stmt, 1, uint) != SQLITE_OK) ) { 01672 ConfigurationException ce("set_default_uint/update/bind", sqlite3_errmsg(db)); 01673 sqlite3_finalize(stmt); 01674 mutex->unlock(); 01675 throw ce; 01676 } 01677 execute_insert_or_update(stmt); 01678 sqlite3_finalize(stmt); 01679 } catch (Exception &e) { 01680 if ( stmt != NULL ) sqlite3_finalize(stmt); 01681 mutex->unlock(); 01682 throw; 01683 } 01684 01685 if ( sqlite3_changes(db) == 0 ) { 01686 // value did not exist, insert 01687 01688 try { 01689 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "unsigned int", path); 01690 if ( (sqlite3_bind_int(stmt, 3, uint) != SQLITE_OK) ) { 01691 ConfigurationException ce("set_default_uint/insert/bind", sqlite3_errmsg(db)); 01692 sqlite3_finalize(stmt); 01693 mutex->unlock(); 01694 throw ce; 01695 } 01696 execute_insert_or_update(stmt); 01697 sqlite3_finalize(stmt); 01698 } catch (Exception &e) { 01699 if ( stmt != NULL ) sqlite3_finalize(stmt); 01700 mutex->unlock(); 01701 throw; 01702 } 01703 } 01704 mutex->unlock(); 01705 01706 ChangeHandlerList *h = find_handlers(path); 01707 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) { 01708 (*i)->config_value_changed(path, true, uint); 01709 } 01710 delete h; 01711 } 01712 01713 01714 void 01715 SQLiteConfiguration::set_default_int(const char *path, int i) 01716 { 01717 sqlite3_stmt *stmt = NULL; 01718 mutex->lock(); 01719 01720 try { 01721 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path); 01722 if ( (sqlite3_bind_int(stmt, 1, i) != SQLITE_OK) ) { 01723 ConfigurationException ce("set_default_int/update/bind", sqlite3_errmsg(db)); 01724 sqlite3_finalize(stmt); 01725 mutex->unlock(); 01726 throw ce; 01727 } 01728 execute_insert_or_update(stmt); 01729 sqlite3_finalize(stmt); 01730 } catch (Exception &e) { 01731 if ( stmt != NULL ) sqlite3_finalize(stmt); 01732 mutex->unlock(); 01733 throw; 01734 } 01735 01736 if ( sqlite3_changes(db) == 0 ) { 01737 // value did not exist, insert 01738 try { 01739 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "int", path); 01740 if ( (sqlite3_bind_int(stmt, 3, i) != SQLITE_OK) ) { 01741 ConfigurationException ce("set_default_int/insert/bind", sqlite3_errmsg(db)); 01742 sqlite3_finalize(stmt); 01743 mutex->unlock(); 01744 throw ce; 01745 } 01746 execute_insert_or_update(stmt); 01747 sqlite3_finalize(stmt); 01748 } catch (Exception &e) { 01749 if ( stmt != NULL ) sqlite3_finalize(stmt); 01750 mutex->unlock(); 01751 throw; 01752 } 01753 } 01754 01755 mutex->unlock(); 01756 01757 ChangeHandlerList *h = find_handlers(path); 01758 for (ChangeHandlerList::const_iterator j = h->begin(); j != h->end(); ++j) { 01759 (*j)->config_value_changed(path, true, i); 01760 } 01761 delete h; 01762 } 01763 01764 01765 void 01766 SQLiteConfiguration::set_default_bool(const char *path, bool b) 01767 { 01768 sqlite3_stmt *stmt = NULL; 01769 01770 mutex->lock(); 01771 01772 try { 01773 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path); 01774 if ( (sqlite3_bind_int(stmt, 1, (b ? 1 : 0)) != SQLITE_OK) ) { 01775 ConfigurationException ce("set_default_bool/update/bind", sqlite3_errmsg(db)); 01776 sqlite3_finalize(stmt); 01777 mutex->unlock(); 01778 throw ce; 01779 } 01780 execute_insert_or_update(stmt); 01781 sqlite3_finalize(stmt); 01782 } catch (Exception &e) { 01783 if ( stmt != NULL ) sqlite3_finalize(stmt); 01784 mutex->unlock(); 01785 throw; 01786 } 01787 01788 if ( sqlite3_changes(db) == 0 ) { 01789 // value did not exist, insert 01790 01791 try { 01792 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "bool", path); 01793 if ( (sqlite3_bind_int(stmt, 3, (b ? 1 : 0)) != SQLITE_OK) ) { 01794 ConfigurationException ce("set_default_bool/insert/bind", sqlite3_errmsg(db)); 01795 sqlite3_finalize(stmt); 01796 mutex->unlock(); 01797 throw ce; 01798 } 01799 execute_insert_or_update(stmt); 01800 sqlite3_finalize(stmt); 01801 } catch (Exception &e) { 01802 if ( stmt != NULL ) sqlite3_finalize(stmt); 01803 mutex->unlock(); 01804 throw; 01805 } 01806 } 01807 01808 mutex->unlock(); 01809 01810 ChangeHandlerList *h = find_handlers(path); 01811 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) { 01812 (*i)->config_value_changed(path, true, b); 01813 } 01814 delete h; 01815 } 01816 01817 01818 void 01819 SQLiteConfiguration::set_default_string(const char *path, 01820 const char *s) 01821 { 01822 sqlite3_stmt *stmt = NULL; 01823 01824 mutex->lock(); 01825 size_t s_length = strlen(s); 01826 01827 try { 01828 stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path); 01829 if ( (sqlite3_bind_text(stmt, 1, s, s_length, SQLITE_STATIC) != SQLITE_OK) ) { 01830 ConfigurationException ce("set_default_string/update/bind", sqlite3_errmsg(db)); 01831 sqlite3_finalize(stmt); 01832 mutex->unlock(); 01833 throw ce; 01834 } 01835 execute_insert_or_update(stmt); 01836 sqlite3_finalize(stmt); 01837 } catch (Exception &e) { 01838 if ( stmt != NULL ) sqlite3_finalize(stmt); 01839 mutex->unlock(); 01840 throw; 01841 } 01842 01843 if ( sqlite3_changes(db) == 0 ) { 01844 // value did not exist, insert 01845 01846 try { 01847 stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "string", path); 01848 if ( (sqlite3_bind_text(stmt, 3, s, s_length, SQLITE_STATIC) != SQLITE_OK) ) { 01849 ConfigurationException ce("set_default_string/insert/bind", sqlite3_errmsg(db)); 01850 sqlite3_finalize(stmt); 01851 mutex->unlock(); 01852 throw ce; 01853 } 01854 execute_insert_or_update(stmt); 01855 sqlite3_finalize(stmt); 01856 } catch (Exception &e) { 01857 if ( stmt != NULL ) sqlite3_finalize(stmt); 01858 mutex->unlock(); 01859 throw; 01860 } 01861 } 01862 01863 mutex->unlock(); 01864 01865 ChangeHandlerList *h = find_handlers(path); 01866 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) { 01867 (*i)->config_value_changed(path, true, s); 01868 } 01869 delete h; 01870 } 01871 01872 01873 void 01874 SQLiteConfiguration::set_default_string(const char *path, std::string &s) 01875 { 01876 set_default_string(path, s.c_str()); 01877 } 01878 01879 01880 void 01881 SQLiteConfiguration::set_default_comment(const char *path, const char *comment) 01882 { 01883 sqlite3_stmt *stmt = NULL; 01884 01885 mutex->lock(); 01886 size_t s_length = strlen(comment); 01887 01888 try { 01889 stmt = prepare_update(SQL_UPDATE_DEFAULT_COMMENT, path); 01890 if ( (sqlite3_bind_text(stmt, 1, comment, s_length, SQLITE_STATIC) != SQLITE_OK) ) { 01891 ConfigurationException ce("set_default_comment/update/bind", sqlite3_errmsg(db)); 01892 sqlite3_finalize(stmt); 01893 mutex->unlock(); 01894 throw ce; 01895 } 01896 execute_insert_or_update(stmt); 01897 sqlite3_finalize(stmt); 01898 } catch (Exception &e) { 01899 if ( stmt != NULL ) sqlite3_finalize(stmt); 01900 mutex->unlock(); 01901 throw; 01902 } 01903 01904 if ( sqlite3_changes(db) == 0 ) { 01905 // value did not exist, insert 01906 mutex->unlock(); 01907 throw ConfigurationException("set_default_comment", "Cannot set comment for inexistent path"); 01908 } 01909 01910 mutex->unlock(); 01911 01912 ChangeHandlerList *h = find_handlers(path); 01913 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) { 01914 (*i)->config_comment_changed(path, true, comment); 01915 } 01916 delete h; 01917 } 01918 01919 01920 void 01921 SQLiteConfiguration::set_default_comment(const char *path, std::string &comment) 01922 { 01923 set_default_comment(path, comment.c_str()); 01924 } 01925 01926 01927 void 01928 SQLiteConfiguration::erase_default(const char *path) 01929 { 01930 sqlite3_stmt *stmt; 01931 const char *tail; 01932 01933 if ( sqlite3_prepare(db, SQL_DELETE_DEFAULT_VALUE, -1, &stmt, &tail) != SQLITE_OK ) { 01934 throw ConfigurationException("erase_default/prepare", sqlite3_errmsg(db)); 01935 } 01936 if ( sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK ) { 01937 ConfigurationException ce("erase_default/bind", sqlite3_errmsg(db)); 01938 sqlite3_finalize(stmt); 01939 throw ce; 01940 } 01941 01942 if ( sqlite3_step(stmt) != SQLITE_DONE ) { 01943 ConfigurationException ce("erase_default/execute", sqlite3_errmsg(db)); 01944 sqlite3_finalize(stmt); 01945 throw ce; 01946 } 01947 01948 sqlite3_finalize(stmt); 01949 01950 ChangeHandlerList *h = find_handlers(path); 01951 for (ChangeHandlerList::const_iterator i = h->begin(); i != h->end(); ++i) { 01952 (*i)->config_value_erased(path, true); 01953 } 01954 delete h; 01955 } 01956 01957 01958 /** Lock the config. 01959 * No further changes or queries can be executed on the configuration and will block until 01960 * the config is unlocked. 01961 */ 01962 void 01963 SQLiteConfiguration::lock() 01964 { 01965 mutex->lock(); 01966 } 01967 01968 01969 /** Try to lock the config. 01970 * @see Configuration::lock() 01971 * @return true, if the lock has been aquired, false otherwise 01972 */ 01973 bool 01974 SQLiteConfiguration::try_lock() 01975 { 01976 return mutex->try_lock(); 01977 } 01978 01979 /** Unlock the config. 01980 * Modifications and queries are possible again. 01981 */ 01982 void 01983 SQLiteConfiguration::unlock() 01984 { 01985 mutex->unlock(); 01986 } 01987 01988 01989 Configuration::ValueIterator * 01990 SQLiteConfiguration::iterator() 01991 { 01992 sqlite3_stmt *stmt; 01993 const char *tail; 01994 01995 if ( sqlite3_prepare(db, SQL_SELECT_ALL, -1, &stmt, &tail) != SQLITE_OK ) { 01996 throw ConfigurationException("iterator: Preparation SQL failed"); 01997 } 01998 01999 return new SQLiteValueIterator(stmt); 02000 } 02001 02002 02003 Configuration::ValueIterator * 02004 SQLiteConfiguration::iterator_default() 02005 { 02006 sqlite3_stmt *stmt; 02007 const char *tail; 02008 02009 if ( sqlite3_prepare(db, SQL_SELECT_ALL_DEFAULT, -1, &stmt, &tail) != SQLITE_OK ) { 02010 throw ConfigurationException("iterator_default: Preparation SQL failed"); 02011 } 02012 02013 return new SQLiteValueIterator(stmt); 02014 } 02015 02016 Configuration::ValueIterator * 02017 SQLiteConfiguration::iterator_hostspecific() 02018 { 02019 sqlite3_stmt *stmt; 02020 const char *tail; 02021 02022 if ( sqlite3_prepare(db, SQL_SELECT_ALL_HOSTSPECIFIC, -1, &stmt, &tail) != SQLITE_OK ) { 02023 throw ConfigurationException("iterator_hostspecific: Preparation SQL failed"); 02024 } 02025 02026 return new SQLiteValueIterator(stmt); 02027 } 02028 02029 /** Iterator for modified values. 02030 * Returns an iterator that can be used to iterate over all values that have been 02031 * modified in the default database in the last load (added, erased or changed). 02032 * @return iterator over all values 02033 */ 02034 SQLiteConfiguration::SQLiteValueIterator * 02035 SQLiteConfiguration::modified_iterator() 02036 { 02037 sqlite3_stmt *stmt; 02038 const char *tail; 02039 02040 if ( sqlite3_prepare(db, SQL_SELECT_MODIFIED_ALL, -1, &stmt, &tail) != SQLITE_OK ) { 02041 throw ConfigurationException("modified_iterator: Preparation SQL failed"); 02042 } 02043 02044 return new SQLiteValueIterator(stmt); 02045 } 02046 02047 02048 /** Iterator with search results. 02049 * Returns an iterator that can be used to iterate over the search results. All values 02050 * whose component and path start with the given strings are returned. 02051 * A call like 02052 * @code 02053 * config->search(""); 02054 * @endcode 02055 * is effectively the same as a call to iterator(). 02056 * @param path start of path 02057 * @return iterator to search results 02058 */ 02059 Configuration::ValueIterator * 02060 SQLiteConfiguration::search(const char *path) 02061 { 02062 sqlite3_stmt *stmt; 02063 const char *tail; 02064 02065 char *p; 02066 if ( asprintf(&p, "%s%%", path) == -1 ) { 02067 throw ConfigurationException("search: could not allocate component string"); 02068 } 02069 02070 if ( sqlite3_prepare(db, SQL_SELECT_COMPLETE, -1, &stmt, &tail) != SQLITE_OK ) { 02071 free(p); 02072 throw ConfigurationException("begin: Preparation SQL failed"); 02073 } 02074 if ( sqlite3_bind_text(stmt, 1, p, -1, NULL) != SQLITE_OK ) { 02075 free(p); 02076 throw ConfigurationException("begin: Binding text for path failed (1)"); 02077 } 02078 if ( sqlite3_bind_text(stmt, 2, p, -1, NULL) != SQLITE_OK ) { 02079 free(p); 02080 throw ConfigurationException("begin: Binding text for path failed (2)"); 02081 } 02082 02083 return new SQLiteValueIterator(stmt, p); 02084 } 02085 02086 /** @class SQLiteConfiguration::SQLiteValueIterator config/sqlite.h 02087 * SQLite configuration value iterator. 02088 */ 02089 02090 02091 /** Constructor. 02092 * @param stmt compiled SQLite statement 02093 * @param p pointer to arbitrary data that is freed (not deleted!) when the iterator 02094 * is deleted. 02095 */ 02096 SQLiteConfiguration::SQLiteValueIterator::SQLiteValueIterator(::sqlite3_stmt *stmt, void *p) 02097 { 02098 __stmt = stmt; 02099 __p = p; 02100 } 02101 02102 02103 /** Destructor. */ 02104 SQLiteConfiguration::SQLiteValueIterator::~SQLiteValueIterator() 02105 { 02106 if ( __stmt != NULL ) { 02107 sqlite3_finalize(__stmt); 02108 __stmt = NULL; 02109 } 02110 if ( __p != NULL ) { 02111 free(__p); 02112 } 02113 } 02114 02115 02116 /* Check if there is another element and advance to this if possible. 02117 * This advances to the next element, if there is one. 02118 * @return true, if another element has been reached, false otherwise 02119 */ 02120 bool 02121 SQLiteConfiguration::SQLiteValueIterator::next() 02122 { 02123 if ( __stmt == NULL) return false; 02124 02125 if (sqlite3_step(__stmt) == SQLITE_ROW ) { 02126 return true; 02127 } else { 02128 sqlite3_finalize(__stmt); 02129 __stmt = NULL; 02130 return false; 02131 } 02132 } 02133 02134 /** Check if the current element is valid. 02135 * This is much like the classic end element for iterators. If the iterator is 02136 * invalid there all subsequent calls to next() shall fail. 02137 * @return true, if the iterator is still valid, false otherwise 02138 */ 02139 bool 02140 SQLiteConfiguration::SQLiteValueIterator::valid() 02141 { 02142 return ( __stmt != NULL); 02143 } 02144 02145 02146 /** Path of value. 02147 * @return path of value 02148 */ 02149 const char * 02150 SQLiteConfiguration::SQLiteValueIterator::path() 02151 { 02152 return (const char *)sqlite3_column_text(__stmt, 0); 02153 } 02154 02155 02156 /** Type of value. 02157 * @return string representation of value type. 02158 */ 02159 const char * 02160 SQLiteConfiguration::SQLiteValueIterator::type() 02161 { 02162 return (const char *)sqlite3_column_text(__stmt, 1); 02163 } 02164 02165 02166 /** Check if current value is a float. 02167 * @return true, if value is a float, false otherwise 02168 */ 02169 bool 02170 SQLiteConfiguration::SQLiteValueIterator::is_float() 02171 { 02172 return (strcmp("float", (const char *)sqlite3_column_text(__stmt, 1)) == 0); 02173 } 02174 02175 02176 /** Check if current value is a unsigned int. 02177 * @return true, if value is a unsigned int, false otherwise 02178 */ 02179 bool 02180 SQLiteConfiguration::SQLiteValueIterator::is_uint() 02181 { 02182 return (strcmp("unsigned int", (const char *)sqlite3_column_text(__stmt, 1)) == 0); 02183 } 02184 02185 /** Check if current value is a int. 02186 * @return true, if value is a int, false otherwise 02187 */ 02188 bool 02189 SQLiteConfiguration::SQLiteValueIterator::is_int() 02190 { 02191 return (strcmp("int", (const char *)sqlite3_column_text(__stmt, 1)) == 0); 02192 } 02193 02194 02195 /** Check if current value is a bool. 02196 * @return true, if value is a bool, false otherwise 02197 */ 02198 bool 02199 SQLiteConfiguration::SQLiteValueIterator::is_bool() 02200 { 02201 return (strcmp("bool", (const char *)sqlite3_column_text(__stmt, 1)) == 0); 02202 } 02203 02204 02205 /** Check if current value is a string. 02206 * @return true, if value is a string, false otherwise 02207 */ 02208 bool 02209 SQLiteConfiguration::SQLiteValueIterator::is_string() 02210 { 02211 return (strcmp("string", (const char *)sqlite3_column_text(__stmt, 1)) == 0); 02212 } 02213 02214 bool 02215 SQLiteConfiguration::SQLiteValueIterator::is_default() 02216 { 02217 return (sqlite3_column_int(__stmt, 4) == 1); 02218 } 02219 02220 02221 /** Get float value. 02222 * @return value 02223 */ 02224 float 02225 SQLiteConfiguration::SQLiteValueIterator::get_float() 02226 { 02227 return (float)sqlite3_column_double(__stmt, 2); 02228 } 02229 02230 02231 /** Get unsigned int value. 02232 * @return value 02233 */ 02234 unsigned int 02235 SQLiteConfiguration::SQLiteValueIterator::get_uint() 02236 { 02237 int i = sqlite3_column_int(__stmt, 2); 02238 if( i < 0 ) { 02239 return 0; 02240 } else { 02241 return i; 02242 } 02243 } 02244 02245 02246 /** Get int value. 02247 * @return value 02248 */ 02249 int 02250 SQLiteConfiguration::SQLiteValueIterator::get_int() 02251 { 02252 return sqlite3_column_int(__stmt, 2); 02253 } 02254 02255 /** Get bool value. 02256 * @return value 02257 */ 02258 bool 02259 SQLiteConfiguration::SQLiteValueIterator::get_bool() 02260 { 02261 return (sqlite3_column_int(__stmt, 2) != 0); 02262 } 02263 02264 /** Get string value. 02265 * @return value 02266 */ 02267 std::string 02268 SQLiteConfiguration::SQLiteValueIterator::get_string() 02269 { 02270 return (const char *)sqlite3_column_text(__stmt, 2); 02271 } 02272 02273 02274 /** Get value as string. 02275 * @return value 02276 */ 02277 std::string 02278 SQLiteConfiguration::SQLiteValueIterator::get_as_string() 02279 { 02280 return (const char *)sqlite3_column_text(__stmt, 2); 02281 } 02282 02283 /** Get comment. 02284 * @return string comment value 02285 */ 02286 std::string 02287 SQLiteConfiguration::SQLiteValueIterator::get_comment() 02288 { 02289 const char *c = (const char *)sqlite3_column_text(__stmt, 3); 02290 return c ? c : ""; 02291 } 02292 02293 /** Get modification type. 02294 * This can only be called if the iterator has been retrieved via 02295 * SQLiteConfiguration::modified_iterator(). Otherwise the return value is 02296 * always and empty string. 02297 * @return string modification type 02298 */ 02299 std::string 02300 SQLiteConfiguration::SQLiteValueIterator::get_modtype() 02301 { 02302 const char *c = (const char *)sqlite3_column_text(__stmt, 4); 02303 return c ? c : ""; 02304 } 02305 02306 02307 02308 /** Get old value (as string). 02309 * This can only be called if the iterator has been retrieved via 02310 * SQLiteConfiguration::modified_iterator(). The value is always returned 02311 * as string, as it is meant for debugging purposes only. Otherwise the 02312 * return value is always and empty string. 02313 * @return string modification type 02314 */ 02315 std::string 02316 SQLiteConfiguration::SQLiteValueIterator::get_oldvalue() 02317 { 02318 const char *c = (const char *)sqlite3_column_text(__stmt, 5); 02319 return c ? c : ""; 02320 } 02321 02322 02323 } // end namespace fawkes