From: <dg...@su...> - 2009-01-29 23:37:52
|
Author: dgollub Date: Thu Jan 29 22:29:33 2009 New Revision: 5237 URL: http://www.opensync.org/changeset/5237 Log: Introduce support for determining "mixed objtypes". This commit addresses following problem: To create/initialize an OSyncObjEngine at least two member are required which share the same ObjType. With mixed-objtype this this would not work. Example: (objtype) Member 1: event Member 2: calendar The engine would fail in initializing since it would not found a pair of equal objtypes. This commit adds some logic to detect how many possible ObjEngine could be initialized, and would not restrict them to at least one. With the introduction with "dummy" OSyncSinkEngine, an OSyncObjEngine can be created also only with one membr which has "real" support of the ObjType. The detection of this "mixed objtype" is based on format-conversion. Format conversion allows allows in a very generic way to find relation between different objtypes, due to their different formats. All possible conversion pathes get created to determine if "event" and "calendar" can synced together. Modified: trunk/opensync/engine/opensync_engine.c trunk/opensync/group/opensync_group.c trunk/opensync/group/opensync_group_internals.h trunk/opensync/group/opensync_member.c trunk/opensync/group/opensync_member_internals.h Modified: trunk/opensync/engine/opensync_engine.c ============================================================================== --- trunk/opensync/engine/opensync_engine.c Tue Jan 27 18:47:04 2009 (r5236) +++ trunk/opensync/engine/opensync_engine.c Thu Jan 29 22:29:33 2009 (r5237) @@ -1540,7 +1540,8 @@ { osync_bool prev_sync_unclean = FALSE, first_sync = FALSE; OSyncGroup *group = NULL; - int i = 0, num = 0; + OSyncList *o, *supported_objtypes; + int i; osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, engine, error); if (engine->state != OSYNC_ENGINE_STATE_UNINITIALIZED) { @@ -1557,11 +1558,6 @@ goto error; } - if (osync_group_num_objtypes(engine->group) == 0) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "No synchronizable objtype"); - goto error; - } - /* Check if this is the first Synchronization. * On the first synchronization a Slow-Sync is required for all (ObjType)Sinks! */ @@ -1596,16 +1592,11 @@ if (!_osync_engine_initialize_member(engine, member, error)) goto error_finalize; } - - /* Lets see which objtypes are synchronizable in this group */ - num = osync_group_num_objtypes(engine->group); - if (num == 0) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "No synchronizable objtype"); - goto error; - } - for (i = 0; i < num; i++) { - const char *objtype = osync_group_nth_objtype(engine->group, i); + /* Lets see which objtypes are synchronizable in this group */ + supported_objtypes = osync_group_get_supported_objtypes_mixed(engine->group, engine->formatenv); + for (o = supported_objtypes; o; o = o->next) { + const char *objtype = o->data; OSyncObjEngine *objengine = NULL; /* Respect if the object type is disabled */ Modified: trunk/opensync/group/opensync_group.c ============================================================================== --- trunk/opensync/group/opensync_group.c Tue Jan 27 18:47:04 2009 (r5236) +++ trunk/opensync/group/opensync_group.c Thu Jan 29 22:29:33 2009 (r5237) @@ -157,6 +157,12 @@ } } +static void osync_group_build_mixed_list(gpointer key, gpointer value, gpointer user_data) +{ + OSyncList **l = user_data; + *l = osync_list_append(*l, key); +} + static GList *osync_group_get_supported_objtypes(OSyncGroup *group) { GList *m = NULL; @@ -186,6 +192,66 @@ return ret; } +OSyncList *osync_group_get_supported_objtypes_mixed(OSyncGroup *group, OSyncFormatEnv *formatenv) +{ + + GList *m; + OSyncList *ret = NULL; + OSyncList *t, *targetformats = osync_group_get_objformats(group); + + GHashTable *table = g_hash_table_new(g_str_hash, g_str_equal); + + + for (m=group->members; m; m = m->next) { + OSyncMember *member = m->data; + int i, num_member = osync_member_num_objtypes(member); + /* ... and get the objtype from each of the members. */ + for (i = 0; i < num_member; i++) { + const char *objtype = osync_member_nth_objtype(member, i); + osync_assert(objtype); + g_hash_table_replace(table, (char *)objtype, NULL); + } + + for (t=targetformats; t; t = t->next) { + const char *targetformat_name = t->data; + OSyncObjFormat *targetformat = osync_format_env_find_objformat(formatenv, targetformat_name); + const char *target_objtype = osync_objformat_get_objtype(targetformat); + + osync_assert(target_objtype); + + /* If targetformat is not supported, skip it */ + if (!osync_member_support_targetformat(member, formatenv, targetformat)) + continue; + + /* For each objtype, add 1 to the hashtable. */ + g_hash_table_replace(table, (char *)target_objtype, NULL); + + } + } + + g_hash_table_foreach(table, osync_group_build_mixed_list, &ret); + g_hash_table_destroy(table); + + return ret; +} + +OSyncList *osync_group_get_objformats(OSyncGroup *group) +{ + GList *m = NULL; + OSyncList *list = NULL; + + /* Loop over all members... */ + for (m = group->members; m; m = m->next) { + OSyncMember *member = m->data; + OSyncList *objformats = osync_member_get_all_objformats(member); + + list = osync_list_concat(list, objformats); + + } + + return list; +} + #ifdef OPENSYNC_UNITTESTS void osync_group_set_schemadir(OSyncGroup *group, const char *schemadir) Modified: trunk/opensync/group/opensync_group_internals.h ============================================================================== --- trunk/opensync/group/opensync_group_internals.h Tue Jan 27 18:47:04 2009 (r5236) +++ trunk/opensync/group/opensync_group_internals.h Thu Jan 29 22:29:33 2009 (r5237) @@ -109,6 +109,36 @@ */ OSYNC_TEST_EXPORT OSyncFilter *osync_group_nth_filter(OSyncGroup *group, int nth); +/** @brief Gets list of all supported object types in this group, including + * mixed object types + * + * So called "mixed object types" are object types which actually are able + * to be represeented in each other object type. + * + * An example could be: + * + * Object Format: vcalendar Object Type: calendar + * Object Format: vevent10 Object Type: event + * + * To detect "mixed object type" all potential conversion path get build. + * For this is a loaded OSyncFormatEnv required. + * + * @param group The group + * @param formatenv Pointer to loaded OSyncFormatEnv + * @returns List of supported object types, including mixed ones + * + */ +OSYNC_TEST_EXPORT OSyncList *osync_group_get_supported_objtypes_mixed(OSyncGroup *group, OSyncFormatEnv *formatenv); + +/** @brief Get list of all list of all used OSyncObjFormat elemets + * + * Very complex/expensive! + * + * @param group The group + * @returns The list of ObjFormat elements, or NULL + */ +OSYNC_TEST_EXPORT OSyncList *osync_group_get_objformats(OSyncGroup *group); + #ifdef OPENSYNC_UNITTESTS /** @brief Set the schemadir for configuration validation to a custom directory. * This is actually only inteded for UNITTESTS to run tests without Modified: trunk/opensync/group/opensync_member.c ============================================================================== --- trunk/opensync/group/opensync_member.c Tue Jan 27 18:47:04 2009 (r5236) +++ trunk/opensync/group/opensync_member.c Thu Jan 29 22:29:33 2009 (r5237) @@ -492,6 +492,7 @@ for (i = 0; i < osync_objtype_sink_num_objformat_sinks(sink); i++) { OSyncObjFormatSink *format_sink = osync_objtype_sink_nth_objformat_sink(sink, i); + osync_assert(format_sink); const char *format = osync_objformat_sink_get_objformat(format_sink); const char *format_config = osync_objformat_sink_get_config(format_sink); xmlNode *objformat_node = xmlNewChild(node, NULL, (xmlChar*)"objformat", NULL); @@ -665,6 +666,57 @@ return osync_objtype_sink_get_objformat_sinks(sink); } +OSyncList *osync_member_get_objformat_sinks_all(OSyncMember *member) +{ + GList *o; + OSyncList *list = NULL; + + for (o = member->objtypes; o; o = o->next) { + OSyncObjTypeSink *sink = o->data; + OSyncList *format_sinks = osync_objtype_sink_get_objformat_sinks(sink); + list = osync_list_concat(list, format_sinks); + } + + return list; +} + +osync_bool osync_member_support_targetformat(OSyncMember *member, OSyncFormatEnv *formatenv, OSyncObjFormat *targetformat) +{ + GList *o; + + for (o = member->objtypes; o; o = o->next) { + OSyncObjTypeSink *sink = o->data; + OSyncList *format_sinks = osync_objtype_sink_get_objformat_sinks(sink); + for (; format_sinks; format_sinks = format_sinks->next) { + OSyncObjFormatSink *format_sink = format_sinks->data; + const char *objformat_name = osync_objformat_sink_get_objformat(format_sink); + OSyncObjFormat *sourceformat = osync_format_env_find_objformat(formatenv, objformat_name); + + /** TODO error handling */ + if (osync_format_env_find_path(formatenv, sourceformat, targetformat, NULL)) + return TRUE; + } + } + + return FALSE; +} + +OSyncList *osync_member_get_all_objformats(OSyncMember *member) +{ + OSyncList *o, *format_sinks, *list = NULL; + + format_sinks = osync_member_get_objformat_sinks_all(member); + for (o = format_sinks; o; o = o->next) { + OSyncObjFormatSink *format_sink = o->data; + const char *objformat; + objformat = osync_objformat_sink_get_objformat(format_sink); + + list = osync_list_prepend(list, osync_strdup(objformat)); + } + + return list; +} + void osync_member_add_objtype_sink(OSyncMember *member, OSyncObjTypeSink *sink) { osync_assert(member); Modified: trunk/opensync/group/opensync_member_internals.h ============================================================================== --- trunk/opensync/group/opensync_member_internals.h Tue Jan 27 18:47:04 2009 (r5236) +++ trunk/opensync/group/opensync_member_internals.h Thu Jan 29 22:29:33 2009 (r5237) @@ -55,6 +55,36 @@ #endif /* OPENSYNC_UNITTESTS */ }; +/** @brief Get list of all OSyncObjFormatSink elements + * + * @param member Pointer to member + * @returns Pointer to OSyncList with element of OSyncObjformatSink, or NULL + * + */ +OSYNC_TEST_EXPORT OSyncList *osync_member_get_objformat_sinks_all(OSyncMember *member); + +/** @brief Get names of all object formats of this member + * + * @param member Pointer to member + * @returns Pointer to OSyncList with strings of object formats, or NULL + * + */ +OSYNC_TEST_EXPORT OSyncList *osync_member_get_all_objformats(OSyncMember *member); + +/** @brief Check if a member supports, with the help of various conversions, + * a specific format + * + * To determine if a target format is supported by this member, a loaded + * OSyncFormatEnv is required. + * + * @param member Pointer to member + * @param formatenv Pointer to a loaded OSyncFormatEnv for conversion path building + * @param targetformat The target format to test + * @returns TRUE if member supports with the given OSyncFormatEnv the targetformat, FALSE otherwise + * + */ +OSYNC_TEST_EXPORT osync_bool osync_member_support_targetformat(OSyncMember *member, OSyncFormatEnv *formatenv, OSyncObjFormat *targetformat); + #ifdef OPENSYNC_UNITTESTS /** @brief Set the schemadir for configuration validation to a custom directory. * This is actually only inteded for UNITTESTS to run tests without |