osync_bool osync_obj_engine_initialize(OSyncObjEngine *engine, OSyncError **error)
{
  const char *objtype = NULL;
  int num = 0;
  int i = 0;

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

  osync_trace(TRACE_INTERNAL, "Loaded %i mappings", osync_mapping_table_num_mappings(engine->mapping_table));

  objtype = osync_obj_engine_get_objtype(engine);
	
  num = osync_engine_num_proxies(engine->parent);
  for (i = 0; i < num; i++) {
    OSyncClientProxy *proxy = osync_engine_nth_proxy(engine->parent, i);
    OSyncObjTypeSink *sink = osync_client_proxy_find_objtype_sink(proxy, objtype);
    OSyncSinkEngine *sinkengine = NULL; 
    if (!sink) {
      /* "data" sink engine counts also as valid. */
      sink = osync_client_proxy_find_objtype_sink(proxy, "data"); 
      if (!sink)
        continue;
    }
		
    sinkengine = osync_sink_engine_new(i, proxy, engine, error);
    if (!sinkengine)
      goto error;
		
    engine->sink_engines = g_list_append(engine->sink_engines, sinkengine);
  }

  if (engine->archive && engine->slowsync) {
    if (!osync_mapping_table_flush(engine->mapping_table, engine->archive, engine->objtype, error))
      goto error;
  }

  if (engine->archive) {
    if (!osync_mapping_table_load(engine->mapping_table, engine->archive, engine->objtype, error))
      goto error;
  }

  if (!_create_mapping_engines(engine, error))
    goto error;
	
  osync_trace(TRACE_INTERNAL, "Created %i mapping engine", g_list_length(engine->mapping_engines));

  if (engine->archive) {
    /* inject ignored conflicts from previous syncs */
    if (!_inject_changelog_entries(engine, error))
      goto error;
  }

  osync_trace(TRACE_EXIT, "%s", __func__);
  return TRUE;
 error:

  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
  return FALSE;
}
osync_bool osync_sink_engine_convert_to_dest(OSyncSinkEngine *engine, OSyncFormatEnv *formatenv, OSyncError **error)
{
    OSyncList *o;
    OSyncMember *member;
    OSyncObjTypeSink *objtype_sink;
    const char *objtype;
    OSyncFormatConverterPath *path = NULL;

    osync_assert(engine);
    osync_assert(formatenv);

    member = osync_client_proxy_get_member(engine->proxy);
    osync_assert(member);

    objtype = osync_obj_engine_get_objtype(engine->engine);
    objtype_sink = osync_member_find_objtype_sink(member, objtype);
    osync_assert(objtype_sink);

    for (o = engine->entries; o; o = o->next) {
        OSyncMappingEntryEngine *entry_engine = o->data;
        osync_assert(entry_engine);

        if (entry_engine->change == NULL)
            continue;

        /* If change not meant to get written (change shared among multiple "same" mapping
           entry engines), prevents conversions see #1207 */
        if (!osync_entry_engine_is_dirty(entry_engine))
            continue;

        if (osync_change_get_changetype(entry_engine->change) == OSYNC_CHANGE_TYPE_DELETED)
            continue;

        if (!osync_entry_engine_convert(entry_engine, formatenv, objtype_sink, &path, error))
            goto error;
    }

    if (path)
        osync_converter_path_unref(path);


    return TRUE;

error:
    if (path)
        osync_converter_path_unref(path);

    return FALSE;
}
osync_bool osync_sink_engine_write(OSyncSinkEngine *engine, OSyncArchive *archive, OSyncError **error)
{
    OSyncList *o;
    const char *objtype;
    OSyncMember *member;

    osync_assert(engine);
    osync_assert(archive);

    objtype = osync_obj_engine_get_objtype(engine->engine);
    member = osync_client_proxy_get_member(engine->proxy);

    for (o = engine->entries; o; o = o->next) {
        OSyncMappingEntryEngine *entry_engine = o->data;
        osync_assert(entry_engine);

        if (osync_entry_engine_is_dirty(entry_engine)) {
            OSyncChange *change = osync_entry_engine_get_change(entry_engine);
            osync_assert(change);

            osync_trace(TRACE_INTERNAL, "Writing change %s, changetype %i, format %s , objtype %s from member %i",
                        osync_change_get_uid(change),
                        osync_change_get_changetype(change),
                        osync_objformat_get_name(osync_change_get_objformat(change)),
                        osync_change_get_objtype(change),
                        osync_member_get_id(member));

            if (!osync_client_proxy_commit_change(engine->proxy,
                                                  osync_obj_engine_commit_change_callback,
                                                  entry_engine, change, error))
                goto error;

        } else if (entry_engine->change) {
            OSyncMapping *mapping = entry_engine->mapping_engine->mapping;
            OSyncMappingEntry *entry = entry_engine->entry;

            /* FIXME: Don't mix up in this function objtypes */
            /* osync_assert_msg(!strcmp(objtype, osync_change_get_objtype(entry_engine->change), "Mixed-objtype in final write!")); */

            if (osync_change_get_changetype(entry_engine->change) == OSYNC_CHANGE_TYPE_DELETED) {
                if (!osync_archive_delete_change(archive, osync_mapping_entry_get_id(entry),
                                                 osync_change_get_objtype(entry_engine->change), error))
                    goto error;
            } else {
                if (!osync_archive_save_change(archive,
                                               osync_mapping_entry_get_id(entry),
                                               osync_change_get_uid(entry_engine->change),
                                               osync_change_get_objtype(entry_engine->change),
                                               osync_mapping_get_id(mapping),
                                               osync_member_get_id(member), objtype, error))
                    goto error;
            }
        }
    }

    if (!osync_client_proxy_committed_all(engine->proxy, osync_obj_engine_written_callback, engine, objtype, error))
        goto error;

    return TRUE;

error:
    return FALSE;
}