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