OSyncObjEngine *osync_obj_engine_new(OSyncEngine *parent, const char *objtype, OSyncFormatEnv *formatenv, OSyncError **error)
{
  OSyncObjEngine *engine = NULL;
  osync_assert(parent);
  osync_assert(objtype);
	
  osync_trace(TRACE_ENTRY, "%s(%p, %s, %p, %p)", __func__, parent, objtype, formatenv, error);
	
  engine = osync_try_malloc0(sizeof(OSyncObjEngine), error);
  if (!engine)
    goto error;
  engine->ref_count = 1;
  engine->slowsync = FALSE;
  engine->written = FALSE;
	
  /* we dont reference the parent to avoid circular dependencies. This object is completely
   * dependent on the engine anyways */
  engine->parent = parent;
	
  engine->objtype = g_strdup(objtype);
  engine->formatenv = formatenv;
	
  engine->mapping_table = osync_mapping_table_new(error);
  if (!engine->mapping_table)
    goto error_free_engine;
	
  engine->archive = osync_engine_get_archive(parent);
	
  osync_trace(TRACE_EXIT, "%s: %p", __func__, engine);
  return engine;

 error_free_engine:
  osync_obj_engine_unref(engine);
 error:
  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
  return NULL;
}
void osync_sink_engine_unref(OSyncSinkEngine *engine)
{
    osync_assert(engine);

    if (g_atomic_int_dec_and_test(&(engine->ref_count))) {
        while (engine->unmapped) {
            OSyncChange *change = engine->unmapped->data;
            osync_change_unref(change);

            engine->unmapped = osync_list_remove(engine->unmapped, engine->unmapped->data);
        }

        while (engine->entries) {
            OSyncMappingEntryEngine *entry = engine->entries->data;
            osync_entry_engine_unref(entry);

            engine->entries = osync_list_remove(engine->entries, engine->entries->data);
        }

        osync_obj_engine_unref(engine->engine);

        osync_free(engine);
    }
}