Beispiel #1
0
static void commit_change(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, OSyncChange *change, void *userdata)
{
	OSyncHashTable *hashtable = osync_objtype_sink_get_hashtable(sink);
	
	/*
	 * Here you have to add, modify or delete a object
	 * 
	 */
	switch (osync_change_get_changetype(change)) {
		case OSYNC_CHANGE_TYPE_DELETED:
			//Delete the change
			//Dont forget to answer the call on error
			break;
		case OSYNC_CHANGE_TYPE_ADDED:
			//Add the change
			//Dont forget to answer the call on error
			osync_change_set_hash(change, "new hash");
			break;
		case OSYNC_CHANGE_TYPE_MODIFIED:
			//Modify the change
			//Dont forget to answer the call on error
			osync_change_set_hash(change, "new hash");
			break;
		default:
			;
	}

	//If you are using hashtables you have to calculate the hash here:
	osync_hashtable_update_change(hashtable, change);

	//Answer the call
	osync_context_report_success(ctx);
}
Beispiel #2
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__);
}
Beispiel #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;
}
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);
}
Beispiel #5
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__);
}
Beispiel #6
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__);
}
Beispiel #7
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);
}
Beispiel #8
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__);
}