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