QOF 0.8.2
|
00001 /********************************************************************\ 00002 * qofbackend.c -- utility routines for the data backend * 00003 * Copyright (C) 2000 Linas Vepstas <linas@linas.org> * 00004 * Copyright (C) 2004-2008 Neil Williams <linux@codehelp.co.uk> * 00005 * * 00006 * This program is free software; you can redistribute it and/or * 00007 * modify it under the terms of the GNU General Public License as * 00008 * published by the Free Software Foundation; either version 2 of * 00009 * the License, or (at your option) any later version. * 00010 * * 00011 * This program is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00014 * GNU General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU General Public License* 00017 * along with this program; if not, contact: * 00018 * * 00019 * Free Software Foundation Voice: +1-617-542-5942 * 00020 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 00021 * Boston, MA 02110-1301, USA gnu@gnu.org * 00022 * * 00023 \********************************************************************/ 00024 00025 #include "config.h" 00026 #include <glib.h> 00027 #include <gmodule.h> 00028 #include "qof.h" 00029 #include "qofbackend-p.h" 00030 00031 #define QOF_CONFIG_DESC "desc" 00032 #define QOF_CONFIG_TIP "tip" 00033 00034 static QofLogModule log_module = QOF_MOD_BACKEND; 00035 00036 void 00037 qof_backend_init (QofBackend * be) 00038 { 00039 be->session_begin = NULL; 00040 be->session_end = NULL; 00041 be->destroy_backend = NULL; 00042 be->load = NULL; 00043 be->begin = NULL; 00044 be->commit = NULL; 00045 be->rollback = NULL; 00046 be->compile_query = NULL; 00047 be->free_query = NULL; 00048 be->run_query = NULL; 00049 be->sync = NULL; 00050 be->load_config = NULL; 00051 be->events_pending = NULL; 00052 be->process_events = NULL; 00053 be->percentage = NULL; 00054 be->backend_configuration = kvp_frame_new (); 00055 } 00056 00057 void 00058 qof_backend_run_begin (QofBackend * be, QofInstance * inst) 00059 { 00060 if (!be || !inst) 00061 return; 00062 if (!be->begin) 00063 return; 00064 (be->begin) (be, inst); 00065 } 00066 00067 gboolean 00068 qof_backend_begin_exists (QofBackend * be) 00069 { 00070 if (be->begin) 00071 return TRUE; 00072 else 00073 return FALSE; 00074 } 00075 00076 void 00077 qof_backend_run_commit (QofBackend * be, QofInstance * inst) 00078 { 00079 if (!be || !inst) 00080 return; 00081 if (!be->commit) 00082 return; 00083 (be->commit) (be, inst); 00084 } 00085 00086 /* =========== Backend Configuration ================ */ 00087 00088 void 00089 qof_backend_prepare_frame (QofBackend * be) 00090 { 00091 g_return_if_fail (be); 00092 if (!kvp_frame_is_empty (be->backend_configuration)) 00093 { 00094 kvp_frame_delete (be->backend_configuration); 00095 be->backend_configuration = kvp_frame_new (); 00096 } 00097 be->config_count = 0; 00098 } 00099 00100 void 00101 qof_backend_prepare_option (QofBackend * be, 00102 QofBackendOption * option) 00103 { 00104 KvpValue *value; 00105 gchar *temp; 00106 gint count; 00107 00108 g_return_if_fail (be || option); 00109 count = be->config_count; 00110 count++; 00111 value = NULL; 00112 switch (option->type) 00113 { 00114 case KVP_TYPE_GINT64: 00115 { 00116 value = kvp_value_new_gint64 (*(gint64 *) option->value); 00117 break; 00118 } 00119 case KVP_TYPE_DOUBLE: 00120 { 00121 value = kvp_value_new_double (*(gdouble *) option->value); 00122 break; 00123 } 00124 case KVP_TYPE_NUMERIC: 00125 { 00126 value = kvp_value_new_numeric (*(QofNumeric *) option->value); 00127 break; 00128 } 00129 case KVP_TYPE_STRING: 00130 { 00131 value = kvp_value_new_string ((const gchar *) option->value); 00132 break; 00133 } 00134 case KVP_TYPE_BOOLEAN: 00135 { 00136 break; 00137 } 00138 case KVP_TYPE_GUID: 00139 { 00140 break; 00141 } /* unsupported */ 00142 case KVP_TYPE_TIME : 00143 { 00144 value = kvp_value_new_time ((QofTime*) option->value); 00145 break; 00146 } 00147 case KVP_TYPE_BINARY: 00148 { 00149 break; 00150 } /* unsupported */ 00151 case KVP_TYPE_GLIST: 00152 { 00153 break; 00154 } /* unsupported */ 00155 case KVP_TYPE_FRAME: 00156 { 00157 break; 00158 } /* unsupported */ 00159 } 00160 if (value) 00161 { 00162 temp = g_strdup_printf ("/%s", option->option_name); 00163 kvp_frame_set_value (be->backend_configuration, temp, value); 00164 g_free (temp); 00165 temp = 00166 g_strdup_printf ("/%s/%s", QOF_CONFIG_DESC, 00167 option->option_name); 00168 kvp_frame_set_string (be->backend_configuration, temp, 00169 option->description); 00170 g_free (temp); 00171 temp = 00172 g_strdup_printf ("/%s/%s", QOF_CONFIG_TIP, 00173 option->option_name); 00174 kvp_frame_set_string (be->backend_configuration, temp, 00175 option->tooltip); 00176 g_free (temp); 00177 /* only increment the counter if successful */ 00178 be->config_count = count; 00179 } 00180 } 00181 00182 KvpFrame * 00183 qof_backend_complete_frame (QofBackend * be) 00184 { 00185 g_return_val_if_fail (be, NULL); 00186 be->config_count = 0; 00187 return be->backend_configuration; 00188 } 00189 00190 struct config_iterate 00191 { 00192 QofBackendOptionCB fcn; 00193 gpointer data; 00194 gint count; 00195 KvpFrame *recursive; 00196 }; 00197 00198 /* Set the option with the default KvpValue, 00199 manipulate the option in the supplied callback routine 00200 then set the value of the option into the KvpValue 00201 in the configuration frame. */ 00202 static void 00203 config_foreach_cb (const gchar * key, KvpValue * value, gpointer data) 00204 { 00205 QofBackendOption option; 00206 gint64 int64; 00207 gdouble db; 00208 QofNumeric num; 00209 gchar *parent; 00210 struct config_iterate *helper; 00211 00212 g_return_if_fail (key || value || data); 00213 helper = (struct config_iterate *) data; 00214 if (!helper->recursive) 00215 { 00216 PERR (" no parent frame"); 00217 return; 00218 } 00219 // skip the presets. 00220 if (0 == safe_strcmp (key, QOF_CONFIG_DESC)) 00221 { 00222 return; 00223 } 00224 if (0 == safe_strcmp (key, QOF_CONFIG_TIP)) 00225 { 00226 return; 00227 } 00228 ENTER (" key=%s", key); 00229 option.option_name = key; 00230 option.type = kvp_value_get_type (value); 00231 if (!option.type) 00232 return; 00233 switch (option.type) 00234 { /* set the KvpFrame value into the option */ 00235 case KVP_TYPE_GINT64: 00236 { 00237 int64 = kvp_value_get_gint64 (value); 00238 option.value = (gpointer) & int64; 00239 break; 00240 } 00241 case KVP_TYPE_DOUBLE: 00242 { 00243 db = kvp_value_get_double (value); 00244 option.value = (gpointer) & db; 00245 break; 00246 } 00247 case KVP_TYPE_NUMERIC: 00248 { 00249 num = kvp_value_get_numeric (value); 00250 option.value = (gpointer) & num; 00251 break; 00252 } 00253 case KVP_TYPE_STRING: 00254 { 00255 option.value = (gpointer) kvp_value_get_string (value); 00256 break; 00257 } 00258 case KVP_TYPE_TIME : 00259 { 00260 option.value = (gpointer) kvp_value_get_time (value); 00261 } 00262 case KVP_TYPE_BOOLEAN : 00263 { 00264 break; 00265 } 00266 case KVP_TYPE_GUID: 00267 { 00268 break; 00269 } /* unsupported */ 00270 case KVP_TYPE_BINARY: 00271 { 00272 break; 00273 } /* unsupported */ 00274 case KVP_TYPE_GLIST: 00275 { 00276 break; 00277 } /* unsupported */ 00278 case KVP_TYPE_FRAME: 00279 { 00280 break; 00281 } /* unsupported */ 00282 } 00283 parent = g_strdup_printf ("/%s/%s", QOF_CONFIG_DESC, key); 00284 option.description = kvp_frame_get_string (helper->recursive, parent); 00285 g_free (parent); 00286 parent = g_strdup_printf ("/%s/%s", QOF_CONFIG_TIP, key); 00287 option.tooltip = kvp_frame_get_string (helper->recursive, parent); 00288 g_free (parent); 00289 helper->count++; 00290 /* manipulate the option */ 00291 helper->fcn (&option, helper->data); 00292 switch (option.type) 00293 { /* set the option value into the KvpFrame */ 00294 case KVP_TYPE_GINT64: 00295 { 00296 kvp_frame_set_gint64 (helper->recursive, key, 00297 (*(gint64 *) option.value)); 00298 break; 00299 } 00300 case KVP_TYPE_DOUBLE: 00301 { 00302 kvp_frame_set_double (helper->recursive, key, 00303 (*(gdouble *) option.value)); 00304 break; 00305 } 00306 case KVP_TYPE_NUMERIC: 00307 { 00308 kvp_frame_set_numeric (helper->recursive, key, 00309 (*(QofNumeric *) option.value)); 00310 break; 00311 } 00312 case KVP_TYPE_STRING: 00313 { 00314 kvp_frame_set_string (helper->recursive, key, 00315 (gchar *) option.value); 00316 break; 00317 } 00318 case KVP_TYPE_TIME : 00319 { 00320 kvp_frame_set_time (helper->recursive, key, 00321 (QofTime*) option.value); 00322 break; 00323 } 00324 case KVP_TYPE_BOOLEAN : 00325 { 00326 break; 00327 } 00328 case KVP_TYPE_GUID: 00329 { 00330 break; 00331 } /* unsupported */ 00332 case KVP_TYPE_BINARY: 00333 { 00334 break; 00335 } /* unsupported */ 00336 case KVP_TYPE_GLIST: 00337 { 00338 break; 00339 } /* unsupported */ 00340 case KVP_TYPE_FRAME: 00341 { 00342 break; 00343 } /* unsupported */ 00344 } 00345 LEAVE (" "); 00346 } 00347 00348 void 00349 qof_backend_option_foreach (KvpFrame * config, 00350 QofBackendOptionCB cb, gpointer data) 00351 { 00352 struct config_iterate helper; 00353 00354 if (!config || !cb) 00355 return; 00356 ENTER (" "); 00357 helper.fcn = cb; 00358 helper.count = 1; 00359 helper.data = data; 00360 helper.recursive = config; 00361 kvp_frame_for_each_slot (config, config_foreach_cb, &helper); 00362 LEAVE (" "); 00363 } 00364 00365 void 00366 qof_backend_load_config (QofBackend * be, KvpFrame * config) 00367 { 00368 if (!be || !config) 00369 return; 00370 if (!be->load_config) 00371 return; 00372 (be->load_config) (be, config); 00373 } 00374 00375 KvpFrame * 00376 qof_backend_get_config (QofBackend * be) 00377 { 00378 if (!be) 00379 return NULL; 00380 if (!be->get_config) 00381 return NULL; 00382 return (be->get_config) (be); 00383 } 00384 00385 gboolean 00386 qof_backend_commit_exists (QofBackend * be) 00387 { 00388 if (!be) 00389 return FALSE; 00390 if (be->commit) 00391 return TRUE; 00392 else 00393 return FALSE; 00394 } 00395 00396 gboolean 00397 qof_load_backend_library (const gchar * directory, 00398 const gchar * filename, const gchar * init_fcn) 00399 { 00400 gchar *fullpath; 00401 typedef void (*backend_init) (void); 00402 GModule *backend; 00403 backend_init gmod_init; 00404 gpointer g; 00405 00406 g_return_val_if_fail (g_module_supported (), FALSE); 00407 fullpath = g_module_build_path (directory, filename); 00408 backend = g_module_open (fullpath, G_MODULE_BIND_LAZY); 00409 if (!backend) 00410 { 00411 PERR (" No backend found. %s", g_module_error ()); 00412 return FALSE; 00413 } 00414 g = &gmod_init; 00415 if (!g_module_symbol (backend, init_fcn, g)) 00416 { 00417 PERR (" Backend did not initialise. %s", g_module_error ()); 00418 return FALSE; 00419 } 00420 g_module_make_resident (backend); 00421 gmod_init (); 00422 g_free (fullpath); 00423 return TRUE; 00424 } 00425 00426 /************************* END OF FILE ********************************/