OpenSync  0.22
osengine_mapping.c
1 /*
2  * libopensync - A synchronization framework
3  * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  */
20 
21 #include "engine.h"
22 #include "engine_internals.h"
23 
31 
32 #ifndef DOXYGEN_SHOULD_SKIP_THIS
33 OSyncMappingTable *osengine_mappingtable_new(OSyncEngine *engine)
34 {
35  osync_trace(TRACE_ENTRY, "osengine_mappingtable_new(%p)", engine);
36  OSyncMappingTable *table = g_malloc0(sizeof(OSyncMappingTable));
37  table->engine = engine;
38  table->group = engine->group;
39 
40  GList *c;
41  for (c = engine->clients; c; c = c->next) {
42  OSyncClient *client = c->data;
43  osengine_mappingview_new(table, client);
44  }
45 
46  osync_trace(TRACE_EXIT, "osengine_mappingtable_new: %p", table);
47  return table;
48 }
49 
50 void osengine_mappingtable_reset(OSyncMappingTable *table)
51 {
52  GList *v;
53  for (v = table->views; v; v = v->next) {
54  OSyncMappingView *view = v->data;
55  osengine_mappingview_reset(view);
56  }
57 }
58 
59 void osengine_mappingtable_free(OSyncMappingTable *table)
60 {
61  osync_trace(TRACE_ENTRY, "osengine_mappingtable_free(%p)", table);
62  GList *c = NULL;
63  GList *m = NULL;
64 
65  GList *mappings = g_list_copy(table->mappings);
66  GList *unmapped = g_list_copy(table->unmapped);
67  GList *views = g_list_copy(table->views);
68  osync_trace(TRACE_INTERNAL, "Free mappings");
69  for (m = mappings; m; m = m->next) {
70  OSyncMapping *mapping = m->data;
71  osengine_mapping_free(mapping);
72  }
73  osync_trace(TRACE_INTERNAL, "Free unmapped");
74  for (c = unmapped; c; c = c->next) {
75  OSyncMappingEntry *entry = c->data;
76  osengine_mappingentry_free(entry);
77  }
78  for (c = views; c; c = c->next) {
79  OSyncMappingView *view = c->data;
80  osengine_mappingview_free(view);
81  }
82  g_list_free(mappings);
83  g_list_free(unmapped);
84  g_list_free(views);
85  g_free(table);
86  osync_trace(TRACE_EXIT, "osengine_mappingtable_free");
87 }
88 
89 OSyncMappingEntry *osengine_mappingtable_find_entry(OSyncMappingTable *table, const char *uid, const char *objtype, long long int memberid)
90 {
91  osync_trace(TRACE_ENTRY, "%s(%p, %s, %s)", __func__, table, uid, objtype ? objtype : "None");
92  GList *v;
93  int count_of_entries = 0; /*must not be more the one for objtype=NULL*/
94  OSyncMappingEntry *ret_entry = NULL;
95  for (v = table->views; v; v = v->next) {
96  OSyncMappingView *view = v->data;
97  GList *c;
98 
99  if (memberid && memberid != osync_member_get_id(view->client->member))
100  continue;
101 
102  for (c = view->changes; c; c = c->next) {
103  OSyncMappingEntry *entry = c->data;
104  g_assert(entry->change);
105  if(objtype){
106  if ( (!strcmp(
107  osync_change_get_uid(entry->change), uid)) &&
108  (!strcmp(
110  osync_change_get_objtype(entry->change))
111  , objtype))
112  ) {
113  ret_entry = entry;
114  count_of_entries++;
115  }
116  } else {
117  if (!strcmp(osync_change_get_uid(entry->change), uid)) {
118  ret_entry = entry;
119  count_of_entries++;
120  }
121  }
122  }
123  }
124  if(count_of_entries == 1 && ret_entry){
125  osync_trace(TRACE_EXIT, "%s: %p", __func__, ret_entry);
126  return ret_entry;
127  }
128  if(count_of_entries >1){
129  if (!objtype)
130  {
131  osync_trace(TRACE_EXIT_ERROR, "%s: possible dataloss", __func__ );
132  } else {
133  osync_trace(TRACE_EXIT_ERROR, "%s: changes.db corrupted", __func__ );
134  }
135  return NULL;
136  }
137 
138  osync_trace(TRACE_EXIT, "%s: Not Found", __func__);
139  return NULL;
140 }
141 
142 OSyncMappingEntry *osengine_mappingtable_store_change(OSyncMappingTable *table, OSyncChange *change)
143 {
144  osync_trace(TRACE_ENTRY, "osengine_mappingtable_store_change(%p, %p)", table, change);
145  OSyncMappingView *view = osengine_mappingtable_find_view(table, osync_change_get_member(change));
146  g_assert(view);
147  OSyncMappingEntry *entry = osengine_mappingview_store_change(view, change);
148  osync_trace(TRACE_EXIT, "osengine_mappingtable_store_change: %p", entry);
149  return entry;
150 }
151 
152 OSyncMapping *osengine_mappingtable_find_mapping(OSyncMappingTable *table, OSyncChange *change)
153 {
154  GList *m;
155  for (m = table->mappings; m; m = m->next) {
156  OSyncMapping *mapping = m->data;
157  if (osengine_mapping_find_entry(mapping, change, NULL))
158  return mapping;
159  }
160  return NULL;
161 }
162 
163 OSyncMapping *osengine_mappingtable_mapping_from_id(OSyncMappingTable *table, long long int id)
164 {
165  GList *m;
166  for (m = table->mappings; m; m = m->next) {
167  OSyncMapping *mapping = m->data;
168  if (mapping->id == id)
169  return mapping;
170  }
171  return NULL;
172 }
173 
174 OSyncMappingView *osengine_mappingtable_find_view(OSyncMappingTable *table, OSyncMember *member)
175 {
176  GList *v;
177  for (v = table->views; v; v = v->next) {
178  OSyncMappingView *view = v->data;
179  if (view->memberid == osync_member_get_id(member))
180  return view;
181  }
182  return NULL;
183 }
184 
185 void osengine_mappingtable_add_mapping(OSyncMappingTable *table, OSyncMapping *mapping)
186 {
187  table->mappings = g_list_append(table->mappings, mapping);
188  mapping->table = table;
189 }
190 
191 osync_bool osengine_mappingtable_load(OSyncMappingTable *table, OSyncError **error)
192 {
193  osync_trace(TRACE_ENTRY, "osengine_mappingtable_load(%p, %p)", table, error);
194  OSyncChange **changes = NULL;
195  if (!osync_changes_load(table->group, &changes, error)) {
196  osync_trace(TRACE_EXIT_ERROR, "osengine_mappingtable_load: %s", osync_error_print(error));
197  return FALSE;
198  }
199 
200  int i = 0;
201  OSyncChange *change = NULL;
202  OSyncMapping *mapping = NULL;
203  while ((change = changes[i])) {
204  OSyncMappingEntry *entry = osengine_mappingentry_new(NULL);
205  entry->change = change;
206  //entry->orig_change = change;
207  entry->client = (OSyncClient *)osync_member_get_data(osync_change_get_member(change));
208 
209  if (!osync_change_get_mappingid(change)) {
210  table->unmapped = g_list_append(table->unmapped, entry);
211  } else {
212  if (!mapping || mapping->id != osync_change_get_mappingid(change)) {
213  mapping = osengine_mapping_new(table);
214  mapping->id = osync_change_get_mappingid(change);
215  }
216  osengine_mapping_add_entry(mapping, entry);
217  }
218 
219  osync_flag_set(entry->fl_has_data);
220 
221  OSyncMappingView *view = osengine_mappingtable_find_view(table, osync_change_get_member(change));
222  if (view)
223  osengine_mappingview_add_entry(view, entry);
224 
225  i++;
226  }
227 
228  osync_trace(TRACE_EXIT, "osengine_mappingtable_load: TRUE");
229  return TRUE;
230 }
231 
232 long long int osengine_mappingtable_get_next_id(OSyncMappingTable *table)
233 {
234  long long int new_id = 1;
235  GList *m;
236  for (m = table->mappings; m; m = m->next) {
237  OSyncMapping *mapping = m->data;
238  if (new_id <= mapping->id)
239  new_id = mapping->id + 1;
240  }
241  return new_id;
242 }
243 
244 void osengine_mappingtable_inject_changes(OSyncMappingTable *table)
245 {
246  osync_trace(TRACE_ENTRY, "%s(%p)", __func__, table);
247  //OSyncEngine *engine = table->engine;
248 
249  char **uids = NULL;
250  char **objtypes = NULL;
251  long long int *memberids = NULL;
252  int *types = NULL;
253  char *uid = NULL;
254  char *objtype = NULL;
255  int type = 0;
256  int i = 0;
257  OSyncError *error = NULL;
258  osync_group_open_changelog(table->engine->group, &uids, &objtypes, &memberids, &types, &error);
259 
260  for (i = 0; (uid = uids[i]) ; i++) {
261  type = types[i];
262  objtype = objtypes[i];
263  long long int memberid = memberids[i];
264  OSyncMappingEntry *entry = osengine_mappingtable_find_entry(table, uid, objtype, memberid);
265 
266  if (!entry) {
267  osync_trace(TRACE_INTERNAL, "Mappingtable and changelog inconsistent: no entry with uid %s", uid);
268  /*FIXME: We should be able to return error here. What if entry == NULL? */
269  g_assert_not_reached();
270  }
271 
272  osync_change_set_changetype(entry->change, type);
273  osync_trace(TRACE_INTERNAL, "Injecting %p with changetype %i", entry, osync_change_get_changetype(entry->change));
274  osync_flag_attach(entry->fl_read, table->engine->cmb_read_all);
275 
276  /* Set fl_mapped accordingly, if the entry was already mapped previously */
277  if (entry->mapping)
278  osync_flag_set(entry->fl_mapped);
279 
280  //send_read_change(engine, entry);
281  }
282 
283  osync_trace(TRACE_EXIT, "%s", __func__);
284 }
285 
286 OSyncMappingTable *_osengine_mappingtable_load_group(OSyncGroup *group)
287 {
288  OSyncMappingTable *table = g_malloc0(sizeof(OSyncMappingTable));
289  table->group = group;
290 
291  int i;
292  for (i = 0; i < osync_group_num_members(group); i++) {
293  OSyncMember *member = osync_group_nth_member(group, i);
294  OSyncMappingView *view = g_malloc0(sizeof(OSyncMappingView));
295  table->views = g_list_append(table->views, view);
296  view->table = table;
297  view->memberid = osync_member_get_id(member);
298  }
299 
300  if (!osengine_mappingtable_load(table, NULL))
301  return NULL;
302  return table;
303 }
304 
305 void osengine_mappingtable_close(OSyncMappingTable *table)
306 {
307  osync_changes_close(table->group);
308  //FIXME Free the changes on the views
309 }
310 
311 OSyncMapping *osengine_mapping_new(OSyncMappingTable *table)
312 {
313  g_assert(table);
314  OSyncMapping *mapping = g_malloc0(sizeof(OSyncMapping));
315  osengine_mappingtable_add_mapping(table, mapping);
316  if (table->engine) {
317  mapping->fl_solved = osync_flag_new(NULL);
318 
319  mapping->fl_chkconflict = osync_flag_new(NULL);
320  osync_flag_set(mapping->fl_chkconflict);
321 
322  mapping->fl_multiplied = osync_flag_new(NULL);
323  osync_flag_set(mapping->fl_multiplied);
324 
325  mapping->cmb_has_data = osync_comb_flag_new(FALSE, FALSE);
326  osync_flag_set_pos_trigger(mapping->cmb_has_data, (OSyncFlagTriggerFunc)send_mapping_changed, table->engine, mapping);
327 
328  mapping->cmb_has_info = osync_comb_flag_new(FALSE, FALSE);
329 
330  mapping->cmb_synced = osync_comb_flag_new(FALSE, TRUE);
331 
332  mapping->cmb_deleted = osync_comb_flag_new(FALSE, FALSE);
333 
334  osync_flag_attach(mapping->cmb_synced, table->engine->cmb_synced);
335  osync_flag_attach(mapping->fl_multiplied, table->engine->cmb_multiplied);
336  osync_flag_attach(mapping->fl_chkconflict, table->engine->cmb_chkconflict);
337  }
338  osync_trace(TRACE_INTERNAL, "osengine_mapping_new(%p): %p", table, mapping);
339  return mapping;
340 }
341 
342 void osengine_mapping_free(OSyncMapping *mapping)
343 {
344  osync_trace(TRACE_ENTRY, "osengine_mapping_free(%p)", mapping);
345 
346  while (g_list_nth_data(mapping->entries, 0))
347  osengine_mappingentry_free(g_list_nth_data(mapping->entries, 0));
348 
349  osync_flag_detach(mapping->cmb_synced);
350  osync_flag_detach(mapping->fl_chkconflict);
351  osync_flag_detach(mapping->fl_multiplied);
352 
353  mapping->table->mappings = g_list_remove(mapping->table->mappings, mapping);
354  osync_flag_free(mapping->fl_solved);
355  osync_flag_free(mapping->cmb_has_data);
356  osync_flag_free(mapping->cmb_has_info);
357  osync_flag_free(mapping->cmb_synced);
358  osync_flag_free(mapping->fl_chkconflict);
359  osync_flag_free(mapping->cmb_deleted);
360  osync_flag_free(mapping->fl_multiplied);
361 
362  g_free(mapping);
363  osync_trace(TRACE_EXIT, "osengine_mapping_free");
364 }
365 
366 void osengine_mapping_add_entry(OSyncMapping *mapping, OSyncMappingEntry *entry)
367 {
368  osync_trace(TRACE_INTERNAL, "osengine_mapping_add_entry(%p, %p)", mapping, entry);
369  g_assert(!osengine_mapping_find_entry(mapping, NULL, entry->view));
370  mapping->entries = g_list_append(mapping->entries, entry);
371  entry->mapping = mapping;
372 
373  if (mapping->table->engine) {
374  osync_flag_attach(entry->fl_has_data, mapping->cmb_has_data);
375  osync_flag_attach(entry->fl_has_info, mapping->cmb_has_info);
376  osync_flag_attach(entry->fl_synced, mapping->cmb_synced);
377  osync_flag_attach(entry->fl_deleted, mapping->cmb_deleted);
378  osync_flag_set_pos_trigger(entry->fl_dirty, (OSyncFlagTriggerFunc)send_mappingentry_changed, mapping->table->engine, entry);
379  }
380  osync_change_set_mappingid(entry->change, mapping->id);
381 
382  mapping->table->unmapped = g_list_remove(mapping->table->unmapped, entry);
383  mapping->table->entries = g_list_append(mapping->table->entries, entry);
384 }
385 
386 void osengine_mapping_remove_entry(OSyncMapping *mapping, OSyncMappingEntry *entry)
387 {
388  mapping->entries = g_list_remove(mapping->entries, entry);
389  mapping->table->entries = g_list_remove(mapping->table->entries, entry);
390  entry->mapping = NULL;
391 
392  osync_flag_detach(entry->fl_has_data);
393  osync_flag_detach(entry->fl_has_info);
394  osync_flag_detach(entry->fl_synced);
395  osync_flag_detach(entry->fl_deleted);
396 }
397 
398 OSyncMappingEntry *osengine_mapping_find_entry(OSyncMapping *mapping, OSyncChange *change, OSyncMappingView *view)
399 {
400  GList *e;
401  for (e = mapping->entries; e; e = e->next) {
402  OSyncMappingEntry *entry = e->data;
403  if (change && entry->change == change)
404  return entry;
405  if (view && entry->view == view)
406  return entry;
407  }
408  return NULL;
409 }
410 
411 OSyncMappingEntry *osengine_mapping_nth_entry(OSyncMapping *mapping, int nth)
412 {
413  return (OSyncMappingEntry *)g_list_nth_data(mapping->entries, nth);
414 }
415 
416 int osengine_mapping_num_changes(OSyncMapping *mapping)
417 {
418  return g_list_length(mapping->entries);
419 }
420 
421 OSyncChange *osengine_mapping_nth_change(OSyncMapping *mapping, int nth)
422 {
423  OSyncMappingEntry *entry = g_list_nth_data(mapping->entries, nth);
424  if (!entry)
425  return NULL;
426  return entry->change;
427 }
428 
429 long long osengine_mapping_get_id(OSyncMapping *mapping)
430 {
431  return mapping->id;
432 }
433 
434 void osengine_mapping_reset(OSyncMapping *mapping)
435 {
436  osync_trace(TRACE_ENTRY, "osengine_mapping_reset(%p)", mapping);
437  GList *e;
438  for (e = mapping->entries; e; e = e->next) {
439  OSyncMappingEntry *entry = e->data;
440  osengine_mappingentry_reset(entry);
441  }
442 
443  osync_flag_set(mapping->fl_multiplied);
444  osync_flag_set(mapping->fl_chkconflict);
445  mapping->master = NULL;
446  osync_trace(TRACE_EXIT, "osengine_mapping_reset");
447 }
448 
449 void osengine_mapping_delete(OSyncMapping *mapping)
450 {
451  osync_trace(TRACE_ENTRY, "osengine_mapping_delete(%p)", mapping);
452  GList *entries = g_list_copy(mapping->entries);
453  GList *c = NULL;
454  for (c = entries; c; c = c->next) {
455  OSyncMappingEntry *entry = c->data;
456  osync_change_delete(entry->change, NULL);
457  }
458  g_list_free(entries);
459  osengine_mapping_free(mapping);
460  osync_trace(TRACE_EXIT, "osengine_mapping_delete");
461 }
462 
463 OSyncMappingView *osengine_mappingview_new(OSyncMappingTable *table, OSyncClient *client)
464 {
465  g_assert(table);
466  OSyncMappingView *view = g_malloc0(sizeof(OSyncMappingView));
467  table->views = g_list_append(table->views, view);
468  view->client = client;
469  view->table = table;
470  view->memberid = osync_member_get_id(client->member);
471  osync_trace(TRACE_INTERNAL, "osengine_mappingview_new(%p)", view);
472  return view;
473 }
474 
475 void osengine_mappingview_free(OSyncMappingView *view)
476 {
477  osync_trace(TRACE_INTERNAL, "osengine_mappingview_free(%p)", view);
478  g_list_free(view->changes);
479  view->changes = NULL;
480  g_free(view);
481 }
482 
483 void osengine_mappingview_add_entry(OSyncMappingView *view, OSyncMappingEntry *entry)
484 {
485  view->changes = g_list_append(view->changes, entry);
486  entry->view = view;
487 }
488 
489 OSyncMappingEntry *osengine_mappingview_store_change(OSyncMappingView *view, OSyncChange *change)
490 {
491  osync_trace(TRACE_ENTRY, "osengine_mappingview_store_change(%p, %p)", view, change);
492  g_assert(change);
493  GList *c;
494  for (c = view->changes; c; c = c->next) {
495  OSyncMappingEntry *entry = c->data;
496  g_assert(entry->change);
497 
502  if (!strcmp(osync_change_get_uid(entry->change), osync_change_get_uid(change))) {
503  OSyncObjType * entry_objtype = osync_change_get_objtype(entry->change);
504  OSyncObjType * change_objtype = osync_change_get_objtype(change);
505 
506  const char * entry_objtype_name = osync_objtype_get_name(entry_objtype);
507  const char * change_objtype_name = osync_objtype_get_name(change_objtype);
508 
509  if (
510  (change_objtype_name == NULL) ||
511  (entry_objtype_name == NULL) ||
512  (!strcmp(change_objtype_name, entry_objtype_name)) ||
513  (!strcmp(change_objtype_name, "data")) ||
514  (!strcmp(entry_objtype_name, "data"))
515  ) {
516  osengine_mappingentry_update(entry, change);
517  osync_trace(TRACE_EXIT, "osengine_mappingview_store_change: %p", entry);
518  return entry;
519  }
520  }
521 
522  }
523 
524  OSyncMappingEntry *newentry = osengine_mappingentry_new(NULL);
525  newentry->change = change;
526  newentry->client = view->client;
527  view->table->unmapped = g_list_append(view->table->unmapped, newentry);
528  osengine_mappingview_add_entry(view, newentry);
529  osync_trace(TRACE_EXIT, "osengine_mappingview_store_change: %p (New MappingEntry)", newentry);
530  return newentry;
531 }
532 
533 osync_bool osengine_mappingview_uid_is_unique(OSyncMappingView *view, OSyncMappingEntry *entry, osync_bool spare_deleted)
534 {
535  GList *e = NULL;
536 
537  for (e = view->changes; e; e = e->next) {
538  OSyncMappingEntry *exentry = e->data;
539  if ((exentry != entry) && (!spare_deleted || (osync_change_get_changetype(exentry->change) != CHANGE_DELETED)) && !strcmp(osync_change_get_uid(exentry->change), osync_change_get_uid(entry->change)))
540  return FALSE;
541  }
542  return TRUE;
543 }
544 
545 void osengine_mappingview_reset(OSyncMappingView *view)
546 {
547  //g_list_free(view->changes);
548  //view->changes = NULL;
549 }
550 
551 OSyncMappingEntry *osengine_mappingentry_new(OSyncMapping *mapping)
552 {
553  OSyncMappingEntry *entry = g_malloc0(sizeof(OSyncMappingEntry));
554  osync_trace(TRACE_INTERNAL, "osengine_mappingentry_new(%p): %p", mapping, entry);
555  entry->fl_has_data = osync_flag_new(NULL);
556  entry->fl_dirty = osync_flag_new(NULL);
557  entry->fl_mapped = osync_flag_new(NULL);
558  entry->fl_has_info = osync_flag_new(NULL);
559  entry->fl_synced = osync_flag_new(NULL);
560  entry->fl_deleted = osync_flag_new(NULL);
561  entry->fl_read = osync_flag_new(NULL);
562  entry->fl_committed = osync_flag_new(NULL);
563  osync_flag_set(entry->fl_synced);
564 
565  if (mapping)
566  osengine_mapping_add_entry(mapping, entry);
567 
568  return entry;
569 }
570 
571 void osengine_mappingentry_free(OSyncMappingEntry *entry)
572 {
573  osync_trace(TRACE_INTERNAL, "osengine_mappingentry_free(%p)", entry);
574 
575  if (entry->mapping)
576  osengine_mapping_remove_entry(entry->mapping, entry);
577 
578  osync_flag_free(entry->fl_has_data);
579  osync_flag_free(entry->fl_dirty);
580  osync_flag_free(entry->fl_mapped);
581  osync_flag_free(entry->fl_has_info);
582  osync_flag_free(entry->fl_synced);
583  osync_flag_free(entry->fl_deleted);
584  osync_flag_free(entry->fl_read);
585  osync_flag_free(entry->fl_committed);
586 
587  entry->view->changes = g_list_remove(entry->view->changes, entry);
588  entry->view = NULL;
589 
590  g_free(entry);
591 }
592 
593 void osengine_mappingentry_update(OSyncMappingEntry *entry, OSyncChange *change)
594 {
595  osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, entry, change);
596 
597  OSyncObjFormat *format = osync_change_get_objformat(entry->change);
598  OSyncObjType *type = osync_change_get_objtype(entry->change);
599 
600  osync_change_update(change, entry->change);
601 
602  if (osync_change_get_changetype(change) == CHANGE_DELETED && format && type) {
603  osync_change_set_objformat(entry->change, format);
604  osync_change_set_objtype(entry->change, type);
605 
606  osync_trace(TRACE_INTERNAL, "Change was deleted. Old objtype %s and format %s", osync_change_get_objtype(entry->change) ? osync_objtype_get_name(osync_change_get_objtype(entry->change)) : "None", osync_change_get_objformat(entry->change) ? osync_objformat_get_name(osync_change_get_objformat(entry->change)) : "None");
607  }
608 
609  osync_trace(TRACE_EXIT, "%s", __func__);
610 }
611 
612 OSyncMappingEntry *osengine_mappingentry_copy(OSyncMappingEntry *entry)
613 {
614  OSyncMappingEntry *newentry = osengine_mappingentry_new(NULL);
615 
616  OSyncError *error = NULL;
617  newentry->change = osync_change_copy(entry->change, &error);
618  newentry->client = entry->client;
619  osengine_mappingview_add_entry(entry->view, newentry);
620  return newentry;
621 }
622 
623 void osengine_mappingentry_reset(OSyncMappingEntry *entry)
624 {
625  osync_trace(TRACE_INTERNAL, "osengine_mappingentry_reset(%p)", entry);
626 
627  osync_flag_set(entry->fl_has_data);
628  osync_flag_unset(entry->fl_dirty);
629  osync_flag_unset(entry->fl_has_info);
630  osync_flag_unset(entry->fl_deleted);
631  osync_flag_set(entry->fl_synced);
632 
633  osync_change_reset(entry->change);
634 }
635 #endif
636