Ejemplo n.º 1
0
static osync_bool commit_sink(Command *cmd, OSyncObjTypeSink *sink, OSyncChange *change, OSyncError **error) {
	OSyncContext *context = NULL;
	assert(sink);
	assert(change);

	context = osync_context_new(error);
	if (!context)
		goto error;

	cmd->sink = sink;

	osync_context_set_callback(context, _osyncplugin_ctx_callback_commit_change, cmd);

	osync_plugin_info_set_sink(plugin_info, sink);

	printf("COMMIT:\t%s\t%s\t%s\n", 
	       _osyncplugin_changetype_str(change), 
	       osync_data_get_objtype(osync_change_get_data(change)), 
	       osync_change_get_uid(change));

	osync_objtype_sink_commit_change(sink, plugin_info, change, context);

	osync_context_unref(context);

	return TRUE;

 error:	
	return FALSE;
}
static void _osync_obj_engine_commit_change_callback(OSyncClientProxy *proxy, void *userdata, const char *uid, OSyncError *error)
{
  OSyncMappingEntryEngine *entry_engine = userdata;
  OSyncObjEngine *engine = entry_engine->objengine;
  OSyncSinkEngine *sinkengine = entry_engine->sink_engine;
  OSyncError *locerror = NULL;
  OSyncMapping *mapping = NULL;
  OSyncMember *member = NULL;
  OSyncMappingEntry *entry = NULL;
  const char *objtype = NULL;
  long long int id = 0;

	
  osync_trace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, proxy, userdata, uid, error);
	
  osync_entry_engine_set_dirty(entry_engine, FALSE);
	
  mapping = entry_engine->mapping_engine->mapping;
  member = osync_client_proxy_get_member(proxy);
  entry = entry_engine->entry;
  objtype = osync_change_get_objtype(entry_engine->change);
  id = osync_mapping_entry_get_id(entry);
	
  if (error) {
    /* Error handling (tests: single_commit_error, ...) */

    /* TODO: Review differences between Mapping and Change status events - Are both really needed?! */
    osync_status_update_change(engine->parent, entry_engine->change, osync_client_proxy_get_member(proxy), entry_engine->mapping_engine->mapping, OSYNC_CHANGE_EVENT_ERROR, error);
    osync_status_update_mapping(engine->parent, entry_engine->mapping_engine, OSYNC_MAPPING_EVENT_ERROR, error);

    osync_obj_engine_set_error(engine, error);
    engine->sink_errors = engine->sink_errors | (0x1 << sinkengine->position);
    goto error;
  }
	
  if (uid)
    osync_change_set_uid(entry_engine->change, uid);
	
  if (engine->archive) {
    if (osync_change_get_changetype(entry_engine->change) == OSYNC_CHANGE_TYPE_DELETED) {
      /* TODO error handling */
      osync_archive_delete_change(engine->archive, id, objtype, &locerror);
    } else {

      /* TODO error handling */
      osync_archive_save_change(engine->archive, id, osync_change_get_uid(entry_engine->change), objtype, osync_mapping_get_id(mapping), osync_member_get_id(member), &locerror);
    }
  }

  osync_assert(entry_engine->mapping_engine);
  osync_status_update_change(engine->parent, entry_engine->change, osync_client_proxy_get_member(proxy), entry_engine->mapping_engine->mapping, OSYNC_CHANGE_EVENT_WRITTEN, NULL);
  osync_entry_engine_update(entry_engine, NULL);
	
  osync_trace(TRACE_EXIT, "%s", __func__);
  return;

 error:	
  _osync_obj_engine_generate_written_event(engine, error);
  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(&error));
}
osync_bool osync_mapping_entry_matches(OSyncMappingEntry *entry, OSyncChange *change)
{
	osync_assert(entry);
	osync_assert(change);
	
	if (!strcmp(entry->uid, osync_change_get_uid(change)))
		return TRUE;
	
	return FALSE;
}
Ejemplo n.º 4
0
change_info *find_change_info(member_info *meminfo, OSyncChange *change)
{
	GList *c;
	for (c = meminfo->changes; c; c = c->next) {
		change_info *chinfo = c->data;
		if (chinfo->uid && !strcmp(chinfo->uid, osync_change_get_uid(change)))
			return chinfo;
	}
	return NULL;
}
Ejemplo n.º 5
0
void osync_context_report_change(OSyncContext *context, OSyncChange *change)
{
	OSyncData *data;
	osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, context, change);
	osync_assert(context);
	osync_assert(change);
	
	osync_assert_msg(osync_change_get_uid(change), "You forgot to set a uid on the change you reported!");
	osync_assert_msg(osync_change_get_data(change) || osync_change_get_changetype(change) == OSYNC_CHANGE_TYPE_DELETED, "You need to report some data unless you report CHANGE_DELETED");
	
	data = osync_change_get_data(change);
	
	osync_assert_msg(((data && osync_data_get_objformat(data) != NULL) || osync_change_get_changetype(change) == OSYNC_CHANGE_TYPE_DELETED), "The reported change did not have a format set");
	osync_assert_msg(((data && osync_data_get_objtype(data) != NULL) || osync_change_get_changetype(change) == OSYNC_CHANGE_TYPE_DELETED), "The reported change did not have a objtype set");
		
	osync_trace(TRACE_INTERNAL, "Reporting change with uid %s, changetype %i, data %p", osync_change_get_uid(change), osync_change_get_changetype(change), osync_change_get_data(change));
	
	osync_assert_msg(context->changes_function, "The engine must set a callback to receive changes");
	
	context->changes_function(change, context->callback_data);
	
	osync_trace(TRACE_EXIT, "%s", __func__);
}
Ejemplo n.º 6
0
static void mock_read(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, OSyncChange *change, void *data)
{
	osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, sink, info, ctx, change, data);
	MockDir *dir = data;
	OSyncError *error = NULL;

	char *filename = g_strdup_printf("%s/%s", dir->path, osync_change_get_uid(change));

	OSyncFileFormat *file = osync_try_malloc0(sizeof(OSyncFileFormat), &error);
	osync_assert(file);
	file->path = g_strdup(osync_change_get_uid(change));

	struct stat filestats;
	stat(filename, &filestats);
	file->userid = filestats.st_uid;
	file->groupid = filestats.st_gid;
	file->mode = filestats.st_mode;
	file->last_mod = filestats.st_mtime;

	osync_assert(osync_file_read(filename, &(file->data), &(file->size), &error));

	OSyncData *odata = osync_data_new((char *)file, sizeof(OSyncFileFormat), dir->objformat, &error);
	osync_assert(odata);

	osync_trace(TRACE_INTERNAL, "odata: %p", odata);

	osync_data_set_objtype(odata, osync_objtype_sink_get_name(sink));
	osync_change_set_data(change, odata);
	osync_data_unref(odata);

	osync_context_report_success(ctx);

	g_free(filename);

	osync_trace(TRACE_EXIT, "%s", __func__);
	return;
}
Ejemplo n.º 7
0
//typedef void (* OSyncContextChangeFn) (OSyncChange *, void *);
static void _osyncplugin_ctx_change_callback(OSyncChange *change, void *user_data)
{
	Command *cmd = (Command *) user_data;		
	OSyncObjTypeSink *sink = cmd->sink;

	printf("GETCHANGES:\t%s\t%s\t%s", 
	       _osyncplugin_changetype_str(change), 
	       osync_objtype_sink_get_name(sink),	
	       osync_change_get_uid(change));

	if (osync_change_get_objformat(change))
		printf("\t%s", osync_objformat_get_name(osync_change_get_objformat(change)));

	printf("\n");

	osync_change_ref(change);
	changesList = g_list_append(changesList, change);
}
Ejemplo n.º 8
0
static osync_bool mock_write(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, OSyncChange *change, void *data)
{
	osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, sink, info, ctx, change, data);
	MockDir *dir = data;
	OSyncError *error = NULL;
	OSyncData *odata = NULL;
	char *buffer = NULL;
	unsigned int size = 0;

	char *filename = g_strdup_printf ("%s/%s", dir->path, osync_change_get_uid(change));

	switch (osync_change_get_changetype(change)) {
		case OSYNC_CHANGE_TYPE_DELETED:
			osync_assert(remove(filename) == 0);
			break;
		case OSYNC_CHANGE_TYPE_ADDED:
			osync_assert(!g_file_test(filename, G_FILE_TEST_EXISTS));
			/* No break. Continue below */
		case OSYNC_CHANGE_TYPE_MODIFIED:
			//FIXME add ownership for file-sync
			odata = osync_change_get_data(change);
			g_assert(odata);
			osync_data_get_data(odata, &buffer, &size);
			g_assert(buffer);
			g_assert(size == sizeof(OSyncFileFormat));

			OSyncFileFormat *file = (OSyncFileFormat *)buffer;

			osync_assert(osync_file_write(filename, file->data, file->size, file->mode, &error));
			break;
		case OSYNC_CHANGE_TYPE_UNMODIFIED:
			osync_assert_msg(FALSE, "Unmodified in a change function?!");
			break;
		case OSYNC_CHANGE_TYPE_UNKNOWN:
			osync_assert_msg(FALSE, "Unknown Change Type");
			break;
	}

	g_free(filename);

	osync_trace(TRACE_EXIT, "%s", __func__);
	return TRUE;
}
Ejemplo n.º 9
0
static void mock_commit_change(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, OSyncChange *change, void *data)
{
	osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, sink, info, ctx, change, data);
	MockDir *dir = data;
	OSyncHashTable *hashtable = osync_objtype_sink_get_hashtable(sink);

	char *filename = NULL;

	osync_assert(dir->committed_all == FALSE);

	if (mock_get_error(info->memberid, "COMMIT_ERROR")) {
		osync_context_report_error(ctx, OSYNC_ERROR_EXPECTED, "Triggering COMMIT_ERROR error");
		return;
	}
	if (mock_get_error(info->memberid, "COMMIT_TIMEOUT")) {
		osync_trace(TRACE_EXIT_ERROR, "COMMIT_TIMEOUT (mock-sync)!");
		return;
	}

	if (!mock_write(sink, info, ctx, change, data)) {
		osync_trace(TRACE_EXIT_ERROR, "%s", __func__);
		return;
	}

	filename = g_strdup_printf ("%s/%s", dir->path, osync_change_get_uid(change));
	char *hash = NULL;

	if (osync_change_get_changetype(change) != OSYNC_CHANGE_TYPE_DELETED) {
		struct stat buf;
		stat(filename, &buf);
		hash = mock_generate_hash(&buf);
		osync_change_set_hash(change, hash);
		g_free(hash);
	}
	g_free(filename);


	osync_hashtable_update_change(hashtable, change);

	osync_context_report_success(ctx);

	osync_trace(TRACE_EXIT, "%s", __func__);
}
Ejemplo n.º 10
0
void update_change_list(OSyncEngine *engine)
{
	g_assert(engine);
	members = NULL;
	GList *v;
	GList *e;
	for (v = engine->maptable->views; v; v = v->next) {
		member_info *meminfo = g_malloc0(sizeof(member_info));
		members = g_list_append(members, meminfo);
		OSyncMappingView *view = v->data;
		meminfo->member = view->client->member;
		for (e = view->changes; e; e = e->next) {
			OSyncMappingEntry *entry = e->data;
			change_info *chinfo = g_malloc0(sizeof(change_info));
			meminfo->changes = g_list_append(meminfo->changes, chinfo);
			chinfo->change = entry->change;
			chinfo->type = CHANGE_UNMODIFIED;
			chinfo->uid = g_strdup(osync_change_get_uid(chinfo->change));
		}
	}
}
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;
}
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;
}
osync_bool osync_obj_engine_command(OSyncObjEngine *engine, OSyncEngineCmd cmd, OSyncError **error)
{
  GList *p = NULL;
  GList *m = NULL;
  GList *e = NULL;
  OSyncSinkEngine *sinkengine =  NULL;

	
  osync_trace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, engine, cmd, error);
  osync_assert(engine);
	
  switch (cmd) {
    int write_sinks = 0;
    osync_bool proxy_disconnect = FALSE;
  case OSYNC_ENGINE_COMMAND_CONNECT:
    for (p = engine->sink_engines; p; p = p->next) {
      sinkengine = p->data;

      if (!osync_client_proxy_connect(sinkengine->proxy, _osync_obj_engine_connect_callback, sinkengine, engine->objtype, engine->slowsync, error))
        goto error;
    }
    break;
  case OSYNC_ENGINE_COMMAND_READ:
    for (p = engine->sink_engines; p; p = p->next) {
      sinkengine = p->data;
      for (m = sinkengine->entries; m; m = m->next) {
        OSyncMappingEntryEngine *entry = m->data;
        OSyncChange *change = entry->change;

        if (!change)
          continue;

        if (!osync_client_proxy_read(sinkengine->proxy, _osync_obj_engine_read_ignored_callback, sinkengine, change, error))
          goto error;
      }
    }

    if (engine->archive) {
      /* Flush the changelog - to avoid double entries of ignored entries */
      if (!osync_archive_flush_ignored_conflict(engine->archive, engine->objtype, error))
        goto error;
    }

    write_sinks = _osync_obj_engine_num_write_sinks(engine);

    /* Get change entries since last sync. (get_changes) */
    for (p = engine->sink_engines; p; p = p->next) {
      OSyncMember *member = NULL;
      OSyncObjTypeSink *objtype_sink = NULL;

      sinkengine = p->data;

      member = osync_client_proxy_get_member(sinkengine->proxy);
      objtype_sink = osync_member_find_objtype_sink(member, engine->objtype);

      /* Is there at least one other writeable sink? */
      if (objtype_sink && osync_objtype_sink_get_write(objtype_sink) && write_sinks) {
        _osync_obj_engine_read_callback(sinkengine->proxy, sinkengine, *error);
        osync_trace(TRACE_INTERNAL, "no other writable sinks .... SKIP");
        continue;
      }

      if (!osync_client_proxy_get_changes(sinkengine->proxy, _osync_obj_engine_read_callback, sinkengine, engine->objtype, engine->slowsync, error))
        goto error;
    }

    break;
  case OSYNC_ENGINE_COMMAND_WRITE:
    if (engine->conflicts) {
      osync_trace(TRACE_INTERNAL, "We still have conflict. Delaying write");
      break;
    }
		
    if (engine->written) {
      osync_trace(TRACE_INTERNAL, "Already written");
      break;
    }
				
    engine->written = TRUE;
		
    /* Write the changes. First, we can multiply the winner in the mapping */
    osync_trace(TRACE_INTERNAL, "Preparing write. multiplying %i mappings", g_list_length(engine->mapping_engines));
    for (m = engine->mapping_engines; m; m = m->next) {
      OSyncMappingEngine *mapping_engine = m->data;
      if (!osync_mapping_engine_multiply(mapping_engine, error))
        goto error;
    }
			
    osync_trace(TRACE_INTERNAL, "Starting to write");
    for (p = engine->sink_engines; p; p = p->next) {
      OSyncMember *member = NULL;
      long long int memberid = 0;
      OSyncObjTypeSink *objtype_sink = NULL;
      OSyncFormatConverterPath *path = NULL;

      sinkengine = p->data;
      member = osync_client_proxy_get_member(sinkengine->proxy);
      memberid = osync_member_get_id(member);
      objtype_sink = osync_member_find_objtype_sink(member, engine->objtype);
				
      /* If sink could not be found use "data" sink if available */
      if (!objtype_sink)
        objtype_sink = osync_member_find_objtype_sink(member, "data");
      /* TODO: Review if objtype_sink = NULL is valid at all. */

      for (e = sinkengine->entries; e; e = e->next) {
        OSyncMappingEntryEngine *entry_engine = e->data;
        osync_assert(entry_engine);

        /* Merger - Save the entire xml and demerge */
        /* TODO: is here the right place to save the xml???? */
        if (osync_group_get_merger_enabled(osync_engine_get_group(engine->parent)) &&
            osync_group_get_converter_enabled(osync_engine_get_group(engine->parent)) &&	
            entry_engine->change &&
            (osync_change_get_changetype(entry_engine->change) != OSYNC_CHANGE_TYPE_DELETED) &&
            !strncmp(osync_objformat_get_name(osync_change_get_objformat(entry_engine->change)), "xmlformat-", 10) )
          {
            char *buffer = NULL;
            unsigned int xmlformat_size = 0, size = 0;
            OSyncXMLFormat *xmlformat = NULL;
            const char *objtype = NULL;
            OSyncMapping *mapping = NULL;
            OSyncMerger *merger = NULL; 

            osync_trace(TRACE_INTERNAL, "Entry %s for member %lli: Dirty: %i", osync_change_get_uid(entry_engine->change), memberid, osync_entry_engine_is_dirty(entry_engine));

            osync_trace(TRACE_INTERNAL, "Save the entire XMLFormat and demerge.");
            objtype = osync_change_get_objtype(entry_engine->change);
            mapping = entry_engine->mapping_engine->mapping;
						
            osync_data_get_data(osync_change_get_data(entry_engine->change), (char **) &xmlformat, &xmlformat_size);
            osync_assert(xmlformat_size == osync_xmlformat_size());

            if(!osync_xmlformat_assemble(xmlformat, &buffer, &size)) {
              osync_error_set(error, OSYNC_ERROR_GENERIC, "Could not assamble the xmlformat");
              goto error;	
            }

            if(!osync_archive_save_data(engine->archive, osync_mapping_get_id(mapping), objtype, buffer, size, error)) {
              g_free(buffer);	
              goto error;			
            }
            g_free(buffer);
						
            merger = osync_member_get_merger(osync_client_proxy_get_member(sinkengine->proxy));
            if(merger)
              osync_merger_demerge(merger, xmlformat);
          }


        /* Only commit change if the objtype sink is able/allowed to write. */
        if (objtype_sink && osync_objtype_sink_get_write(objtype_sink) && osync_entry_engine_is_dirty(entry_engine)) {
          OSyncChange *change = entry_engine->change;
          osync_assert(entry_engine->change);

          /* Convert to requested target format if the changetype is not DELETED */
          if (osync_group_get_converter_enabled(osync_engine_get_group(engine->parent)) && (osync_change_get_changetype(change) != OSYNC_CHANGE_TYPE_DELETED)) {

            char *objtype = NULL;
            OSyncList *format_sinks = NULL;
            unsigned int length = 0;
            OSyncFormatConverter *converter = NULL;

            osync_trace(TRACE_INTERNAL, "Starting to convert from objtype %s and format %s", osync_change_get_objtype(entry_engine->change), osync_objformat_get_name(osync_change_get_objformat(entry_engine->change)));
            /* We have to save the objtype of the change so that it does not get
             * overwritten by the conversion */
            objtype = g_strdup(osync_change_get_objtype(change));
							
            /* Now we have to convert to one of the formats
             * that the client can understand */
            format_sinks = osync_objtype_sink_get_objformat_sinks(objtype_sink);
            if (!format_sinks) {
              osync_error_set(error, OSYNC_ERROR_GENERIC, "There are no available format sinks.");
              goto error;
            }
						
            /* We cache the converter path for each sink/member couple */
            if (!path) {
              path = osync_format_env_find_path_formats_with_detectors(engine->formatenv, osync_change_get_data(entry_engine->change), format_sinks, osync_objtype_sink_get_preferred_format(objtype_sink), error);
            }
            if (!path)
              goto error;

            length = osync_converter_path_num_edges(path);
            converter = osync_converter_path_nth_edge(path, length - 1);
            if (converter) {
              OSyncObjFormat *format = osync_converter_get_targetformat(converter);
              OSyncObjFormatSink *formatsink = osync_objtype_sink_find_objformat_sink(objtype_sink, format);
              osync_converter_path_set_config(path, osync_objformat_sink_get_config(formatsink));
            }

            if (!osync_format_env_convert(engine->formatenv, path, osync_change_get_data(entry_engine->change), error)) {
              osync_converter_path_unref(path);
              goto error;
            }
            osync_trace(TRACE_INTERNAL, "converted to format %s", osync_objformat_get_name(osync_change_get_objformat(entry_engine->change)));
							
							
            osync_change_set_objtype(change, objtype);
            g_free(objtype);
          }
						
          osync_trace(TRACE_INTERNAL, "Writing change %s, changetype %i, format %s , objtype %s from member %lli", 
                      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(osync_client_proxy_get_member(sinkengine->proxy)));
	
          if (!osync_client_proxy_commit_change(sinkengine->proxy, _osync_obj_engine_commit_change_callback, entry_engine, osync_entry_engine_get_change(entry_engine), error))
            goto error;
        } else if (entry_engine->change) {
          OSyncMapping *mapping = entry_engine->mapping_engine->mapping;
          OSyncMember *member = osync_client_proxy_get_member(sinkengine->proxy);
          OSyncMappingEntry *entry = entry_engine->entry;
          const char *objtype = osync_change_get_objtype(entry_engine->change);
						
          if (engine->archive) {
            if (osync_change_get_changetype(entry_engine->change) == OSYNC_CHANGE_TYPE_DELETED) {
              if (!osync_archive_delete_change(engine->archive, osync_mapping_entry_get_id(entry), objtype, error))
                goto error;
            } else {
              if (!osync_archive_save_change(engine->archive, osync_mapping_entry_get_id(entry), osync_change_get_uid(entry_engine->change), objtype, osync_mapping_get_id(mapping), osync_member_get_id(member), error))
                goto error;
            }
          }
        }
      }
			
      if (path)
        osync_converter_path_unref(path);

      if (!osync_client_proxy_committed_all(sinkengine->proxy, _osync_obj_engine_written_callback, sinkengine, engine->objtype, error))
        goto error;
    }
    break;
  case OSYNC_ENGINE_COMMAND_SYNC_DONE:
    for (p = engine->sink_engines; p; p = p->next) {
      sinkengine = p->data;
      if (!osync_client_proxy_sync_done(sinkengine->proxy, _osync_obj_engine_sync_done_callback, sinkengine, engine->objtype, error))
        goto error;
    }
    break;
  case OSYNC_ENGINE_COMMAND_DISCONNECT:;
    for (p = engine->sink_engines; p; p = p->next) {
      sinkengine = p->data;

      /* Don't call client disconnect functions if the sink is already disconnected.
         This avoids unintended disconnect calls of clients/plugins which might not prepared
         for a disconnect call when their never got connected. (testcases: *_connect_error, *_connect_timeout ..) */
      if (!osync_sink_engine_is_connected(sinkengine))
        continue;

      proxy_disconnect = TRUE;

      if (!osync_client_proxy_disconnect(sinkengine->proxy, _osync_obj_engine_disconnect_callback, sinkengine, engine->objtype, error))
        goto error;
    }
			
    /* If no client needs to be disconnected, we MUST NOT expected any 
       disconnected_callback which generates an OSYNC_ENGINE_EVENT_DISCONNECTED event.
       So we directly generate such event on our own. (testcases: double_connect_*, triple_connnect_*) */ 
    if (!proxy_disconnect)
      _osync_obj_engine_generate_event_disconnected(engine, NULL);

    break;
  case OSYNC_ENGINE_COMMAND_SOLVE:
  case OSYNC_ENGINE_COMMAND_DISCOVER:
  case OSYNC_ENGINE_COMMAND_ABORT:
    break;
  }
	
  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_obj_engine_map_changes(OSyncObjEngine *engine, OSyncError **error)
{
  OSyncMappingEngine *mapping_engine = NULL;
  GList *new_mappings = NULL, *v = NULL;
	
  osync_trace(TRACE_ENTRY, "%s(%p)", __func__, engine);
  //osync_trace_disable();

  /* Go through all sink engines that are available */
  for (v = engine->sink_engines; v; v = v->next) {
    OSyncSinkEngine *sinkengine = v->data;
		
    /* We use a temp list to speed things up. We dont have to compare with newly created mappings for
     * the current sinkengine, since there will be only one entry (for the current sinkengine) so there
     * is no need to compare */
    new_mappings = NULL;
		
    /* For each sinkengine, go through all unmapped changes */
    while (sinkengine->unmapped) {
      OSyncChange *change = sinkengine->unmapped->data;
      OSyncConvCmpResult result = 0;
      OSyncMappingEntryEngine *entry_engine = NULL;
			
      osync_trace(TRACE_INTERNAL, "Looking for mapping for change %s, changetype %i from member %lli", osync_change_get_uid(change), osync_change_get_changetype(change), osync_member_get_id(osync_client_proxy_get_member(sinkengine->proxy)));
	
      /* See if there is an exisiting mapping, which fits the unmapped change */
      result = _osync_obj_engine_mapping_find(engine, change, sinkengine, &mapping_engine);
      if (result == OSYNC_CONV_DATA_MISMATCH) {
        /* If there is none, create one */
        mapping_engine = _osync_obj_engine_create_mapping_engine(engine, error);
        if (!mapping_engine)
          goto error;
				
        osync_trace(TRACE_INTERNAL, "Unable to find mapping. Creating new mapping with id %lli", osync_mapping_get_id(mapping_engine->mapping));
				
        new_mappings = g_list_append(new_mappings, mapping_engine);
      } else if (result == OSYNC_CONV_DATA_SIMILAR) {
        mapping_engine->conflict = TRUE;
      }
      /* Update the entry which belongs to our sinkengine with the the change */
      entry_engine = osync_mapping_engine_get_entry(mapping_engine, sinkengine);
      osync_assert(entry_engine);
			
      osync_entry_engine_update(entry_engine, change);
      sinkengine->unmapped = g_list_remove(sinkengine->unmapped, sinkengine->unmapped->data);
      osync_change_unref(change);
    }
		
    engine->mapping_engines = g_list_concat(engine->mapping_engines, new_mappings);
  }
	
  //osync_trace_enable();
  osync_trace(TRACE_EXIT, "%s", __func__);
  return TRUE;

 error:
  osync_trace_enable();
  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
  return FALSE;
}
Ejemplo n.º 15
0
void claws_mail_event_get_changes(void *userdata, OSyncPluginInfo *info,
																	OSyncContext *ctx)
{
	int ii;
	char **uids;
	char *vevent;

	osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, userdata, info, ctx);

	OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
	ClawsMailSinkEnv *sinkenv = osync_objtype_sink_get_userdata(sink);

	OSyncError *error = NULL;

	osync_hashtable_reset_reports(sinkenv->hashtable);

	/* check for slowsync and prepare the "event" hashtable if needed */
	if(osync_objtype_sink_get_slowsync(sinkenv->sink)) {
		osync_trace(TRACE_INTERNAL, "Slow sync requested");
		if(!osync_hashtable_slowsync(sinkenv->hashtable, &error))	{
			osync_context_report_osyncerror(ctx, error);
			osync_trace(TRACE_EXIT_ERROR, "%s - %s", __func__,
									osync_error_print(&error));
			osync_error_unref(&error);
			return;
		}
	}

	/* While getting all events, one at a time */
	while((vevent = claws_mail_connect_get_events()) != NULL) {
		gchar *uid;
		gchar *hash;
		char *data;
		OSyncChangeType changetype;
		OSyncChange *change;
		OSyncData *odata;
		
		hash = event_hash(vevent);
		uid = get_uid_from_event(vevent);

		/* Now get the data of this change */
		data = vevent;

		/* Report every entry .. every unreported entry got deleted. */
		osync_trace(TRACE_INTERNAL, "hhb: Report: %s",uid);
		osync_hashtable_report(sinkenv->hashtable, uid);

		changetype = osync_hashtable_get_changetype(sinkenv->hashtable, uid, hash);

		if (changetype == OSYNC_CHANGE_TYPE_UNMODIFIED) {
			g_free(hash);
			g_free(uid);
			continue;
		}

		/* Set the hash of the object */
		osync_hashtable_update_hash(sinkenv->hashtable, changetype, uid, hash);

		/* Make the new change to report */
		change = osync_change_new(&error);

		if(!change) {
			osync_context_report_osyncwarning(ctx, error);
			osync_error_unref(&error);
			g_free(uid);
			g_free(hash);
			continue;
		}

		/* Now set the uid of the object */
		osync_change_set_uid(change, uid);
		osync_change_set_hash(change, hash);
		osync_change_set_changetype(change, changetype);

		g_free(hash);
		g_free(uid);

		odata = osync_data_new(data, strlen(data), sinkenv->objformat, &error);
		if (!odata) {
			osync_change_unref(change);
			osync_context_report_osyncwarning(ctx, error);
			osync_error_unref(&error);
			continue;
		}

		osync_data_set_objtype(odata, osync_objtype_sink_get_name(sinkenv->sink));

		/* Set the data for the object */
		osync_change_set_data(change, odata);
		osync_data_unref(odata);

		/* Report the change */
		osync_context_report_change(ctx, change);

		osync_change_unref(change);
	}

	/* Check for deleted entries */
	uids = osync_hashtable_get_deleted(sinkenv->hashtable);

	for (ii=0; uids[ii]; ii++) {
		OSyncData *odata;
		OSyncChange *change = osync_change_new(&error);
		if (!change) {
			g_free(uids[ii]);
			osync_context_report_osyncwarning(ctx, error);
			osync_error_unref(&error);
			continue;
		}

		osync_change_set_uid(change, uids[ii]);
		osync_change_set_changetype(change, OSYNC_CHANGE_TYPE_DELETED);

		odata = osync_data_new(NULL, 0, sinkenv->objformat, &error);
		if (!odata) {
			g_free(uids[ii]);
			osync_change_unref(change);
			osync_context_report_osyncwarning(ctx, error);
			osync_error_unref(&error);
			continue;
		}

		osync_data_set_objtype(odata, osync_objtype_sink_get_name(sinkenv->sink));
		osync_change_set_data(change, odata);
		osync_data_unref(odata);

		osync_context_report_change(ctx, change);

		osync_hashtable_update_hash(sinkenv->hashtable,
				osync_change_get_changetype(change), osync_change_get_uid(change),
																NULL);

		osync_change_unref(change);
		g_free(uids[ii]);
	}
	g_free(uids);

	osync_context_report_success(ctx);
	osync_trace(TRACE_EXIT, "%s", __func__);
}
Ejemplo n.º 16
0
$NetBSD$

Don't continue the if block.

--- tools/osyncstress.c.orig	2009-09-20 20:14:18.000000000 +0000
+++ tools/osyncstress.c
@@ -184,7 +184,7 @@ void change_content(OSyncEngine *engine)
 					case 2:
 						if (osync_member_delete_data(meminfo->member, chinfo->change)) {
 							printf("Deleting data %s for member %lli. Objtype: %s Format: %s\n", osync_change_get_uid(chinfo->change), osync_member_get_id(meminfo->member), osync_objtype_get_name(osync_change_get_objtype(chinfo->change)), osync_objformat_get_name(osync_change_get_objformat(chinfo->change)));
-							if (!osync_group_get_slow_sync(engine->group, osync_objtype_get_name(osync_change_get_objtype(chinfo->change))));
+							if (!osync_group_get_slow_sync(engine->group, osync_objtype_get_name(osync_change_get_objtype(chinfo->change))))
 								chinfo->type = CHANGE_DELETED;
 						}
 						break;
/** @brief Solves the conflict by duplicating the conflicting entries
 * 
 * @param engine The engine
 * @param dupe_mapping The conflicting mapping to duplicate
 * 
 */
osync_bool osync_mapping_engine_duplicate(OSyncMappingEngine *existingMapping, OSyncError **error)
{
  int elevation = 0;
  OSyncObjEngine *objengine = NULL;
  GList *entries = NULL, *e = NULL, *mappings = NULL;

  osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, existingMapping, error);
  g_assert(existingMapping);
	
  objengine = existingMapping->parent;
	
  /* Remove all deleted items first and copy the changes to a list */
  e = existingMapping->entries;
  for (; e; e = e->next) {
    OSyncMappingEntryEngine *entry = e->data;
    if (entry->change) {
      if (osync_change_get_changetype(entry->change) == OSYNC_CHANGE_TYPE_MODIFIED || osync_change_get_changetype(entry->change) == OSYNC_CHANGE_TYPE_ADDED) {
        osync_trace(TRACE_INTERNAL, "Appending entry %s, changetype %i from member %lli", osync_change_get_uid(entry->change), osync_change_get_changetype(entry->change), osync_member_get_id(osync_client_proxy_get_member(entry->sink_engine->proxy)));
		
        entries = g_list_append(entries, entry);
      } else {
        osync_trace(TRACE_INTERNAL, "Removing entry %s, changetype %i from member %lli", osync_change_get_uid(entry->change), osync_change_get_changetype(entry->change), osync_member_get_id(osync_client_proxy_get_member(entry->sink_engine->proxy)));
        osync_entry_engine_update(entry, NULL);
      }
    } else {
      osync_trace(TRACE_INTERNAL, "member %lli does not have a entry", osync_member_get_id(osync_client_proxy_get_member(entry->sink_engine->proxy)));
    }
  }
	
  /* Create a list with mappings. In the beginning, only the exisiting mapping is in the list */
  mappings = g_list_append(NULL, existingMapping);
  osync_mapping_engine_ref(existingMapping);
	
  while (entries) {
    OSyncMappingEntryEngine *existingEntry = entries->data;
		
    /* Now lets see which mapping is the correct one for the entry */
    GList *m = NULL;
    OSyncMappingEngine *mapping = NULL;
    OSyncChange *existingChange = NULL;
    osync_bool dirty = FALSE;
    OSyncMappingEntryEngine *newEntry = NULL;

    elevation = 0;
    for (m = mappings; m; m = m->next) {
      GList *e = NULL;
      OSyncChange *change = NULL;
      OSyncMappingEntryEngine *entry = NULL;
      mapping = m->data;
			
      /* Get the first change of the mapping to test. Compare the given change with this change.
       * If they are not the same, we have found a new mapping */
      for (e = mapping->entries; e; e = e->next) {
        entry = e->data;
        change = entry->change;
        if (change)
          break;
      }
			
      if (!change || osync_change_compare(existingEntry->change, change) == OSYNC_CONV_DATA_SAME){
        existingChange = existingEntry->change;
        osync_change_ref(existingChange);
        osync_assert(osync_change_get_uid(existingChange));
        break;
      }


      mapping = NULL;
      elevation++;
		
      existingChange = osync_change_clone(existingEntry->change, error);
      osync_assert(osync_change_get_uid(existingChange));
    }
		
		
    if (!mapping) {
      /* Unable to find a mapping. We have to create a new one */
      mapping = _osync_obj_engine_create_mapping_engine(objengine, error);
      if (!mapping)
        goto error;
      mappings = g_list_append(mappings, mapping);
      objengine->mapping_engines = g_list_append(objengine->mapping_engines, mapping);
      osync_mapping_engine_ref(mapping);
    }
		
    /* update the uid and the content to suit the new level */
    if (!_osync_change_elevate(existingChange, elevation, &dirty, error))
      goto error;

    /* Lets add the entry to the mapping */
    newEntry = osync_mapping_engine_get_entry(mapping, existingEntry->sink_engine);
    osync_assert(newEntry);
    osync_entry_engine_update(newEntry, existingChange);
    osync_mapping_entry_set_uid(newEntry->entry, osync_change_get_uid(existingChange));
    osync_change_unref(existingChange);
		
    /* Set the last entry as the master */
    osync_mapping_engine_set_master(mapping, newEntry);
		
    /* Update the dirty status. If the duplicate function said
     * that the returned item needs to be written, we will set
     * this information here */
    newEntry->dirty = dirty;
		
    entries = g_list_remove(entries, existingEntry);
  }
	
	
  while (mappings) {
    OSyncMappingEngine *mapping = mappings->data;
    osync_mapping_engine_unref(mapping);
    mappings = g_list_remove(mappings, mapping);
  }
	
  objengine->conflicts = g_list_remove(objengine->conflicts, existingMapping);
  osync_status_update_mapping(objengine->parent, existingMapping, OSYNC_MAPPING_EVENT_SOLVED, NULL);
	
  if (osync_engine_check_get_changes(objengine->parent) && osync_bitcount(objengine->sink_errors | objengine->sink_get_changes) == g_list_length(objengine->sink_engines)) {
    if (!osync_obj_engine_command(objengine, OSYNC_ENGINE_COMMAND_WRITE, error))
      goto error;
  } else
    osync_trace(TRACE_INTERNAL, "Not triggering write. didnt receive all reads yet");

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

 error:
  while (mappings) {
    OSyncMappingEngine *mapping = mappings->data;
    osync_mapping_engine_unref(mapping);
    mappings = g_list_remove(mappings, mapping);
  }
  osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
  return FALSE;
}
Ejemplo n.º 18
0
void change_content(OSyncEngine *engine)
{
	GList *m;
	for (m = members; m; m = m->next) {
		member_info *meminfo = m->data;
		
		busy = TRUE;
		osync_member_connect(meminfo->member, (OSyncEngCallback)stress_message_callback, NULL);
		if (busy)
			g_main_loop_run(loop);
		
		GList *c = NULL;
		for (c = meminfo->changes; c; c = c->next) {
			change_info *chinfo = c->data;
			if (g_random_int_range(0, 3) == 0) {
				switch (g_random_int_range(1, 6)) {
					case 1:
					case 5:
						if (osync_member_modify_random_data(meminfo->member, chinfo->change)) {
							printf("Modifying data %s for member %lli. Objtype: %s Format: %s\n", osync_change_get_uid(chinfo->change), osync_member_get_id(meminfo->member), osync_objtype_get_name(osync_change_get_objtype(chinfo->change)), osync_objformat_get_name(osync_change_get_objformat(chinfo->change)));
							chinfo->type = CHANGE_MODIFIED;
						}
						break;
					case 2:
						if (osync_member_delete_data(meminfo->member, chinfo->change)) {
							printf("Deleting data %s for member %lli. Objtype: %s Format: %s\n", osync_change_get_uid(chinfo->change), osync_member_get_id(meminfo->member), osync_objtype_get_name(osync_change_get_objtype(chinfo->change)), osync_objformat_get_name(osync_change_get_objformat(chinfo->change)));
							if (!osync_group_get_slow_sync(engine->group, osync_objtype_get_name(osync_change_get_objtype(chinfo->change))));
								chinfo->type = CHANGE_DELETED;
						}
						break;
					case 3:
						//printf("Modifying all for %s\n", osync_change_get_uid(change));
						break;
					case 4:
						//printf("Deleting all for %s\n", osync_change_get_uid(change));
						break;
					default:
						printf("error\n");
				}
			}
		}
		
		int num_new = g_random_int_range(0, 8);
		int n = 0;;
		for (n = 0; n < num_new; n++) {
			change_info *chinfo = g_malloc0(sizeof(change_info));
			if ((chinfo->change = osync_member_add_random_data(meminfo->member, NULL))) {
				if (find_change_info(meminfo, chinfo->change))
					continue;
				meminfo->changes = g_list_append(meminfo->changes, chinfo);
				chinfo->type = CHANGE_ADDED;
				chinfo->uid = g_strdup(osync_change_get_uid(chinfo->change));
				printf("Adding new data %s for member %lli. Objtype: %s Format: %s\n", osync_change_get_uid(chinfo->change), osync_member_get_id(meminfo->member), osync_objtype_get_name(osync_change_get_objtype(chinfo->change)), osync_objformat_get_name(osync_change_get_objformat(chinfo->change)));
			}
		}
		
		busy = TRUE;
		osync_member_disconnect(meminfo->member, (OSyncEngCallback)stress_message_callback, NULL);
		if (busy)
			g_main_loop_run(loop);
	}
}
Ejemplo n.º 19
0
/** Add or change an incidence on the calendar. This function
 * is used for events and to-dos
 */
bool KCalSharedResource::commit(OSyncDataSource *dsobj, OSyncContext *ctx, OSyncChange *chg)
{
	OSyncChangeType type = osync_change_get_changetype(chg);
	switch (type) {
		case OSYNC_CHANGE_TYPE_DELETED: {
			KCal::Incidence *e = calendar->incidence(QString::fromUtf8(osync_change_get_uid(chg)));
			if (!e) {
				osync_context_report_error(ctx, OSYNC_ERROR_FILE_NOT_FOUND, "Event not found while deleting");
				return false;
			}
			calendar->deleteIncidence(e);
			break;
		}
		case OSYNC_CHANGE_TYPE_ADDED:
		case OSYNC_CHANGE_TYPE_MODIFIED: {
			KCal::ICalFormat format;

			OSyncData *odata = osync_change_get_data(chg);

			char *databuf;
			//size_t databuf_size;
			// osync_data_get_data requires an unsigned int which is not compatible with size_t on 64bit machines
			unsigned int databuf_size = 0;
			osync_data_get_data(odata, &databuf, &databuf_size);

			/* First, parse to a temporary calendar, because
				* we should set the uid on the events
				*/

			KCal::CalendarLocal cal(QString::fromLatin1( "UTC" ));
			QString data = QString::fromUtf8(databuf, databuf_size);
			if (!format.fromString(&cal, data)) {
				osync_context_report_error(ctx, OSYNC_ERROR_CONVERT, "Couldn't import calendar data");
				return false;
			}

			KCal::Incidence *oldevt = calendar->incidence(QString::fromUtf8(osync_change_get_uid(chg)));
			if (oldevt) {
				calendar->deleteIncidence(oldevt);
                        }

			/* Add the events from the temporary calendar, setting the UID
				*
				* We iterate over the list, but it should have only one event.
				*/
			KCal::Incidence::List evts = cal.incidences();
			for (KCal::Incidence::List::ConstIterator i = evts.begin(); i != evts.end(); i++) {
				KCal::Incidence *e = (*i)->clone();
				if (type == OSYNC_CHANGE_TYPE_MODIFIED)
					e->setUid(QString::fromUtf8(osync_change_get_uid(chg)));

				// if we run with a configured category filter, but the received added incidence does
				// not contain that category, add the filter-categories so that the incidence will be
				// found again on the next sync
				if ( ! dsobj->has_category(e->categories()) )
        {
          QStringList cats = e->categories();

					for (QStringList::const_iterator it = dsobj->categories.constBegin(); it != dsobj->categories.constEnd(); ++it )
						cats.append(*it);

          e->setCategories(cats);
				}

				osync_change_set_uid(chg, e->uid().utf8());
				QString hash = calc_hash(*i);
				osync_change_set_hash(chg, hash.utf8());
				calendar->addIncidence(e);
			}
			break;
		}
		default: {
			osync_context_report_error(ctx, OSYNC_ERROR_NOT_SUPPORTED, "Invalid or unsupported change type");
			return false;
		}
	}

	return true;
}
Ejemplo n.º 20
0
void claws_mail_event_commit_change(void *userdata, OSyncPluginInfo *info,
																		OSyncContext *ctx, OSyncChange *change)
{
	gboolean retVal;
	gchar *vevent;
	char *uid;
	char *hash;
	char *new_event = NULL;
	OSyncError *error = NULL;

	osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)",
							__func__, userdata, info, ctx, change);
	
	OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
	ClawsMailSinkEnv *sinkenv = osync_objtype_sink_get_userdata(sink);
	
	osync_data_get_data(osync_change_get_data(change), &vevent, NULL);

	switch (osync_change_get_changetype(change)) {
		
	case OSYNC_CHANGE_TYPE_DELETED:
		retVal = claws_mail_connect_delete_event(osync_change_get_uid(change));
		if(!retVal) {
			osync_error_set(&error, OSYNC_ERROR_GENERIC,
											"Unable to delete event.");
			goto error;
		}
		break;

	case OSYNC_CHANGE_TYPE_ADDED:
		if((new_event = claws_mail_connect_add_event(vevent)) == NULL) {
			osync_error_set(&error, OSYNC_ERROR_GENERIC, "Unable to write event.");
			goto error;
		}

		/* generate and set hash of entry */
		hash = event_hash(new_event);
		osync_change_set_hash(change, hash);
		g_free(hash);
		g_free(new_event);
		break;
		
	case OSYNC_CHANGE_TYPE_MODIFIED:
		uid = (gchar*) osync_change_get_uid(change);
		new_event = claws_mail_connect_modify_event(uid,vevent);
		if(!new_event) {
			osync_error_set(&error, OSYNC_ERROR_GENERIC,
											"Unable to modify event.");
			goto error;
		}
		hash = event_hash(new_event);
		osync_change_set_hash(change, hash);
		g_free(hash);
		g_free(new_event);
		break;

	default:
		osync_trace(TRACE_INTERNAL, "Unknown change type");
		break;
	}

	/* Calculate the hash */
	osync_hashtable_update_hash(sinkenv->hashtable,
															osync_change_get_changetype(change),
															osync_change_get_uid(change),
															osync_change_get_hash(change));

	/* Answer the call */
	osync_context_report_success(ctx);

	osync_trace(TRACE_EXIT, "%s", __func__);
	return;

 error:

	osync_context_report_osyncerror(ctx, error);
	osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(&error));
	osync_error_unref(&error);
}