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); }
void KCalTodoDataSource::commit(OSyncObjTypeSink *sink, OSyncPluginInfo *, OSyncContext *ctx, OSyncChange *chg) { // We use the same function for calendar and to-do if (!kcal->commit(this, ctx, chg)) return; OSyncHashTable *hashtable = osync_objtype_sink_get_hashtable(sink); osync_hashtable_update_change(hashtable, chg); osync_context_report_success(ctx); }
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__); }
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); }
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__); }
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__); }
/** 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__); }