• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

opensync/opensync_changecmds.c

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 

Generated on Fri Sep 17 2010 for OpenSync by  doxygen 1.7.1