static void _osyncplugin_ctx_callback_disconnect(void *user_data, OSyncError *error) { OSyncError *locerror = NULL; Command *cmd = NULL; OSyncObjTypeSink *sink = NULL; assert(user_data); cmd = (Command *) user_data; sink = cmd->sink; if (error) { osync_error_set_from_error(&locerror, &error); goto error; } if (osync_objtype_sink_get_name(sink)) printf("Sink \"%s\"", osync_objtype_sink_get_name(sink)); else printf("Main Sink"); printf(" disconnected.\n"); g_mutex_lock(cmd->mutex); g_cond_signal(cmd->cond); cmd->done = TRUE; g_mutex_unlock(cmd->mutex); return; error: fprintf(stderr, "ERROR: %s\n", osync_error_print(&locerror)); return; }
static void _osyncplugin_ctx_callback_slowsync(void *user_data) { OSyncObjTypeSink *sink = (OSyncObjTypeSink *) user_data; printf("SlowSync got requested by CONNECT function"); if (osync_objtype_sink_get_name(sink)) printf(" for ObjType: \"%s\"", osync_objtype_sink_get_name(sink)); connect_requested_slowsync = TRUE; printf(".\n"); }
static void _osyncplugin_ctx_callback_syncdone(void *user_data, OSyncError *error) { OSyncError *locerror = NULL; Command *cmd = (Command *) user_data; OSyncObjTypeSink *sink = NULL; assert(user_data); sink = cmd->sink; if (error) { osync_error_set_from_error(&locerror, &error); goto error; } g_mutex_lock(cmd->mutex); g_cond_signal(cmd->cond); cmd->done = TRUE; g_mutex_unlock(cmd->mutex); return; error: fprintf(stderr, "ERROR for sink \"%s\": %s\n", osync_objtype_sink_get_name(sink), osync_error_print(&locerror)); return; }
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); }
//typedef void (* OSyncContextCallbackFn)(void *, OSyncError *); static void _osyncplugin_ctx_callback_getchanges(void *user_data, OSyncError *error) { Command *cmd = (Command *) user_data; OSyncObjTypeSink *sink = cmd->sink; if (error) fprintf(stderr, "Sink \"%s\": %s\n", osync_objtype_sink_get_name(sink), osync_error_print(&error)); g_mutex_lock(cmd->mutex); g_cond_signal(cmd->cond); cmd->done = TRUE; g_mutex_unlock(cmd->mutex); }
//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); }
OSyncObjTypeSink *osync_plugin_info_find_objtype(OSyncPluginInfo *info, const char *name) { OSyncList *p; OSyncObjTypeSink *sink = NULL; osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, info, name); osync_assert(info); for (p = info->objtype_sinks; p; p = p->next) { sink = p->data; if (g_ascii_strcasecmp(osync_objtype_sink_get_name(sink), name) == 0) goto done; } osync_trace(TRACE_EXIT, "%s: NULL", __func__); return NULL; done: osync_trace(TRACE_EXIT, "%s: %p", __func__, sink); return sink; }
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 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 *initialize(OSyncPlugin *plugin, OSyncPluginInfo *info, OSyncError **error) { /* * get the config */ OSyncPluginConfig *config = osync_plugin_info_get_config(info); if (!config) { osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to get config."); goto error; } /* * You need to specify the <some name>_environment somewhere with * all the members you need */ plugin_environment *env = osync_try_malloc0(sizeof(plugin_environment), error); if (!env) goto error; env->sink_envs = NULL; osync_trace(TRACE_INTERNAL, "The config: %s", osync_plugin_info_get_config(info)); /* * Process the config here and set the options on your environment */ /* * Process plugin specific advanced options */ OSyncList *optslist = osync_plugin_config_get_advancedoptions(config); for (; optslist; optslist = optslist->next) { OSyncPluginAdvancedOption *option = optslist->data; const char *val = osync_plugin_advancedoption_get_value(option); const char *name = osync_plugin_advancedoption_get_name(option); if (!strcmp(name,"<your-option>")) { if (!strcmp(val, "<your-value>")) { /* * set a varaible to a specific value */; } } } /* * Process Ressource options */ int i, numobjs = osync_plugin_info_num_objtypes(info); for (i = 0; i < numobjs; i++) { sink_environment *sinkenv = osync_try_malloc0(sizeof(sink_environment), error); if (!sinkenv) goto error_free_env; sinkenv->sink = osync_plugin_info_nth_objtype(info, i); osync_assert(sinkenv->sink); const char *objtype = osync_objtype_sink_get_name(sinkenv->sink); OSyncPluginResource *res = osync_plugin_config_find_active_resource(config, objtype); /* get objformat sinks */ OSyncList *s = osync_plugin_resource_get_objformat_sinks(res); for (; s; s = s->next) { OSyncObjFormatSink *fsink = s->data; // there could be only one sink const char *objformat = osync_objformat_sink_get_objformat(fsink); osync_assert(objformat); osync_trace(TRACE_INTERNAL, "objtype %s has objformat %s", objtype, objformat); } /* Every sink can have different functions ... */ OSyncObjTypeSinkFunctions functions; memset(&functions, 0, sizeof(functions)); functions.connect = connect; functions.disconnect = disconnect; functions.get_changes = get_changes; functions.commit = commit_change; functions.sync_done = sync_done; /* We pass the OSyncFileDir object to the sink, so we dont have to look it up * again once the functions are called */ osync_objtype_sink_set_functions(sinkenv->sink, functions, sinkenv); osync_trace(TRACE_INTERNAL, "The configdir: %s", osync_plugin_info_get_configdir(info)); char *tablepath = osync_strdup_printf("%s/hashtable.db", osync_plugin_info_get_configdir(info)); sinkenv->hashtable = osync_hashtable_new(tablepath, objtype, error); osync_free(tablepath); env->sink_envs = osync_list_append(env->sink_envs, sinkenv); } //Now your return your struct. return (void *) env; error_free_env: free_env(env); error: osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return NULL; }
static void *initialize(OSyncPlugin *plugin, OSyncPluginInfo *info, OSyncError **error) { /* * get the config */ OSyncPluginConfig *config = osync_plugin_info_get_config(info); if (!config) { osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to get config."); goto error; } /* * You need to specify the <some name>_environment somewhere with * all the members you need */ plugin_environment *env = osync_try_malloc0(sizeof(plugin_environment), error); if (!env) goto error; /* * Process the config here and set the options on your environment * if required. */ /* * Process plugin specific advanced options */ OSyncList *optslist = osync_plugin_config_get_advancedoptions(config); OSyncList *o; for (o = optslist; o; o = o->next) { OSyncPluginAdvancedOption *option = o->data; const char *val = osync_plugin_advancedoption_get_value(option); const char *name = osync_plugin_advancedoption_get_name(option); if (!strcmp(name,"<your-option>")) { if (!strcmp(val, "<your-value>")) { /* * set a varaible to a specific value */; } } } osync_list_free(optslist); /* * Process Ressource options */ OSyncList *l, *list = NULL; list = osync_plugin_info_get_objtype_sinks(info); for (l=list; l; l = l->next) { OSyncObjTypeSink *sink = (OSyncObjTypeSink *) l->data; const char *objtype = osync_objtype_sink_get_name(sink); OSyncPluginResource *res = osync_plugin_config_find_active_resource(config, objtype); /* get objformat sinks */ OSyncList *s = NULL; OSyncList *objformats = osync_plugin_resource_get_objformat_sinks(res); for (s = objformats; s; s = s->next) { OSyncObjFormatSink *fsink = s->data; // there could be only one sink const char *objformat = osync_objformat_sink_get_objformat(fsink); osync_assert(objformat); osync_trace(TRACE_INTERNAL, "objtype %s has objformat %s", objtype, objformat); } osync_list_free(objformats); /* Every sink can have different functions ... */ osync_objtype_sink_set_connect_func(sink, connect); osync_objtype_sink_set_disconnect_func(sink, disconnect); osync_objtype_sink_set_get_changes_func(sink, get_changes); osync_objtype_sink_set_commit_func(sink, commit_change); osync_objtype_sink_set_sync_done_func(sink, sync_done); /* * If you need plugin specific userdata passed to this * plugin sink functions. You can set it with: * * osync_objtype_sink_set_userdata(sink, userdata_pointer); */ /* Request a Hahstable here - if you need it. * It will be later available via osync_objtype_sink_get_hashtable(OSyncObjTypeSink *) * in the plugin sink functions (e.g. connect, get_changes, commit, ...) */ osync_objtype_sink_enable_hashtable(sink, TRUE); } osync_list_free(list); //Now your return your environemtn struct. return (void *) env; error: osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return NULL; }
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__); }
/* In initialize, we get the config for the plugin. Here we also must register * all _possible_ objtype sinks. */ static void *mock_initialize(OSyncPlugin *plugin, OSyncPluginInfo *info, OSyncError **error) { osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, plugin, info, error); if (mock_get_error(info->memberid, "INIT_NULL_NOERROR")) { osync_trace(TRACE_EXIT, "%s: %s", __func__, "Everything is fine. I don't need plugin userdata."); return NULL; } if (mock_get_error(info->memberid, "INIT_NULL")) { osync_error_set(error, OSYNC_ERROR_EXPECTED, "Triggering INIT_NULL error"); osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return NULL; } mock_env *env = osync_try_malloc0(sizeof(mock_env), error); osync_assert(env); OSyncFormatEnv *formatenv = osync_plugin_info_get_format_env(info); osync_assert(formatenv); OSyncPluginConfig *config = osync_plugin_info_get_config(info); osync_assert(config); if (mock_get_error(info->memberid, "MAINSINK_CONNECT")) { env->mainsink = osync_objtype_main_sink_new(error); osync_objtype_sink_set_connect_func(env->mainsink, mock_connect); osync_objtype_sink_set_disconnect_func(env->mainsink, mock_mainsink_disconnect); osync_objtype_sink_set_userdata(env->mainsink, env); osync_plugin_info_set_main_sink(info, env->mainsink); } /* Now we register the objtypes that we can sync. This plugin is special. It can * synchronize any objtype we configure it to sync and where a conversion * path to the file format can be found */ OSyncList *objtypesinks = osync_plugin_info_get_objtype_sinks(info); OSyncList *list = NULL; for (list = objtypesinks;list; list = list->next) { MockDir *dir = osync_try_malloc0(sizeof(MockDir), error); osync_assert(dir); dir->committed_all = TRUE; OSyncObjTypeSink *sink = (OSyncObjTypeSink*)list->data; osync_assert(sink); const char *objtype = osync_objtype_sink_get_name(sink); dir->res = osync_plugin_config_find_active_resource(config, objtype); osync_plugin_resource_ref(dir->res); dir->path = osync_plugin_resource_get_path(dir->res); osync_assert(dir->path); OSyncList *format_sinks = osync_plugin_resource_get_objformat_sinks(dir->res); osync_assert(osync_list_length(format_sinks) == 1); OSyncObjFormatSink *format_sink = osync_list_nth_data(format_sinks, 0); const char *objformat_str = osync_objformat_sink_get_objformat(format_sink); osync_assert(objformat_str); dir->objformat = osync_format_env_find_objformat(formatenv, objformat_str); osync_assert(dir->objformat); osync_objformat_ref(dir->objformat); osync_list_free(format_sinks); /* const char *objformat = osync_objformat_get_name(dir->objformat); OSyncObjFormatSink *format_sink = osync_objformat_sink_new(objformat, error); if (!format_sink) return NULL; osync_objtype_sink_add_objformat_sink(sink, format_sink); */ /* Sanity check for connect_done */ dir->connect_done = TRUE; if (!mock_get_error(info->memberid, "MAINSINK_CONNECT")) { osync_objtype_sink_set_connect_func(sink, mock_connect); osync_objtype_sink_set_connect_done_func(sink, mock_connect_done); osync_objtype_sink_set_disconnect_func(sink, mock_disconnect); } osync_objtype_sink_set_get_changes_func(sink, mock_get_changes); osync_objtype_sink_set_committed_all_func(sink, mock_committed_all); osync_objtype_sink_set_commit_func(sink, mock_commit_change); osync_objtype_sink_set_read_func(sink, mock_read); osync_objtype_sink_set_sync_done_func(sink, mock_sync_done); /* We pass the MockDir object to the sink, so we dont have to look it up * again once the functions are called */ osync_objtype_sink_set_userdata(sink, dir); /* Request an Anchor */ osync_objtype_sink_enable_state_db(sink, TRUE); /* Request an Hashtable */ osync_objtype_sink_enable_hashtable(sink, TRUE); //Lets reduce the timeouts a bit so the checks work faster osync_objtype_sink_set_connect_timeout(sink, 2); osync_objtype_sink_set_getchanges_timeout(sink, 2); osync_objtype_sink_set_commit_timeout(sink, 4); osync_objtype_sink_set_committedall_timeout(sink, 4); osync_objtype_sink_set_syncdone_timeout(sink, 2); osync_objtype_sink_set_disconnect_timeout(sink, 2); osync_objtype_sink_set_read_timeout(sink, 2); /* XXX No testcase is currently using this at all! */ #if 0 if (g_getenv("NO_TIMEOUTS")) { /* XXX Timeout value of wouldn't work out, since the Sink object would fallback to the default timeout value: sink->timeout.connect ? sink->timeout.connect : OSYNC_SINK_TIMEOUT_CONNECT; Really needed?! */ osync_objtype_sink_set_connect_timeout(sink, 0); osync_objtype_sink_set_getchanges_timeout(sink, 0); osync_objtype_sink_set_commit_timeout(sink, 0); osync_objtype_sink_set_committedall_timeout(sink, 0); osync_objtype_sink_set_syncdone_timeout(sink, 0); osync_objtype_sink_set_disconnect_timeout(sink, 0); osync_objtype_sink_set_read_timeout(sink, 0); } /* What is meant by this?! Maybe OSyncPlugin.useable?! Not used at all... if (g_getenv("IS_AVAILABLE")) info->functions.is_available = mock_is_available; */ #endif env->directories = g_list_append(env->directories, dir); } osync_list_free(objtypesinks); osync_trace(TRACE_EXIT, "%s: %p", __func__, env); return (void *)env; }
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__); }