00001 #include "config_db_private.h" 00002 00003 #include "ac_app_context.h" 00004 #include "application_config.h" 00005 #include "db_creation.h" 00006 #include "er_errors.h" 00007 #include "lua_cl2.h" 00008 #include "sqlite_cl2.h" 00009 00010 #include "common/threading_mutex.h" 00011 00012 #include <string.h> 00013 00014 /** Config database file. 00015 */ 00016 #define CONFIGDB_BASENAME "config.db" 00017 #define CONFIGDB_DIR CONFIG_DIR 00018 #define CONFIGDB_FILE (CONFIGDB_DIR DIR_SEP CONFIGDB_BASENAME) 00019 00020 static const char create_tables_sql[] = 00021 "create table configuration (name TEXT UNIQUE, value TEXT);"; 00022 00023 static gboolean create_config_db(GError** error) 00024 { 00025 return create_database(CONFIGDB_DIR, 00026 CONFIGDB_FILE, 00027 create_tables_sql, 00028 error); 00029 } 00030 00031 static gboolean ensure_config_db_created(GError** error) 00032 { 00033 assert_error_unset(error); 00034 00035 if (!g_file_test(CONFIGDB_FILE, G_FILE_TEST_EXISTS)) { 00036 logg("file '%s' does not exist", CONFIGDB_FILE); 00037 return create_config_db(error); 00038 } 00039 00040 return TRUE; 00041 } 00042 00043 struct _ConfigDb 00044 { 00045 sqlite3* db; 00046 00047 sqlite3_stmt* getStmt; 00048 sqlite3_stmt* setStmt; 00049 00050 #if THREAD_SAFETY 00051 pthread_mutex_t mutex; 00052 #endif 00053 }; 00054 00055 static gboolean prepare_sql_statements(ConfigDb *self, GError **error) 00056 { 00057 if (sqlite_prepare(self->db, "select * from configuration where name = ? limit 1;", -1, &(self->getStmt), 0)) { goto fail; } 00058 // The OR REPLACE clause here states how to do conflict resolution 00059 // if the uniqueness constraints (in our case for "name") would be 00060 // violated. 00061 if (sqlite_prepare(self->db, "insert or replace into configuration (name, value) values (?, ?);", -1, &(self->setStmt), 0)) { goto fail; } 00062 return TRUE; 00063 00064 fail: 00065 if (error) 00066 *error = gx_error_new(domain_cl2app, code_database_state_init, "error preparing statements for database '%s': %s (%d)", CONFIGDB_FILE, sqlite3_errmsg(self->db), sqlite3_errcode(self->db)); 00067 return FALSE; 00068 } 00069 00070 #define FINALIZE_SQL_STATEMENT(lvalue) \ 00071 if (lvalue) { sqlite3_finalize(lvalue); lvalue = NULL; } 00072 00073 static void destroy_sql_statements(ConfigDb *self) 00074 { 00075 FINALIZE_SQL_STATEMENT(self->getStmt); 00076 FINALIZE_SQL_STATEMENT(self->setStmt); 00077 } 00078 00079 static void close_config_db_session(ConfigDb* self) 00080 { 00081 if (self->db) { 00082 destroy_sql_statements(self); 00083 00084 // Note that prepared statements and BLOB handles must be 00085 // freed separately. 00086 int errCode = sqlite3_close(self->db); 00087 #if __DO_LOGGING__ 00088 if (errCode) { 00089 // A close failure is probably a programming error, so we 00090 // shall log it. 00091 logg("sqlite3_close failure %d", errCode); 00092 } 00093 #endif 00094 self->db = NULL; 00095 } 00096 } 00097 00098 static gboolean open_config_db_session(ConfigDb* self, GError** error) 00099 { 00100 // This still allocates a handle, except for those cases in which 00101 // the memory for the handle cannot be allocated. We can hence get 00102 // an error message if "db" is non-NULL. 00103 int errCode = sqlite3_open(CONFIGDB_FILE, &self->db); 00104 if (errCode) { 00105 if (error) 00106 *error = gx_error_new(domain_cl2app, code_database_open, "error opening database '%s': %s (%d)", CONFIGDB_FILE, sqlite_get_error_string(self->db), errCode); 00107 close_config_db_session(self); 00108 return FALSE; 00109 } 00110 00111 if (!prepare_sql_statements(self, error)) { 00112 close_config_db_session(self); 00113 return FALSE; 00114 } 00115 00116 return TRUE; 00117 } 00118 00119 ConfigDb* ConfigDb_new(GError** error) 00120 { 00121 if (!ensure_config_db_created(error)) { 00122 // If getting this error, do make sure that you have any database 00123 // binary right, statically linked or otherwise. 00124 return NULL; 00125 } 00126 00127 ConfigDb* self = g_try_new0(ConfigDb, 1); 00128 if (G_UNLIKELY(!self)) { 00129 if (error) *error = gx_error_no_memory; 00130 return NULL; 00131 } 00132 00133 mutex_init(&self->mutex); 00134 00135 if (!open_config_db_session(self, error)) { 00136 // If getting this error, do make sure that you have any database 00137 // binary right, statically linked or otherwise. 00138 ConfigDb_destroy(self); 00139 return NULL; 00140 } 00141 00142 return self; 00143 } 00144 00145 void ConfigDb_destroy(ConfigDb* self) 00146 { 00147 if (self) { 00148 close_config_db_session(self); 00149 mutex_destroy(&self->mutex); 00150 g_free(self); 00151 } 00152 } 00153 00154 #define do_nothing ((void)0) 00155 00156 #define set_sql_error \ 00157 if (error) \ 00158 *error = gx_error_new(domain_cl2app, code_database_command, \ 00159 "ConfigDb database access error: %s (%d)", \ 00160 sqlite3_errmsg(self->db), \ 00161 sqlite3_errcode(self->db)); 00162 00163 #define handle_sql_error_done { set_sql_error; goto done; } 00164 00165 #define handle_sql_error_false { set_sql_error; return FALSE; } 00166 00167 static gchar* db_get(ConfigDb* self, 00168 const gchar* name, 00169 GError** error) 00170 { 00171 gchar* value = NULL; 00172 00173 { 00174 if (sqlite3_bind_text(self->getStmt, 1, name, strlen(name), 00175 SQLITE_STATIC)) { 00176 handle_sql_error_done; 00177 } 00178 00179 // Upon success we should get either SQLITE_ROW and SQLITE_DONE. 00180 // Anything else we consider an error, since there should be no 00181 // locking issues or anything. Any of a number of error codes 00182 // could be returned, since we are (possibly) using the "v2" 00183 // interface. SQLITE_ROW should mean that we got our (one) row 00184 // of data, and an (immediate) SQLITE_DONE should mean that 00185 // there is no data that matched the request. 00186 int res = sqlite3_step(self->getStmt); 00187 switch (res) 00188 { 00189 case SQLITE_DONE: 00190 { 00191 if (error) *error = new_not_found_error; 00192 sqlite3_reset(self->getStmt); 00193 goto done; 00194 } 00195 case SQLITE_ROW: 00196 { 00197 // "value" will be NULL if there is an OOM error. 00198 value = (gchar *)sqlite3_column_text(self->getStmt, 1); 00199 if (value) { 00200 value = strdup(value); 00201 } 00202 if (!value) { 00203 if (error) *error = gx_error_no_memory; 00204 sqlite3_reset(self->getStmt); 00205 goto done; 00206 } 00207 break; 00208 } 00209 default: // some error 00210 { 00211 sqlite3_reset(self->getStmt); 00212 handle_sql_error_done; 00213 } 00214 } 00215 00216 // Note that this does not clear bindings, but we should not 00217 // need to, unless we must later use unbound parameters (which 00218 // are interpreted as NULL); see sqlite3_clear_bindings(). 00219 if (sqlite3_reset(self->getStmt)) { 00220 handle_sql_error_done; 00221 } 00222 00223 done: 00224 do_nothing; 00225 } 00226 00227 return value; 00228 } 00229 00230 gchar* ConfigDb_get_generic(ConfigDb* self, 00231 const gchar* name, 00232 GError** error) 00233 { 00234 gchar* value = NULL; 00235 mutex_synchronized(&self->mutex, value = db_get(self, name, error)); 00236 return value; 00237 } 00238 00239 static gboolean db_set(ConfigDb* self, 00240 const gchar* name, 00241 const gchar* value, 00242 GError** error) 00243 { 00244 assert(value); 00245 00246 if (!validate_lua_syntax(value, error)) { 00247 return FALSE; 00248 } 00249 00250 GError* getError = NULL; 00251 gchar* oldValue = db_get(self, name, &getError); 00252 if (!oldValue) { 00253 if (is_not_found_error(getError)) { 00254 g_error_free(getError); 00255 } else { 00256 if (error) *error = getError; 00257 else g_error_free(getError); 00258 return FALSE; 00259 } 00260 } 00261 00262 if (oldValue) { 00263 if (strcmp(oldValue, value) == 0) { 00264 g_free(oldValue); 00265 return TRUE; 00266 } 00267 g_free(oldValue); 00268 } 00269 00270 // Update database. 00271 { 00272 if (sqlite3_bind_text(self->setStmt, 1, name, strlen(name), 00273 SQLITE_STATIC)) { 00274 handle_sql_error_false; 00275 } 00276 00277 if (sqlite3_bind_text(self->setStmt, 2, value, strlen(value), 00278 SQLITE_STATIC)) { 00279 sqlite3_reset(self->setStmt); 00280 handle_sql_error_false; 00281 } 00282 00283 int res = sqlite3_step(self->setStmt); 00284 if (res != SQLITE_DONE) { 00285 sqlite3_reset(self->setStmt); 00286 handle_sql_error_false; 00287 } 00288 00289 if (sqlite3_reset(self->setStmt)) { 00290 handle_sql_error_false; 00291 } 00292 } 00293 00294 return TRUE; 00295 } 00296 00297 gboolean ConfigDb_set_generic(ConfigDb* self, 00298 const gchar* name, 00299 const gchar* value, 00300 GError** error) 00301 { 00302 gboolean success = FALSE; 00303 mutex_synchronized(&self->mutex, success = db_set(self, name, value, error)); 00304 00305 if (success) { 00306 // A question here is; what should we do if the notification should 00307 // fail. Should we perhaps roll back the ConfigDb change? We are not 00308 // doing that, and we consider it a separate issue whether the 00309 // concerned components are actually able to honor the new 00310 // configuration or not. 00311 kr_Controller* kr = ac_global_Controller; 00312 if (!kr_Controller_reconfigure(kr, name, value, error)) 00313 return FALSE; 00314 } 00315 00316 return success; 00317 } 00318 00319 /** 00320 00321 config_db.c 00322 00323 Copyright 2009 Helsinki Institute for Information Technology (HIIT) 00324 and the authors. All rights reserved. 00325 00326 Authors: Tero Hasu <tero.hasu@hut.fi> 00327 00328 Permission is hereby granted, free of charge, to any person 00329 obtaining a copy of this software and associated documentation files 00330 (the "Software"), to deal in the Software without restriction, 00331 including without limitation the rights to use, copy, modify, merge, 00332 publish, distribute, sublicense, and/or sell copies of the Software, 00333 and to permit persons to whom the Software is furnished to do so, 00334 subject to the following conditions: 00335 00336 The above copyright notice and this permission notice shall be 00337 included in all copies or substantial portions of the Software. 00338 00339 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00340 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00341 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00342 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 00343 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 00344 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00345 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00346 SOFTWARE. 00347 00348 **/
ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:52 2011 by Doxygen 1.6.1