Fawkes API  Fawkes Development Version
sqlite.cpp
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