OpenSync
0.22
|
00001 /* 00002 * libopensync - A synchronization framework 00003 * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2.1 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 * 00019 */ 00020 00021 #include "opensync.h" 00022 #include "opensync_internals.h" 00023 00024 00032 00033 #ifndef DOXYGEN_SHOULD_SKIP_THIS 00034 OSyncObjTypeSink *osync_objtype_sink_from_template(OSyncGroup *group, OSyncObjTypeTemplate *template) 00035 { 00036 g_assert(group); 00037 g_assert(template); 00038 OSyncObjTypeSink *sink = g_malloc0(sizeof(OSyncObjTypeSink)); 00039 OSyncObjType *type = osync_conv_find_objtype(group->conv_env, template->name); 00040 if (!type) { 00041 osync_debug("OSYNC", 0, "Unable to find objtype named %s to create objtype sink", template->name); 00042 return NULL; 00043 } 00044 sink->objtype = type; 00045 sink->enabled = TRUE; 00046 sink->write = TRUE; 00047 sink->read = TRUE; 00048 return sink; 00049 } 00050 00051 OSyncObjFormatSink *osync_objformat_sink_from_template(OSyncGroup *group, OSyncObjFormatTemplate *template) 00052 { 00053 OSyncObjFormatSink *sink = g_malloc0(sizeof(OSyncObjFormatSink)); 00054 OSyncObjFormat *format = osync_conv_find_objformat(group->conv_env, template->name); 00055 if (!format) 00056 return NULL; 00057 sink->format = format; 00058 sink->functions.commit_change = template->commit_change; 00059 sink->functions.access = template->access; 00060 sink->functions.read = template->read; 00061 sink->functions.committed_all = template->committed_all; 00062 sink->functions.batch_commit = template->batch_commit; 00063 sink->extension_name = g_strdup(template->extension_name); 00064 return sink; 00065 } 00066 00067 OSyncObjTypeTemplate *osync_plugin_find_objtype_template(OSyncPlugin *plugin, const char *objtypestr) 00068 { 00069 GList *o; 00070 for (o = plugin->accepted_objtypes; o; o = o->next) { 00071 OSyncObjTypeTemplate *template = o->data; 00072 if (!strcmp(template->name, objtypestr)) 00073 return template; 00074 } 00075 return NULL; 00076 } 00077 00078 OSyncObjFormatTemplate *osync_plugin_find_objformat_template(OSyncObjTypeTemplate *type_template, const char *objformatstr) 00079 { 00080 GList *f; 00081 for (f = type_template->formats; f; f = f->next) { 00082 OSyncObjFormatTemplate *template = f->data; 00083 if (!strcmp(template->name, objformatstr)) 00084 return template; 00085 } 00086 return NULL; 00087 } 00088 00089 OSyncObjFormatSink *osync_objtype_find_format_sink(OSyncObjTypeSink *sink, const char *formatstr) 00090 { 00091 GList *f; 00092 for (f = sink->formatsinks; f; f = f->next) { 00093 OSyncObjFormatSink *sink = f->data; 00094 if (!strcmp(sink->format->name, formatstr)) 00095 return sink; 00096 } 00097 return NULL; 00098 } 00099 00100 void _osync_format_set_commit(OSyncObjTypeTemplate *template, const char *formatstr, OSyncFormatCommitFn commit_change) 00101 { 00102 OSyncObjFormatTemplate *format_template = NULL; 00103 if (formatstr) { 00104 OSyncObjFormatTemplate *format_template = osync_plugin_find_objformat_template(template, formatstr); 00105 osync_assert_msg(format_template, "Unable to set commit function. Did you forget to add the objformat?"); 00106 format_template->commit_change = commit_change; 00107 } else { 00108 GList *f = NULL; 00109 for (f = template->formats; f; f = f->next) { 00110 format_template = f->data; 00111 format_template->commit_change = commit_change; 00112 } 00113 } 00114 } 00115 00116 void _osync_format_set_access(OSyncObjTypeTemplate *template, const char *formatstr, OSyncFormatAccessFn access) 00117 { 00118 OSyncObjFormatTemplate *format_template = NULL; 00119 if (formatstr) { 00120 format_template = osync_plugin_find_objformat_template(template, formatstr); 00121 osync_assert_msg(format_template, "Unable to set commit function. Did you forget to add the objformat?"); 00122 format_template->access = access; 00123 } else { 00124 GList *f = NULL; 00125 for (f = template->formats; f; f = f->next) { 00126 format_template = f->data; 00127 format_template->access = access; 00128 } 00129 } 00130 } 00131 00132 void _osync_format_set_batch(OSyncObjTypeTemplate *template, const char *formatstr, OSyncFormatBatchCommitFn batch) 00133 { 00134 OSyncObjFormatTemplate *format_template = NULL; 00135 if (formatstr) { 00136 format_template = osync_plugin_find_objformat_template(template, formatstr); 00137 osync_assert_msg(format_template, "Unable to set batch commit function. Did you forget to add the objformat?"); 00138 format_template->batch_commit = batch; 00139 } else { 00140 GList *f = NULL; 00141 for (f = template->formats; f; f = f->next) { 00142 format_template = f->data; 00143 format_template->batch_commit = batch; 00144 } 00145 } 00146 } 00147 #endif 00148 00158 00167 OSyncPlugin *osync_plugin_new(OSyncEnv *env) 00168 { 00169 OSyncPlugin *plugin = g_malloc0(sizeof(OSyncPlugin)); 00170 g_assert(plugin); 00171 memset(&(plugin->info), 0, sizeof(plugin->info)); 00172 memset(&(plugin->info.functions), 0, sizeof(plugin->info.functions)); 00173 memset(&(plugin->info.timeouts), 0, sizeof(plugin->info.timeouts)); 00174 00175 //Set the default timeouts; 00176 plugin->info.timeouts.connect_timeout = 60; 00177 plugin->info.timeouts.sync_done_timeout = 60; 00178 plugin->info.timeouts.disconnect_timeout = 60; 00179 plugin->info.timeouts.get_changeinfo_timeout = 60; 00180 plugin->info.timeouts.get_data_timeout = 60; 00181 plugin->info.timeouts.commit_timeout = 60; 00182 plugin->info.timeouts.read_change_timeout = 60; 00183 00184 plugin->info.plugin = plugin; 00185 plugin->info.config_type = NEEDS_CONFIGURATION; 00186 00187 if (env) { 00188 env->plugins = g_list_append(env->plugins, plugin); 00189 plugin->env = env; 00190 plugin->real_plugin = env->current_module; 00191 } 00192 00193 return plugin; 00194 } 00195 00196 00205 OSyncPluginInfo *osync_plugin_new_info(OSyncEnv *env) 00206 { 00207 OSyncPlugin *plg = osync_plugin_new(env); 00208 osync_trace(TRACE_INTERNAL, "%s(%p): %p", __func__, env, plg); 00209 if (!plg) 00210 return NULL; 00211 00212 return &plg->info; 00213 } 00214 00222 void osync_plugin_free(OSyncPlugin *plugin) 00223 { 00224 osync_trace(TRACE_INTERNAL, "osync_plugin_free(%p)", plugin); 00225 g_assert(plugin); 00226 if (plugin->env) 00227 plugin->env->plugins = g_list_remove(plugin->env->plugins, plugin); 00228 00229 //FIXME Free more stuff? 00230 g_free(plugin); 00231 } 00232 00243 void *osync_plugin_get_function(OSyncPlugin *plugin, const char *name, OSyncError **error) 00244 { 00245 void *function; 00246 if (!plugin->real_plugin) { 00247 osync_debug("OSPLG", 1, "You need to load a plugin before getting a function"); 00248 osync_error_set(error, OSYNC_ERROR_MISCONFIGURATION, "You need to load a plugin before getting a function"); 00249 return NULL; 00250 } 00251 00252 if (!g_module_symbol (plugin->real_plugin, name, &function)) { 00253 osync_debug("OSPLG", 0, "Unable to locate symbol %s on plugin", name); 00254 osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to locate symbol %s: %s", name, g_module_error()); 00255 return NULL; 00256 } 00257 return function; 00258 } 00259 00270 osync_bool osync_module_load(OSyncEnv *env, const char *path, OSyncError **error) 00271 { 00272 osync_trace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, env, path, error); 00273 /* Check if this platform supports dynamic 00274 * loading of modules */ 00275 00276 if (!g_module_supported()) { 00277 osync_error_set(error, OSYNC_ERROR_GENERIC, "This platform does not support loading of modules"); 00278 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 00279 return FALSE; 00280 } 00281 00282 /* Try to open the module or fail if an error occurs */ 00283 GModule *module = g_module_open(path, 0); 00284 if (!module) { 00285 osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to open module %s: %s", path, g_module_error()); 00286 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 00287 return FALSE; 00288 } 00289 00290 /* Load the get_info symbol */ 00291 void (* fct_info)(OSyncEnv *env) = NULL; 00292 void (** fct_infop)(OSyncEnv *env) = &fct_info; 00293 if (!g_module_symbol(module, "get_info", (void **)fct_infop)) { 00294 /* If there is no get_info symbol, the file must be a implementation library 00295 * for one of the other modules. So dont throw an error error since it has been 00296 * confusing users */ 00297 osync_trace(TRACE_EXIT, "%s: Not loading implementation library", __func__); 00298 return TRUE; 00299 } 00300 env->modules = g_list_append(env->modules, module); 00301 00302 /* Call the get_info function */ 00303 env->current_module = module; 00304 fct_info(env); 00305 env->current_module = NULL; 00306 00307 osync_trace(TRACE_EXIT, "%s: %p", __func__, module); 00308 return TRUE; 00309 } 00310 00317 void osync_module_unload(OSyncEnv *env, GModule *module) 00318 { 00319 osync_trace(TRACE_INTERNAL, "%s(%p, %p)", __func__, env, module); 00320 //FIXME Close the module! This crashes the evo2 plugin at the moment, i have no idea why... 00321 //g_module_close(plugin->real_plugin); 00322 env->modules = g_list_remove(env->modules, module); 00323 } 00324 00336 osync_bool osync_module_load_dir(OSyncEnv *env, const char *path, osync_bool must_exist, OSyncError **error) 00337 { 00338 osync_trace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, env, path, error); 00339 GDir *dir; 00340 GError *gerror = NULL; 00341 char *filename = NULL; 00342 00343 if (!path) { 00344 osync_error_set(error, OSYNC_ERROR_GENERIC, "Not path given to load the modules from"); 00345 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 00346 return FALSE; 00347 } 00348 00349 //Load all available shared libraries (plugins) 00350 if (!g_file_test(path, G_FILE_TEST_IS_DIR)) { 00351 if (must_exist) { 00352 osync_error_set(error, OSYNC_ERROR_GENERIC, "Path is not loadable"); 00353 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 00354 return FALSE; 00355 } else { 00356 osync_trace(TRACE_EXIT, "%s: Directory does not exist (non-fatal)", __func__); 00357 return TRUE; 00358 } 00359 } 00360 00361 dir = g_dir_open(path, 0, &gerror); 00362 if (!dir) { 00363 osync_error_set(error, OSYNC_ERROR_IO_ERROR, "Unable to open directory %s: %s", path, gerror->message); 00364 g_error_free(gerror); 00365 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 00366 return FALSE; 00367 } 00368 00369 const gchar *de = NULL; 00370 while ((de = g_dir_read_name(dir))) { 00371 filename = g_strdup_printf ("%s/%s", path, de); 00372 00373 if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR) || g_file_test(filename, G_FILE_TEST_IS_SYMLINK) || !g_pattern_match_simple("*.so", filename)) { 00374 g_free(filename); 00375 continue; 00376 } 00377 00378 OSyncError *error = NULL; 00379 if (!osync_module_load(env, filename, &error)) { 00380 osync_debug("OSPLG", 0, "Unable to load plugin %s: %s", filename, error->message); 00381 osync_error_free(&error); 00382 } 00383 g_free(filename); 00384 } 00385 g_dir_close(dir); 00386 00387 osync_trace(TRACE_EXIT, "%s", __func__); 00388 return TRUE; 00389 } 00390 00397 const char *osync_plugin_get_name(OSyncPlugin *plugin) 00398 { 00399 g_assert(plugin); 00400 return plugin->info.name; 00401 } 00402 00409 const char *osync_plugin_get_longname(OSyncPlugin *plugin) 00410 { 00411 g_assert(plugin); 00412 return plugin->info.longname; 00413 } 00414 00421 const char *osync_plugin_get_description(OSyncPlugin *plugin) 00422 { 00423 g_assert(plugin); 00424 return plugin->info.description; 00425 } 00426 00433 OSyncPluginTimeouts osync_plugin_get_timeouts(OSyncPlugin *plugin) 00434 { 00435 g_assert(plugin); 00436 return plugin->info.timeouts; 00437 } 00438 00444 void *osync_plugin_get_plugin_data(OSyncPlugin *plugin) 00445 { 00446 g_assert(plugin); 00447 return plugin->info.plugin_data; 00448 } 00449 00455 const char *osync_plugin_get_path(OSyncPlugin *plugin) 00456 { 00457 g_assert(plugin); 00458 return g_module_name(plugin->real_plugin); 00459 } 00460 00469 void osync_plugin_set_commit_objformat(OSyncPluginInfo *info, const char *objtypestr, const char *formatstr, OSyncFormatCommitFn commit_change) 00470 { 00471 OSyncObjTypeTemplate *template = NULL; 00472 00473 if (objtypestr) { 00474 OSyncObjTypeTemplate *template = osync_plugin_find_objtype_template(info->plugin, objtypestr); 00475 osync_assert_msg(template, "Unable to accept objformat. Did you forget to add the objtype?"); 00476 _osync_format_set_commit(template, formatstr, commit_change); 00477 } else { 00478 GList *o = NULL; 00479 for (o = info->plugin->accepted_objtypes; o; o = o->next) { 00480 template = o->data; 00481 _osync_format_set_commit(template, formatstr, commit_change); 00482 } 00483 } 00484 } 00485 00494 void osync_plugin_set_access_objformat(OSyncPluginInfo *info, const char *objtypestr, const char *formatstr, OSyncFormatAccessFn access) 00495 { 00496 OSyncObjTypeTemplate *template = NULL; 00497 00498 if (objtypestr) { 00499 //template = osync_plugin_find_objtype_template(info->plugin, objtypestr); 00500 //osync_assert_msg(template, "Unable to accept objformat. Did you forget to add the objtype?"); 00501 //_osync_format_set_access(template, formatstr, access); 00502 } else { 00503 GList *o = NULL; 00504 for (o = info->plugin->accepted_objtypes; o; o = o->next) { 00505 template = o->data; 00506 _osync_format_set_access(template, formatstr, access); 00507 } 00508 } 00509 } 00510 00519 void osync_plugin_set_read_objformat(OSyncPluginInfo *info, const char *objtypestr, const char *formatstr, OSyncFormatReadFn read) 00520 { 00521 OSyncObjTypeTemplate *template = osync_plugin_find_objtype_template(info->plugin, objtypestr); 00522 osync_assert_msg(template, "Unable to accept objformat. Did you forget to add the objtype?"); 00523 OSyncObjFormatTemplate *format_template = osync_plugin_find_objformat_template(template, formatstr); 00524 osync_assert_msg(format_template, "Unable to set commit function. Did you forget to add the objformat?"); 00525 format_template->read = read; 00526 } 00527 00536 void osync_plugin_set_batch_commit_objformat(OSyncPluginInfo *info, const char *objtypestr, const char *formatstr, OSyncFormatBatchCommitFn batch) 00537 { 00538 OSyncObjTypeTemplate *template = NULL; 00539 00540 if (objtypestr) { 00541 template = osync_plugin_find_objtype_template(info->plugin, objtypestr); 00542 osync_assert_msg(template, "Unable to accept objformat. Did you forget to add the objtype?"); 00543 _osync_format_set_batch(template, formatstr, batch); 00544 } else { 00545 GList *o = NULL; 00546 for (o = info->plugin->accepted_objtypes; o; o = o->next) { 00547 template = o->data; 00548 _osync_format_set_batch(template, formatstr, batch); 00549 } 00550 } 00551 } 00552 00561 void osync_plugin_set_committed_all_objformat(OSyncPluginInfo *info, const char *objtypestr, const char *formatstr, OSyncFormatCommittedAllFn committed_all) 00562 { 00563 OSyncObjTypeTemplate *template = osync_plugin_find_objtype_template(info->plugin, objtypestr); 00564 osync_assert_msg(template, "Unable to accept objformat. Did you forget to add the objtype?"); 00565 OSyncObjFormatTemplate *format_template = osync_plugin_find_objformat_template(template, formatstr); 00566 osync_assert_msg(format_template, "Unable to set committed_all function. Did you forget to add the objformat?"); 00567 format_template->committed_all = committed_all; 00568 } 00569 00579 void osync_plugin_accept_objtype(OSyncPluginInfo *info, const char *objtypestr) 00580 { 00581 OSyncObjTypeTemplate *template = g_malloc0(sizeof(OSyncObjTypeTemplate)); 00582 template->name = g_strdup(objtypestr); 00583 info->plugin->accepted_objtypes = g_list_append(info->plugin->accepted_objtypes, template); 00584 } 00585 00597 void osync_plugin_accept_objformat(OSyncPluginInfo *info, const char *objtypestr, const char *formatstr, const char *extension) 00598 { 00599 OSyncObjTypeTemplate *template = osync_plugin_find_objtype_template(info->plugin, objtypestr); 00600 osync_assert_msg(template, "Unable to accept objformat. Did you forget to add the objtype?"); 00601 OSyncObjFormatTemplate *format_template = g_malloc0(sizeof(OSyncObjFormatTemplate)); 00602 format_template->name = g_strdup(formatstr); 00603 if (extension) 00604 format_template->extension_name = g_strdup(extension); 00605 template->formats = g_list_append(template->formats, format_template); 00606 } 00607