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
00024
00029 static osync_bool target_fn_fmtnames(const void *data, OSyncObjFormat *fmt)
00030 {
00031 const char * const *list = data;
00032 const char * const *i;
00033 for (i = list; *i; i++) {
00034 if (!strcmp(fmt->name, *i))
00035
00036 return TRUE;
00037 }
00038
00039
00040 return FALSE;
00041 }
00042
00047 static osync_bool target_fn_simple(const void *data, OSyncObjFormat *fmt)
00048 {
00049 const OSyncObjFormat *target = data;
00050 return target == fmt;
00051 }
00052
00057 static osync_bool target_fn_fmtname(const void *data, OSyncObjFormat *fmt)
00058 {
00059 const char *name = data;
00060 return !strcmp(name, fmt->name);
00061 }
00062
00067 static osync_bool target_fn_membersink(const void *data, OSyncObjFormat *fmt)
00068 {
00069 const OSyncMember *memb = data;
00070 GList *i;
00071 for (i = memb->format_sinks; i; i = i->next) {
00072 OSyncObjFormatSink *sink = i->data;
00073 if (sink->format == fmt)
00074 return TRUE;
00075 }
00076
00077
00078 return FALSE;
00079 }
00080
00087
00097 char *osync_change_get_printable(OSyncChange *change)
00098 {
00099 g_assert(change);
00100 if (!change->has_data)
00101 return NULL;
00102
00103 OSyncObjFormat *format = osync_change_get_objformat(change);
00104 g_assert(format);
00105
00106 if (!format->print_func)
00107 return g_strndup(change->data, change->size);
00108
00109 return format->print_func(change);
00110 }
00111
00119 time_t osync_change_get_revision(OSyncChange *change, OSyncError **error)
00120 {
00121 osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, change, error);
00122
00123 g_assert(change);
00124 if (!change->has_data) {
00125 osync_error_set(error, OSYNC_ERROR_GENERIC, "No data set when asking for the timestamp");
00126 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00127 return -1;
00128 }
00129
00130 OSyncObjFormat *format = osync_change_get_objformat(change);
00131 g_assert(format);
00132
00133 if (!format->revision_func) {
00134 osync_error_set(error, OSYNC_ERROR_GENERIC, "No revision function set");
00135 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00136 return -1;
00137 }
00138
00139 time_t time = format->revision_func(change, error);
00140
00141 osync_trace(osync_error_is_set(error) ? TRACE_EXIT_ERROR : TRACE_EXIT, "%s: %s, %i", __func__, osync_error_print(error), time);
00142 return time;
00143 }
00144
00157 OSyncConvCmpResult osync_change_compare_data(OSyncChange *leftchange, OSyncChange *rightchange)
00158 {
00159 osync_trace(TRACE_ENTRY, "osync_change_compare_data(%p, %p)", leftchange, rightchange);
00160
00161 g_assert(rightchange);
00162 g_assert(leftchange);
00163
00164 OSyncError *error = NULL;
00165 if (!osync_change_convert_to_common(leftchange, &error)) {
00166 osync_trace(TRACE_INTERNAL, "osync_change_compare_data: %s", osync_error_print(&error));
00167 osync_error_free(&error);
00168 osync_trace(TRACE_EXIT, "osync_change_compare_data: MISMATCH: Could not convert leftchange to common format");
00169 return CONV_DATA_MISMATCH;
00170 }
00171 if (!osync_change_convert_to_common(rightchange, &error)) {
00172 osync_trace(TRACE_INTERNAL, "osync_change_compare_data: %s", osync_error_print(&error));
00173 osync_error_free(&error);
00174 osync_trace(TRACE_EXIT, "osync_change_compare_data: MISMATCH: Could not convert rightchange to common format");
00175 return CONV_DATA_MISMATCH;
00176 }
00177
00178 if (!(rightchange->data == leftchange->data)) {
00179 if (!(osync_change_get_objtype(leftchange) == osync_change_get_objtype(rightchange))) {
00180 osync_trace(TRACE_EXIT, "osync_change_compare_data: MISMATCH: Objtypes do not match");
00181 return CONV_DATA_MISMATCH;
00182 }
00183 if (leftchange->format != rightchange->format) {
00184 osync_trace(TRACE_EXIT, "osync_change_compare_data: MISMATCH: Objformats do not match");
00185 return CONV_DATA_MISMATCH;
00186 }
00187 if (!rightchange->data || !leftchange->data) {
00188 osync_trace(TRACE_EXIT, "osync_change_compare_data: MISMATCH: One change has no data");
00189 return CONV_DATA_MISMATCH;
00190 }
00191 OSyncObjFormat *format = osync_change_get_objformat(leftchange);
00192 g_assert(format);
00193
00194 OSyncConvCmpResult ret = format->cmp_func(leftchange, rightchange);
00195 osync_trace(TRACE_EXIT, "osync_change_compare_data: %i", ret);
00196 return ret;
00197 } else {
00198 osync_trace(TRACE_EXIT, "osync_change_compare_data: SAME: OK. data point to same memory");
00199 return CONV_DATA_SAME;
00200 }
00201 }
00202
00217 OSyncConvCmpResult osync_change_compare(OSyncChange *leftchange, OSyncChange *rightchange)
00218 {
00219 osync_trace(TRACE_ENTRY, "osync_change_compare(%p, %p)", leftchange, rightchange);
00220
00221 g_assert(rightchange);
00222 g_assert(leftchange);
00223
00224 OSyncError *error = NULL;
00225 if (!osync_change_convert_to_common(leftchange, &error)) {
00226 osync_trace(TRACE_INTERNAL, "osync_change_compare: %s", osync_error_print(&error));
00227 osync_error_free(&error);
00228 osync_trace(TRACE_EXIT, "osync_change_compare: MISMATCH: Could not convert leftchange to common format");
00229 return CONV_DATA_MISMATCH;
00230 }
00231 if (!osync_change_convert_to_common(rightchange, &error)) {
00232 osync_trace(TRACE_INTERNAL, "osync_change_compare: %s", osync_error_print(&error));
00233 osync_error_free(&error);
00234 osync_trace(TRACE_EXIT, "osync_change_compare: MISMATCH: Could not convert leftchange to common format");
00235 return CONV_DATA_MISMATCH;
00236 }
00237
00238 if (rightchange->changetype == leftchange->changetype) {
00239 OSyncConvCmpResult ret = osync_change_compare_data(leftchange, rightchange);
00240 osync_trace(TRACE_EXIT, "osync_change_compare: Compare data: %i", ret);
00241 return ret;
00242 } else {
00243 osync_trace(TRACE_EXIT, "osync_change_compare: MISMATCH: Change types do not match");
00244 return CONV_DATA_MISMATCH;
00245 }
00246 }
00247
00256 osync_bool osync_change_copy_data(OSyncChange *source, OSyncChange *target, OSyncError **error)
00257 {
00258 osync_trace(TRACE_ENTRY, "osync_change_copy_data(%p, %p, %p)", source, target, error);
00259
00260 OSyncObjFormat *format = NULL;
00261 format = source->format;
00262 if (!format)
00263 format = target->format;
00264
00265 if (target->data)
00266 osync_change_free_data(target);
00267
00268 if (!source->data) {
00269 target->data = NULL;
00270 target->size = 0;
00271 osync_trace(TRACE_EXIT, "%s: Source had not data", __func__);
00272 return TRUE;
00273 }
00274
00275 if (!format || !format->copy_func) {
00276 osync_trace(TRACE_INTERNAL, "We cannot copy the change, falling back to memcpy");
00277 target->data = g_malloc0(sizeof(char) * (source->size + 1));
00278 memcpy(target->data, source->data, source->size);
00279
00280
00281 target->data[source->size] = 0;
00282 target->size = source->size;
00283 } else {
00284 if (!format->copy_func(source->data, source->size, &(target->data), &(target->size))) {
00285 osync_error_set(error, OSYNC_ERROR_GENERIC, "Something went wrong during copying");
00286 osync_trace(TRACE_EXIT_ERROR, "osync_change_copy_data: %s", osync_error_print(error));
00287 return FALSE;
00288 }
00289 }
00290
00291 osync_trace(TRACE_EXIT, "osync_change_copy_data");
00292 return TRUE;
00293 }
00294
00302 OSyncChange *osync_change_copy(OSyncChange *source, OSyncError **error)
00303 {
00304 osync_trace(TRACE_ENTRY, "osync_change_copy(%p, %p)", source, error);
00305 g_assert(source);
00306
00307 OSyncChange *newchange = osync_change_new();
00308 newchange->uid = g_strdup(source->uid);
00309 newchange->hash = g_strdup(source->hash);
00310
00311 newchange->has_data = source->has_data;
00312 newchange->changetype = source->changetype;
00313 newchange->format = osync_change_get_objformat(source);
00314 newchange->objtype = osync_change_get_objtype(source);
00315 newchange->sourceobjtype = g_strdup(osync_change_get_objtype(source)->name);
00316 newchange->changes_db = source->changes_db;
00317 newchange->member = source->member;
00318
00319 if (!osync_change_copy_data(source, newchange, error)) {
00320 osync_change_free(newchange);
00321 osync_trace(TRACE_EXIT_ERROR, "osync_change_copy: %s", osync_error_print(error));
00322 return NULL;
00323 }
00324
00325 osync_trace(TRACE_EXIT, "osync_change_copy: %p", newchange);
00326 return newchange;
00327 }
00328
00338 osync_bool osync_change_duplicate(OSyncChange *change)
00339 {
00340 g_assert(change);
00341 OSyncObjFormat *format = osync_change_get_objformat(change);
00342 osync_debug("OSCONV", 3, "Duplicating change %s with format %s\n", change->uid, format->name);
00343 if (!format || !format->duplicate_func)
00344 return FALSE;
00345 format->duplicate_func(change);
00346 return TRUE;
00347 }
00348
00363 osync_bool osync_change_convert_extension(OSyncFormatEnv *env, OSyncChange *change, OSyncObjFormat *targetformat, const char *extension_name, OSyncError **error)
00364 {
00365 osync_trace(TRACE_ENTRY, "osync_change_convert(%p, %p, %p:%s, %s, %p)", env, change, targetformat, targetformat ? targetformat->name : "NONE", extension_name, error);
00366 if (osync_conv_convert_fn(env, change, target_fn_simple, targetformat, extension_name, error)) {
00367 osync_trace(TRACE_EXIT, "osync_change_convert: TRUE");
00368 return TRUE;
00369 } else {
00370 osync_trace(TRACE_EXIT_ERROR, "osync_change_convert: %s", osync_error_print(error));
00371 return FALSE;
00372 }
00373 }
00374
00387 osync_bool osync_change_convert(OSyncFormatEnv *env, OSyncChange *change, OSyncObjFormat *targetformat, OSyncError **error)
00388 {
00389 return osync_change_convert_extension(env, change, targetformat, NULL, error);
00390 }
00391
00399 osync_bool osync_change_convert_to_common(OSyncChange *change, OSyncError **error)
00400 {
00401 osync_trace(TRACE_ENTRY, "osync_change_convert_to_common(%p, %p)", change, error);
00402
00403 if (!osync_change_get_objtype(change)) {
00404 osync_error_set(error, OSYNC_ERROR_GENERIC, "The change has no objtype");
00405 osync_trace(TRACE_EXIT_ERROR, "osync_change_convert_to_common: %s", osync_error_print(error));
00406 return FALSE;
00407 }
00408 OSyncFormatEnv *env = osync_change_get_objtype(change)->env;
00409
00410 if (!osync_change_get_objtype(change)->common_format) {
00411 osync_trace(TRACE_EXIT, "osync_change_convert_to_common: No common format set");
00412 return TRUE;
00413 }
00414
00415 osync_trace(TRACE_INTERNAL, "Converting from %s to %s", osync_change_get_objformat(change)->name, osync_change_get_objtype(change)->common_format->name);
00416
00417 if (osync_change_convert(env, change, osync_change_get_objtype(change)->common_format, error)) {
00418 osync_trace(TRACE_EXIT, "osync_change_convert_to_common: TRUE");
00419 return TRUE;
00420 } else {
00421 osync_trace(TRACE_EXIT_ERROR, "osync_change_convert_to_common: %s", osync_error_print(error));
00422 return FALSE;
00423 }
00424 }
00425
00438 osync_bool osync_change_convert_fmtname(OSyncFormatEnv *env, OSyncChange *change, const char *targetname, OSyncError **error)
00439 {
00440 return osync_conv_convert_fn(env, change, target_fn_fmtname, targetname, NULL, error);
00441 }
00442
00455 osync_bool osync_change_convert_fmtnames(OSyncFormatEnv *env, OSyncChange *change, const char **targetnames, OSyncError **error)
00456 {
00457 return osync_conv_convert_fn(env, change, target_fn_fmtnames, targetnames, NULL, error);
00458 }
00459
00470 osync_bool osync_change_convert_member_sink(OSyncFormatEnv *env, OSyncChange *change, OSyncMember *member, OSyncError **error)
00471 {
00472 if (!osync_member_require_sink_info(member, error))
00473 return FALSE;
00474
00475 return osync_conv_convert_fn(env, change, target_fn_membersink, member, member->extension, error);
00476 }
00477
00489 OSyncObjType *osync_change_detect_objtype(OSyncFormatEnv *env, OSyncChange *change, OSyncError **error)
00490 {
00491 OSyncObjFormat *format = NULL;
00492 if (!(format = osync_change_detect_objformat(env, change, error)))
00493 return NULL;
00494 return format->objtype;
00495 }
00496
00509 OSyncObjType *osync_change_detect_objtype_full(OSyncFormatEnv *env, OSyncChange *change, OSyncError **error)
00510 {
00511 OSyncObjFormat *format = NULL;
00512 if (!(format = osync_change_detect_objformat_full(env, change, error)))
00513 return NULL;
00514 return format->objtype;
00515 }
00516
00528 OSyncObjFormat *osync_change_detect_objformat(OSyncFormatEnv *env, OSyncChange *change, OSyncError **error)
00529 {
00530 osync_trace(TRACE_ENTRY, "osync_change_detect_objformat(%p, %p, %p)", env, change, error);
00531 if (!change->has_data) {
00532 osync_error_set(error, OSYNC_ERROR_GENERIC, "The change has no data");
00533 osync_trace(TRACE_EXIT_ERROR, "osync_change_detect_objformat: %s", osync_error_print(error));
00534 return NULL;
00535 }
00536
00537
00538 GList *d = NULL;
00539 for (d = env->converters; d; d = d->next) {
00540 OSyncFormatConverter *converter = d->data;
00541 osync_trace(TRACE_INTERNAL, "running detector %s for format %s\n", converter->source_format->name, osync_change_get_objformat(change)->name);
00542 if (!strcmp(converter->source_format->name, osync_change_get_objformat(change)->name)) {
00543 if (converter->detect_func && converter->detect_func(env, change->data, change->size)) {
00544 osync_trace(TRACE_EXIT, "osync_change_detect_objformat: %p:%s", converter->target_format, converter->target_format->name);
00545 return converter->target_format;
00546 }
00547 }
00548 }
00549
00550 osync_error_set(error, OSYNC_ERROR_GENERIC, "None of the detectors was able to recognize this data");
00551 osync_trace(TRACE_EXIT_ERROR, "osync_change_detect_objformat: %s", osync_error_print(error));
00552 return NULL;
00553 }
00554
00567 OSyncObjFormat *osync_change_detect_objformat_full(OSyncFormatEnv *env, OSyncChange *change, OSyncError **error)
00568 {
00569 osync_trace(TRACE_ENTRY, "osync_change_detect_objformat_full(%p, %p, %p)", env, change, error);
00570 if (!change->has_data) {
00571 osync_error_set(error, OSYNC_ERROR_GENERIC, "The change has no data");
00572 osync_trace(TRACE_EXIT_ERROR, "osync_change_detect_objformat: %s", osync_error_print(error));
00573 return NULL;
00574 }
00575 OSyncChange *new_change = change;
00576
00577
00578 while (1) {
00579 GList *d = NULL;
00580 for (d = env->converters; d; d = d->next) {
00581 OSyncFormatConverter *converter = d->data;
00582 if (!strcmp(converter->source_format->name, osync_change_get_objformat(change)->name) && converter->type == CONVERTER_DECAP) {
00583 osync_bool free_output = FALSE;
00584 if (!(new_change = osync_converter_invoke_decap(converter, new_change, &free_output))) {
00585 osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to decap the change");
00586 osync_trace(TRACE_EXIT_ERROR, "osync_change_detect_objformat_full: %s", osync_error_print(error));
00587 return NULL;
00588 }
00589 continue;
00590 }
00591 }
00592 break;
00593 }
00594
00595 OSyncObjFormat *ret = osync_change_detect_objformat(env, new_change, error);
00596 if (!ret)
00597 osync_trace(TRACE_EXIT_ERROR, "osync_change_detect_objformat_full: %s", osync_error_print(error));
00598 else
00599 osync_trace(TRACE_EXIT, "osync_change_detect_objformat_full: %p:%s", ret, ret->name);
00600 return ret;
00601 }
00602