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 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 /* Found */ 00036 return TRUE; 00037 } 00038 00039 /* Not found */ 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 /* Not found */ 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 /* Make sure that its null terminated */ 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 //Run all datadetectors for our source type 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 //Try to decap the change as far as possible 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