static osync_bool _inject_changelog_entries(OSyncObjEngine *engine, OSyncError **error) {
  OSyncList *ids = NULL;
  OSyncList *changetypes = NULL;
  OSyncList *j = NULL, *t = NULL;

  osync_trace(TRACE_ENTRY, "%s(%p)", __func__, engine);

  osync_assert(engine);
  osync_assert(engine->archive);
  osync_assert(engine->objtype);
	
  if (!osync_archive_load_ignored_conflicts(engine->archive, engine->objtype, &ids, &changetypes, error)) {
    osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
    return FALSE;
  }

  t = changetypes;
  for (j = ids; j; j = j->next) {
    long long int id = (long long int)GPOINTER_TO_INT(j->data);

    OSyncMapping *ignored_mapping = osync_mapping_table_find_mapping(engine->mapping_table, id);

    GList *e;
    for (e = engine->mapping_engines; e; e = e->next) {
      OSyncMappingEngine *mapping_engine = e->data;

      if (mapping_engine->mapping == ignored_mapping) {
        GList *m;
        for (m = mapping_engine->entries; m; m = m->next) {
          OSyncMappingEntryEngine *entry = m->data;
          OSyncChangeType changetype = (OSyncChangeType) t->data;
          OSyncChange *ignored_change = osync_change_new(error);
          OSyncObjFormat *dummyformat = NULL;
          OSyncData *data = NULL;

          osync_change_set_changetype(ignored_change, changetype); 
          osync_entry_engine_update(entry, ignored_change);

          dummyformat = osync_objformat_new("plain", engine->objtype, NULL);
          data = osync_data_new(NULL, 0, dummyformat, NULL);
          osync_change_set_data(ignored_change, data);
          osync_objformat_unref(dummyformat);

          osync_change_set_uid(ignored_change, osync_mapping_entry_get_uid(entry->entry));

          osync_trace(TRACE_INTERNAL, "CHANGE: %p", entry->change);
        }
        break;
      }
    }

    t = t->next;
  }

  osync_list_free(ids);
  osync_list_free(changetypes);

  osync_trace(TRACE_EXIT, "%s", __func__);
  return TRUE;
}
Beispiel #2
0
void check_mapping(OSyncMappingTable *maptable, int memberid, int mappingid, unsigned int numentries, const char *uid)
{
	unsigned int i = 0;
	osync_trace(TRACE_ENTRY, "%s(%p, %i, %i, %i, %s)", __func__, maptable, memberid, mappingid, numentries, uid);
	
	for (i = 0; i < osync_mapping_table_num_mappings(maptable); i++) {
		OSyncMapping *mapping = osync_mapping_table_nth_mapping(maptable, i);
		OSyncMappingEntry *testentry = osync_mapping_find_entry_by_member_id(mapping, memberid);
		if (testentry) {
			if ((mappingid != -1 && osync_mapping_get_id(mapping) == mappingid) || (mappingid == -1 && !strcmp(osync_mapping_entry_get_uid(testentry), uid))) {
				unsigned int n = 0;
				fail_unless(osync_mapping_num_entries(mapping) == numentries);
				for (n = 0; n < osync_mapping_num_entries(mapping); n++) {
					OSyncMappingEntry *entry = osync_mapping_nth_entry(mapping, n);
					if (osync_mapping_entry_get_member_id(entry) == memberid) {
						fail_unless(!strcmp(osync_mapping_entry_get_uid(entry), uid), NULL);
						goto out;
					}
				}
				fail(NULL);
			}
		}
	}
	fail(NULL);

out:
	osync_trace(TRACE_EXIT, "%s", __func__);
}
osync_bool osync_mapping_engine_multiply(OSyncMappingEngine *engine, OSyncError **error)
{
  GList *e = NULL;
  osync_assert(engine);
  osync_assert(engine->mapping);
	
  osync_trace(TRACE_ENTRY, "%s(%p(%lli), %p)", __func__, engine, osync_mapping_get_id(engine->mapping), error);
		
  if (engine->synced) {
    osync_trace(TRACE_EXIT, "%s: No need to multiply. Already synced", __func__);
    return TRUE;
  }

  if (!engine->master) {
    osync_error_set(error, OSYNC_ERROR_GENERIC, "No master set");
    goto error;
  }

  for (e = engine->entries; e; e = e->next) {
    OSyncChange *existChange = NULL, *masterChange = NULL;
    OSyncData *masterData = NULL, *newData = NULL;
    OSyncMappingEntryEngine *entry_engine = e->data;
    OSyncChangeType existChangeType = 0, newChangeType = 0;
    if (entry_engine == engine->master)
      continue;
		
    osync_trace(TRACE_INTERNAL, "Propagating change %s to %p from %p", osync_mapping_entry_get_uid(entry_engine->entry), entry_engine, engine->master);
		
    /* Input is:
     * masterChange -> change that solved the mapping
     * masterData -> data of masterChange
     * existChange -> change that will be overwritten (if any) */
		
    existChange = entry_engine->change;
    masterChange = osync_entry_engine_get_change(engine->master);
    masterData = osync_change_get_data(masterChange);
		
    /* Clone the masterData. This has to be done since the data
     * might get changed (converted) and we dont want to touch the 
     * original data */
    newData = osync_data_clone(masterData, error);
    if (!newData)
      goto error;
		
    if (!existChange) {
      existChange = osync_change_new(error);
      if (!existChange)
        goto error;
			
      osync_change_set_changetype(existChange, OSYNC_CHANGE_TYPE_UNKNOWN);
    } else {
      /* Ref the change so that we can unref it later */
      osync_change_ref(existChange);
    }
		
    /* Save the changetypes, so that we can calculate the correct changetype later */
    existChangeType = osync_change_get_changetype(existChange);
    newChangeType = osync_change_get_changetype(masterChange);
		
    osync_trace(TRACE_INTERNAL, "Orig change type: %i New change type: %i", existChangeType, newChangeType);

    /* Now update the entry with the change */
    osync_entry_engine_update(entry_engine, existChange);
		
    /* We have to use the uid of the entry, so that the member
     * can correctly identify the entry 
     *
     * prahal: added a check if the entry has a uid to send the existing uid
     * to the plugins in case we have a slow-sync (both are added and have a uid) 
     * This to avoid creating duplicates by sending the plugins a different uid 
     * with the same or merged data 
     *
     * dgollub: enhanced the check if the entry has a uid to send the existing uid
     * to the plugins in case we have a slow-sync - both have changetype ADDED - and
     * for odd plugins/protocolls which mark new entries as MODIFIED all the time.
     * Changetype MODIFIED of new entries has atleast the IrMC plugin and likely some
     * SE SyncML implementation...
     * 
     * ^^irmc hacks in the irmc plugin ;-)
     *
     * dgollub: Set masterChange UID for existChange if entry_engine->entry doesn't have 
     * mapping uid, even if the newChangeType is UNKOWN. Bug: #571  
     *
     * prahal : rely on the fact that there are no mapping nor the entry existed to detect new change
     *	    Also avoid changing the id of the change if one existed and there where no mapping :
     *	    this way we send the id known to the member in case of a "modify". Fixing syncml plugin
     *	    freezing the phone and mozilla sync receiving an id it cannot do anything with for modify
     *	    in slow sync (no existing mapping).
     *
     */
    if ((!osync_mapping_entry_get_uid(entry_engine->entry) && !osync_change_get_uid(existChange))  ) 
      osync_change_set_uid(existChange, osync_change_get_uid(masterChange));
    else if(osync_mapping_entry_get_uid(entry_engine->entry)) 
      osync_change_set_uid(existChange, osync_mapping_entry_get_uid(entry_engine->entry));

    osync_change_set_data(existChange, newData);
    osync_change_set_changetype(existChange, osync_change_get_changetype(masterChange));
		
    /* We also have to update the changetype of the new change */
    if (newChangeType == OSYNC_CHANGE_TYPE_ADDED && (existChangeType != OSYNC_CHANGE_TYPE_DELETED && existChangeType != OSYNC_CHANGE_TYPE_UNKNOWN)) {
      osync_trace(TRACE_INTERNAL, "Updating change type to MODIFIED");
      osync_change_set_changetype(existChange, OSYNC_CHANGE_TYPE_MODIFIED);
      /* Only adapt the change to ADDED if the existing Change got deleted. Don't update it to ADDED if existChangeType is UNKOWN.
         The exitChangeType is at least also UNKOWN if the file-sync has only one modified entry. */
    } else if (newChangeType == OSYNC_CHANGE_TYPE_MODIFIED && (existChangeType == OSYNC_CHANGE_TYPE_DELETED)) {
      osync_trace(TRACE_INTERNAL, "Updating change type to ADDED");
      osync_change_set_changetype(existChange, OSYNC_CHANGE_TYPE_ADDED);
    }
		
    osync_change_unref(existChange);
    /* Also unref newData. Otherwise this cannot be freed when it is written. */
    osync_data_unref(newData);
			
    osync_entry_engine_set_dirty(entry_engine, TRUE);
  }
	
  osync_trace(TRACE_EXIT, "%s", __func__);
  return TRUE;

 error:
  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
  return FALSE;
}