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;
}
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));
}
示例#3
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;
}
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;
}
示例#5
0
END_TEST

START_TEST (hashtable_reload)
{
	OSyncError *error = NULL;
	char *testbed = setup_testbed(NULL);

	osync_bool new_hashtable = FALSE;

	reset_hashtable_counters();

	char *hashpath = g_strdup_printf("%s%chashtable.db", testbed, G_DIR_SEPARATOR);
	OSyncHashTable *table = osync_hashtable_new(hashpath, "contact", &new_hashtable, &error);
	fail_unless(!error, NULL);
	fail_unless(table != NULL, NULL);
	fail_unless(new_hashtable != FALSE, NULL); /* Expecting a new/fresh hastable */

	/***** load */
	fail_unless(osync_hashtable_load(table, &error), NULL);

	OSyncChange *fakechange = osync_change_new(&error);

	osync_change_set_uid(fakechange, "test1");

	char *rndhash = osync_rand_str(g_random_int_range(100, 200), &error);
	osync_assert(error == NULL);

	osync_change_set_hash(fakechange, rndhash);
	osync_change_set_changetype(fakechange, OSYNC_CHANGE_TYPE_ADDED);

	osync_hashtable_update_change(table, fakechange);
	osync_change_unref(fakechange);

	/*** store - commit hashtable */
	fail_unless(osync_hashtable_save(table, &error), NULL);
	fail_unless(!error, NULL);

	osync_hashtable_unref(table);
	table = NULL;

	/** reload the hashtable */
	OSyncHashTable *newtable = osync_hashtable_new(hashpath, "contact", &new_hashtable, &error);
	fail_unless(!error, NULL);
	fail_unless(newtable != NULL, NULL);
	fail_unless(new_hashtable != TRUE, NULL); /* We expect here no new hashtable */

	/* 0 entries - since not loaded! */
	fail_unless(osync_hashtable_num_entries(newtable) == 0, NULL);

	/* load and count and compare hashs */
	fail_unless(osync_hashtable_load(newtable, &error), NULL);

	fail_unless(osync_hashtable_num_entries(newtable) == 1, NULL);

	const char *newhash = osync_hashtable_get_hash(newtable, "test1");
	fail_unless(newhash != NULL, NULL);
	fail_unless(!strcmp(newhash, rndhash), NULL);
	g_free(rndhash);


	g_free(hashpath);

	destroy_testbed(testbed);
}
示例#6
0
static void get_changes(void *userdata, OSyncPluginInfo *info, OSyncContext *ctx)
{
	osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, userdata, info, ctx);

	//plugin_environment *env = (plugin_environment *)userdata;
	OSyncFormatEnv *formatenv = osync_plugin_info_get_format_env(info);
	OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
	sink_environment *sinkenv = osync_objtype_sink_get_userdata(sink);

	OSyncError *error = NULL;

	//If you use opensync hashtables you can detect if you need
	//to do a slow-sync and set this on the hastable directly
	//otherwise you have to make 2 function like "get_changes" and
	//"get_all" and decide which to use using
	//osync_objtype_sink_get_slow_sync
	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;
		}

	}

	/*
	 * Now you can get the changes.
	 * Loop over all changes you get and do the following:
	 */

	do {
		char *hash = osync_strdup("<the calculated hash of the object>");
		char *uid = osync_strdup("<some uid>");

		//Now get the data of this change
		char *data = NULL;

		//Make the new change to report
		OSyncChange *change = osync_change_new(&error);
		if (!change) {
			osync_context_report_osyncwarning(ctx, error);
			osync_error_unref(&error);
			continue;
		}

		//Now set the uid of the object
		osync_change_set_uid(change, uid);
		osync_change_set_hash(change, hash);
		
		OSyncChangeType changetype = osync_hashtable_get_changetype(sinkenv->hashtable, change);
		osync_change_set_changetype(change, changetype);
		
		// Update entry.
		// Set the hash of the object (optional, only required if you use hashtabled)
		osync_hashtable_update_change(sinkenv->hashtable, change);
		
		if (changetype == OSYNC_CHANGE_TYPE_UNMODIFIED) {
			osync_free(hash);
			osync_free(uid);
			osync_change_unref(change);
			continue;
		}

		osync_free(hash);
		osync_free(uid);

		OSyncObjFormat *format = osync_format_env_find_objformat(formatenv, "<objformat>");
		
		OSyncData *odata = osync_data_new(data, 0, format, &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));

		//Now you can set the data for the object
		osync_change_set_data(change, odata);
		osync_data_unref(odata);

		// just report the change via
		osync_context_report_change(ctx, change);

		osync_change_unref(change);

		osync_free(uid);
	} while(0);

	//When you are done looping and if you are using hashtables
	//check for deleted entries ... via hashtable
	OSyncList *u, *uids = osync_hashtable_get_deleted(sinkenv->hashtable);
	for (u = uids; u; u = u->next) {
		OSyncChange *change = osync_change_new(&error);
		if (!change) {
			osync_context_report_osyncwarning(ctx, error);
			osync_error_unref(&error);
			continue;
		}

		const char *uid = u->data;
		osync_change_set_uid(change, uid);
		osync_change_set_changetype(change, OSYNC_CHANGE_TYPE_DELETED);
		
		OSyncObjFormat *format = osync_format_env_find_objformat(formatenv, "<objformat>");
		
		OSyncData *odata = osync_data_new(NULL, 0, format, &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));
		osync_change_set_data(change, odata);
		osync_data_unref(odata);

		osync_context_report_change(ctx, change);

		osync_hashtable_update_change(sinkenv->hashtable, change);

		osync_change_unref(change);
	}
	osync_list_free(uids);

	//Now we need to answer the call
	osync_context_report_success(ctx);
	osync_trace(TRACE_EXIT, "%s", __func__);
}
示例#7
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__);
}
示例#8
0
static void mock_get_changes(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, osync_bool slow_sync, void *data)
{
	osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %i, %p)", __func__, sink, info, ctx, slow_sync, data);
	MockDir *dir = data;
	OSyncError *error = NULL;
	OSyncHashTable *hashtable = osync_objtype_sink_get_hashtable(sink);

	osync_assert(dir->committed_all == TRUE);
	dir->committed_all = FALSE;

	osync_assert(dir->connect_done == TRUE);
	dir->connect_done = FALSE;

	/* Validate that connect_doene and get_changes slow_sync
	 * is the same. To avoid mix-up of a "late slow-sync".
	 */
	if (!mock_get_error(info->memberid, "MAINSINK_CONNECT"))
		osync_assert(dir->connect_done_slowsync == slow_sync);

	if (mock_get_error(info->memberid, "GET_CHANGES_ERROR")) {
		osync_context_report_error(ctx, OSYNC_ERROR_EXPECTED, "Triggering GET_CHANGES_ERROR error");
		osync_trace(TRACE_EXIT_ERROR, "%s - Triggering GET_CHANGES error", __func__);
		return;
	}

	if (mock_get_error(info->memberid, "GET_CHANGES_TIMEOUT")) {
		osync_trace(TRACE_EXIT, "%s - Triggering GET_CHANGES_TIMEOUT (without context report!)", __func__);
		return;
	}

	if (mock_get_error(info->memberid, "GET_CHANGES_TIMEOUT2"))
		g_usleep(8*G_USEC_PER_SEC);

	if (slow_sync) {
		osync_trace(TRACE_INTERNAL, "Slow sync requested");
		osync_assert(osync_hashtable_slowsync(hashtable, &error));
	}

	osync_trace(TRACE_INTERNAL, "get_changes for %s", osync_objtype_sink_get_name(sink));

	mock_report_dir(dir, NULL, ctx, info, sink);

	OSyncList *u, *uids = osync_hashtable_get_deleted(hashtable);
	for (u = uids; u; u = u->next) {
		OSyncChange *change = osync_change_new(&error);
		osync_assert(change);

		const char *uid = u->data;

		osync_change_set_uid(change, uid);
		osync_change_set_changetype(change, OSYNC_CHANGE_TYPE_DELETED);

		OSyncData *odata = osync_data_new(NULL, 0, dir->objformat, &error);
		osync_assert(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_change(ctx, change);

		osync_hashtable_update_change(hashtable, change);

		osync_change_unref(change);
	}

	osync_context_report_success(ctx);
	osync_trace(TRACE_EXIT, "%s", __func__);
}
示例#9
0
/** Report files on a directory
 *
 * NOTE: If 'dir' is non-empty it MUST start it a slash. This is just
 * to make easier concatenation of the paths, and we can just concatenate
 * fsinfo->path and subdir to get the complete path.
 *
 * @param dir The fsinfo->path subdirectory that should be reported. Use
 *            an empty string to report files on fsinfo->path. Should
 *            start with a slash. See note above.
 *
 */
static void mock_report_dir(MockDir *directory, const char *subdir, OSyncContext *ctx, OSyncPluginInfo *info, OSyncObjTypeSink *sink)
{
	GError *gerror = NULL;
	const char *de = NULL;
	char *path = NULL;
	GDir *dir = NULL;
	OSyncError *error = NULL;
	OSyncList *sorted_dir_list = NULL;

	osync_trace(TRACE_ENTRY, "%s(%p, %s, %p, %p)", __func__, directory, subdir, ctx, sink);

	OSyncHashTable *hashtable = osync_objtype_sink_get_hashtable(sink);
	OSyncFormatEnv *formatenv = osync_plugin_info_get_format_env(info);
	osync_assert(formatenv);

	path = g_build_filename(directory->path, subdir, NULL);
	osync_trace(TRACE_INTERNAL, "path %s", path);

	dir = g_dir_open(path, 0, &gerror);
	osync_assert(dir);

	while((de = g_dir_read_name(dir))) {
		sorted_dir_list = osync_list_insert_sorted(sorted_dir_list,
			g_strdup(de), (OSyncCompareFunc)strcmp);
	}

	g_dir_close(dir);

	while(sorted_dir_list) {
		de = sorted_dir_list->data;
		char *filename = g_build_filename(path, de, NULL);
		char *relative_filename = NULL;
		if (!subdir)
			relative_filename = g_strdup(de);
		else
			relative_filename = g_build_filename(subdir, de, NULL);
		g_free(sorted_dir_list->data);
		sorted_dir_list = osync_list_remove(sorted_dir_list, sorted_dir_list->data);

		osync_trace(TRACE_INTERNAL, "path2 %s %s", filename, relative_filename);

		if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {

			struct stat buf;
			stat(filename, &buf);
			char *hash = mock_generate_hash(&buf);

			/* Report normal files */
			OSyncChange *change = osync_change_new(&error);
			osync_assert(change);

			osync_change_set_uid(change, relative_filename);

			osync_change_set_hash(change, hash);
			g_free(hash);

			OSyncChangeType type = osync_hashtable_get_changetype(hashtable, change);

			osync_change_set_changetype(change, type);
			osync_hashtable_update_change(hashtable, change);

			if (type == OSYNC_CHANGE_TYPE_UNMODIFIED) {
				g_free(filename);
				g_free(relative_filename);
				osync_change_unref(change);
				continue;
			}

			OSyncFileFormat *file = osync_try_malloc0(sizeof(OSyncFileFormat), &error);
			osync_assert(file);

			file->path = g_strdup(relative_filename);

			OSyncData *odata = NULL;

			if (!mock_get_error(info->memberid, "ONLY_INFO")) {
				osync_assert(osync_file_read(filename, &(file->data), &(file->size), &error));

				if (mock_get_error(info->memberid, "SLOW_REPORT"))
					g_usleep(1*G_USEC_PER_SEC);

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


				osync_change_set_data(change, odata);

			}

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

			osync_context_report_change(ctx, change);

			osync_change_unref(change);
		}

		g_free(filename);
		g_free(relative_filename);

	}

	g_free(path);
	osync_trace(TRACE_EXIT, "%s", __func__);
}