22 #include "opensync_internals.h" 29 #ifndef DOXYGEN_SHOULD_SKIP_THIS 30 typedef struct conv_tree {
40 typedef struct vertice {
49 osync_bool free_change_data;
50 osync_bool free_change;
63 unsigned objtype_changes;
71 GList *element = NULL;
72 for (element = env->
converters; element; element = element->next) {
74 if (fmt_src == converter->source_format && fmt_trg == converter->target_format)
83 osync_trace(
TRACE_INTERNAL,
"converter: Type: %i, source: %s, target %s", converter->type, converter->source_format->name, converter->target_format->name);
86 osync_bool ret = TRUE;
87 if (converter->type == CONVERTER_DETECTOR && !converter->convert_func) {
88 change->
format = converter->target_format;
94 if (!converter->convert_func) {
103 osync_bool free_input = FALSE;
104 if ((ret = converter->convert_func(converter_data, change->
data, change->
size, &data, &datasize, &free_input, error))) {
106 if (converter->type == CONVERTER_DECAP) {
109 if (!converter->target_format->copy_func) {
113 osync_debug(
"OSYNC", 0,
"Format %s don't have a copy function, but a no-copy converter was registered", converter->target_format->name);
114 osync_error_set(error, OSYNC_ERROR_GENERIC,
"Format %s don't have a copy function, but a no-copy converter was registered", converter->target_format->name);
118 converter->target_format->copy_func(data, datasize, &data, &datasize);
123 if (converter->source_format->destroy_func) {
124 converter->source_format->destroy_func(change->
data, change->
size);
126 osync_debug(
"OSYNC", 1,
"Format %s don't have a destroy function. Possible memory leak", converter->source_format->name);
129 change->
size = datasize;
136 osync_debug(
"OSYNC", 3,
"Converting! replacing format %s with %s", converter->source_format->name, converter->target_format->name);
137 change->
format = converter->target_format;
149 *free_output = FALSE;
151 if (!converter->convert_func) {
156 if (converter->type != CONVERTER_DECAP) {
167 if (!converter->convert_func(NULL, change->
data, change->
size, &(new_change->
data), &(new_change->
size), free_output, &error)) {
174 osync_debug(
"OSYNC", 3,
"Converting! replacing format %s with %s", converter->source_format->name, converter->target_format->name);
175 new_change->
format = converter->target_format;
191 const vertice *va = a;
192 const vertice *vb = b;
193 if (va->losses < vb->losses)
195 else if (va->losses > vb->losses)
197 else if (va->objtype_changes < vb->objtype_changes)
199 else if (va->objtype_changes > vb->objtype_changes)
201 else if (va->conversions < vb->conversions)
203 else if (va->conversions > vb->conversions)
217 static void deref_vertice(vertice *vertice)
223 if (--vertice->references > 0)
226 g_list_free(vertice->path);
227 if (vertice->change && vertice->free_change) {
228 if (vertice->free_change_data)
244 osync_trace(
TRACE_ENTRY,
"get_next_vertice_neighbour(%p, %p, %p:%s)", env, tree, ve, ve->format ? ve->format->name :
"None");
246 for (c = tree->unused; c; c = c->next) {
251 if (strcmp(converter->source_format->name, ve->format->name))
255 if (converter->detect_func) {
258 "We would call a converter to %s, but there is no change data on vertice", fmt_target->name);
263 if (!converter->detect_func(env, ve->change->data, ve->change->size)) {
264 osync_trace(
TRACE_INTERNAL,
"Invoked detector for converter from %s to %s: FALSE", converter->source_format->name, converter->target_format->name);
269 osync_trace(
TRACE_INTERNAL,
"Invoked detector for converter from %s to %s: TRUE", converter->source_format->name, converter->target_format->name);
273 osync_bool free_output = TRUE;
274 if (converter->type == CONVERTER_DECAP) {
276 osync_trace(
TRACE_INTERNAL,
"A desencapsulator to %s would be called, but we can't because the data on this vertice wasn't converted", fmt_target->name);
280 if (!(new_change = osync_converter_invoke_decap(converter, ve->change, &free_output)))
289 tree->unused = g_list_remove(tree->unused, converter);
292 vertice *neigh = g_malloc0(
sizeof(vertice));
294 neigh->references = 1;
295 neigh->format = fmt_target;
296 neigh->path = g_list_copy(ve->path);
297 neigh->path = g_list_append(neigh->path, converter);
300 neigh->change = new_change;
301 neigh->free_change = TRUE;
302 neigh->free_change_data = free_output;
304 neigh->change = NULL;
305 neigh->free_change = FALSE;
306 neigh->free_change_data = FALSE;
310 neigh->conversions = ve->conversions + 1;
311 neigh->losses = ve->losses;
312 if (converter->type == CONVERTER_DECAP)
314 neigh->objtype_changes = ve->objtype_changes;
315 if (converter->source_format->objtype != converter->target_format->objtype)
316 neigh->objtype_changes++;
318 osync_trace(
TRACE_EXIT,
"get_next_vertice_neighbour: %p:%s", neigh, neigh->format ? neigh->format->name :
"None");
348 static osync_bool osync_conv_find_path_fn(
OSyncFormatEnv *env,
OSyncChange *start, OSyncPathTargetFn target_fn,
const void *fndata, GList **path_edges)
350 osync_trace(
TRACE_ENTRY,
"osync_conv_find_path_fn(%p, %p(%s, %s), %p, %p, %p)", env, start, start ? start->
uid :
"None", start ? start->
format->name :
"None", target_fn, fndata, path_edges);
355 osync_bool ret = FALSE;
356 vertice *result = NULL;
362 conv_tree *tree = g_malloc0(
sizeof(conv_tree));
367 vertice *begin = g_malloc0(
sizeof(vertice));
368 begin->format = start->
format;
370 begin->references = 1;
371 begin->change = start;
372 begin->free_change_data = FALSE;
373 begin->free_change = FALSE;
375 tree->search = g_list_append(NULL, begin);
377 while (g_list_length(tree->search)) {
378 vertice *neighbour = NULL;
381 vertice *current = tree->search->data;
382 tree->search = g_list_remove(tree->search, current);
384 osync_debug(
"OSCONV", 4,
"Next vertice: %s.", current->format->name);
386 if (target_fn(fndata, current->format)) {
391 osync_debug(
"OSCONV", 4,
"Looking at %s's neighbours.", current->format->name);
393 osync_debug(
"OSCONV", 4,
"%s's neighbour: %s", current->format->name, neighbour->format->name);
397 deref_vertice(current);
400 g_list_foreach(tree->search, (GFunc)deref_vertice, NULL);
404 *path_edges = g_list_copy(result->path);
406 deref_vertice(result);
412 g_list_free(tree->unused);
413 g_list_free(tree->search);
422 osync_bool osync_conv_convert_fn(
OSyncFormatEnv *env,
OSyncChange *change, OSyncPathTargetFn target_fn,
const void *fndata,
const char *extension_name,
OSyncError **error)
424 osync_trace(
TRACE_ENTRY,
"osync_conv_convert_fn(%p, %p, %p, %p, %p)", env, change, target_fn, fndata, error);
428 osync_assert_msg(source,
"Cannot convert! change has no objformat!");
430 osync_bool ret = TRUE;
433 if (target_fn(fndata, source)) {
452 if (!osync_conv_find_path_fn(env, change, target_fn, fndata, &path)) {
453 osync_error_set(error, OSYNC_ERROR_GENERIC,
"Unable to find a conversion path to the format requested");
460 change->
format = converter->target_format;
463 for (; path; path = path->next) {
469 void *converter_data = NULL;
470 if (converter->init_func)
471 converter_data = converter->init_func();
473 if (extension_name) {
480 extension->init_func(converter_data);
489 osync_trace(
TRACE_INTERNAL,
"%p:%p %p:%p", extension->from_format, converter->source_format, extension->to_format, converter->target_format);
490 if (extension->from_format == converter->source_format && extension->to_format == converter->target_format)
491 extension->init_func(converter_data);
495 if (!osync_converter_invoke(converter, change, converter_data, error)) {
501 if (converter->fin_func)
502 converter->fin_func(converter_data);
519 static osync_bool target_fn_fmtlist(
const void *data,
OSyncObjFormat *fmt)
521 const GList *l = data;
523 for (i = l; i; i = i->next) {
525 if (!strcmp(fmt->name, f->name))
536 return osync_conv_convert_fn(env, change, target_fn_fmtlist, targets, NULL, NULL);
541 return osync_conv_find_path_fn(env, start, target_fn_fmtlist, targets, retlist);
544 osync_bool osync_conv_objtype_is_any(
const char *objstr)
546 if (!strcmp(objstr,
"data"))
577 for (o = env->objtype_templates; o; o = o->next) {
578 OSyncObjTypeTemplate *otempl = o->data;
580 type->name = g_strdup(otempl->name);
581 type->env = conv_env;
587 for (f = env->format_templates; f; f = f->next) {
588 OSyncObjFormatTemplate *ftempl = f->data;
592 format->env = conv_env;
593 format->name = g_strdup(ftempl->name);
594 format->objtype = type;
596 format->cmp_func = ftempl->cmp_func;
597 format->merge_func = ftempl->merge_func;
598 format->duplicate_func = ftempl->duplicate_func;
599 format->copy_func = ftempl->copy_func;
600 format->create_func = ftempl->create_func;
601 format->destroy_func = ftempl->destroy_func;
602 format->print_func = ftempl->print_func;
603 format->revision_func = ftempl->revision_func;
604 format->marshall_func = ftempl->marshall_func;
605 format->demarshall_func = ftempl->demarshall_func;
606 type->formats = g_list_append(type->formats, format);
612 for (i = env->extension_templates; i; i = i->next) {
613 OSyncFormatExtensionTemplate *extension_template = i->data;
616 if (!from_format || !to_format)
620 extension->name = g_strdup(extension_template->name);
621 extension->init_func = extension_template->init_func;
622 extension->from_format = from_format;
623 extension->to_format = to_format;
629 for (i = env->converter_templates; i; i = i->next) {
630 OSyncConverterTemplate *convtmpl = i->data;
636 if (!fmt_src || !fmt_trg)
639 converter->source_format = fmt_src;
640 converter->target_format = fmt_trg;
641 converter->convert_func = convtmpl->convert_func;
642 converter->type = convtmpl->type;
643 converter->init_func = convtmpl->init_func;
649 for (i = env->data_detectors; i; i = i->next) {
655 if (!fmt_src || !fmt_trg)
658 converter->source_format = fmt_src;
659 converter->target_format = fmt_trg;
660 converter->type = CONVERTER_DETECTOR;
662 converter->detect_func = detector->detect_func;
707 osync_error_set(error, OSYNC_ERROR_GENERIC,
"Unable to set a common format: Unable to find the object-type \"%s\"", objtypestr);
712 osync_error_set(error, OSYNC_ERROR_GENERIC,
"Unable to set a common format: Unable to find the format \"%s\"", formatname);
715 type->common_format = format;
731 GList *element = NULL;
732 for (element = env->
objtypes; element; element = element->next) {
734 if (!strcmp(type->name, name))
737 osync_debug(
"CONV", 1,
"Unable to find the requested objtype \"%s\"", name);
750 return g_list_length(env->
objtypes);
763 return g_list_nth_data(env->
objtypes, nth);
778 GList *element = NULL;
779 for (element = env->
objformats; element; element = element->next) {
781 if (!strcmp(format->name, name))
796 return g_list_length(type->formats);
809 return g_list_nth_data(type->formats, nth);
823 g_assert(sourcename);
824 g_assert(targetname);
833 return osync_conv_find_converter_objformat(env, fmt_src, fmt_trg);
848 g_assert(extension_name);
853 osync_trace(
TRACE_INTERNAL,
"comparing format %p:%p %p:%p name %s:%s", extension->from_format, from_format, extension->to_format, to_format, extension->name, extension_name);
854 if ((extension->from_format == from_format || !from_format) && (extension->to_format == to_format || !to_format) && !strcmp(extension->name, extension_name))
893 return format->objtype;
void osync_change_free(OSyncChange *change)
Frees a change.
int osync_conv_num_objtypes(OSyncFormatEnv *env)
Returns the number of available object types.
OSyncObjType * osync_objformat_get_objtype(OSyncObjFormat *format)
Returns the object type of a format.
void osync_change_free_data(OSyncChange *change)
Frees the data of a change.
OSyncObjFormat * osync_conv_find_objformat(OSyncFormatEnv *env, const char *name)
Finds the object format with the given name.
OSyncFormatConverter * osync_conv_find_converter(OSyncFormatEnv *env, const char *sourcename, const char *targetname)
Finds the converter with the given source and target format.
int compare_vertice_distance(const void *a, const void *b)
vertice * get_next_vertice_neighbour(OSyncFormatEnv *env, conv_tree *tree, vertice *ve)
OSyncFormatExtension * osync_conv_find_extension(OSyncFormatEnv *env, OSyncObjFormat *from_format, OSyncObjFormat *to_format, const char *extension_name)
Finds the extension that will be invoked when going from the given source to the target format with t...
An extension to a format.
OSyncChange * osync_change_new(void)
Spawns a new change object.
int osync_conv_num_objformats(OSyncObjType *type)
Returns the number of available object formats.
void osync_error_free(OSyncError **error)
Frees the error so it can be reused.
OSyncObjFormat * osync_change_get_objformat(OSyncChange *change)
Gets the object format of a change.
osync_bool osync_conv_convert_fmtlist(OSyncFormatEnv *env, OSyncChange *change, GList *targets)
OSyncObjType * osync_conv_find_objtype(OSyncFormatEnv *env, const char *name)
Finds the object type with the given name.
void osync_debug(const char *subpart, int level, const char *message,...)
Used for debugging.
const char * osync_objformat_get_name(OSyncObjFormat *format)
Returns the name of a object format.
OSyncObjType * osync_conv_nth_objtype(OSyncFormatEnv *env, int nth)
Gets the nth object type.
OSyncObjFormat * osync_conv_nth_objformat(OSyncObjType *type, int nth)
Gets the nth object format.
OSyncFormatEnv * osync_conv_env_new(OSyncEnv *env)
This will create a new opensync format environment.
void osync_error_set(OSyncError **error, OSyncErrorType type, const char *format,...)
Sets the error.
const char * osync_error_print(OSyncError **error)
Returns the message of the error.
void osync_conv_env_free(OSyncFormatEnv *env)
Frees a osync format environment.
void osync_trace(OSyncTraceType type, const char *message,...)
Used for tracing the application.
Represent a detector for a given format.
const char * osync_objtype_get_name(OSyncObjType *type)
Returns the name of a object type.
osync_bool osync_conv_set_common_format(OSyncFormatEnv *env, const char *objtypestr, const char *formatname, OSyncError **error)
Sets the common format for a object type.
Represent a abstract object type (like "contact")
OSyncChangeType changetype