Ticket #1170 (closed defect: fixed)

Opened 2 years ago

Last modified 2 years ago

Error in _osync_obj_engine_mapping_find

Reported by: henrik Owned by: dgollub
Priority: high Milestone: OpenSync 0.40
Component: OpenSync Version: 0.39
Severity: blocker Keywords:
Cc:

Description

When slow-syncing two identical members, _osync_obj_engine_mapping_find does not work correctly.

For the first member, osync_obj_engine_map_changes correctly creates new mappings.

However, for the second member, _osync_obj_engine_mapping_find seems to compare changes from second member to changes from second member, where it should compare to changes from first member.

Unfortunately r5869 did not solve the problem.

I believe the attached patch solves the problem.

Any comments? Can I commit the patch?

Index: opensync_obj_engine.c
===================================================================
--- opensync_obj_engine.c	(revision 5870)
+++ opensync_obj_engine.c	(working copy)
@@ -311,14 +311,14 @@
 			osync_trace(TRACE_INTERNAL, "Member1-caps: %p Member2-caps: %p", caps1, caps2);
 
 			if (caps1) {
-				clone_change1 = _osync_obj_engine_clone_and_demerge_change(sinkengine->engine, caps1, change2, error);
+				clone_change1 = _osync_obj_engine_clone_and_demerge_change(sinkengine->engine, caps1, change1, error);
 				if (!clone_change1)
 					goto error;
 
 			}
 
 			if (caps2) {
-				clone_change2 = _osync_obj_engine_clone_and_demerge_change(sinkengine->engine, caps2, change1, error);
+				clone_change2 = _osync_obj_engine_clone_and_demerge_change(sinkengine->engine, caps2, change2, error);
 				if (!clone_change2)
 					goto error;

Attachments

opensync_obj_engine.patch Download (852 bytes) - added by henrik 2 years ago.

Change History

Changed 2 years ago by henrik

comment:1 Changed 2 years ago by dgollub

  • Status changed from new to assigned

No actually this "mixup" of change1 with change2 is intended.

The _osync_obj_engine_clone_and_demerge_change() creates a copy/clone of the give change. And then demerges the unsupported fields with the given capabilities. It makes only sense to run the demerge with the capabilities of "other" member. Why?

Why demerge with the other capabilities before compare?

Example: Group with 2 Members

  • Member 1 - capabilities: {{{

E-Mail Name Telephone }}}

  • Member 2 - capabilities: {{{

Name Telephone }}}

This is now the first sync and both members commit one single entry/change which is "logical" the same contact ... but unfortuantely not 1:1 the same, due to the missing capability "E-Mail".

  • Member 1 - (UID:) Change1 {{{

EMAIL:gollub@b1 N:Daniel TEL:555 }}}

  • Member 2 - (UID:) Change2 {{{

N:Daniel Tel:555 }}}

Without demerging the unsupported capabilities (e.g. EMAIL) the compare would result in SIMILAR and not SAME. Since we have the capabilities information we can modify the entries to have more "successful" comparison results, which result in SAME. So what we do here is we demerge all fields/capabilities which are not supported by the opponent member:

  • Demerge all fields of change1 (from Member1) which aren't part of Member2's capabilities
    • e.g. demerge/remove EMAIL
  • Demerge all fields of change2 (from Member2) which aren't part of Member1's capabilities
    • e.g. ... in this example nothing todo no unsupported fields for member1 caps

Note: not the original change get modifiy, a copy/clone.

This modified clone_changes get compared:

clone_change1: {{{ N:Daniel TEL:555 }}}

clone_change2: {{{ N:Daniel TEL:555 }}}

This clone_changes get used for the osync_change_compare call which should result in SAME changes, and a successful mapping, without conflict.

This only works if we really used caps2 for change1 and caps2 for change1 when demerging ..

Your patch would remove this essential detail .. in fact this is a very important detail which is lacking a very detailed description in the source code as comment ...

I hope i can use this ticket as reference and add later some brief description.

Could you provide trace files of the actual error - or a step by step testcase instruction to reproduce the problem?

comment:2 Changed 2 years ago by henrik

Thanks for the explanation. But I still think the code is wrong (and my patch wrong as well).

Original code:

clone_change1 = _osync_obj_engine_clone_and_demerge_change(sinkengine->engine, caps1, change2, error);

This clones *second* member changes with *first* member caps (fine), but calls it a clone of the *first* member (which it is not). Maybe this is the solution:

clone_change1 = _osync_obj_engine_clone_and_demerge_change(sinkengine->engine, caps2, change1, error);

comment:3 Changed 2 years ago by henrik

The following patch seems to work:

Index: opensync/engine/opensync_obj_engine.c
===================================================================
--- opensync/engine/opensync_obj_engine.c	(revision 5870)
+++ opensync/engine/opensync_obj_engine.c	(working copy)
@@ -310,15 +310,15 @@
 
 			osync_trace(TRACE_INTERNAL, "Member1-caps: %p Member2-caps: %p", caps1, caps2);
 
-			if (caps1) {
-				clone_change1 = _osync_obj_engine_clone_and_demerge_change(sinkengine->engine, caps1, change2, error);
+			if (caps2) {
+				clone_change1 = _osync_obj_engine_clone_and_demerge_change(sinkengine->engine, caps2, change1, error);
 				if (!clone_change1)
 					goto error;
 
 			}
 
-			if (caps2) {
-				clone_change2 = _osync_obj_engine_clone_and_demerge_change(sinkengine->engine, caps2, change1, error);
+			if (caps1) {
+				clone_change2 = _osync_obj_engine_clone_and_demerge_change(sinkengine->engine, caps1, change2, error);
 				if (!clone_change2)
 					goto error;
 
@@ -333,10 +333,10 @@
 
 			tmp_result = osync_change_compare(change1, change2, error);
 
-			if (caps1)
+			if (caps2)
 				osync_change_unref(clone_change1);
 
-			if (caps2)
+			if (caps1)
 				osync_change_unref(clone_change2);
 
 			if(tmp_result == OSYNC_CONV_DATA_SAME) {

At least it now compares one side to the other!

(I am not able to test in depth, due to bug 1173)

comment:4 Changed 2 years ago by dgollub

Ok, looks good. Please commit.

comment:5 Changed 2 years ago by henrik

  • Status changed from assigned to closed
  • Resolution set to fixed

(In [5874]) Correct cloning of mapping change in _osync_obj_engine_mapping_find. Fixes ticket 1170

Note: See TracTickets for help on using tickets.