00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "opensync.h"
00022 #include "opensync_internals.h"
00023
00031
00032 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00033 OSyncMemberFunctions *osync_memberfunctions_new()
00034 {
00035 OSyncMemberFunctions *functions = g_malloc0(sizeof(OSyncMemberFunctions));
00036 return functions;
00037 }
00038
00039 OSyncMemberFunctions *osync_member_get_memberfunctions(OSyncMember *member)
00040 {
00041 return member->memberfunctions;
00042 }
00043
00044 OSyncFormatEnv *osync_member_get_format_env(OSyncMember *member)
00045 {
00046 g_assert(member);
00047 return osync_group_get_format_env(member->group);
00048 }
00049
00054 OSyncObjTypeSink *osync_member_find_objtype_sink(OSyncMember *member, const char *objtypestr)
00055 {
00056 GList *o;
00057 for (o = member->objtype_sinks; o; o = o->next) {
00058 OSyncObjTypeSink *sink = o->data;
00059 if (osync_conv_objtype_is_any(sink->objtype->name) || !strcmp(sink->objtype->name, objtypestr))
00060 return sink;
00061 }
00062 return NULL;
00063 }
00064
00074 osync_bool osync_member_require_sink_info(OSyncMember *member, OSyncError **error)
00075 {
00076
00077
00078 if (!osync_member_instance_default_plugin(member, error))
00079 return FALSE;
00080
00081 return TRUE;
00082 }
00083
00092 osync_bool osync_member_get_objtype_sinks(OSyncMember *member, GList **list_ptr, OSyncError **error)
00093 {
00094 if (!osync_member_require_sink_info(member, error))
00095 return FALSE;
00096
00097 *list_ptr = member->objtype_sinks;
00098 return TRUE;
00099 }
00100
00120 osync_bool osync_member_read_config(OSyncMember *member, char **data, int *size, OSyncError **error)
00121 {
00122 osync_trace(TRACE_ENTRY, "osync_member_read_config(%p, %p, %p, %p)", member, data, size, error);
00123
00124 if (!osync_member_instance_default_plugin(member, error)) {
00125 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00126 return FALSE;
00127 }
00128
00129 OSyncPluginFunctions functions = member->plugin->info.functions;
00130 osync_bool ret = FALSE;
00131 if (!member->configdir) {
00132 osync_error_set(error, OSYNC_ERROR_GENERIC, "Member has no config directory set");
00133 osync_trace(TRACE_EXIT_ERROR, "osync_member_read_config: %i", osync_error_print(error));
00134 return FALSE;
00135 }
00136
00137 if (functions.get_config) {
00138 ret = functions.get_config(member->configdir, data, size);
00139 } else {
00140 char *filename = g_strdup_printf("%s/%s.conf", member->configdir, osync_plugin_get_name(member->plugin));
00141 ret = osync_file_read(filename, data, size, error);
00142 g_free(filename);
00143 }
00144
00145 if (ret)
00146 osync_trace(TRACE_EXIT, "osync_member_read_config: TRUE");
00147 else
00148 osync_trace(TRACE_EXIT_ERROR, "osync_member_read_config: %s", osync_error_print(error));
00149 return ret;
00150 }
00151
00152 #endif
00153
00163
00170 OSyncMember *osync_member_new(OSyncGroup *group)
00171 {
00172 OSyncMember *member = g_malloc0(sizeof(OSyncMember));
00173 if (group) {
00174 osync_group_add_member(group, member);
00175 member->group = group;
00176 }
00177
00178 member->memberfunctions = osync_memberfunctions_new();
00179 member->name = NULL;
00180
00181 return member;
00182 }
00183
00189 void osync_member_free(OSyncMember *member)
00190 {
00191 osync_assert_msg(member, "You must set a member to free");
00192
00193 if (member->group)
00194 osync_group_remove_member(member->group, member);
00195
00196
00197
00198
00199
00200
00201
00202 if (member->pluginname)
00203 g_free(member->pluginname);
00204
00205 g_free(member->memberfunctions);
00206 g_free(member);
00207 }
00208
00214 void osync_member_unload_plugin(OSyncMember *member)
00215 {
00216 g_assert(member);
00217 if (!member->plugin)
00218 return;
00219
00220
00221
00222
00223
00224
00225 g_list_free(member->objtype_sinks);
00226 g_list_free(member->format_sinks);
00227
00228
00229 member->objtype_sinks = NULL;
00230 member->format_sinks = NULL;
00231 member->plugin = NULL;
00232 }
00233
00242 osync_bool osync_member_instance_plugin(OSyncMember *member, const char *pluginname, OSyncError **error)
00243 {
00244 g_assert(member);
00245 g_assert(member->group);
00246 g_assert(pluginname);
00247
00248 OSyncPlugin *plugin = osync_env_find_plugin(member->group->env, pluginname);
00249 if (!plugin) {
00250 osync_debug("OSPLG", 0, "Couldn't find the plugin %s for member", pluginname);
00251 osync_error_set(error, OSYNC_ERROR_MISCONFIGURATION, "Unable to find the plugin \"%s\"", pluginname);
00252 return FALSE;
00253 }
00254
00255 osync_member_unload_plugin(member);
00256
00257
00258 member->plugin = plugin;
00259
00260
00261
00262
00263
00264
00265
00266 member->pluginname = g_strdup(osync_plugin_get_name(member->plugin));
00267
00268
00269 GList *o;
00270 for (o = member->plugin->accepted_objtypes; o; o = o->next) {
00271 OSyncObjTypeTemplate *objtemplate = o->data;
00272 OSyncObjTypeSink *objsink = osync_objtype_sink_from_template(member->group, objtemplate);
00273 if (!objsink) {
00274 osync_error_set(error, OSYNC_ERROR_GENERIC, "Could not find object type \"%s\"", objtemplate->name);
00275 return FALSE;
00276 }
00277 member->objtype_sinks = g_list_append(member->objtype_sinks, objsink);
00278 GList *f;
00279 for (f = objtemplate->formats; f; f = f->next) {
00280 OSyncObjFormatTemplate *frmtemplate = f->data;
00281 OSyncObjFormatSink *format_sink = osync_objformat_sink_from_template(member->group, frmtemplate);
00282 if (!format_sink) {
00283 osync_error_set(error, OSYNC_ERROR_GENERIC, "Could not find format \"%s\"", frmtemplate->name);
00284 return FALSE;
00285 }
00286 objsink->formatsinks = g_list_append(objsink->formatsinks, format_sink);
00287 format_sink->objtype_sink = objsink;
00288 member->format_sinks = g_list_append(member->format_sinks, format_sink);
00289 if (frmtemplate->extension_name)
00290 member->extension = g_strdup(frmtemplate->extension_name);
00291 }
00292 }
00293
00294 member->pluginname = g_strdup(pluginname);
00295 return TRUE;
00296 }
00297
00305 osync_bool osync_member_instance_default_plugin(OSyncMember *member, OSyncError **error)
00306 {
00307 if (member->plugin)
00308 return TRUE;
00309
00310 if (!member->pluginname) {
00311 osync_error_set(error, OSYNC_ERROR_GENERIC, "No default plugin set while instancing");
00312 return FALSE;
00313 }
00314
00315 return osync_member_instance_plugin(member, member->pluginname, error);
00316 }
00317
00324 OSyncPlugin *osync_member_get_plugin(OSyncMember *member)
00325 {
00326 g_assert(member);
00327 osync_member_instance_default_plugin(member, NULL);
00328 return member->plugin;
00329 }
00330
00337 const char *osync_member_get_pluginname(OSyncMember *member)
00338 {
00339 g_assert(member);
00340 return member->pluginname;
00341 }
00342
00349 void osync_member_set_pluginname(OSyncMember *member, const char *pluginname)
00350 {
00351 g_assert(member);
00352 if (member->pluginname)
00353 g_free(member->pluginname);
00354 member->pluginname = g_strdup(pluginname);
00355 }
00356
00367 void *osync_member_get_plugindata(OSyncMember *member)
00368 {
00369 g_assert(member);
00370 OSyncPlugin *plugin = osync_member_get_plugin(member);
00371 return osync_plugin_get_plugin_data(plugin);
00372 }
00373
00380 const char *osync_member_get_configdir(OSyncMember *member)
00381 {
00382 g_assert(member);
00383 return member->configdir;
00384 }
00385
00392 void osync_member_set_configdir(OSyncMember *member, const char *configdir)
00393 {
00394 g_assert(member);
00395 if (member->configdir)
00396 g_free(member->configdir);
00397 member->configdir = g_strdup(configdir);
00398 }
00399
00400 osync_bool osync_member_need_config(OSyncMember *member, OSyncConfigurationTypes *type, OSyncError **error)
00401 {
00402 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, member, type, error);
00403 g_assert(member);
00404 g_assert(type);
00405 *type = NO_CONFIGURATION;
00406
00407 if (!osync_member_instance_default_plugin(member, error))
00408 goto error;
00409
00410 *type = member->plugin->info.config_type;
00411
00412 osync_trace(TRACE_EXIT, "%s: %i", __func__, *type);
00413 return TRUE;
00414
00415 error:
00416 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00417 return FALSE;
00418 }
00419
00437 osync_bool osync_member_get_config_or_default(OSyncMember *member, char **data, int *size, OSyncError **error)
00438 {
00439 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, member, data, size, error);
00440 g_assert(member);
00441 osync_bool ret = TRUE;
00442
00443 if (member->configdata) {
00444 *data = member->configdata;
00445 *size = member->configsize;
00446 osync_trace(TRACE_EXIT, "%s: Configdata already in memory", __func__);
00447 return TRUE;
00448 }
00449
00450 if (!osync_member_read_config(member, data, size, error)) {
00451 if (osync_error_is_set(error)) {
00452 osync_trace(TRACE_INTERNAL, "Read config not successfull: %s", osync_error_print(error));
00453 osync_error_free(error);
00454 }
00455
00456 char *filename = g_strdup_printf(OPENSYNC_CONFIGDIR"/%s", member->pluginname);
00457 osync_debug("OSMEM", 3, "Reading default2 config file for member %lli from %s", member->id, filename);
00458 ret = osync_file_read(filename, data, size, error);
00459 g_free(filename);
00460 }
00461 osync_trace(TRACE_EXIT, "%s: %i", __func__, ret);
00462 return ret;
00463 }
00464
00483 osync_bool osync_member_get_config(OSyncMember *member, char **data, int *size, OSyncError **error)
00484 {
00485 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, member, data, size, error);
00486 g_assert(member);
00487 osync_bool ret = TRUE;
00488
00489 if (!osync_member_instance_default_plugin(member, error)) {
00490 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00491 return FALSE;
00492 }
00493
00494 if (member->plugin->info.config_type == NO_CONFIGURATION) {
00495 osync_error_set(error, OSYNC_ERROR_GENERIC, "This member has no configuration options");
00496 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00497 return FALSE;
00498 }
00499
00500 if (member->configdata) {
00501 *data = member->configdata;
00502 *size = member->configsize;
00503 osync_trace(TRACE_EXIT, "%s: Configdata already in memory", __func__);
00504 return TRUE;
00505 }
00506
00507 if (!osync_member_read_config(member, data, size, error)) {
00508 if (osync_error_is_set(error)) {
00509 osync_trace(TRACE_INTERNAL, "Read config not successfull: %s", osync_error_print(error));
00510 osync_error_free(error);
00511 }
00512
00513 if (member->plugin->info.config_type == NEEDS_CONFIGURATION) {
00514
00515 osync_error_set(error, OSYNC_ERROR_MISCONFIGURATION, "Member has not been configured");
00516 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00517 return FALSE;
00518 }
00519
00520 char *filename = g_strdup_printf(OPENSYNC_CONFIGDIR"/%s", member->pluginname);
00521 osync_debug("OSMEM", 3, "Reading default2 config file for member %lli from %s", member->id, filename);
00522 ret = osync_file_read(filename, data, size, error);
00523 g_free(filename);
00524 }
00525 osync_trace(TRACE_EXIT, "%s: %i", __func__, ret);
00526 return ret;
00527 }
00528
00538 void osync_member_set_config(OSyncMember *member, const char *data, int size)
00539 {
00540 osync_trace(TRACE_ENTRY, "%s(%p, %p, %i)", __func__, member, data, size);
00541 g_assert(member);
00542
00543 member->configdata = g_strdup(data);
00544 member->configsize = size;
00545
00546 osync_trace(TRACE_EXIT, "%s", __func__);
00547 }
00548
00555 void *osync_member_get_loop(OSyncMember *member)
00556 {
00557 g_assert(member);
00558 osync_trace(TRACE_INTERNAL, "%s: %p %p", __func__, member, member->loop);
00559 return member->loop;
00560 }
00561
00568 void osync_member_set_loop(OSyncMember *member, void *loop)
00569 {
00570 g_assert(member);
00571 osync_trace(TRACE_INTERNAL, "%s: %p %p", __func__, member, loop);
00572 member->loop = loop;
00573 }
00574
00575
00582 osync_bool osync_member_has_configuration(OSyncMember *member)
00583 {
00584 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, member);
00585 g_assert(member);
00586
00587 osync_bool ret = (member->plugin->info.config_type == NEEDS_CONFIGURATION || member->plugin->info.config_type == OPTIONAL_CONFIGURATION);
00588
00589 osync_trace(TRACE_EXIT, "%s: %i", __func__, ret);
00590 return ret;
00591 }
00592
00601 OSyncMember *osync_member_load(OSyncGroup *group, const char *path, OSyncError **error)
00602 {
00603 osync_trace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, group, path, error);
00604 xmlDocPtr doc;
00605 xmlNodePtr cur;
00606 char *filename = NULL;
00607
00608 filename = g_strdup_printf ("%s/syncmember.conf", path);
00609
00610 OSyncMember *member = osync_member_new(group);
00611 char *basename = g_path_get_basename(path);
00612 member->id = atoi(basename);
00613 g_free(basename);
00614 member->configdir = g_strdup(path);
00615
00616 if (!_osync_open_xml_file(&doc, &cur, filename, "syncmember", error)) {
00617 osync_member_free(member);
00618 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00619 return NULL;
00620 }
00621
00622 while (cur != NULL) {
00623 char *str = (char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
00624 if (str) {
00625 if (!xmlStrcmp(cur->name, (const xmlChar *)"pluginname"))
00626 member->pluginname = g_strdup(str);
00627 if (!xmlStrcmp(cur->name, (const xmlChar *)"name"))
00628 member->name = g_strdup(str);
00629 xmlFree(str);
00630 }
00631 cur = cur->next;
00632 }
00633 xmlFreeDoc(doc);
00634 g_free(filename);
00635
00636 osync_trace(TRACE_EXIT, "%s: Loaded member: %p", __func__, member);
00637 return member;
00638 }
00639
00647 osync_bool osync_member_save(OSyncMember *member, OSyncError **error)
00648 {
00649 osync_trace(TRACE_ENTRY, "%s(%p:(%lli), %p)", __func__, member, member ? member->id : 0, error);
00650 char *filename = NULL;
00651
00652 if (!osync_member_instance_default_plugin(member, error)) {
00653 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00654 return FALSE;
00655 }
00656
00657 if (!member->id) {
00658 member->id = osync_group_create_member_id(member->group);
00659 member->configdir = g_strdup_printf("%s/%lli", member->group->configdir, member->id);
00660 }
00661
00662 g_assert(member->configdir);
00663 if (!g_file_test(member->configdir, G_FILE_TEST_IS_DIR)) {
00664 osync_debug("OSMEM", 3, "Creating config directory: %s for member %i", member->configdir, member->id);
00665 if (mkdir(member->configdir, 0700)) {
00666 osync_error_set(error, OSYNC_ERROR_IO_ERROR, "Unable to create directory for member %li\n", member->id);
00667 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00668 return FALSE;
00669 }
00670 }
00671
00672
00673 filename = g_strdup_printf ("%s/syncmember.conf", member->configdir);
00674 xmlDocPtr doc;
00675 doc = xmlNewDoc((xmlChar*)"1.0");
00676 doc->children = xmlNewDocNode(doc, NULL, (xmlChar*)"syncmember", NULL);
00677
00678 xmlNewTextChild(doc->children, NULL, (xmlChar*)"pluginname", (xmlChar*)member->pluginname);
00679
00680 xmlNewTextChild(doc->children, NULL, (xmlChar*)"name", (xmlChar*)member->name);
00681 xmlSaveFile(filename, doc);
00682 xmlFreeDoc(doc);
00683 g_free(filename);
00684
00685
00686 osync_bool ret = TRUE;
00687 if (member->configdata) {
00688 OSyncPluginFunctions functions = member->plugin->info.functions;
00689
00690 if (functions.store_config) {
00691 ret = functions.store_config(member->configdir, member->configdata, member->configsize);
00692 } else {
00693 filename = g_strdup_printf("%s/%s.conf", member->configdir, osync_plugin_get_name(member->plugin));
00694 if (!osync_file_write(filename, member->configdata, member->configsize, 0600, error)) {
00695 ret = FALSE;
00696 }
00697 g_free(filename);
00698 }
00699 g_free(member->configdata);
00700 member->configdata = NULL;
00701 member->configsize = 0;
00702 }
00703
00704 osync_trace(TRACE_EXIT, "%s: %s", __func__, osync_error_print(error));
00705 return ret;
00706 }
00707
00714 long long int osync_member_get_id(OSyncMember *member)
00715 {
00716 g_assert(member);
00717 return member->id;
00718 }
00719
00731 void *osync_member_call_plugin(OSyncMember *member, const char *function, void *data, OSyncError **error)
00732 {
00733 if (!osync_member_instance_default_plugin(member, error))
00734 return FALSE;
00735
00736 void *(*plgfunc) (void *, void *, OSyncError **);
00737 if (!(plgfunc = osync_plugin_get_function(member->plugin, function, error)))
00738 return NULL;
00739 return plgfunc(member->plugindata, data, error);
00740 }
00741
00749 void osync_member_set_slow_sync(OSyncMember *member, const char *objtypestr, osync_bool slow_sync)
00750 {
00751 g_assert(member);
00752 OSyncGroup *group = osync_member_get_group(member);
00753 g_assert(group);
00754
00755 osync_group_set_slow_sync(group, objtypestr, slow_sync);
00756 }
00757
00765 osync_bool osync_member_get_slow_sync(OSyncMember *member, const char *objtypestr)
00766 {
00767 osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, member, objtypestr);
00768 g_assert(member);
00769 OSyncGroup *group = osync_member_get_group(member);
00770 g_assert(group);
00771
00772 osync_bool needs_slow_sync = osync_group_get_slow_sync(group, objtypestr);
00773
00774 osync_trace(TRACE_EXIT, "%s: %i", __func__, needs_slow_sync);
00775 return needs_slow_sync;
00776 }
00777
00783 void osync_member_request_synchronization(OSyncMember *member)
00784 {
00785 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, member);
00786 g_assert(member);
00787
00788 if (member->memberfunctions->rf_sync_alert)
00789 member->memberfunctions->rf_sync_alert(member);
00790 else {
00791 osync_trace(TRACE_EXIT_ERROR, "%s: Alert not handled", __func__);
00792 return;
00793 }
00794 osync_trace(TRACE_EXIT, "%s", __func__);
00795 }
00796
00797
00806 OSyncObjFormatSink *osync_member_make_random_data(OSyncMember *member, OSyncChange *change, const char *objtypename)
00807 {
00808 int retry = 0;
00809 g_assert(member);
00810 OSyncFormatEnv *env = osync_member_get_format_env(member);
00811
00812 OSyncObjFormatSink *format_sink = NULL;
00813
00814 for (retry = 0; retry < 100; retry++) {
00815 if (retry > 20) {
00816 osync_trace(TRACE_INTERNAL, "%s: Giving up", __func__);
00817 return NULL;
00818 }
00819
00820
00821 OSyncObjType *objtype = NULL;
00822 int selected = 0;
00823 if (!objtypename) {
00824 selected = g_random_int_range(0, g_list_length(env->objtypes));
00825 objtype = g_list_nth_data(env->objtypes, selected);
00826 } else
00827 objtype = osync_conv_find_objtype(member->group->conv_env, objtypename);
00828 osync_change_set_objtype(change, objtype);
00829
00830
00831 if (!g_list_length(objtype->formats)) {
00832 osync_trace(TRACE_INTERNAL, "%s: Next. No formats", __func__);
00833 continue;
00834 }
00835 OSyncObjFormat *format = NULL;
00836 selected = g_random_int_range(0, g_list_length(objtype->formats));
00837 format = g_list_nth_data(objtype->formats, selected);
00838
00839 if (!format->create_func) {
00840 osync_trace(TRACE_INTERNAL, "%s: Next. Format %s has no create function", __func__, format->name);
00841 continue;
00842 }
00843
00844 format->create_func(change);
00845
00846 osync_change_set_objformat(change, format);
00847
00848 OSyncObjTypeSink *objtype_sink = osync_member_find_objtype_sink(member, objtype->name);
00849 if (!objtype_sink) {
00850 osync_trace(TRACE_INTERNAL, "%s: Next. No objtype sink for %s", __func__, objtype->name);
00851 continue;
00852 }
00853
00854 selected = g_random_int_range(0, g_list_length(objtype_sink->formatsinks));
00855 format_sink = g_list_nth_data(objtype_sink->formatsinks, selected);
00856
00857 OSyncError *error = NULL;
00858 if (!osync_change_convert(env, change, format_sink->format, &error)) {
00859 osync_trace(TRACE_INTERNAL, "%s: Next. Unable to convert: %s", __func__, osync_error_print(&error));
00860 continue;
00861 }
00862
00863 break;
00864 }
00865 return format_sink;
00866 }
00867
00868
00875 void *osync_member_get_data(OSyncMember *member)
00876 {
00877 g_assert(member);
00878 return member->enginedata;
00879 }
00880
00887 void osync_member_set_data(OSyncMember *member, void *data)
00888 {
00889 g_assert(member);
00890 member->enginedata = data;
00891 }
00892
00899 OSyncGroup *osync_member_get_group(OSyncMember *member)
00900 {
00901 g_assert(member);
00902 return member->group;
00903 }
00904
00912 OSyncMember *osync_member_from_id(OSyncGroup *group, int id)
00913 {
00914 OSyncMember *member;
00915 int i;
00916 for (i = 0; i < osync_group_num_members(group); i++) {
00917 member = osync_group_nth_member(group, i);
00918 if (member->id == id) {
00919 return member;
00920 }
00921 }
00922 osync_debug("OSPLG", 0, "Couldnt find the member with the id %i", id);
00923 return NULL;
00924 }
00925
00926
00927
00935 osync_bool osync_member_objtype_enabled(OSyncMember *member, const char *objtype)
00936 {
00937 g_assert(member);
00938 OSyncObjTypeSink *sink = osync_member_find_objtype_sink(member, objtype);
00939 g_assert(sink);
00940 return sink->enabled;
00941 }
00942
00955 void osync_member_set_objtype_enabled(OSyncMember *member, const char *objtypestr, osync_bool enabled)
00956 {
00957 osync_trace(TRACE_ENTRY, "%s(%p, %s, %i)", __func__, member, objtypestr, enabled);
00958 OSyncObjTypeSink *sink = NULL;
00959 g_assert(member);
00960
00961 if (osync_conv_objtype_is_any(objtypestr)) {
00962 GList *o = NULL;
00963 for (o = member->objtype_sinks; o; o = o->next) {
00964 OSyncObjTypeSink *sink = o->data;
00965 sink->enabled = enabled;
00966 }
00967 } else {
00968 GList *o = NULL;
00969 for (o = member->objtype_sinks; o; o = o->next) {
00970 sink = o->data;
00971 if (!strcmp(sink->objtype->name, objtypestr))
00972 break;
00973 sink = NULL;
00974 }
00975
00976 if (!sink) {
00977 osync_trace(TRACE_EXIT_ERROR, "Unable to find sink with name \"%s\"", objtypestr);
00978 return;
00979 }
00980 sink->enabled = enabled;
00981 }
00982 osync_trace(TRACE_EXIT, "%s", __func__);
00983 }
00984
00994
01004 osync_bool osync_member_initialize(OSyncMember *member, OSyncError **error)
01005 {
01006 osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, member, error);
01007 if (!osync_member_instance_default_plugin(member, error)) {
01008 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
01009 return FALSE;
01010 }
01011
01012 g_assert(member);
01013 g_assert(member->plugin);
01014 OSyncPluginFunctions functions = member->plugin->info.functions;
01015 g_assert(functions.initialize);
01016 if (!(member->plugindata = functions.initialize(member, error))) {
01017 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
01018 return FALSE;
01019 }
01020
01021 osync_trace(TRACE_EXIT, "%s", __func__);
01022 return TRUE;
01023 }
01024
01032 void osync_member_finalize(OSyncMember *member)
01033 {
01034 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, member);
01035 g_assert(member);
01036 g_assert(member->plugin);
01037 OSyncPluginFunctions functions = member->plugin->info.functions;
01038 if (functions.finalize)
01039 functions.finalize(member->plugindata);
01040 osync_trace(TRACE_EXIT, "%s", __func__);
01041 }
01042
01052 void osync_member_get_changeinfo(OSyncMember *member, OSyncEngCallback function, void *user_data)
01053 {
01054 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, member, function, user_data);
01055 OSyncPluginFunctions functions = member->plugin->info.functions;
01056 OSyncContext *context = osync_context_new(member);
01057 context->callback_function = function;
01058 context->calldata = user_data;
01059 if (!functions.get_changeinfo) {
01060 osync_context_report_error(context, OSYNC_ERROR_GENERIC, "No get_changeinfo function was given");
01061 osync_trace(TRACE_EXIT_ERROR, "%s: No get_changeinfo function was given", __func__);
01062 return;
01063 }
01064 functions.get_changeinfo(context);
01065 osync_trace(TRACE_EXIT, "%s", __func__);
01066 }
01067
01078 void osync_member_read_change(OSyncMember *member, OSyncChange *change, OSyncEngCallback function, void *user_data)
01079 {
01080 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, member, change, function, user_data);
01081
01082 g_assert(change);
01083 g_assert(change->uid);
01084 g_assert(osync_change_get_objformat(change));
01085
01086 OSyncContext *context = osync_context_new(member);
01087 context->callback_function = function;
01088 context->calldata = user_data;
01089
01090
01091 GList *i;
01092 osync_debug("OSYNC", 2, "Searching for sink");
01093 for (i = member->format_sinks; i; i = i->next) {
01094 OSyncObjFormatSink *fmtsink = i->data;
01095
01096 if (fmtsink->format == osync_change_get_objformat(change)) {
01097
01098 g_assert(fmtsink->functions.read != NULL);
01099 fmtsink->functions.read(context, change);
01100 osync_trace(TRACE_EXIT, "%s", __func__);
01101 return;
01102 }
01103 }
01104
01105 osync_context_report_error(context, OSYNC_ERROR_CONVERT, "Unable to send changes");
01106 osync_trace(TRACE_EXIT_ERROR, "%s: Unable to find a sink", __func__);
01107 }
01108
01116 osync_bool osync_member_has_read_function(OSyncMember *member, OSyncObjType *objtype)
01117 {
01118 GList *i;
01119 for (i = member->format_sinks; i; i = i->next) {
01120 OSyncObjFormatSink *fmtsink = i->data;
01121
01122 if (osync_objformat_get_objtype(fmtsink->format) == objtype)
01123 return fmtsink->functions.read ? TRUE : FALSE;
01124 }
01125 return FALSE;
01126 }
01127
01138 void osync_member_get_change_data(OSyncMember *member, OSyncChange *change, OSyncEngCallback function, void *user_data)
01139 {
01140 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, member, change, function, user_data);
01141 OSyncPluginFunctions functions = member->plugin->info.functions;
01142 g_assert(change != NULL);
01143 OSyncContext *context = osync_context_new(member);
01144 context->callback_function = function;
01145 context->calldata = user_data;
01146 functions.get_data(context, change);
01147 osync_trace(TRACE_EXIT, "%s", __func__);
01148 }
01149
01159 void osync_member_connect(OSyncMember *member, OSyncEngCallback function, void *user_data)
01160 {
01161 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, member, function, user_data);
01162 OSyncPluginFunctions functions = member->plugin->info.functions;
01163 OSyncContext *context = osync_context_new(member);
01164 context->callback_function = function;
01165 context->calldata = user_data;
01166 if (!functions.connect) {
01167 osync_context_report_error(context, OSYNC_ERROR_GENERIC, "No connect function was given");
01168 osync_trace(TRACE_EXIT_ERROR, "%s: No connect function was given", __func__);
01169 return;
01170 }
01171 functions.connect(context);
01172 osync_trace(TRACE_EXIT, "%s", __func__);
01173 }
01174
01184 void osync_member_disconnect(OSyncMember *member, OSyncEngCallback function, void *user_data)
01185 {
01186 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, member, function, user_data);
01187 OSyncPluginFunctions functions = member->plugin->info.functions;
01188 OSyncContext *context = osync_context_new(member);
01189 context->callback_function = function;
01190 context->calldata = user_data;
01191 if (!functions.disconnect) {
01192 osync_context_report_error(context, OSYNC_ERROR_GENERIC, "No disconnect function was given");
01193 osync_trace(TRACE_EXIT_ERROR, "%s: No disconnect function was given", __func__);
01194 return;
01195 }
01196 functions.disconnect(context);
01197 osync_trace(TRACE_EXIT, "%s", __func__);
01198 }
01199
01209 void osync_member_sync_done(OSyncMember *member, OSyncEngCallback function, void *user_data)
01210 {
01211 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, member, function, user_data);
01212 OSyncPluginFunctions functions = member->plugin->info.functions;
01213 OSyncContext *context = osync_context_new(member);
01214 context->callback_function = function;
01215 context->calldata = user_data;
01216 osync_member_set_slow_sync(member, "data", FALSE);
01217 if (functions.sync_done) {
01218 functions.sync_done(context);
01219 } else {
01220 osync_context_report_success(context);
01221 }
01222 osync_trace(TRACE_EXIT, "%s", __func__);
01223 }
01224
01235 void osync_member_commit_change(OSyncMember *member, OSyncChange *change, OSyncEngCallback function, void *user_data)
01236 {
01237 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, member, change, function, user_data);
01238 g_assert(member);
01239 g_assert(change);
01240
01241 OSyncContext *context = osync_context_new(member);
01242 context->callback_function = function;
01243 context->calldata = user_data;
01244
01245
01246 OSyncObjType *type = osync_change_get_objtype(change);
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260 OSyncObjTypeSink *sink = osync_member_find_objtype_sink(member, type->name);
01261 if (sink && !sink->enabled) {
01262 osync_context_report_success(context);
01263 osync_trace(TRACE_EXIT, "%s: Sink not enabled", __func__);
01264 return;
01265 }
01266
01267
01268
01269
01270 change->destobjtype = g_strdup(osync_change_get_objtype(change)->name);
01271
01272
01273 if (!osync_filter_change_allowed(member, change)) {
01274 osync_context_report_success(context);
01275 osync_trace(TRACE_EXIT, "%s: Change filtered", __func__);
01276 return;
01277 }
01278
01279
01280
01281 GList *i;
01282 osync_debug("OSYNC", 2, "Searching for sink");
01283 for (i = member->format_sinks; i; i = i->next) {
01284 OSyncObjFormatSink *fmtsink = i->data;
01285
01286 osync_debug("OSYNC", 2, "Comparing change %s with sink %s", osync_change_get_objformat(change)->name, fmtsink->format ? fmtsink->format->name : "None");
01287 if (fmtsink->format == osync_change_get_objformat(change)) {
01288 if (fmtsink->functions.batch_commit) {
01289
01290 fmtsink->commit_changes = g_list_append(fmtsink->commit_changes, change);
01291 fmtsink->commit_contexts = g_list_append(fmtsink->commit_contexts, context);
01292 osync_trace(TRACE_EXIT, "%s: Waiting for batch processing", __func__);
01293 return;
01294 } else {
01295
01296 if (!fmtsink->functions.commit_change) {
01297 osync_context_report_error(context, OSYNC_ERROR_GENERIC, "No commit_change function was given");
01298 osync_trace(TRACE_EXIT_ERROR, "%s: No commit_change function was given", __func__);
01299 return;
01300 }
01301 fmtsink->functions.commit_change(context, change);
01302 osync_trace(TRACE_EXIT, "%s", __func__);
01303 return;
01304 }
01305 }
01306 }
01307
01308 osync_context_report_error(context, OSYNC_ERROR_CONVERT, "Unable to send changes");
01309 osync_trace(TRACE_EXIT_ERROR, "%s: Unable to find a sink", __func__);
01310 }
01311
01322 void osync_member_committed_all(OSyncMember *member, OSyncEngCallback function, void *user_data)
01323 {
01324 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, member);
01325 OSyncChange **changes = NULL;
01326 OSyncContext **contexts = NULL;
01327
01328 OSyncContext *context = osync_context_new(member);
01329 context->callback_function = function;
01330 context->calldata = user_data;
01331
01332 GList *pendingchanges = NULL;
01333 GList *pendingcontexts = NULL;
01334
01335 GList *f;
01336 for (f = member->format_sinks; f; f = f->next) {
01337 OSyncObjFormatSink *fmtsink = f->data;
01338 osync_debug("OSYNC", 2, "Sending changes to sink %p:%s", fmtsink, fmtsink->format ? fmtsink->format->name : "None");
01339
01340 OSyncFormatFunctions functions = fmtsink->functions;
01341
01342 if (functions.batch_commit) {
01343 pendingchanges = g_list_concat(pendingchanges, fmtsink->commit_changes);
01344 pendingcontexts = g_list_concat(pendingcontexts, fmtsink->commit_contexts);
01345
01346 fmtsink->commit_changes = NULL;
01347 fmtsink->commit_contexts = NULL;
01348 }
01349 }
01350
01351 f = member->format_sinks;
01352 if (f) {
01353 OSyncObjFormatSink *fmtsink = f->data;
01354 osync_debug("OSYNC", 2, "Sending committed all to sink %p:%s", fmtsink, fmtsink->format ? fmtsink->format->name : "None");
01355
01356 OSyncFormatFunctions functions = fmtsink->functions;
01357
01358 if (functions.batch_commit) {
01359 int i = 0;
01360 changes = g_malloc0(sizeof(OSyncChange *) * (g_list_length(pendingchanges) + 1));
01361 contexts = g_malloc0(sizeof(OSyncContext *) * (g_list_length(pendingcontexts) + 1));;
01362 GList *o = pendingcontexts;
01363 GList *c = NULL;
01364
01365 for (c = pendingchanges; c && o; c = c->next) {
01366 OSyncChange *change = c->data;
01367 OSyncContext *context = o->data;
01368
01369 changes[i] = change;
01370 contexts[i] = context;
01371
01372 i++;
01373 o = o->next;
01374 }
01375
01376 g_list_free(pendingchanges);
01377 g_list_free(pendingcontexts);
01378
01379 functions.batch_commit(context, contexts, changes);
01380
01381 g_free(changes);
01382 g_free(contexts);
01383 } else if (functions.committed_all) {
01384 functions.committed_all(context);
01385 } else {
01386 osync_context_report_success(context);
01387 }
01388 }
01389
01390 osync_trace(TRACE_EXIT, "%s", __func__);
01391 }
01392
01393 void osync_member_set_name(OSyncMember *member, const char *name)
01394 {
01395 g_assert(member);
01396 if (member->name)
01397 g_free(member->name);
01398 member->name = g_strdup(name);
01399 }
01400
01401 const char *osync_member_get_name(OSyncMember *member)
01402 {
01403 return member->name;
01404 }
01405
01416 OSyncChange *osync_member_add_random_data(OSyncMember *member, const char *objtype)
01417 {
01418 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, member);
01419 OSyncContext *context = osync_context_new(member);
01420 OSyncChange *change = osync_change_new();
01421 change->changetype = CHANGE_ADDED;
01422 OSyncObjFormatSink *format_sink;
01423 if (!(format_sink = osync_member_make_random_data(member, change, objtype))) {
01424 osync_trace(TRACE_EXIT_ERROR, "%s: Unable to make random data", __func__);
01425 return NULL;
01426 }
01427
01428 if (!format_sink->functions.access) {
01429 osync_trace(TRACE_EXIT_ERROR, "%s: No access function", __func__);
01430 return NULL;
01431 }
01432
01433 if (!format_sink->functions.access(context, change)) {
01434 osync_trace(TRACE_EXIT_ERROR, "%s: Unable to write change", __func__);
01435 return NULL;
01436 }
01437
01438 osync_trace(TRACE_EXIT, "%s: %p", __func__, change);
01439 return change;
01440 }
01441
01452 osync_bool osync_member_modify_random_data(OSyncMember *member, OSyncChange *change)
01453 {
01454 osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, member, change);
01455 OSyncContext *context = osync_context_new(member);
01456 change->changetype = CHANGE_MODIFIED;
01457 OSyncObjFormatSink *format_sink;
01458 char *uid = g_strdup(osync_change_get_uid(change));
01459
01460 if (!(format_sink = osync_member_make_random_data(member, change, osync_change_get_objtype(change)->name))) {
01461 osync_trace(TRACE_EXIT_ERROR, "%s: Unable to make random data", __func__);
01462 return FALSE;
01463 }
01464
01465 osync_change_set_uid(change, uid);
01466
01467 if (!format_sink->functions.access) {
01468 osync_trace(TRACE_EXIT_ERROR, "%s: No access function", __func__);
01469 return FALSE;
01470 }
01471
01472 if (!format_sink->functions.access(context, change)) {
01473 osync_trace(TRACE_EXIT_ERROR, "%s: Unable to modify change", __func__);
01474 return FALSE;
01475 }
01476
01477 osync_trace(TRACE_EXIT, "%s", __func__);
01478 return TRUE;
01479 }
01480
01491 osync_bool osync_member_delete_data(OSyncMember *member, OSyncChange *change)
01492 {
01493 osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, member, change);
01494 OSyncContext *context = osync_context_new(member);
01495 change->changetype = CHANGE_DELETED;
01496
01497 OSyncObjTypeSink *objtype_sink = osync_member_find_objtype_sink(member, osync_change_get_objtype(change)->name);
01498 if (!objtype_sink) {
01499 osync_trace(TRACE_EXIT_ERROR, "%s: Unable to find objsink for %s", __func__, osync_change_get_objtype(change)->name);
01500 return FALSE;
01501 }
01502
01503 OSyncObjFormat *format = osync_change_get_objformat(change);
01504 OSyncObjFormatSink *format_sink = osync_objtype_find_format_sink(objtype_sink, format->name);
01505 if (!format_sink) {
01506 osync_trace(TRACE_EXIT_ERROR, "%s: Unable to find format sink for %s", __func__, format->name);
01507 return FALSE;
01508 }
01509
01510 if (format_sink->functions.batch_commit) {
01511
01512 format_sink->commit_changes = g_list_append(format_sink->commit_changes, change);
01513 format_sink->commit_contexts = g_list_append(format_sink->commit_contexts, context);
01514 osync_trace(TRACE_EXIT, "%s: Waiting for batch processing", __func__);
01515 return TRUE;
01516 } else {
01517 if (!format_sink->functions.access) {
01518 osync_trace(TRACE_EXIT_ERROR, "%s: No access function", __func__);
01519 return FALSE;
01520 }
01521
01522 if (!format_sink->functions.access(context, change)) {
01523 osync_trace(TRACE_EXIT_ERROR, "%s: Unable to modify change", __func__);
01524 return FALSE;
01525 }
01526 }
01527
01528 osync_trace(TRACE_EXIT, "%s", __func__);
01529 return TRUE;
01530 }
01531
01536 void osync_member_write_sink_info(OSyncMember *member, OSyncMessage *message)
01537 {
01538 GList *obj = NULL;
01539 for (osync_member_get_objtype_sinks(member, &obj, NULL); obj; obj = obj->next) {
01540 OSyncObjTypeSink *sink = obj->data;
01541 int slow;
01542 slow = osync_member_get_slow_sync(member, sink->objtype->name);
01543 osync_message_write_string(message, sink->objtype->name);
01544 osync_message_write_int(message, sink->read);
01545 osync_message_write_int(message, sink->write);
01546 osync_message_write_int(message, sink->enabled);
01547 osync_message_write_int(message, slow);
01548 }
01549 osync_message_write_string(message, NULL);
01550 }
01551
01556 int __sync_member_read_sink_info(OSyncMember *member, OSyncMessage *message)
01557 {
01558 char *objtypestr;
01559 int r = 0;
01560 for (;;) {
01561 int read, write, enabled, slow;
01562 osync_message_read_string(message, &objtypestr);
01563 if (!objtypestr)
01564 break;
01565
01566 osync_message_read_int(message, &read);
01567 osync_message_read_int(message, &write);
01568 osync_message_read_int(message, &enabled);
01569 osync_message_read_int(message, &slow);
01570
01571 OSyncObjTypeSink *sink = osync_member_find_objtype_sink(member, objtypestr);
01572 if (!sink)
01573 continue;
01574
01575 sink->read = read;
01576 sink->write = write;
01577 sink->enabled = enabled;
01578
01579 if (slow) {
01580 osync_member_set_slow_sync(member, objtypestr, TRUE);
01581 r++;
01582 }
01583
01584 free(objtypestr);
01585 }
01586 return r;
01587 }
01588
01589
01603 void osync_member_read_sink_info_full(OSyncMember *member, OSyncMessage *message)
01604 {
01605 osync_group_reset_slow_sync(member->group, "data");
01606 __sync_member_read_sink_info(member, message);
01607 }
01608
01621 void osync_member_read_sink_info(OSyncMember *member, OSyncMessage *message)
01622 {
01623 int set_for_any;
01624
01625 set_for_any = __sync_member_read_sink_info(member, message);
01626
01627 if (set_for_any) {
01628
01629
01630
01631
01632
01633 osync_member_set_slow_sync(member, "data", TRUE);
01634 }
01635 }
01636