Fawkes API  Fawkes Development Version
sqlite.cpp
1 
2 /***************************************************************************
3  * sqlite.cpp - Fawkes configuration stored in a SQLite database
4  *
5  * Created: Wed Dec 06 17:23:00 2006
6  * Copyright 2006-2018 Tim Niemueller [www.niemueller.de]
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version. A runtime exception applies to
13  * this software (see LICENSE.GPL_WRE file mentioned below for details).
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
21  */
22 
23 #include <config/sqlite.h>
24 #include <core/exceptions/software.h>
25 #include <core/exceptions/system.h>
26 #include <core/threading/mutex.h>
27 
28 #include <sqlite3.h>
29 
30 #ifndef _GNU_SOURCE
31 # define _GNU_SOURCE
32 #endif
33 #include <cerrno>
34 #include <cstdio>
35 #include <cstdlib>
36 #include <cstring>
37 #include <fnmatch.h>
38 #include <unistd.h>
39 
40 namespace fawkes {
41 
42 /* SQLite statements */
43 
44 #define TABLE_HOST_CONFIG "config"
45 #define TABLE_DEFAULT_CONFIG "defaults.config"
46 
47 #define SQL_CREATE_TABLE_HOST_CONFIG \
48  "CREATE TABLE IF NOT EXISTS config (\n" \
49  " path TEXT NOT NULL,\n" \
50  " type TEXT NOT NULL,\n" \
51  " value NOT NULL,\n" \
52  " comment TEXT,\n" \
53  " PRIMARY KEY (path)\n" \
54  ")"
55 
56 #define SQL_CREATE_TABLE_DEFAULT_CONFIG \
57  "CREATE TABLE IF NOT EXISTS defaults.config (\n" \
58  " path TEXT NOT NULL,\n" \
59  " type TEXT NOT NULL,\n" \
60  " value NOT NULL,\n" \
61  " comment TEXT,\n" \
62  " PRIMARY KEY (path)\n" \
63  ")"
64 
65 #define SQL_CREATE_TABLE_MODIFIED_CONFIG \
66  "CREATE TABLE IF NOT EXISTS modified.config (\n" \
67  " path TEXT NOT NULL,\n" \
68  " type TEXT NOT NULL,\n" \
69  " value NOT NULL,\n" \
70  " comment TEXT,\n" \
71  " modtype TEXT NOT NULL,\n" \
72  " oldvalue NOT NULL,\n" \
73  " PRIMARY KEY (path)\n" \
74  ")"
75 
76 #define SQL_ATTACH_DEFAULTS "ATTACH DATABASE '%s' AS defaults"
77 
78 #define SQL_ATTACH_MODIFIED "ATTACH DATABASE ':memory:' AS modified"
79 
80 #define SQL_ATTACH_DUMPED "ATTACH DATABASE '%s' AS dumped"
81 
82 #define SQL_DETACH_DUMPED "DETACH DATABASE dumped"
83 
84 #define SQL_SELECT_VALUE_TYPE \
85  "SELECT type, value, 0 AS is_default FROM config WHERE path=? UNION " \
86  "SELECT type, value, 1 AS is_default FROM defaults.config AS dc " \
87  "WHERE path=? AND NOT EXISTS " \
88  "(SELECT path FROM config WHERE dc.path=path)"
89 
90 #define SQL_SELECT_COMPLETE \
91  "SELECT *, 0 AS is_default FROM config WHERE path LIKE ? UNION " \
92  "SELECT *, 1 AS is_default FROM defaults.config AS dc " \
93  "WHERE path LIKE ? AND NOT EXISTS " \
94  "(SELECT path FROM config WHERE dc.path = path) " \
95  "ORDER BY path"
96 
97 #define SQL_SELECT_TYPE \
98  "SELECT type, 0 AS is_default FROM config WHERE path=? UNION " \
99  "SELECT type, 1 AS is_default FROM defaults.config AS dc " \
100  "WHERE path=? AND NOT EXISTS " \
101  "(SELECT path FROM config WHERE dc.path = path)"
102 
103 #define SQL_SELECT_COMMENT "SELECT comment, 0 AS is_default FROM config WHERE path=?"
104 
105 #define SQL_SELECT_DEFAULT_COMMENT \
106  "SELECT comment, 1 AS is_default FROM defaults.config AS dc " \
107  "WHERE dc.path=?"
108 
109 #define SQL_UPDATE_VALUE "UPDATE config SET value=? WHERE path=?"
110 
111 #define SQL_UPDATE_DEFAULT_VALUE "UPDATE defaults.config SET value=? WHERE path=?"
112 
113 #define SQL_UPDATE_COMMENT "UPDATE config SET comment=? WHERE path=?"
114 
115 #define SQL_UPDATE_DEFAULT_COMMENT "UPDATE defaults.config SET comment=? WHERE path=?"
116 
117 #define SQL_INSERT_VALUE "INSERT INTO config (path, type, value) VALUES (?, ?, ?)"
118 
119 #define SQL_INSERT_DEFAULT_VALUE "INSERT INTO defaults.config (path, type, value) VALUES (?, ?, ?)"
120 
121 #define SQL_SELECT_ALL \
122  "SELECT *, 0 AS is_default FROM config UNION " \
123  "SELECT *, 1 AS is_default FROM defaults.config AS dc " \
124  "WHERE NOT EXISTS " \
125  "(SELECT path FROM config WHERE dc.path = path) " \
126  "ORDER BY path"
127 
128 #define SQL_SELECT_ALL_DEFAULT "SELECT *, 1 AS is_default FROM defaults.config"
129 
130 #define SQL_SELECT_ALL_HOSTSPECIFIC "SELECT *, 0 AS is_default FROM config"
131 
132 #define SQL_DELETE_VALUE "DELETE FROM config WHERE path=?"
133 
134 #define SQL_DELETE_DEFAULT_VALUE "DELETE FROM defaults.config WHERE path=?"
135 
136 #define SQL_UPDATE_DEFAULT_DB \
137  "INSERT INTO config SELECT * FROM defaults.config AS dc " \
138  "WHERE NOT EXISTS (SELECT path from config WHERE path = dc.path)"
139 
140 #define SQL_UPDATE_MODIFIED_DB_ADDED \
141  "INSERT INTO modified.config " \
142  " SELECT duc.*,'added' AS modtype, duc.value " \
143  " FROM dumped.config AS duc " \
144  " WHERE NOT EXISTS (SELECT dc.path FROM defaults.config AS dc " \
145  " WHERE dc.path=duc.path) " \
146  " ORDER BY path"
147 
148 #define SQL_UPDATE_MODIFIED_DB_ERASED \
149  "INSERT INTO modified.config " \
150  " SELECT dc.*,'erased' AS modtype, dc.value " \
151  " FROM defaults.config AS dc " \
152  " WHERE NOT EXISTS (SELECT duc.path FROM dumped.config AS duc " \
153  " WHERE duc.path=dc.path) " \
154  " ORDER BY path"
155 
156 #define SQL_UPDATE_MODIFIED_DB_CHANGED \
157  "INSERT INTO modified.config " \
158  " SELECT duc.*,'changed' AS modtype, dc.value " \
159  " FROM dumped.config AS duc, defaults.config AS dc " \
160  " WHERE duc.path = dc.path " \
161  " AND (dc.type != duc.type OR dc.value != duc.value) " \
162  " ORDER BY duc.path"
163 
164 #define SQL_COPY_DUMP \
165  "DELETE FROM defaults.config; " \
166  "INSERT INTO defaults.config SELECT * FROM dumped.config"
167 
168 #define SQL_SELECT_MODIFIED_ALL "SELECT * FROM modified.config"
169 
170 #define MEMORY_DUMP_DB_NAME "file:tmp_dump_db?mode=memory&cache=shared"
171 
172 /** @class SQLiteConfiguration <config/sqlite.h>
173  * Configuration storage using SQLite.
174  * This implementation of the Configuration interface uses SQLite to store the
175  * configuration.
176  *
177  * The configuration uses two databases, one is used to store the host-specific
178  * configuration and the other one is used to store the default values. Only the
179  * default database is meant to reside under version control.
180  *
181  * See init() for the structure of the databases. This class strictly serializes
182  * all accesses to the database such that only one thread at a time can modify the
183  * database.
184  */
185 
186 /** Constructor. */
188 {
189  opened = false;
190  mutex = new Mutex();
191 
192  sysconfdir_ = NULL;
193  userconfdir_ = NULL;
194  default_file_ = NULL;
195  default_sql_ = NULL;
196 }
197 
198 /** Constructor.
199  * @param sysconfdir system configuration directory, will be searched for
200  * default configuration file, and system will try to create host-specific
201  * database if writable
202  * @param userconfdir user configuration directory, will be searched preferably
203  * for default configuration file, and will be used to create host-specific
204  * database if sysconfdir is not writable. This directory will be created
205  * if it does not exist during load().
206  */
207 SQLiteConfiguration::SQLiteConfiguration(const char *sysconfdir, const char *userconfdir)
208 {
209  opened = false;
210  mutex = new Mutex();
211 
212  sysconfdir_ = strdup(sysconfdir);
213  default_file_ = NULL;
214  default_sql_ = NULL;
215 
216  if (userconfdir != NULL) {
217  userconfdir_ = strdup(userconfdir);
218  } else {
219  const char *homedir = getenv("HOME");
220  if (homedir == NULL) {
221  userconfdir_ = strdup(sysconfdir);
222  } else {
223  if (asprintf(&userconfdir_, "%s/%s", homedir, USERDIR) == -1) {
224  userconfdir_ = strdup(sysconfdir);
225  }
226  }
227  }
228 }
229 
230 /** Destructor. */
232 {
233  if (opened) {
234  opened = false;
235  if (sqlite3_close(db) == SQLITE_BUSY) {
236  printf("Boom, we are dead, database cannot be closed "
237  "because there are open handles\n");
238  }
239  }
240 
241  if (host_file_)
242  free(host_file_);
243  if (default_file_)
244  free(default_file_);
245  if (default_sql_)
246  free(default_sql_);
247  if (sysconfdir_)
248  free(sysconfdir_);
249  if (userconfdir_)
250  free(userconfdir_);
251  delete mutex;
252 }
253 
254 /** Initialize the configuration database(s).
255  * Initialize databases. If the host-specific database already exists
256  * an exception is thrown. You have to delete it before calling
257  * init(). First the host-specific database is created. It will
258  * contain one table, named 'config'. The 'config' table will hold the
259  * current configuration for this machine.
260  *
261  * The 'config' table is created with the following schema:
262  * @code
263  * CREATE TABLE IF NOT EXISTS config (
264  * path TEXT NOT NULL,
265  * type TEXT NOT NULL,
266  * value NOT NULL,
267  * comment TEXT,
268  * PRIMARY KEY (path)
269  * )
270  * @endcode
271  * If a default database is found the values from this database are copied
272  * to the config table.
273  * The defaults config database is created with the following structure:
274  * @code
275  * CREATE TABLE IF NOT EXISTS defaults.config (
276  * path TEXT NOT NULL,
277  * type TEXT NOT NULL,
278  * value NOT NULL,
279  * comment TEXT,
280  * PRIMARY KEY (path)
281  * )
282  * @endcode
283  *
284  * If no default database exists it is created. The database is kept in a file
285  * called default.db. It contains a single table called 'config' with the same
286  * structure as the 'config' table in the host-specific database.
287  */
288 void
289 SQLiteConfiguration::init_dbs()
290 {
291  char *errmsg;
292  if ((sqlite3_exec(db, SQL_CREATE_TABLE_HOST_CONFIG, NULL, NULL, &errmsg) != SQLITE_OK)
293  || (sqlite3_exec(db, SQL_CREATE_TABLE_DEFAULT_CONFIG, NULL, NULL, &errmsg) != SQLITE_OK)) {
294  CouldNotOpenConfigException ce(sqlite3_errmsg(db));
295  sqlite3_close(db);
296  throw ce;
297  }
298 }
299 
300 /** Dump table.
301  * Dumps a table to the given file.
302  * @param f file to write to
303  * @param tdb SQLite3 database to read from
304  * @param table_name Name of the table to dump
305  */
306 static void
307 dump_table(FILE *f, ::sqlite3 *tdb, const char *table_name)
308 {
309  std::string tisql = "PRAGMA table_info(\"";
310  tisql += table_name;
311  tisql += "\");";
312 
313  sqlite3_stmt *stmt;
314  if (sqlite3_prepare(tdb, tisql.c_str(), -1, &stmt, 0) != SQLITE_OK) {
315  throw ConfigurationException("dump_table/prepare", sqlite3_errmsg(tdb));
316  }
317  std::string value_query = "SELECT 'INSERT INTO ' || '\"";
318  value_query += table_name;
319  value_query += "\"' || ' VALUES(' || ";
320  int rv = sqlite3_step(stmt);
321  while (rv == SQLITE_ROW) {
322  value_query += "quote(\"";
323  value_query += (const char *)sqlite3_column_text(stmt, 1);
324  value_query += "\") || ";
325  rv = sqlite3_step(stmt);
326  if (rv == SQLITE_ROW) {
327  value_query += " ',' || ";
328  }
329  }
330  value_query += "')' FROM ";
331  value_query += table_name;
332  sqlite3_finalize(stmt);
333 
334  sqlite3_stmt *vstmt;
335  if (sqlite3_prepare(tdb, value_query.c_str(), -1, &vstmt, 0) != SQLITE_OK) {
336  throw ConfigurationException("dump_table/prepare 2", sqlite3_errmsg(tdb));
337  }
338  while (sqlite3_step(vstmt) == SQLITE_ROW) {
339  fprintf(f, "%s;\n", sqlite3_column_text(vstmt, 0));
340  }
341  sqlite3_finalize(vstmt);
342 }
343 
344 void
345 SQLiteConfiguration::dump(::sqlite3 *tdb, const char *dumpfile)
346 {
347  FILE *f = fopen(dumpfile, "w");
348  if (!f) {
349  throw CouldNotOpenFileException(dumpfile, errno, "Could not open dump file");
350  }
351 
352  fprintf(f, "BEGIN TRANSACTION;\n");
353 
354  const char *sql = "SELECT name, sql FROM sqlite_master "
355  "WHERE sql NOT NULL AND type=='table'";
356  sqlite3_stmt *stmt;
357  if ((sqlite3_prepare(tdb, sql, -1, &stmt, 0) != SQLITE_OK) || !stmt) {
358  throw ConfigurationException("dump_query/prepare", sqlite3_errmsg(tdb));
359  }
360  while (sqlite3_step(stmt) == SQLITE_ROW) {
361  fprintf(f, "%s;\n", sqlite3_column_text(stmt, 1));
362  dump_table(f, tdb, (const char *)sqlite3_column_text(stmt, 0));
363  }
364  sqlite3_finalize(stmt);
365 
366  fprintf(f, "COMMIT;\n");
367  fclose(f);
368 }
369 
370 /** Try to dump default configuration.
371  * This method will try to open the SQL dump file for writing and dump
372  * the current content of the default database into the file.
373  * @exception Exception thrown if dumping fails
374  */
375 void
377 {
378  if (default_sql_) {
379  sqlite3 *tdb;
380  if (sqlite3_open(default_file_, &tdb) == SQLITE_OK) {
381  try {
382  dump(tdb, default_sql_);
383  sqlite3_close(tdb);
384  } catch (Exception &e) {
385  sqlite3_close(tdb);
386  throw;
387  }
388  }
389  }
390 }
391 
392 /** SQL escaping stub.
393  * This could be extended to perform actual escaping on the provided
394  * SQL line.
395  * @param line line to check
396  * @return string conversion of line
397  */
398 static std::string
399 sql_escape_noop(const char *line)
400 {
401  return std::string(line);
402 }
403 
404 void
405 SQLiteConfiguration::import(::sqlite3 *tdb, const char *dumpfile)
406 {
407  FILE *f = fopen(dumpfile, "r");
408 
409  if (!f) {
410  throw CouldNotOpenConfigException("Import failed, could not open dump file");
411  }
412 
413  char line[4096];
414  char *errmsg;
415  while (!feof(f)) {
416  line[0] = 0;
417  unsigned int i = 0;
418  while (!feof(f) && (i < sizeof(line) - 1)) {
419  if (fread(&(line[i]), 1, 1, f) == 1) {
420  ++i;
421  if ((i > 2) && (line[i - 1] == '\n') && (line[i - 2] == ';')) {
422  break;
423  }
424  } else {
425  break;
426  }
427  }
428  line[i] = 0;
429  if (line[0] != 0) {
430  std::string stmt{sql_escape_noop(line)};
431 
432  if (sqlite3_exec(tdb, stmt.c_str(), 0, 0, &errmsg) != SQLITE_OK) {
433  ConfigurationException e(errmsg, line);
434  sqlite3_free(errmsg);
435  fclose(f);
436  throw e;
437  }
438  }
439  }
440 
441  fclose(f);
442 }
443 
444 void
445 SQLiteConfiguration::import_default(const char *default_sql)
446 {
447  // Import .sql file into dump database (temporary file)
448  sqlite3 *dump_db;
449  if (sqlite3_open(MEMORY_DUMP_DB_NAME, &dump_db) == SQLITE_OK) {
450  import(dump_db, default_sql);
451  sqlite3_close(dump_db);
452  } else {
453  throw CouldNotOpenConfigException("Failed to import dump file into temp DB");
454  }
455 
456  // Attach dump database as "dumped"
457  char *attach_sql;
458  char *errmsg;
459  if (asprintf(&attach_sql, SQL_ATTACH_DUMPED, MEMORY_DUMP_DB_NAME) == -1) {
460  throw CouldNotOpenConfigException("Could not create attachment SQL in merge");
461  }
462  if (sqlite3_exec(db, attach_sql, NULL, NULL, &errmsg) != SQLITE_OK) {
463  free(attach_sql);
464  CouldNotOpenConfigException e("Could not attach dump DB in merge: %s", errmsg);
465  sqlite3_free(errmsg);
466  throw e;
467  }
468  free(attach_sql);
469 
470  // Create "modified" database for a list of modified values, only stored in RAM
471  if ((sqlite3_exec(db, SQL_ATTACH_MODIFIED, NULL, NULL, &errmsg) != SQLITE_OK)
472  || (sqlite3_exec(db, SQL_CREATE_TABLE_MODIFIED_CONFIG, NULL, NULL, &errmsg) != SQLITE_OK)) {
473  CouldNotOpenConfigException ce("Could not create or attach modified memory database: %s",
474  errmsg);
475  sqlite3_free(errmsg);
476  throw ce;
477  }
478 
479  // Compare old and new database, copying modifications to "modified" database
480  if ((sqlite3_exec(db, SQL_UPDATE_MODIFIED_DB_ADDED, NULL, NULL, &errmsg) != SQLITE_OK)
481  || (sqlite3_exec(db, SQL_UPDATE_MODIFIED_DB_ERASED, NULL, NULL, &errmsg) != SQLITE_OK)
482  || (sqlite3_exec(db, SQL_UPDATE_MODIFIED_DB_CHANGED, NULL, NULL, &errmsg) != SQLITE_OK)) {
483  CouldNotOpenConfigException ce("Could not update modified memory database: %s", errmsg);
484  sqlite3_free(errmsg);
485  throw ce;
486  }
487 
488  // Copy dump to defaults DB, overwriting everything
489  if ((sqlite3_exec(db, SQL_COPY_DUMP, NULL, NULL, &errmsg) != SQLITE_OK)) {
490  CouldNotOpenConfigException ce("Could not copy dump to default: %s", errmsg);
491  sqlite3_free(errmsg);
492  throw ce;
493  }
494 
495  // Detach dumped DB, no longer required
496  if (sqlite3_exec(db, SQL_DETACH_DUMPED, NULL, NULL, &errmsg) != SQLITE_OK) {
497  CouldNotOpenConfigException e("Could not detach dump DB in import: %s", errmsg);
498  sqlite3_free(errmsg);
499  throw e;
500  }
501 }
502 
503 /** Begin SQL Transaction.
504  * @param ttype transaction type
505  */
506 void
508 {
509  const char *sql = "BEGIN DEFERRED TRANSACTION;";
510  if (ttype == TRANSACTION_IMMEDIATE) {
511  sql = "BEGIN IMMEDIATE TRANSACTION;";
512  } else if (ttype == TRANSACTION_EXCLUSIVE) {
513  sql = "BEGIN EXCLUSIVE TRANSACTION;";
514  }
515 
516  char *errmsg;
517  if ((sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)) {
518  throw ConfigurationException("Could not begin transaction (%s)", errmsg);
519  }
520 }
521 
522 /** Commit SQL Transaction. */
523 void
525 {
526  const char *sql = "COMMIT TRANSACTION;";
527 
528  char *errmsg;
529  if ((sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)) {
530  throw ConfigurationException("Could not commit transaction (%s)", errmsg);
531  }
532 }
533 
534 /** Rollback SQL Transaction. */
535 void
537 {
538  const char *sql = "ROLLBACK TRANSACTION;";
539 
540  char *errmsg;
541  if ((sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)) {
542  throw ConfigurationException("Could not rollback transaction (%s)", errmsg);
543  }
544 }
545 
546 void
547 SQLiteConfiguration::attach_default(const char *db_file)
548 {
549  char *errmsg;
550  char *attach_sql;
551  if (asprintf(&attach_sql, SQL_ATTACH_DEFAULTS, db_file) == -1) {
552  throw CouldNotOpenConfigException("Could not create attachment SQL");
553  }
554  if (sqlite3_exec(db, attach_sql, NULL, NULL, &errmsg) != SQLITE_OK) {
555  CouldNotOpenConfigException ce(sqlite3_errmsg(db));
556  ce.append("Failed to attach default file (%s)", db_file);
557  free(attach_sql);
558  throw ce;
559  }
560  free(attach_sql);
561 }
562 
563 void
564 SQLiteConfiguration::load(const char *file_path)
565 {
566  mutex->lock();
567 
568  if (default_file_)
569  free(default_file_);
570  if (default_sql_)
571  free(default_sql_);
572  default_file_ = NULL;
573  default_sql_ = NULL;
574 
575  const char *try_paths[] = {sysconfdir_, userconfdir_};
576  int try_paths_len = 2;
577 
578  char *host_name = NULL;
579 
580  if (strcmp(file_path, ":memory:") == 0) {
581  host_file_ = strdup(":memory:");
582 
583  if (sqlite3_open(file_path, &db) != SQLITE_OK) {
584  CouldNotOpenConfigException ce(sqlite3_errmsg(db));
585  ce.append("Failed to open memory database");
586  throw ce;
587  }
588  } else {
589  HostInfo hostinfo;
590  if (asprintf(&host_name, "%s.db", hostinfo.short_name()) == -1) {
591  host_name = strdup(hostinfo.short_name());
592  }
593 
594  // determine host file
595  // try sysconfdir and userconfdir
596  for (int i = 0; i < try_paths_len; ++i) {
597  char *path;
598  if (asprintf(&path, "%s/%s", try_paths[i], host_name) != -1) {
599  if (sqlite3_open(path, &db) == SQLITE_OK) {
600  host_file_ = path;
601  break;
602  } else {
603  free(path);
604  }
605  }
606  }
607  }
608 
609  if (host_file_ == NULL) {
610  CouldNotOpenConfigException ce(sqlite3_errmsg(db));
611  ce.append("Failed to open host db (paths)");
612  if (host_name)
613  free(host_name);
614  throw ce;
615  }
616 
617  if (file_path == NULL) {
618  file_path = "default.sql";
619  }
620 
621  // determine default file
622  if (strcmp(file_path, ":memory:") == 0) {
623  try {
624  attach_default(":memory:");
625  } catch (...) {
626  if (host_name)
627  free(host_name);
628  throw;
629  }
630  default_file_ = strdup(":memory:");
631  } else {
632  if (file_path[0] == '/') {
633  // absolute path, take as is
634  default_sql_ = strdup(file_path);
635  } else {
636  // try sysconfdir and userconfdir
637  for (int i = 0; i < try_paths_len; ++i) {
638  char *path;
639  if (asprintf(&path, "%s/%s", try_paths[i], file_path) != -1) {
640  if (access(path, F_OK | R_OK) == 0) {
641  default_sql_ = path;
642  break;
643  } else {
644  free(path);
645  }
646  }
647  }
648  }
649 
650  // Now go for the .db filename
651 
652  // generate filename
653  char * defaults_db;
654  size_t len = strlen(file_path);
655  if (fnmatch("*.sql", file_path, FNM_PATHNAME) == 0) {
656  defaults_db = (char *)calloc(1, len); // yes, that's one byte less!
657  strncpy(defaults_db, file_path, len - 3);
658  strcat(defaults_db, "db");
659  } else {
660  defaults_db = (char *)calloc(1, len + 4);
661  strcpy(defaults_db, file_path);
662  strcat(defaults_db, ".db");
663  }
664 
665  if (defaults_db[0] == '/') {
666  try {
667  attach_default(defaults_db);
668  default_file_ = defaults_db;
669  } catch (...) {
670  if (host_name)
671  free(host_name);
672  free(defaults_db);
673  throw;
674  }
675  } else {
676  // check directories
677  for (int i = 0; i < try_paths_len; ++i) {
678  char *path;
679  if (asprintf(&path, "%s/%s", try_paths[i], defaults_db) != -1) {
680  try {
681  attach_default(path);
682  default_file_ = path;
683  break;
684  } catch (CouldNotOpenConfigException &e) {
685  free(path);
686  }
687  }
688  }
689  }
690  free(defaults_db);
691 
692  if (default_file_ == NULL) {
693  if (host_name)
694  free(host_name);
695  throw CouldNotOpenConfigException("Could not create default filename");
696  }
697  }
698 
699  init_dbs();
700 
701  if (default_sql_)
702  import_default(default_sql_);
703  if (host_name)
704  free(host_name);
705 
706  opened = true;
707 
708  mutex->unlock();
709 }
710 
711 /** Copy all values from the given configuration.
712  * All values from the given configuration are copied. Old values are not erased
713  * so that the copied values will overwrite existing values, new values are
714  * created, but values existent in current config but not in the copie config
715  * will remain unchanged.
716  * @param copyconf configuration to copy
717  */
718 void
720 {
721  copyconf->lock();
723  Configuration::ValueIterator *i = copyconf->iterator();
724  while (i->next()) {
725  if (i->is_float()) {
726  set_float(i->path(), i->get_float());
727  } else if (i->is_int()) {
728  set_int(i->path(), i->get_int());
729  } else if (i->is_uint()) {
730  set_uint(i->path(), i->get_uint());
731  } else if (i->is_bool()) {
732  set_bool(i->path(), i->get_bool());
733  } else if (i->is_string()) {
734  std::string s = i->get_string();
735  set_string(i->path(), s);
736  }
737  }
738  delete i;
740  copyconf->unlock();
741 }
742 
743 bool
745 {
746  mutex->lock();
747  sqlite3_stmt *stmt;
748  const char * tail;
749  bool e;
750 
751  if (sqlite3_prepare(db, SQL_SELECT_TYPE, -1, &stmt, &tail) != SQLITE_OK) {
752  mutex->unlock();
753  throw ConfigurationException("exists/prepare", sqlite3_errmsg(db));
754  }
755  if (sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK) {
756  mutex->unlock();
757  throw ConfigurationException("exists/bind/path", sqlite3_errmsg(db));
758  }
759  if (sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK) {
760  mutex->unlock();
761  throw ConfigurationException("exists/bind/path", sqlite3_errmsg(db));
762  }
763  e = (sqlite3_step(stmt) == SQLITE_ROW);
764  sqlite3_finalize(stmt);
765 
766  mutex->unlock();
767  return e;
768 }
769 
770 std::string
772 {
773  sqlite3_stmt *stmt;
774  const char * tail;
775  std::string s = "";
776 
777  mutex->lock();
778 
779  if (sqlite3_prepare(db, SQL_SELECT_TYPE, -1, &stmt, &tail) != SQLITE_OK) {
780  mutex->unlock();
781  throw ConfigurationException("get_type: Preparation SQL failed");
782  }
783  if (sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK) {
784  mutex->unlock();
785  throw ConfigurationException("get_type: Binding text for path failed (1)");
786  }
787  if (sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK) {
788  mutex->unlock();
789  throw ConfigurationException("get_type: Binding text for path failed (2)");
790  }
791  if (sqlite3_step(stmt) == SQLITE_ROW) {
792  s = (char *)sqlite3_column_text(stmt, 0);
793  sqlite3_finalize(stmt);
794  mutex->unlock();
795  return s;
796  } else {
797  sqlite3_finalize(stmt);
798  mutex->unlock();
799  throw ConfigEntryNotFoundException(path);
800  }
801 }
802 
803 std::string
805 {
806  sqlite3_stmt *stmt;
807  const char * tail;
808  std::string s = "";
809 
810  mutex->lock();
811 
812  if (sqlite3_prepare(db, SQL_SELECT_COMMENT, -1, &stmt, &tail) != SQLITE_OK) {
813  mutex->unlock();
814  throw ConfigurationException("get_comment: Preparation SQL failed");
815  }
816  if (sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK) {
817  mutex->unlock();
818  throw ConfigurationException("get_comment: Binding text for path failed (1)");
819  }
820  if (sqlite3_step(stmt) == SQLITE_ROW) {
821  s = (char *)sqlite3_column_text(stmt, 0);
822  sqlite3_finalize(stmt);
823  mutex->unlock();
824  return s;
825  } else {
826  sqlite3_finalize(stmt);
827  mutex->unlock();
828  throw ConfigEntryNotFoundException(path);
829  }
830 }
831 
832 std::string
834 {
835  sqlite3_stmt *stmt;
836  const char * tail;
837  std::string s = "";
838 
839  mutex->lock();
840 
841  if (sqlite3_prepare(db, SQL_SELECT_DEFAULT_COMMENT, -1, &stmt, &tail) != SQLITE_OK) {
842  mutex->unlock();
843  throw ConfigurationException("get_default_comment: Preparation SQL failed");
844  }
845  if (sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK) {
846  mutex->unlock();
847  throw ConfigurationException("get_default_comment: Binding text for path failed (1)");
848  }
849  if (sqlite3_step(stmt) == SQLITE_ROW) {
850  s = (char *)sqlite3_column_text(stmt, 0);
851  sqlite3_finalize(stmt);
852  mutex->unlock();
853  return s;
854  } else {
855  sqlite3_finalize(stmt);
856  mutex->unlock();
857  throw ConfigEntryNotFoundException(path);
858  }
859 }
860 
861 bool
863 {
864  return (get_type(path) == "float");
865 }
866 
867 bool
869 {
870  return (get_type(path) == "unsigned int");
871 }
872 
873 bool
875 {
876  return (get_type(path) == "int");
877 }
878 
879 bool
881 {
882  return (get_type(path) == "bool");
883 }
884 
885 bool
887 {
888  return (get_type(path) == "string");
889 }
890 
891 bool
893 {
894  return false;
895 }
896 
897 bool
899 {
900  mutex->lock();
901  sqlite3_stmt *stmt;
902  const char * tail;
903  bool e;
904 
905  if (sqlite3_prepare(db, SQL_SELECT_TYPE, -1, &stmt, &tail) != SQLITE_OK) {
906  mutex->unlock();
907  throw ConfigurationException("is_default/prepare", sqlite3_errmsg(db));
908  }
909  if (sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK) {
910  mutex->unlock();
911  throw ConfigurationException("is_default/bind/path", sqlite3_errmsg(db));
912  }
913  if (sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK) {
914  mutex->unlock();
915  throw ConfigurationException("is_default/bind/path", sqlite3_errmsg(db));
916  }
917  e = ((sqlite3_step(stmt) == SQLITE_ROW) && (sqlite3_column_int(stmt, 1) == 1));
918  sqlite3_finalize(stmt);
919 
920  mutex->unlock();
921  return e;
922 }
923 
924 /** Get a value from the database.
925  * @param path path
926  * @param type desired value, NULL to omit type check
927  */
928 sqlite3_stmt *
929 SQLiteConfiguration::get_typed_value(const char *path, const char *type)
930 {
931  sqlite3_stmt *stmt;
932  const char * tail;
933 
934  if (sqlite3_prepare(db, SQL_SELECT_VALUE_TYPE, -1, &stmt, &tail) != SQLITE_OK) {
935  throw ConfigurationException("get_typed_value/prepare", sqlite3_errmsg(db));
936  }
937  if (sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK) {
938  throw ConfigurationException("get_typed_value/bind/path (1)", sqlite3_errmsg(db));
939  }
940  if (sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK) {
941  throw ConfigurationException("get_typed_value/bind/path (2)", sqlite3_errmsg(db));
942  }
943 
944  if (sqlite3_step(stmt) == SQLITE_ROW) {
945  if (type == NULL) {
946  // type check omitted
947  return stmt;
948  } else {
949  if (strcmp((char *)sqlite3_column_text(stmt, 0), type) != 0) {
950  ConfigTypeMismatchException ce(path, (char *)sqlite3_column_text(stmt, 0), type);
951  sqlite3_finalize(stmt);
952  throw ce;
953  } else {
954  return stmt;
955  }
956  }
957  } else {
958  sqlite3_finalize(stmt);
959  throw ConfigEntryNotFoundException(path);
960  }
961 }
962 
963 float
965 {
966  sqlite3_stmt *stmt;
967  mutex->lock();
968  try {
969  stmt = get_typed_value(path, "float");
970  float f = (float)sqlite3_column_double(stmt, 1);
971  sqlite3_finalize(stmt);
972  mutex->unlock();
973  return f;
974  } catch (Exception &e) {
975  // we can't handle
976  mutex->unlock();
977  throw;
978  }
979 }
980 
981 unsigned int
983 {
984  sqlite3_stmt *stmt;
985  mutex->lock();
986  try {
987  stmt = get_typed_value(path, "unsigned int");
988  int i = sqlite3_column_int(stmt, 1);
989  sqlite3_finalize(stmt);
990  if (i < 0) {
991  mutex->unlock();
992  throw ConfigTypeMismatchException(path, "int", "unsigned int");
993  }
994  mutex->unlock();
995  return i;
996  } catch (Exception &e) {
997  // we can't handle
998  mutex->unlock();
999  throw;
1000  }
1001 }
1002 
1003 int
1005 {
1006  sqlite3_stmt *stmt;
1007  mutex->lock();
1008  try {
1009  stmt = get_typed_value(path, "int");
1010  int i = sqlite3_column_int(stmt, 1);
1011  sqlite3_finalize(stmt);
1012  mutex->unlock();
1013  return i;
1014  } catch (Exception &e) {
1015  // we can't handle
1016  mutex->unlock();
1017  throw;
1018  }
1019 }
1020 
1021 bool
1023 {
1024  sqlite3_stmt *stmt;
1025  mutex->lock();
1026  try {
1027  stmt = get_typed_value(path, "bool");
1028  int i = sqlite3_column_int(stmt, 1);
1029  sqlite3_finalize(stmt);
1030  mutex->unlock();
1031  return (i != 0);
1032  } catch (Exception &e) {
1033  // we can't handle
1034  mutex->unlock();
1035  throw;
1036  }
1037 }
1038 
1039 std::string
1041 {
1042  sqlite3_stmt *stmt;
1043  mutex->lock();
1044  try {
1045  stmt = get_typed_value(path, "string");
1046  const char *c = (char *)sqlite3_column_text(stmt, 1);
1047  std::string rv = c;
1048  sqlite3_finalize(stmt);
1049  mutex->unlock();
1050  return rv;
1051  } catch (Exception &e) {
1052  // we can't handle
1053  e.append("SQLiteConfiguration::get_string: Fetching %s failed.", path);
1054  mutex->unlock();
1055  throw;
1056  }
1057 }
1058 
1059 std::vector<float>
1061 {
1062  throw NotImplementedException("SQLiteConf: list values are not supported");
1063 }
1064 
1065 std::vector<unsigned int>
1067 {
1068  throw NotImplementedException("SQLiteConf: list values are not supported");
1069 }
1070 
1071 std::vector<int>
1073 {
1074  throw NotImplementedException("SQLiteConf: list values are not supported");
1075 }
1076 
1077 std::vector<bool>
1079 {
1080  throw NotImplementedException("SQLiteConf: list values are not supported");
1081 }
1082 
1083 std::vector<std::string>
1085 {
1086  throw NotImplementedException("SQLiteConf: list values are not supported");
1087 }
1088 
1091 {
1092  sqlite3_stmt *stmt;
1093  const char * tail;
1094 
1095  if (sqlite3_prepare(db, SQL_SELECT_COMPLETE, -1, &stmt, &tail) != SQLITE_OK) {
1096  throw ConfigurationException("get_value/prepare", sqlite3_errmsg(db));
1097  }
1098  if (sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK) {
1099  throw ConfigurationException("get_value/bind/path (1)", sqlite3_errmsg(db));
1100  }
1101  if (sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK) {
1102  throw ConfigurationException("get_value/bind/path (2)", sqlite3_errmsg(db));
1103  }
1104 
1105  return new SQLiteValueIterator(stmt);
1106 }
1107 
1108 sqlite3_stmt *
1109 SQLiteConfiguration::prepare_update(const char *sql, const char *path)
1110 {
1111  sqlite3_stmt *stmt;
1112  const char * tail;
1113 
1114  if (sqlite3_prepare(db, sql, -1, &stmt, &tail) != SQLITE_OK) {
1115  throw ConfigurationException("prepare_update/prepare", sqlite3_errmsg(db));
1116  }
1117  if (sqlite3_bind_text(stmt, 2, path, -1, NULL) != SQLITE_OK) {
1118  ConfigurationException ce("prepare_update/bind", sqlite3_errmsg(db));
1119  sqlite3_finalize(stmt);
1120  throw ce;
1121  }
1122 
1123  return stmt;
1124 }
1125 
1126 sqlite3_stmt *
1127 SQLiteConfiguration::prepare_insert_value(const char *sql, const char *type, const char *path)
1128 {
1129  sqlite3_stmt *stmt;
1130  const char * tail;
1131 
1132  if (sqlite3_prepare(db, sql, -1, &stmt, &tail) != SQLITE_OK) {
1133  throw ConfigurationException("prepare_insert_value/prepare", sqlite3_errmsg(db));
1134  }
1135  if ((sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK)
1136  || (sqlite3_bind_text(stmt, 2, type, -1, NULL) != SQLITE_OK)) {
1137  ConfigurationException ce("prepare_insert_value/bind", sqlite3_errmsg(db));
1138  sqlite3_finalize(stmt);
1139  throw ce;
1140  }
1141 
1142  return stmt;
1143 }
1144 
1145 void
1146 SQLiteConfiguration::execute_insert_or_update(sqlite3_stmt *stmt)
1147 {
1148  if (sqlite3_step(stmt) != SQLITE_DONE) {
1149  ConfigurationException ce("execute_insert_or_update", sqlite3_errmsg(db));
1150  sqlite3_finalize(stmt);
1151  throw ce;
1152  }
1153 }
1154 
1155 void
1156 SQLiteConfiguration::set_float(const char *path, float f)
1157 {
1158  sqlite3_stmt *stmt = NULL;
1159 
1160  mutex->lock();
1161 
1162  try {
1163  stmt = prepare_update(SQL_UPDATE_VALUE, path);
1164  if ((sqlite3_bind_double(stmt, 1, f) != SQLITE_OK)) {
1165  ConfigurationException ce("set_float/update/bind", sqlite3_errmsg(db));
1166  sqlite3_finalize(stmt);
1167  mutex->unlock();
1168  throw ce;
1169  }
1170  execute_insert_or_update(stmt);
1171  sqlite3_finalize(stmt);
1172  } catch (Exception &e) {
1173  if (stmt != NULL)
1174  sqlite3_finalize(stmt);
1175  mutex->unlock();
1176  throw;
1177  }
1178 
1179  if (sqlite3_changes(db) == 0) {
1180  // value did not exist, insert
1181 
1182  try {
1183  stmt = prepare_insert_value(SQL_INSERT_VALUE, "float", path);
1184  if ((sqlite3_bind_double(stmt, 3, f) != SQLITE_OK)) {
1185  ConfigurationException ce("set_float/insert/bind", sqlite3_errmsg(db));
1186  sqlite3_finalize(stmt);
1187  mutex->unlock();
1188  throw ce;
1189  }
1190  execute_insert_or_update(stmt);
1191  sqlite3_finalize(stmt);
1192  } catch (Exception &e) {
1193  if (stmt != NULL)
1194  sqlite3_finalize(stmt);
1195  mutex->unlock();
1196  throw;
1197  }
1198  }
1199 
1200  mutex->unlock();
1201 
1202  notify_handlers(path);
1203 }
1204 
1205 void
1206 SQLiteConfiguration::set_uint(const char *path, unsigned int uint)
1207 {
1208  sqlite3_stmt *stmt = NULL;
1209 
1210  mutex->lock();
1211 
1212  try {
1213  stmt = prepare_update(SQL_UPDATE_VALUE, path);
1214  if ((sqlite3_bind_int(stmt, 1, uint) != SQLITE_OK)) {
1215  ConfigurationException ce("set_uint/update/bind", sqlite3_errmsg(db));
1216  sqlite3_finalize(stmt);
1217  mutex->unlock();
1218  throw ce;
1219  }
1220  execute_insert_or_update(stmt);
1221  sqlite3_finalize(stmt);
1222  } catch (Exception &e) {
1223  if (stmt != NULL)
1224  sqlite3_finalize(stmt);
1225  mutex->unlock();
1226  throw;
1227  }
1228 
1229  if (sqlite3_changes(db) == 0) {
1230  // value did not exist, insert
1231 
1232  try {
1233  stmt = prepare_insert_value(SQL_INSERT_VALUE, "unsigned int", path);
1234  if ((sqlite3_bind_int(stmt, 3, uint) != SQLITE_OK)) {
1235  ConfigurationException ce("set_uint/insert/bind", sqlite3_errmsg(db));
1236  sqlite3_finalize(stmt);
1237  mutex->unlock();
1238  throw ce;
1239  }
1240  execute_insert_or_update(stmt);
1241  sqlite3_finalize(stmt);
1242  } catch (Exception &e) {
1243  if (stmt != NULL)
1244  sqlite3_finalize(stmt);
1245  mutex->unlock();
1246  throw;
1247  }
1248  }
1249  mutex->unlock();
1250 
1251  notify_handlers(path);
1252 }
1253 
1254 void
1255 SQLiteConfiguration::set_int(const char *path, int i)
1256 {
1257  sqlite3_stmt *stmt = NULL;
1258 
1259  mutex->lock();
1260 
1261  try {
1262  stmt = prepare_update(SQL_UPDATE_VALUE, path);
1263  if ((sqlite3_bind_int(stmt, 1, i) != SQLITE_OK)) {
1264  ConfigurationException ce("set_int/update/bind", sqlite3_errmsg(db));
1265  sqlite3_finalize(stmt);
1266  mutex->unlock();
1267  throw ce;
1268  }
1269  execute_insert_or_update(stmt);
1270  sqlite3_finalize(stmt);
1271  } catch (Exception &e) {
1272  if (stmt != NULL)
1273  sqlite3_finalize(stmt);
1274  mutex->unlock();
1275  throw;
1276  }
1277 
1278  if (sqlite3_changes(db) == 0) {
1279  // value did not exist, insert
1280 
1281  try {
1282  stmt = prepare_insert_value(SQL_INSERT_VALUE, "int", path);
1283  if ((sqlite3_bind_int(stmt, 3, i) != SQLITE_OK)) {
1284  ConfigurationException ce("set_int/insert/bind", sqlite3_errmsg(db));
1285  sqlite3_finalize(stmt);
1286  mutex->unlock();
1287  throw ce;
1288  }
1289  execute_insert_or_update(stmt);
1290  sqlite3_finalize(stmt);
1291  } catch (Exception &e) {
1292  if (stmt != NULL)
1293  sqlite3_finalize(stmt);
1294  mutex->unlock();
1295  throw;
1296  }
1297  }
1298 
1299  mutex->unlock();
1300 
1301  notify_handlers(path);
1302 }
1303 
1304 void
1305 SQLiteConfiguration::set_bool(const char *path, bool b)
1306 {
1307  sqlite3_stmt *stmt = NULL;
1308 
1309  mutex->lock();
1310 
1311  try {
1312  stmt = prepare_update(SQL_UPDATE_VALUE, path);
1313  if ((sqlite3_bind_int(stmt, 1, (b ? 1 : 0)) != SQLITE_OK)) {
1314  ConfigurationException ce("set_bool/update/bind", sqlite3_errmsg(db));
1315  sqlite3_finalize(stmt);
1316  mutex->unlock();
1317  throw ce;
1318  }
1319  execute_insert_or_update(stmt);
1320  sqlite3_finalize(stmt);
1321  } catch (Exception &e) {
1322  if (stmt != NULL)
1323  sqlite3_finalize(stmt);
1324  mutex->unlock();
1325  throw;
1326  }
1327 
1328  if (sqlite3_changes(db) == 0) {
1329  // value did not exist, insert
1330 
1331  try {
1332  stmt = prepare_insert_value(SQL_INSERT_VALUE, "bool", path);
1333  if ((sqlite3_bind_int(stmt, 3, (b ? 1 : 0)) != SQLITE_OK)) {
1334  ConfigurationException ce("set_bool/insert/bind", sqlite3_errmsg(db));
1335  sqlite3_finalize(stmt);
1336  mutex->unlock();
1337  throw ce;
1338  }
1339  execute_insert_or_update(stmt);
1340  sqlite3_finalize(stmt);
1341  } catch (Exception &e) {
1342  if (stmt != NULL)
1343  sqlite3_finalize(stmt);
1344  mutex->unlock();
1345  throw;
1346  }
1347  }
1348 
1349  mutex->unlock();
1350 
1351  notify_handlers(path);
1352 }
1353 
1354 void
1355 SQLiteConfiguration::set_string(const char *path, const char *s)
1356 {
1357  sqlite3_stmt *stmt = NULL;
1358 
1359  mutex->lock();
1360 
1361  size_t s_length = strlen(s);
1362 
1363  try {
1364  stmt = prepare_update(SQL_UPDATE_VALUE, path);
1365  if ((sqlite3_bind_text(stmt, 1, s, s_length, SQLITE_STATIC) != SQLITE_OK)) {
1366  ConfigurationException ce("set_string/update/bind", sqlite3_errmsg(db));
1367  sqlite3_finalize(stmt);
1368  mutex->unlock();
1369  throw ce;
1370  }
1371  execute_insert_or_update(stmt);
1372  sqlite3_finalize(stmt);
1373  } catch (Exception &e) {
1374  if (stmt != NULL)
1375  sqlite3_finalize(stmt);
1376  mutex->unlock();
1377  throw;
1378  }
1379 
1380  if (sqlite3_changes(db) == 0) {
1381  // value did not exist, insert
1382 
1383  try {
1384  stmt = prepare_insert_value(SQL_INSERT_VALUE, "string", path);
1385  if ((sqlite3_bind_text(stmt, 3, s, s_length, SQLITE_STATIC) != SQLITE_OK)) {
1386  ConfigurationException ce("set_string/insert/bind", sqlite3_errmsg(db));
1387  sqlite3_finalize(stmt);
1388  mutex->unlock();
1389  throw ce;
1390  }
1391  execute_insert_or_update(stmt);
1392  sqlite3_finalize(stmt);
1393  } catch (Exception &e) {
1394  if (stmt != NULL)
1395  sqlite3_finalize(stmt);
1396  mutex->unlock();
1397  throw;
1398  }
1399  }
1400 
1401  mutex->unlock();
1402 
1403  notify_handlers(path);
1404 }
1405 
1406 void
1407 SQLiteConfiguration::set_string(const char *path, std::string &s)
1408 {
1409  set_string(path, s.c_str());
1410 }
1411 
1412 void
1413 SQLiteConfiguration::set_floats(const char *path, std::vector<float> &f)
1414 {
1415  throw NotImplementedException("SQLiteConf: list values are not supported");
1416 }
1417 
1418 void
1419 SQLiteConfiguration::set_uints(const char *path, std::vector<unsigned int> &u)
1420 {
1421  throw NotImplementedException("SQLiteConf: list values are not supported");
1422 }
1423 
1424 void
1425 SQLiteConfiguration::set_ints(const char *path, std::vector<int> &i)
1426 {
1427  throw NotImplementedException("SQLiteConf: list values are not supported");
1428 }
1429 
1430 void
1431 SQLiteConfiguration::set_bools(const char *path, std::vector<bool> &b)
1432 {
1433  throw NotImplementedException("SQLiteConf: list values are not supported");
1434 }
1435 
1436 void
1437 SQLiteConfiguration::set_strings(const char *path, std::vector<std::string> &s)
1438 {
1439  throw NotImplementedException("SQLiteConf: list values are not supported");
1440 }
1441 
1442 void
1443 SQLiteConfiguration::set_strings(const char *path, std::vector<const char *> &s)
1444 {
1445  throw NotImplementedException("SQLiteConf: list values are not supported");
1446 }
1447 
1448 void
1449 SQLiteConfiguration::set_comment(const char *path, const char *comment)
1450 {
1451  sqlite3_stmt *stmt = NULL;
1452 
1453  mutex->lock();
1454 
1455  size_t s_length = strlen(comment);
1456 
1457  try {
1458  stmt = prepare_update(SQL_UPDATE_COMMENT, path);
1459  if ((sqlite3_bind_text(stmt, 1, comment, s_length, SQLITE_STATIC) != SQLITE_OK)) {
1460  ConfigurationException ce("set_string/update/bind", sqlite3_errmsg(db));
1461  sqlite3_finalize(stmt);
1462  mutex->unlock();
1463  throw ce;
1464  }
1465  execute_insert_or_update(stmt);
1466  sqlite3_finalize(stmt);
1467  } catch (Exception &e) {
1468  if (stmt != NULL)
1469  sqlite3_finalize(stmt);
1470  mutex->unlock();
1471  throw;
1472  }
1473 
1474  if (sqlite3_changes(db) == 0) {
1475  // value did not exist, insert
1476  mutex->unlock();
1477  throw ConfigurationException("set_comment", "Cannot set comment for inexistent path");
1478  }
1479 
1480  mutex->unlock();
1481 
1482  notify_handlers(path, true);
1483 }
1484 
1485 void
1486 SQLiteConfiguration::set_comment(const char *path, std::string &comment)
1487 {
1488  set_comment(path, comment.c_str());
1489 }
1490 
1491 void
1493 {
1494  sqlite3_stmt *stmt;
1495  const char * tail;
1496 
1497  if (sqlite3_prepare(db, SQL_DELETE_VALUE, -1, &stmt, &tail) != SQLITE_OK) {
1498  throw ConfigurationException("erase/prepare", sqlite3_errmsg(db));
1499  }
1500  if (sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK) {
1501  ConfigurationException ce("erase/bind", sqlite3_errmsg(db));
1502  sqlite3_finalize(stmt);
1503  throw ce;
1504  }
1505 
1506  if (sqlite3_step(stmt) != SQLITE_DONE) {
1507  ConfigurationException ce("erase/execute", sqlite3_errmsg(db));
1508  sqlite3_finalize(stmt);
1509  throw ce;
1510  }
1511 
1512  sqlite3_finalize(stmt);
1513 
1514  notify_handlers(path);
1515 }
1516 
1517 void
1518 SQLiteConfiguration::set_default_float(const char *path, float f)
1519 {
1520  sqlite3_stmt *stmt = NULL;
1521 
1522  mutex->lock();
1523 
1524  try {
1525  stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path);
1526  if ((sqlite3_bind_double(stmt, 1, f) != SQLITE_OK)) {
1527  ConfigurationException ce("set_default_float/update/bind", sqlite3_errmsg(db));
1528  sqlite3_finalize(stmt);
1529  mutex->unlock();
1530  throw ce;
1531  }
1532  execute_insert_or_update(stmt);
1533  sqlite3_finalize(stmt);
1534  } catch (Exception &e) {
1535  if (stmt != NULL)
1536  sqlite3_finalize(stmt);
1537  mutex->unlock();
1538  throw;
1539  }
1540 
1541  if (sqlite3_changes(db) == 0) {
1542  // value did not exist, insert
1543 
1544  try {
1545  stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "float", path);
1546  if ((sqlite3_bind_double(stmt, 3, f) != SQLITE_OK)) {
1547  ConfigurationException ce("set_default_float/insert/bind", sqlite3_errmsg(db));
1548  sqlite3_finalize(stmt);
1549  mutex->unlock();
1550  throw ce;
1551  }
1552  execute_insert_or_update(stmt);
1553  sqlite3_finalize(stmt);
1554  } catch (Exception &e) {
1555  if (stmt != NULL)
1556  sqlite3_finalize(stmt);
1557  mutex->unlock();
1558  throw;
1559  }
1560  }
1561 
1562  mutex->unlock();
1563 
1564  notify_handlers(path);
1565 }
1566 
1567 void
1568 SQLiteConfiguration::set_default_uint(const char *path, unsigned int uint)
1569 {
1570  sqlite3_stmt *stmt = NULL;
1571 
1572  mutex->lock();
1573 
1574  try {
1575  stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path);
1576  if ((sqlite3_bind_int(stmt, 1, uint) != SQLITE_OK)) {
1577  ConfigurationException ce("set_default_uint/update/bind", sqlite3_errmsg(db));
1578  sqlite3_finalize(stmt);
1579  mutex->unlock();
1580  throw ce;
1581  }
1582  execute_insert_or_update(stmt);
1583  sqlite3_finalize(stmt);
1584  } catch (Exception &e) {
1585  if (stmt != NULL)
1586  sqlite3_finalize(stmt);
1587  mutex->unlock();
1588  throw;
1589  }
1590 
1591  if (sqlite3_changes(db) == 0) {
1592  // value did not exist, insert
1593 
1594  try {
1595  stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "unsigned int", path);
1596  if ((sqlite3_bind_int(stmt, 3, uint) != SQLITE_OK)) {
1597  ConfigurationException ce("set_default_uint/insert/bind", sqlite3_errmsg(db));
1598  sqlite3_finalize(stmt);
1599  mutex->unlock();
1600  throw ce;
1601  }
1602  execute_insert_or_update(stmt);
1603  sqlite3_finalize(stmt);
1604  } catch (Exception &e) {
1605  if (stmt != NULL)
1606  sqlite3_finalize(stmt);
1607  mutex->unlock();
1608  throw;
1609  }
1610  }
1611  mutex->unlock();
1612 
1613  notify_handlers(path);
1614 }
1615 
1616 void
1618 {
1619  sqlite3_stmt *stmt = NULL;
1620  mutex->lock();
1621 
1622  try {
1623  stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path);
1624  if ((sqlite3_bind_int(stmt, 1, i) != SQLITE_OK)) {
1625  ConfigurationException ce("set_default_int/update/bind", sqlite3_errmsg(db));
1626  sqlite3_finalize(stmt);
1627  mutex->unlock();
1628  throw ce;
1629  }
1630  execute_insert_or_update(stmt);
1631  sqlite3_finalize(stmt);
1632  } catch (Exception &e) {
1633  if (stmt != NULL)
1634  sqlite3_finalize(stmt);
1635  mutex->unlock();
1636  throw;
1637  }
1638 
1639  if (sqlite3_changes(db) == 0) {
1640  // value did not exist, insert
1641  try {
1642  stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "int", path);
1643  if ((sqlite3_bind_int(stmt, 3, i) != SQLITE_OK)) {
1644  ConfigurationException ce("set_default_int/insert/bind", sqlite3_errmsg(db));
1645  sqlite3_finalize(stmt);
1646  mutex->unlock();
1647  throw ce;
1648  }
1649  execute_insert_or_update(stmt);
1650  sqlite3_finalize(stmt);
1651  } catch (Exception &e) {
1652  if (stmt != NULL)
1653  sqlite3_finalize(stmt);
1654  mutex->unlock();
1655  throw;
1656  }
1657  }
1658 
1659  mutex->unlock();
1660 
1661  notify_handlers(path);
1662 }
1663 
1664 void
1665 SQLiteConfiguration::set_default_bool(const char *path, bool b)
1666 {
1667  sqlite3_stmt *stmt = NULL;
1668 
1669  mutex->lock();
1670 
1671  try {
1672  stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path);
1673  if ((sqlite3_bind_int(stmt, 1, (b ? 1 : 0)) != SQLITE_OK)) {
1674  ConfigurationException ce("set_default_bool/update/bind", sqlite3_errmsg(db));
1675  sqlite3_finalize(stmt);
1676  mutex->unlock();
1677  throw ce;
1678  }
1679  execute_insert_or_update(stmt);
1680  sqlite3_finalize(stmt);
1681  } catch (Exception &e) {
1682  if (stmt != NULL)
1683  sqlite3_finalize(stmt);
1684  mutex->unlock();
1685  throw;
1686  }
1687 
1688  if (sqlite3_changes(db) == 0) {
1689  // value did not exist, insert
1690 
1691  try {
1692  stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "bool", path);
1693  if ((sqlite3_bind_int(stmt, 3, (b ? 1 : 0)) != SQLITE_OK)) {
1694  ConfigurationException ce("set_default_bool/insert/bind", sqlite3_errmsg(db));
1695  sqlite3_finalize(stmt);
1696  mutex->unlock();
1697  throw ce;
1698  }
1699  execute_insert_or_update(stmt);
1700  sqlite3_finalize(stmt);
1701  } catch (Exception &e) {
1702  if (stmt != NULL)
1703  sqlite3_finalize(stmt);
1704  mutex->unlock();
1705  throw;
1706  }
1707  }
1708 
1709  mutex->unlock();
1710 
1711  notify_handlers(path);
1712 }
1713 
1714 void
1715 SQLiteConfiguration::set_default_string(const char *path, const char *s)
1716 {
1717  sqlite3_stmt *stmt = NULL;
1718 
1719  mutex->lock();
1720  size_t s_length = strlen(s);
1721 
1722  try {
1723  stmt = prepare_update(SQL_UPDATE_DEFAULT_VALUE, path);
1724  if ((sqlite3_bind_text(stmt, 1, s, s_length, SQLITE_STATIC) != SQLITE_OK)) {
1725  ConfigurationException ce("set_default_string/update/bind", sqlite3_errmsg(db));
1726  sqlite3_finalize(stmt);
1727  mutex->unlock();
1728  throw ce;
1729  }
1730  execute_insert_or_update(stmt);
1731  sqlite3_finalize(stmt);
1732  } catch (Exception &e) {
1733  if (stmt != NULL)
1734  sqlite3_finalize(stmt);
1735  mutex->unlock();
1736  throw;
1737  }
1738 
1739  if (sqlite3_changes(db) == 0) {
1740  // value did not exist, insert
1741 
1742  try {
1743  stmt = prepare_insert_value(SQL_INSERT_DEFAULT_VALUE, "string", path);
1744  if ((sqlite3_bind_text(stmt, 3, s, s_length, SQLITE_STATIC) != SQLITE_OK)) {
1745  ConfigurationException ce("set_default_string/insert/bind", sqlite3_errmsg(db));
1746  sqlite3_finalize(stmt);
1747  mutex->unlock();
1748  throw ce;
1749  }
1750  execute_insert_or_update(stmt);
1751  sqlite3_finalize(stmt);
1752  } catch (Exception &e) {
1753  if (stmt != NULL)
1754  sqlite3_finalize(stmt);
1755  mutex->unlock();
1756  throw;
1757  }
1758  }
1759 
1760  mutex->unlock();
1761 
1762  notify_handlers(path);
1763 }
1764 
1765 void
1766 SQLiteConfiguration::set_default_string(const char *path, std::string &s)
1767 {
1768  set_default_string(path, s.c_str());
1769 }
1770 
1771 void
1772 SQLiteConfiguration::set_default_comment(const char *path, const char *comment)
1773 {
1774  sqlite3_stmt *stmt = NULL;
1775 
1776  mutex->lock();
1777  size_t s_length = strlen(comment);
1778 
1779  try {
1780  stmt = prepare_update(SQL_UPDATE_DEFAULT_COMMENT, path);
1781  if ((sqlite3_bind_text(stmt, 1, comment, s_length, SQLITE_STATIC) != SQLITE_OK)) {
1782  ConfigurationException ce("set_default_comment/update/bind", sqlite3_errmsg(db));
1783  sqlite3_finalize(stmt);
1784  mutex->unlock();
1785  throw ce;
1786  }
1787  execute_insert_or_update(stmt);
1788  sqlite3_finalize(stmt);
1789  } catch (Exception &e) {
1790  if (stmt != NULL)
1791  sqlite3_finalize(stmt);
1792  mutex->unlock();
1793  throw;
1794  }
1795 
1796  if (sqlite3_changes(db) == 0) {
1797  // value did not exist, insert
1798  mutex->unlock();
1799  throw ConfigurationException("set_default_comment", "Cannot set comment for inexistent path");
1800  }
1801 
1802  mutex->unlock();
1803 
1804  notify_handlers(path);
1805 }
1806 
1807 void
1808 SQLiteConfiguration::set_default_comment(const char *path, std::string &comment)
1809 {
1810  set_default_comment(path, comment.c_str());
1811 }
1812 
1813 void
1815 {
1816  sqlite3_stmt *stmt;
1817  const char * tail;
1818 
1819  if (sqlite3_prepare(db, SQL_DELETE_DEFAULT_VALUE, -1, &stmt, &tail) != SQLITE_OK) {
1820  throw ConfigurationException("erase_default/prepare", sqlite3_errmsg(db));
1821  }
1822  if (sqlite3_bind_text(stmt, 1, path, -1, NULL) != SQLITE_OK) {
1823  ConfigurationException ce("erase_default/bind", sqlite3_errmsg(db));
1824  sqlite3_finalize(stmt);
1825  throw ce;
1826  }
1827 
1828  if (sqlite3_step(stmt) != SQLITE_DONE) {
1829  ConfigurationException ce("erase_default/execute", sqlite3_errmsg(db));
1830  sqlite3_finalize(stmt);
1831  throw ce;
1832  }
1833 
1834  sqlite3_finalize(stmt);
1835 
1836  notify_handlers(path);
1837 }
1838 
1839 /** Lock the config.
1840  * No further changes or queries can be executed on the configuration and will block until
1841  * the config is unlocked.
1842  */
1843 void
1845 {
1846  mutex->lock();
1847 }
1848 
1849 /** Try to lock the config.
1850  * @see Configuration::lock()
1851  * @return true, if the lock has been aquired, false otherwise
1852  */
1853 bool
1855 {
1856  return mutex->try_lock();
1857 }
1858 
1859 /** Unlock the config.
1860  * Modifications and queries are possible again.
1861  */
1862 void
1864 {
1865  mutex->unlock();
1866 }
1867 
1870 {
1871  sqlite3_stmt *stmt;
1872  const char * tail;
1873 
1874  if (sqlite3_prepare(db, SQL_SELECT_ALL, -1, &stmt, &tail) != SQLITE_OK) {
1875  throw ConfigurationException("iterator: Preparation SQL failed");
1876  }
1877 
1878  return new SQLiteValueIterator(stmt);
1879 }
1880 
1881 /** Iterator for all default values.
1882  * Returns an iterator that can be used to iterate over all default values in
1883  * the current default configuration. Note that this might return less paths than
1884  * available, because the values for which no default entry exists are not
1885  * returned.
1886  * @return iterator over all default values
1887  */
1890 {
1891  sqlite3_stmt *stmt;
1892  const char * tail;
1893 
1894  if (sqlite3_prepare(db, SQL_SELECT_ALL_DEFAULT, -1, &stmt, &tail) != SQLITE_OK) {
1895  throw ConfigurationException("iterator_default: Preparation SQL failed");
1896  }
1897 
1898  return new SQLiteValueIterator(stmt);
1899 }
1900 
1901 /** Iterator for all host-specific values.
1902  * Returns an iterator that can be used to iterate over all host-specific values
1903  * in the current configuration. Note that this might return less paths than
1904  * available, because the default values for which no host-specific entry exists
1905  * are not returned.
1906  * @return iterator over all host-specific values
1907  */
1910 {
1911  sqlite3_stmt *stmt;
1912  const char * tail;
1913 
1914  if (sqlite3_prepare(db, SQL_SELECT_ALL_HOSTSPECIFIC, -1, &stmt, &tail) != SQLITE_OK) {
1915  throw ConfigurationException("iterator_hostspecific: Preparation SQL failed");
1916  }
1917 
1918  return new SQLiteValueIterator(stmt);
1919 }
1920 
1921 /** Iterator for modified values.
1922  * Returns an iterator that can be used to iterate over all values that have been
1923  * modified in the default database in the last load (added, erased or changed).
1924  * @return iterator over all values
1925  */
1928 {
1929  sqlite3_stmt *stmt;
1930  const char * tail;
1931 
1932  if (sqlite3_prepare(db, SQL_SELECT_MODIFIED_ALL, -1, &stmt, &tail) != SQLITE_OK) {
1933  throw ConfigurationException("modified_iterator: Preparation SQL failed");
1934  }
1935 
1936  return new SQLiteValueIterator(stmt);
1937 }
1938 
1939 /** Iterator with search results.
1940  * Returns an iterator that can be used to iterate over the search results. All values
1941  * whose component and path start with the given strings are returned.
1942  * A call like
1943  * @code
1944  * config->search("");
1945  * @endcode
1946  * is effectively the same as a call to iterator().
1947  * @param path start of path
1948  * @return iterator to search results
1949  */
1952 {
1953  sqlite3_stmt *stmt;
1954  const char * tail;
1955 
1956  char *p;
1957  if (asprintf(&p, "%s%%", path) == -1) {
1958  throw ConfigurationException("search: could not allocate component string");
1959  }
1960 
1961  if (sqlite3_prepare(db, SQL_SELECT_COMPLETE, -1, &stmt, &tail) != SQLITE_OK) {
1962  free(p);
1963  throw ConfigurationException("begin: Preparation SQL failed");
1964  }
1965  if (sqlite3_bind_text(stmt, 1, p, -1, NULL) != SQLITE_OK) {
1966  free(p);
1967  throw ConfigurationException("begin: Binding text for path failed (1)");
1968  }
1969  if (sqlite3_bind_text(stmt, 2, p, -1, NULL) != SQLITE_OK) {
1970  free(p);
1971  throw ConfigurationException("begin: Binding text for path failed (2)");
1972  }
1973 
1974  return new SQLiteValueIterator(stmt, p);
1975 }
1976 
1977 /** @class SQLiteConfiguration::SQLiteValueIterator config/sqlite.h
1978  * SQLite configuration value iterator.
1979  */
1980 
1981 /** Constructor.
1982  * @param stmt compiled SQLite statement
1983  * @param p pointer to arbitrary data that is freed (not deleted!) when the iterator
1984  * is deleted.
1985  */
1987 {
1988  stmt_ = stmt;
1989  p_ = p;
1990 }
1991 
1992 /** Destructor. */
1994 {
1995  if (stmt_ != NULL) {
1996  sqlite3_finalize(stmt_);
1997  stmt_ = NULL;
1998  }
1999  if (p_ != NULL) {
2000  free(p_);
2001  }
2002 }
2003 
2004 /* Check if there is another element and advance to this if possible.
2005  * This advances to the next element, if there is one.
2006  * @return true, if another element has been reached, false otherwise
2007  */
2008 bool
2010 {
2011  if (stmt_ == NULL)
2012  return false;
2013 
2014  if (sqlite3_step(stmt_) == SQLITE_ROW) {
2015  return true;
2016  } else {
2017  sqlite3_finalize(stmt_);
2018  stmt_ = NULL;
2019  return false;
2020  }
2021 }
2022 
2023 /** Check if the current element is valid.
2024  * This is much like the classic end element for iterators. If the iterator is
2025  * invalid there all subsequent calls to next() shall fail.
2026  * @return true, if the iterator is still valid, false otherwise
2027  */
2028 bool
2030 {
2031  return (stmt_ != NULL);
2032 }
2033 
2034 /** Path of value.
2035  * @return path of value
2036  */
2037 const char *
2039 {
2040  return (const char *)sqlite3_column_text(stmt_, 0);
2041 }
2042 
2043 /** Type of value.
2044  * @return string representation of value type.
2045  */
2046 const char *
2048 {
2049  return (const char *)sqlite3_column_text(stmt_, 1);
2050 }
2051 
2052 bool
2054 {
2055  return (strcmp("float", (const char *)sqlite3_column_text(stmt_, 1)) == 0);
2056 }
2057 
2058 bool
2060 {
2061  return (strcmp("unsigned int", (const char *)sqlite3_column_text(stmt_, 1)) == 0);
2062 }
2063 
2064 bool
2066 {
2067  return (strcmp("int", (const char *)sqlite3_column_text(stmt_, 1)) == 0);
2068 }
2069 
2070 bool
2072 {
2073  return (strcmp("bool", (const char *)sqlite3_column_text(stmt_, 1)) == 0);
2074 }
2075 
2076 bool
2078 {
2079  return (strcmp("string", (const char *)sqlite3_column_text(stmt_, 1)) == 0);
2080 }
2081 
2082 bool
2084 {
2085  return false;
2086 }
2087 
2088 size_t
2090 {
2091  return 0;
2092 }
2093 
2094 bool
2096 {
2097  return (sqlite3_column_int(stmt_, 4) == 1);
2098 }
2099 
2100 /** Get float value.
2101  * @return value
2102  */
2103 float
2105 {
2106  return (float)sqlite3_column_double(stmt_, 2);
2107 }
2108 
2109 /** Get unsigned int value.
2110  * @return value
2111  */
2112 unsigned int
2114 {
2115  int i = sqlite3_column_int(stmt_, 2);
2116  if (i < 0) {
2117  return 0;
2118  } else {
2119  return i;
2120  }
2121 }
2122 
2123 /** Get int value.
2124  * @return value
2125  */
2126 int
2128 {
2129  return sqlite3_column_int(stmt_, 2);
2130 }
2131 
2132 /** Get bool value.
2133  * @return value
2134  */
2135 bool
2137 {
2138  return (sqlite3_column_int(stmt_, 2) != 0);
2139 }
2140 
2141 /** Get string value.
2142  * @return value
2143  */
2144 std::string
2146 {
2147  return (const char *)sqlite3_column_text(stmt_, 2);
2148 }
2149 
2150 std::vector<float>
2152 {
2153  throw NotImplementedException("SQLiteConf: list values are not supported");
2154 }
2155 
2156 std::vector<unsigned int>
2158 {
2159  throw NotImplementedException("SQLiteConf: list values are not supported");
2160 }
2161 
2162 std::vector<int>
2164 {
2165  throw NotImplementedException("SQLiteConf: list values are not supported");
2166 }
2167 
2168 std::vector<bool>
2170 {
2171  throw NotImplementedException("SQLiteConf: list values are not supported");
2172 }
2173 
2174 std::vector<std::string>
2176 {
2177  throw NotImplementedException("SQLiteConf: list values are not supported");
2178 }
2179 
2180 /** Get value as string.
2181  * @return value
2182  */
2183 std::string
2185 {
2186  return (const char *)sqlite3_column_text(stmt_, 2);
2187 }
2188 
2189 /** Get comment.
2190  * @return string comment value
2191  */
2192 std::string
2194 {
2195  const char *c = (const char *)sqlite3_column_text(stmt_, 3);
2196  return c ? c : "";
2197 }
2198 
2199 /** Get modification type.
2200  * This can only be called if the iterator has been retrieved via
2201  * SQLiteConfiguration::modified_iterator(). Otherwise the return value is
2202  * always and empty string.
2203  * @return string modification type
2204  */
2205 std::string
2207 {
2208  const char *c = (const char *)sqlite3_column_text(stmt_, 4);
2209  return c ? c : "";
2210 }
2211 
2212 /** Get old value (as string).
2213  * This can only be called if the iterator has been retrieved via
2214  * SQLiteConfiguration::modified_iterator(). The value is always returned
2215  * as string, as it is meant for debugging purposes only. Otherwise the
2216  * return value is always and empty string.
2217  * @return string modification type
2218  */
2219 std::string
2221 {
2222  const char *c = (const char *)sqlite3_column_text(stmt_, 5);
2223  return c ? c : "";
2224 }
2225 
2226 } // end namespace fawkes
fawkes::Mutex::lock
void lock()
Lock this mutex.
Definition: mutex.cpp:93
fawkes::SQLiteConfiguration::iterator
ValueIterator * iterator()
Definition: sqlite.cpp:1869
fawkes::SQLiteConfiguration::modified_iterator
SQLiteValueIterator * modified_iterator()
Iterator for modified values.
Definition: sqlite.cpp:1927
fawkes::SQLiteConfiguration::set_default_int
virtual void set_default_int(const char *path, int i)
Definition: sqlite.cpp:1617
fawkes::dump_table
static void dump_table(FILE *f, ::sqlite3 *tdb, const char *table_name)
Dump table.
Definition: sqlite.cpp:307
fawkes::Configuration::iterator
virtual ValueIterator * iterator()=0
fawkes::SQLiteConfiguration::SQLiteValueIterator::valid
virtual bool valid() const
Check if the current element is valid.
Definition: sqlite.cpp:2029
fawkes::SQLiteConfiguration::get_string
virtual std::string get_string(const char *path)
Definition: sqlite.cpp:1040
fawkes::SQLiteConfiguration::SQLiteConfiguration
SQLiteConfiguration()
Constructor.
Definition: sqlite.cpp:187
fawkes::SQLiteConfiguration::get_bool
virtual bool get_bool(const char *path)
Definition: sqlite.cpp:1022
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_modtype
std::string get_modtype() const
Get modification type.
Definition: sqlite.cpp:2206
fawkes::Configuration::ValueIterator::get_bool
virtual bool get_bool() const =0
fawkes::SQLiteConfiguration::TRANSACTION_EXCLUSIVE
@ TRANSACTION_EXCLUSIVE
Immediately acquire lock, no more reading or writing possible.
Definition: sqlite.h:110
fawkes::Configuration::lock
virtual void lock()=0
fawkes::SQLiteConfiguration::is_default
virtual bool is_default(const char *path)
Definition: sqlite.cpp:898
fawkes::SQLiteConfiguration::get_int
virtual int get_int(const char *path)
Definition: sqlite.cpp:1004
fawkes::Mutex
Definition: mutex.h:38
fawkes::SQLiteConfiguration::get_floats
virtual std::vector< float > get_floats(const char *path)
Definition: sqlite.cpp:1060
fawkes::SQLiteConfiguration::is_list
virtual bool is_list(const char *path)
Definition: sqlite.cpp:892
fawkes::SQLiteConfiguration::set_bools
virtual void set_bools(const char *path, std::vector< bool > &b)
Definition: sqlite.cpp:1431
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_oldvalue
std::string get_oldvalue() const
Get old value (as string).
Definition: sqlite.cpp:2220
fawkes::SQLiteConfiguration::SQLiteValueIterator::next
virtual bool next()
Definition: sqlite.cpp:2009
fawkes::SQLiteConfiguration::search
ValueIterator * search(const char *path)
Iterator with search results.
Definition: sqlite.cpp:1951
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_uints
virtual std::vector< unsigned int > get_uints() const
Definition: sqlite.cpp:2157
fawkes::SQLiteConfiguration::get_default_comment
virtual std::string get_default_comment(const char *path)
Definition: sqlite.cpp:833
fawkes::Configuration::ValueIterator::is_string
virtual bool is_string() const =0
fawkes::SQLiteConfiguration::SQLiteValueIterator::type
virtual const char * type() const
Type of value.
Definition: sqlite.cpp:2047
fawkes::SQLiteConfiguration::SQLiteValueIterator::is_list
virtual bool is_list() const
Definition: sqlite.cpp:2083
fawkes::SQLiteConfiguration::try_lock
bool try_lock()
Try to lock the config.
Definition: sqlite.cpp:1854
fawkes::Configuration::ValueIterator::get_string
virtual std::string get_string() const =0
fawkes::SQLiteConfiguration::get_comment
virtual std::string get_comment(const char *path)
Definition: sqlite.cpp:804
fawkes::SQLiteConfiguration::get_uint
virtual unsigned int get_uint(const char *path)
Definition: sqlite.cpp:982
fawkes::SQLiteConfiguration::set_default_bool
virtual void set_default_bool(const char *path, bool b)
Definition: sqlite.cpp:1665
fawkes::SQLiteConfiguration::try_dump
void try_dump()
Try to dump default configuration.
Definition: sqlite.cpp:376
fawkes::SQLiteConfiguration::load
virtual void load(const char *filename)
Definition: sqlite.cpp:564
fawkes::SQLiteConfiguration::SQLiteValueIterator::is_float
virtual bool is_float() const
Definition: sqlite.cpp:2053
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_bools
virtual std::vector< bool > get_bools() const
Definition: sqlite.cpp:2169
fawkes::Mutex::unlock
void unlock()
Unlock the mutex.
Definition: mutex.cpp:137
fawkes::SQLiteConfiguration::SQLiteValueIterator
Definition: sqlite.h:118
fawkes::SQLiteConfiguration::is_int
virtual bool is_int(const char *path)
Definition: sqlite.cpp:874
fawkes::SQLiteConfiguration::set_default_string
virtual void set_default_string(const char *path, std::string &s)
Definition: sqlite.cpp:1766
fawkes::Configuration::ValueIterator
Definition: config.h:77
fawkes::SQLiteConfiguration::get_uints
virtual std::vector< unsigned int > get_uints(const char *path)
Definition: sqlite.cpp:1066
fawkes::Configuration
Definition: config.h:70
fawkes::Exception::append
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:333
fawkes::SQLiteConfiguration::SQLiteValueIterator::is_default
virtual bool is_default() const
Definition: sqlite.cpp:2095
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_bool
virtual bool get_bool() const
Get bool value.
Definition: sqlite.cpp:2136
fawkes::ConfigEntryNotFoundException
Definition: config.h:52
fawkes::SQLiteConfiguration::get_bools
virtual std::vector< bool > get_bools(const char *path)
Definition: sqlite.cpp:1078
fawkes::SQLiteConfiguration::get_float
virtual float get_float(const char *path)
Definition: sqlite.cpp:964
fawkes::SQLiteConfiguration::set_default_float
virtual void set_default_float(const char *path, float f)
Definition: sqlite.cpp:1518
fawkes::SQLiteConfiguration::copy
virtual void copy(Configuration *copyconf)
Copy all values from the given configuration.
Definition: sqlite.cpp:719
fawkes::SQLiteConfiguration::transaction_begin
void transaction_begin(transaction_type_t ttype=TRANSACTION_DEFERRED)
Begin SQL Transaction.
Definition: sqlite.cpp:507
fawkes::SQLiteConfiguration::set_strings
virtual void set_strings(const char *path, std::vector< std::string > &s)
Definition: sqlite.cpp:1437
fawkes::Configuration::ValueIterator::is_bool
virtual bool is_bool() const =0
fawkes::SQLiteConfiguration::is_uint
virtual bool is_uint(const char *path)
Definition: sqlite.cpp:868
fawkes::SQLiteConfiguration::set_float
virtual void set_float(const char *path, float f)
Definition: sqlite.cpp:1156
fawkes::SQLiteConfiguration::is_string
virtual bool is_string(const char *path)
Definition: sqlite.cpp:886
fawkes::HostInfo::short_name
const char * short_name()
Get short hostname (up to first dot).
Definition: hostinfo.cpp:115
fawkes::SQLiteConfiguration::set_default_comment
virtual void set_default_comment(const char *path, const char *comment)
Definition: sqlite.cpp:1772
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_comment
virtual std::string get_comment() const
Get comment.
Definition: sqlite.cpp:2193
fawkes::SQLiteConfiguration::~SQLiteConfiguration
virtual ~SQLiteConfiguration()
Destructor.
Definition: sqlite.cpp:231
fawkes::SQLiteConfiguration::SQLiteValueIterator::SQLiteValueIterator
SQLiteValueIterator(::sqlite3_stmt *stmt, void *p=NULL)
Constructor.
Definition: sqlite.cpp:1986
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_strings
virtual std::vector< std::string > get_strings() const
Definition: sqlite.cpp:2175
fawkes::SQLiteConfiguration::get_type
virtual std::string get_type(const char *path)
Definition: sqlite.cpp:771
fawkes::SQLiteConfiguration::get_ints
virtual std::vector< int > get_ints(const char *path)
Definition: sqlite.cpp:1072
fawkes::SQLiteConfiguration::SQLiteValueIterator::path
virtual const char * path() const
Path of value.
Definition: sqlite.cpp:2038
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_float
virtual float get_float() const
Get float value.
Definition: sqlite.cpp:2104
fawkes
fawkes::SQLiteConfiguration::set_bool
virtual void set_bool(const char *path, bool b)
Definition: sqlite.cpp:1305
fawkes::Configuration::unlock
virtual void unlock()=0
fawkes::SQLiteConfiguration::SQLiteValueIterator::is_bool
virtual bool is_bool() const
Definition: sqlite.cpp:2071
fawkes::SQLiteConfiguration::transaction_rollback
void transaction_rollback()
Rollback SQL Transaction.
Definition: sqlite.cpp:536
fawkes::Configuration::ValueIterator::is_float
virtual bool is_float() const =0
fawkes::SQLiteConfiguration::exists
virtual bool exists(const char *path)
Definition: sqlite.cpp:744
fawkes::ConfigTypeMismatchException
Definition: config.h:58
fawkes::SQLiteConfiguration::set_int
virtual void set_int(const char *path, int i)
Definition: sqlite.cpp:1255
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_int
virtual int get_int() const
Get int value.
Definition: sqlite.cpp:2127
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_uint
virtual unsigned int get_uint() const
Get unsigned int value.
Definition: sqlite.cpp:2113
fawkes::SQLiteConfiguration::is_bool
virtual bool is_bool(const char *path)
Definition: sqlite.cpp:880
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_list_size
virtual size_t get_list_size() const
Definition: sqlite.cpp:2089
fawkes::Configuration::ValueIterator::is_int
virtual bool is_int() const =0
fawkes::SQLiteConfiguration::iterator_hostspecific
ValueIterator * iterator_hostspecific()
Iterator for all host-specific values.
Definition: sqlite.cpp:1909
fawkes::CouldNotOpenConfigException
Definition: config.h:64
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_floats
virtual std::vector< float > get_floats() const
Definition: sqlite.cpp:2151
fawkes::Mutex::try_lock
bool try_lock()
Tries to lock the mutex.
Definition: mutex.cpp:123
fawkes::SQLiteConfiguration::set_uint
virtual void set_uint(const char *path, unsigned int uint)
Definition: sqlite.cpp:1206
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_ints
virtual std::vector< int > get_ints() const
Definition: sqlite.cpp:2163
fawkes::NotImplementedException
Definition: software.h:110
fawkes::HostInfo
Definition: hostinfo.h:31
fawkes::SQLiteConfiguration::is_float
virtual bool is_float(const char *path)
Definition: sqlite.cpp:862
fawkes::SQLiteConfiguration::set_ints
virtual void set_ints(const char *path, std::vector< int > &i)
Definition: sqlite.cpp:1425
fawkes::SQLiteConfiguration::set_string
virtual void set_string(const char *path, std::string &s)
Definition: sqlite.cpp:1407
fawkes::SQLiteConfiguration::transaction_commit
void transaction_commit()
Commit SQL Transaction.
Definition: sqlite.cpp:524
fawkes::SQLiteConfiguration::iterator_default
ValueIterator * iterator_default()
Iterator for all default values.
Definition: sqlite.cpp:1889
fawkes::Configuration::ValueIterator::get_int
virtual int get_int() const =0
fawkes::SQLiteConfiguration::erase_default
virtual void erase_default(const char *path)
Definition: sqlite.cpp:1814
fawkes::SQLiteConfiguration::get_value
virtual ValueIterator * get_value(const char *path)
Definition: sqlite.cpp:1090
fawkes::SQLiteConfiguration::get_strings
virtual std::vector< std::string > get_strings(const char *path)
Definition: sqlite.cpp:1084
fawkes::SQLiteConfiguration::SQLiteValueIterator::is_string
virtual bool is_string() const
Definition: sqlite.cpp:2077
fawkes::SQLiteConfiguration::unlock
void unlock()
Unlock the config.
Definition: sqlite.cpp:1863
fawkes::SQLiteConfiguration::set_floats
virtual void set_floats(const char *path, std::vector< float > &f)
Definition: sqlite.cpp:1413
fawkes::SQLiteConfiguration::set_uints
virtual void set_uints(const char *path, std::vector< unsigned int > &uint)
Definition: sqlite.cpp:1419
fawkes::SQLiteConfiguration::set_default_uint
virtual void set_default_uint(const char *path, unsigned int uint)
Definition: sqlite.cpp:1568
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_string
virtual std::string get_string() const
Get string value.
Definition: sqlite.cpp:2145
fawkes::ConfigurationException
Definition: config.h:45
fawkes::SQLiteConfiguration::set_comment
virtual void set_comment(const char *path, std::string &comment)
Definition: sqlite.cpp:1486
fawkes::Configuration::notify_handlers
void notify_handlers(const char *path, bool comment_changed=false)
Notify handlers for given path.
Definition: config.cpp:680
fawkes::Configuration::ValueIterator::path
virtual const char * path() const =0
fawkes::SQLiteConfiguration::transaction_type_t
transaction_type_t
Transaction type.
Definition: sqlite.h:107
fawkes::Configuration::ValueIterator::get_uint
virtual unsigned int get_uint() const =0
fawkes::Configuration::ValueIterator::next
virtual bool next()=0
fawkes::Configuration::ValueIterator::is_uint
virtual bool is_uint() const =0
fawkes::Configuration::ValueIterator::get_float
virtual float get_float() const =0
fawkes::SQLiteConfiguration::SQLiteValueIterator::is_uint
virtual bool is_uint() const
Definition: sqlite.cpp:2059
fawkes::SQLiteConfiguration::SQLiteValueIterator::get_as_string
virtual std::string get_as_string() const
Get value as string.
Definition: sqlite.cpp:2184
fawkes::sql_escape_noop
static std::string sql_escape_noop(const char *line)
SQL escaping stub.
Definition: sqlite.cpp:399
fawkes::SQLiteConfiguration::TRANSACTION_IMMEDIATE
@ TRANSACTION_IMMEDIATE
Immediately acquire lock, reading remains possible.
Definition: sqlite.h:109
fawkes::SQLiteConfiguration::SQLiteValueIterator::~SQLiteValueIterator
virtual ~SQLiteValueIterator()
Destructor.
Definition: sqlite.cpp:1993
fawkes::SQLiteConfiguration::lock
void lock()
Lock the config.
Definition: sqlite.cpp:1844
fawkes::SQLiteConfiguration::erase
virtual void erase(const char *path)
Definition: sqlite.cpp:1492
fawkes::SQLiteConfiguration::SQLiteValueIterator::is_int
virtual bool is_int() const
Definition: sqlite.cpp:2065
fawkes::Exception
Definition: exception.h:41