22 #include "engine_internals.h" 29 static OSyncMappingEntry *_osync_find_next_diff(OSyncMapping *mapping, OSyncMappingEntry *orig_entry)
32 for (e = mapping->entries; e; e = e->next) {
33 OSyncMappingEntry *entry = e->data;
43 static OSyncMappingEntry *_osync_find_next_same(OSyncMapping *mapping, OSyncMappingEntry *orig_entry)
46 for (e = mapping->entries; e; e = e->next) {
47 OSyncMappingEntry *entry = e->data;
57 static OSyncMappingEntry *_osync_change_clone(OSyncEngine *engine, OSyncMapping *new_mapping, OSyncMappingEntry *comp_entry)
59 OSyncMappingEntry *newentry = osengine_mappingentry_new(NULL);
61 newentry->client = comp_entry->client;
62 osengine_mapping_add_entry(new_mapping, newentry);
63 osengine_mappingview_add_entry(comp_entry->view, newentry);
64 osengine_mappingentry_update(newentry, comp_entry->change);
66 osync_flag_set(newentry->fl_has_data);
67 osync_flag_set(newentry->fl_mapped);
68 osync_flag_set(newentry->fl_has_info);
69 osync_flag_set(newentry->fl_dirty);
70 osync_flag_unset(newentry->fl_synced);
75 osync_bool osync_change_elevate(OSyncEngine *engine,
OSyncChange *change,
int level)
79 for (i = 0; i < level; i++) {
88 osync_bool osync_change_check_level(OSyncEngine *engine, OSyncMappingEntry *entry)
92 for (c = engine->clients; c; c = c->next) {
93 OSyncClient *client = c->data;
94 OSyncMappingView *view = osengine_mappingtable_find_view(engine->maptable, client->member);
95 if (!osengine_mappingview_uid_is_unique(view, entry, TRUE))
101 static int prod(
int n)
104 for (ret = 0; n > 0; n--)
109 void osengine_mapping_multiply_master(OSyncEngine *engine, OSyncMapping *mapping)
114 OSyncMappingTable *table = engine->maptable;
115 OSyncMappingEntry *entry = NULL;
116 OSyncMappingEntry *master = NULL;
118 master = mapping->master;
120 if (osync_flag_is_not_set(master->fl_dirty))
121 osync_flag_set(master->fl_synced);
123 osync_flag_attach(master->fl_committed, table->engine->cmb_committed_all);
127 for (v = table->views; v; v = v->next) {
128 OSyncMappingView *view = v->data;
130 entry = osengine_mapping_find_entry(mapping, NULL, view);
134 if (osync_flag_is_not_set(entry->fl_dirty))
135 osync_flag_set(entry->fl_synced);
139 entry = osengine_mappingentry_new(NULL);
141 entry->client = view->client;
142 osengine_mappingview_add_entry(view, entry);
143 osengine_mappingentry_update(entry, master->change);
146 osengine_mapping_add_entry(mapping, entry);
149 osengine_mappingentry_update(entry, master->change);
158 if (osync_flag_is_set(view->client->fl_sent_changes)) {
160 osync_flag_set(entry->fl_dirty);
161 osync_flag_set(entry->fl_has_data);
162 osync_flag_set(entry->fl_mapped);
163 osync_flag_set(entry->fl_has_info);
164 osync_flag_unset(entry->fl_synced);
167 osync_flag_attach(entry->fl_committed, table->engine->cmb_committed_all);
174 osync_flag_set(mapping->fl_multiplied);
180 void osengine_mapping_check_conflict(OSyncEngine *engine, OSyncMapping *mapping)
185 osync_bool is_conflict = FALSE;
187 OSyncMappingEntry *leftentry = NULL;
188 OSyncMappingEntry *rightentry = NULL;
190 g_assert(engine != NULL);
191 g_assert(mapping != NULL);
192 g_assert(!mapping->master);
194 for (e = mapping->entries; e; e = e->next) {
198 mapping->master = leftentry;
199 for (n = e->next; n; n = n->next) {
200 rightentry = n->data;
216 osync_debug(
"MAP", 2,
"Got conflict for mapping %p", mapping);
217 osync_status_conflict(engine, mapping);
218 osync_flag_set(mapping->fl_chkconflict);
222 g_assert(mapping->master);
223 osync_flag_set(mapping->fl_chkconflict);
226 osync_flag_set(mapping->fl_solved);
228 if (is_same == prod(g_list_length(engine->maptable->views) - 1)) {
230 osync_flag_set(mapping->cmb_synced);
231 osync_flag_set(mapping->fl_multiplied);
234 send_mapping_changed(engine, mapping);
238 static OSyncMapping *_osengine_mapping_find(OSyncMappingTable *table, OSyncMappingEntry *orig_entry)
242 osync_bool mapping_found = FALSE;
244 for (i = table->mappings; i; i = i->next) {
245 OSyncMapping *mapping = i->data;
247 if (!osengine_mapping_find_entry(mapping, NULL, orig_entry->view)) {
248 mapping_found = TRUE;
249 for (n = mapping->entries; n; n = n->next) {
250 OSyncMappingEntry *entry = n->data;
252 mapping_found = FALSE;
263 void osengine_change_map(OSyncEngine *engine, OSyncMappingEntry *entry)
266 OSyncMapping *mapping = NULL;
267 if (!(mapping = _osengine_mapping_find(engine->maptable, entry))) {
268 mapping = osengine_mapping_new(engine->maptable);
269 osync_flag_unset(mapping->fl_chkconflict);
270 osync_flag_unset(mapping->fl_multiplied);
271 mapping->id = osengine_mappingtable_get_next_id(engine->maptable);
274 osengine_mapping_add_entry(mapping, entry);
275 osync_flag_set(entry->fl_mapped);
299 g_assert(dupe_mapping);
301 OSyncMappingEntry *orig_entry = NULL;
302 OSyncMappingEntry *first_diff_entry = NULL;
303 OSyncMappingEntry *next_entry = NULL;
304 OSyncMapping *new_mapping = NULL;
308 entries = g_list_copy(dupe_mapping->entries);
309 for (e = entries; e; e = e->next) {
310 OSyncMappingEntry *entry = e->data;
313 osengine_mappingentry_free(entry);
316 g_list_free(entries);
319 GList *i = dupe_mapping->entries;
321 orig_entry = i->data;
324 dupe_mapping->master = orig_entry;
333 while ((first_diff_entry = _osync_find_next_diff(dupe_mapping, orig_entry))) {
336 new_mapping = osengine_mapping_new(engine->maptable);
337 new_mapping->id = osengine_mappingtable_get_next_id(engine->maptable);
338 osync_flag_unset(new_mapping->cmb_synced);
339 osync_flag_set(new_mapping->fl_chkconflict);
340 osync_flag_unset(new_mapping->fl_multiplied);
341 osync_flag_set(new_mapping->fl_solved);
342 send_mapping_changed(engine, new_mapping);
343 osync_debug(
"MAP", 3,
"Created new mapping for duplication %p with mappingid %lli", new_mapping, new_mapping->id);
347 OSyncMappingEntry *newentry = osengine_mappingentry_copy(first_diff_entry);
348 new_mapping->master = newentry;
349 osengine_mapping_add_entry(new_mapping, newentry);
351 osync_flag_set(newentry->fl_has_data);
352 osync_flag_set(newentry->fl_mapped);
353 osync_flag_set(newentry->fl_has_info);
354 osync_flag_set(newentry->fl_dirty);
355 osync_flag_unset(newentry->fl_synced);
361 if (!osync_change_elevate(engine, newentry->change, 1))
364 }
while (!osync_change_check_level(engine, newentry));
371 while ((next_entry = _osync_find_next_same(dupe_mapping, first_diff_entry))) {
372 newentry = _osync_change_clone(engine, new_mapping, first_diff_entry);
373 osync_change_elevate(engine, newentry->change, elevation);
374 osengine_mappingentry_update(orig_entry, next_entry->change);
383 send_mapping_changed(engine, new_mapping);
387 osync_flag_set(dupe_mapping->fl_solved);
388 send_mapping_changed(engine, dupe_mapping);
404 OSyncMappingEntry *entry = osengine_mapping_find_entry(mapping, change, NULL);
405 mapping->master = entry;
406 osync_flag_set(mapping->fl_solved);
407 send_mapping_changed(engine, mapping);
425 osync_error_set(error, OSYNC_ERROR_GENERIC,
"Ignore is not supported for this mapping");
431 for (e = mapping->entries; e; e = e->next) {
432 OSyncMappingEntry *entry = e->data;
441 osync_flag_set(mapping->fl_multiplied);
442 osync_flag_set(mapping->cmb_synced);
443 osync_flag_set(mapping->cmb_has_info);
470 count = osengine_mapping_num_changes(mapping);
471 for (i = 0; i < count; ++i) {
472 change = osengine_mapping_nth_change(mapping, i);
504 time_t latesttime = 0;
505 osync_bool preveq = FALSE;
508 for (e = mapping->entries; e; e = e->next) {
509 OSyncMappingEntry *entry = e->data;
515 mapping->master = NULL;
519 if (time > latesttime) {
521 mapping->master = entry;
523 }
else if (time == latesttime)
528 if (preveq == TRUE) {
529 osync_error_set(error, OSYNC_ERROR_GENERIC,
"Could not decide for one entry. Timestamps where equal");
530 mapping->master = NULL;
535 osync_flag_set(mapping->fl_solved);
536 send_mapping_changed(engine, mapping);
559 time_t latesttime = 0;
560 osync_bool preveq = FALSE;
563 for (e = mapping->entries; e; e = e->next) {
564 OSyncMappingEntry *entry = e->data;
573 if (time > latesttime) {
576 }
else if (time == latesttime)
581 if (preveq == TRUE) {
582 osync_error_set(error, OSYNC_ERROR_GENERIC,
"Could not decide for one entry. Timestamps where equal");
604 OSyncMappingEntry *entry = osengine_mapping_find_entry(mapping, change, NULL);
605 mapping->master = entry;
607 osync_flag_set(entry->fl_dirty);
608 osync_flag_unset(entry->fl_synced);
609 send_mappingentry_changed(engine, entry);
611 osync_flag_set(mapping->fl_solved);
612 send_mapping_changed(engine, mapping);
OSyncChangeType osync_change_get_changetype(OSyncChange *change)
Gets the changetype of a change.
osync_bool osync_change_duplicate(OSyncChange *change)
Duplicates the uid of the change.
void osengine_mapping_solve_updated(OSyncEngine *engine, OSyncMapping *mapping, OSyncChange *change)
Solves a mapping by setting an updated change.
osync_bool osengine_mapping_ignore_conflict(OSyncEngine *engine, OSyncMapping *mapping, OSyncError **error)
Ignores a conflict.
osync_bool osync_member_get_slow_sync(OSyncMember *member, const char *objtypestr)
Returns if slow-sync has been set for a object type.
void osync_change_set_uid(OSyncChange *change, const char *uid)
Sets the uid of a change.
osync_bool osync_member_has_read_function(OSyncMember *member, OSyncObjType *objtype)
Checks if the member has a read method for the given objtype.
OSyncChange * osync_change_new(void)
Spawns a new change object.
osync_bool osync_group_save_changelog(OSyncGroup *group, OSyncChange *change, OSyncError **error)
Saves a change to the changelog.
const char * osync_change_get_uid(OSyncChange *change)
Gets the uid of a change.
osync_bool osync_change_has_data(OSyncChange *change)
Returns wether the complete data already has been set.
A member of a group which represent a single device.
void osengine_mapping_duplicate(OSyncEngine *engine, OSyncMapping *dupe_mapping)
Solves the conflict by duplicating the conflicting entries.
void osync_change_set_changetype(OSyncChange *change, OSyncChangeType type)
Sets the changetype of a change.
osync_bool osengine_mapping_solve_latest(OSyncEngine *engine, OSyncMapping *mapping, OSyncError **error)
Solves a mapping by choosing the entry that was last modified.
void osync_debug(const char *subpart, int level, const char *message,...)
Used for debugging.
osync_bool osengine_mapping_ignore_supported(OSyncEngine *engine, OSyncMapping *mapping)
Checks if a conflict can be ignore.
OSyncMember * osync_change_get_member(OSyncChange *change)
Gets the member which reported a change.
time_t osync_change_get_revision(OSyncChange *change, OSyncError **error)
Returns the revision of the object.
void osync_change_set_member(OSyncChange *change, OSyncMember *member)
Sets the member of a change.
osync_bool osengine_mapping_check_timestamps(OSyncEngine *engine, OSyncMapping *mapping, OSyncError **error)
Checks if the mapping could be solved with solve_latest.
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_trace(OSyncTraceType type, const char *message,...)
Used for tracing the application.
void osengine_mapping_solve(OSyncEngine *engine, OSyncMapping *mapping, OSyncChange *change)
Solves the mapping by choosing a winner.
const char * osync_objtype_get_name(OSyncObjType *type)
Returns the name of a object type.
OSyncObjType * osync_change_get_objtype(OSyncChange *change)
Gets the object type of a change.
Represent a abstract object type (like "contact")
osync_bool osync_change_delete(OSyncChange *change, OSyncError **error)
This will delete a change from the database.
OSyncConvCmpResult osync_change_compare(OSyncChange *leftchange, OSyncChange *rightchange)
Compares 2 changes.
OSyncConvCmpResult osync_change_compare_data(OSyncChange *leftchange, OSyncChange *rightchange)
Compares the data of 2 changes.
osync_bool osync_change_save(OSyncChange *change, osync_bool save_format, OSyncError **error)
This will save a change into the database.