static void disconnect(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *userdata) { //Close all stuff you need to close //Answer the call osync_context_report_success(ctx); }
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); }
static void sync_done(void *userdata, OSyncPluginInfo *info, OSyncContext *ctx) { /* * This function will only be called if the sync was successful */ OSyncError *error = NULL; OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info); sink_environment *sinkenv = osync_objtype_sink_get_userdata(sink); //If we use anchors we have to update it now. //Now you get/calculate the current anchor of the device char *lanchor = NULL; char *anchorpath = osync_strdup_printf("%s/anchor.db", osync_plugin_info_get_configdir(info)); osync_anchor_update(anchorpath, "lanchor", lanchor); osync_free(anchorpath); //Save hashtable to database if (!osync_hashtable_save(sinkenv->hashtable, &error)) goto error; //Answer the call osync_context_report_success(ctx); return; error: osync_context_report_osyncerror(ctx, error); osync_error_unref(&error); return; }
static void mock_sync_done(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *data) { osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, sink, info, ctx, data); OSyncSinkStateDB *state_db = osync_objtype_sink_get_state_db(sink); MockDir *dir = data; if (mock_get_error(info->memberid, "SYNC_DONE_ERROR")) { osync_context_report_error(ctx, OSYNC_ERROR_EXPECTED, "Triggering SYNC_DONE_ERROR error"); return; } if (mock_get_error(info->memberid, "SYNC_DONE_TIMEOUT")) return; if (mock_get_error(info->memberid, "SYNC_DONE_REPORT_UID_UPDATE")) { unsigned int i, updates = atoi(g_getenv("SYNC_DONE_REPORT_UID_UPDATES")); const char *olduids = g_getenv("SYNC_DONE_REPORT_UID_UPDATES_OLDUIDS"); const char *newuids = g_getenv("SYNC_DONE_REPORT_UID_UPDATES_NEWUIDS"); for (i=0; i < updates; i++) { char *olduid = g_strdup_printf("%c", olduids[i]); char *newuid = g_strdup_printf("%c", newuids[i]); osync_context_report_uid_update(ctx, olduid, newuid); } } osync_assert_msg(osync_sink_state_set(state_db, "path", dir->path, NULL), "Not expected to fail!"); osync_context_report_success(ctx); osync_trace(TRACE_EXIT, "%s", __func__); }
void KCalTodoDataSource::get_changes(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, osync_bool slow_sync) { osync_trace(TRACE_ENTRY, "%s(%p, %p)", __PRETTY_FUNCTION__, info, ctx); OSyncError *error = NULL; OSyncFormatEnv *formatenv = osync_plugin_info_get_format_env(info); OSyncObjFormat *objformat = osync_format_env_find_objformat(formatenv, "vtodo20"); OSyncHashTable *hashtable = osync_objtype_sink_get_hashtable(sink); if (slow_sync) { osync_trace(TRACE_INTERNAL, "Got slow-sync"); if (!osync_hashtable_slowsync(hashtable, &error)) { osync_context_report_osyncerror(ctx, error); osync_trace(TRACE_EXIT_ERROR, "%s: %s", __PRETTY_FUNCTION__, osync_error_print(&error)); return; } } if (!kcal->get_todo_changes(this, sink, info, ctx)) { osync_trace(TRACE_EXIT_ERROR, "%s: error in get_todo_changes", __PRETTY_FUNCTION__); osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Error while detecting latest changes."); return; } if (!report_deleted(sink, info, ctx, objformat)) { osync_trace(TRACE_EXIT_ERROR, "%s", __PRETTY_FUNCTION__); osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Error while detecting deleted entries."); return; } osync_context_report_success(ctx); osync_trace(TRACE_EXIT, "%s", __PRETTY_FUNCTION__); }
static void mock_mainsink_disconnect(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *data) { osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, sink, info, ctx, data); mock_env *env = data; osync_assert(data); GList *o = env->directories; for (; o; o = o->next) { MockDir *sink_dir = o->data; if (!g_getenv("NO_COMMITTED_ALL_CHECK")) osync_assert(sink_dir->committed_all == TRUE); sink_dir->committed_all = FALSE; } if (mock_get_error(info->memberid, "DISCONNECT_ERROR")) { osync_context_report_error(ctx, OSYNC_ERROR_EXPECTED, "Triggering DISCONNECT_ERROR error"); return; } if (mock_get_error(info->memberid, "DISCONNECT_TIMEOUT")) return; osync_context_report_success(ctx); osync_trace(TRACE_EXIT, "%s", __func__); }
static void get_changes(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, osync_bool slow_sync, void *data) { printf("[EXTERNAL-DEMO]: %s slow_sync: %s\n", __func__, slow_sync ? "yes" : "no"); /** XXX: here you get your changes and report them via osync_context_report_change() */ osync_context_report_success(ctx); }
static void connect(void *userdata, OSyncPluginInfo *info, OSyncContext *ctx) { osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, userdata, info, ctx); //Each time you get passed a context (which is used to track //calls to your plugin) you can get the data your returned in //initialize via this call: // plugin_environment *env = (plugin_environment *)userdata; //The sink specific userdata you can get with this calls: OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info); sink_environment *sinkenv = osync_objtype_sink_get_userdata(sink); OSyncError *error = NULL; /* * Now connect to your devices and report * * an error via: * osync_context_report_error(ctx, ERROR_CODE, "Some message"); * * or success via: * osync_context_report_success(ctx); * * You have to use one of these 2 somewhere to answer the context. * */ //If you need a hashtable you make it here char *tablepath = osync_strdup_printf("%s/hashtable.db", osync_plugin_info_get_configdir(info)); sinkenv->hashtable = osync_hashtable_new(tablepath, osync_objtype_sink_get_name(sink), &error); osync_free(tablepath); if (!sinkenv->hashtable) goto error; //you can also use the anchor system to detect a device reset //or some parameter change here. Check the docs to see how it works char *lanchor = NULL; //Now you get the last stored anchor from the device char *anchorpath = osync_strdup_printf("%s/anchor.db", osync_plugin_info_get_configdir(info)); if (!osync_anchor_compare(anchorpath, "lanchor", lanchor)) osync_objtype_sink_set_slowsync(sink, TRUE); osync_free(anchorpath); 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); }
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_connect(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *data) { osync_bool state_match; OSyncSinkStateDB *state_db = osync_objtype_sink_get_state_db(sink); MockDir *dir = data; osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, sink, info, ctx, data); if (mock_get_error(info->memberid, "CONNECT_ERROR")) { osync_context_report_error(ctx, OSYNC_ERROR_EXPECTED, "Triggering CONNECT_ERROR error"); osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, "Triggering CONNECT_ERROR error"); return; } if (mock_get_error(info->memberid, "CONNECT_TIMEOUT")) { /* Don't report context back ... let it timeout! */ osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, "Triggering CONNECT_TIMEOUT error"); return; } if (mock_get_error(info->memberid, "CONNECT_SLOWSYNC")) osync_context_report_slowsync(ctx); /* Skip Objtype related stuff like hashtable and state db */ if (mock_get_error(info->memberid, "MAINSINK_CONNECT")) goto end; /* From this line MockDir *dir is required, for ObjTypeSink specific stuff: #821 */ osync_assert(dir); dir->committed_all = TRUE; /* Sanity check for connect_done - reset it to FALSE. * To make sure it get reseted to TRUE before get_changes(). */ dir->connect_done = FALSE; osync_assert_msg(osync_sink_state_equal(state_db, "path", dir->path, &state_match, NULL), "Not expected to fail"); if (!state_match) osync_context_report_slowsync(ctx); osync_assert(g_file_test(dir->path, G_FILE_TEST_IS_DIR)); end: osync_context_report_success(ctx); osync_trace(TRACE_EXIT, "%s", __func__); return; }
static void disconnect(void *userdata, OSyncPluginInfo *info, OSyncContext *ctx) { OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info); sink_environment *sinkenv = osync_objtype_sink_get_userdata(sink); //Close all stuff you need to close //Close the hashtable osync_hashtable_unref(sinkenv->hashtable); sinkenv->hashtable = NULL; //Answer the call osync_context_report_success(ctx); }
static void connect(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *userdata) { osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, sink, info, ctx, userdata); //Each time you get passed a context (which is used to track //calls to your plugin) OSyncError *error = NULL; /* * Now connect to your devices and report * * an error via: * osync_context_report_error(ctx, ERROR_CODE, "Some message"); * * or success via: * osync_context_report_success(ctx); * * You have to use one of these 2 somewhere to answer the context. * */ //you can also use the anchor system to detect a device reset //or some parameter change here. Check the docs to see how it works //Now you get the last stored anchor from the device OSyncSinkStateDB *state_db = osync_objtype_sink_get_state_db(sink); osync_bool anchormatch; if (!osync_sink_state_equal(state_db, "anchor_key", "dynamic_anchor_value", &anchormatch, &error)) { /* anchor couldn't be compared */ goto error; } if (!anchormatch) { /* request slow sync */ osync_context_report_slowsync(ctx); } 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); }
static void mock_committed_all(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *context, void *data) { osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, sink, info, context, data); MockDir *dir = data; osync_assert(dir->committed_all == FALSE); dir->committed_all = TRUE; if (mock_get_error(info->memberid, "COMMITTED_ALL_ERROR")) { osync_context_report_error(context, OSYNC_ERROR_EXPECTED, "Triggering COMMITTED_ALL_ERROR error"); osync_trace(TRACE_EXIT_ERROR, "%s: Reporting error", __func__); return; } osync_context_report_success(context); osync_trace(TRACE_EXIT, "%s", __func__); }
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__); }
static void sync_done(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *userdata) { /* * This function will only be called if the sync was successful */ OSyncError *error = NULL; //If we use anchors we have to update it now. //Now you get/calculate the current anchor of the device OSyncSinkStateDB *state_db = osync_objtype_sink_get_state_db(sink); if (!osync_sink_state_set(state_db, "anchor_key", "dynamic_anchor_value", &error)) { goto error; } //Answer the call osync_context_report_success(ctx); return; error: osync_context_report_osyncerror(ctx, error); osync_error_unref(&error); return; }
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; }
static void mock_connect_done(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; dir->connect_done_slowsync = slow_sync; if (mock_get_error(info->memberid, "CONNECT_DONE_ERROR")) { osync_context_report_error(ctx, OSYNC_ERROR_EXPECTED, "Triggering CONNECT_DONE_ERROR error"); return; } if (mock_get_error(info->memberid, "CONNECT_DONE_TIMEOUT")) return; /* Validate connect_done() call before get_changes(), * and after connect(). */ osync_assert(!dir->connect_done); dir->connect_done = TRUE; osync_context_report_success(ctx); osync_trace(TRACE_EXIT, "%s", __func__); }
void KCalTodoDataSource::disconnect(OSyncObjTypeSink *, OSyncPluginInfo *, OSyncContext *ctx) { if (kcal->close(ctx)) osync_context_report_success(ctx); }
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__); }
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); }
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__); }