|
From: <svn...@op...> - 2009-10-30 21:30:31
|
Author: dgollub Date: Fri Oct 30 22:30:07 2009 New Revision: 5895 URL: http://www.opensync.org/changeset/5895 Log: Added reference implementation of an EXTERNAL plugin, which can be a standalone userspace application. Currently a stub plugin-module is required to register the plugin to OpenSync's plugin environment and configure the start type to OSYNC_START_TYPE_EXTERNAL. This will be obsolate soon and replaced by simple config files instead, so no programming of a stub plugin is required .. Proof of Concept: ~~~~~~~~~~~~~~~~~ $ ./example_external_demo ~/.config/opensync/0.40/group6/1/pluginpipe & [1] 10841 $ [EXTERNAL-DEMO]: OSyncPlugin:0x40159d OSyncClient:0x603040 [EXTERNAL-DEMO]: Starting (blocking) OSyncClient ... $ $ osynctool --sync external Synchronizing group "external" [EXTERNAL-DEMO]: initialize data sink of member 2 of type file-sync just connected Main sink of member 2 of type file-sync just connected data sink of member 1 of type external-demo just connected Main sink of member 1 of type external-demo just connected All clients connected or error [EXTERNAL-DEMO]: get_changes slow_sync: no data sink of member 2 of type file-sync just sent all changes data sink of member 1 of type external-demo just sent all changes Main sink of member 1 of type external-demo just sent all changes Main sink of member 2 of type file-sync just sent all changes [...] The sync was successful data sink of member 1 of type external-demo just disconnected Main sink of member 1 of type external-demo just disconnected data sink of member 2 of type file-sync just disconnected Main sink of member 2 of type file-sync just disconnected All clients have disconnected [EXTERNAL-DEMO]: OSyncClient completed. [1]+ Done ./example_external_demo ~/.config/opensync/0.40/group6/1/pluginpipe $ Added: trunk/docs/examples/plugins/src/external-demo trunk/docs/examples/plugins/src/external_demo.c trunk/docs/examples/plugins/src/external_plugin.c - copied, changed from r5893, trunk/docs/examples/plugins/src/simple_plugin.c Modified: trunk/docs/examples/plugins/src/CMakeLists.txt Modified: trunk/docs/examples/plugins/src/CMakeLists.txt ============================================================================== --- trunk/docs/examples/plugins/src/CMakeLists.txt Fri Oct 30 22:09:28 2009 (r5894) +++ trunk/docs/examples/plugins/src/CMakeLists.txt Fri Oct 30 22:30:07 2009 (r5895) @@ -11,6 +11,15 @@ TARGET_LINK_LIBRARIES( example_plugin ${OPENSYNC_LIBRARIES} ) OPENSYNC_PLUGIN_INSTALL( example_plugin ) +### External Synchronization Plugin ######## +OPENSYNC_PLUGIN_ADD( example_external_plugin external_plugin.c ) +OPENSYNC_PLUGIN_CONFIG(external-demo ) +TARGET_LINK_LIBRARIES( example_external_plugin ${OPENSYNC_LIBRARIES} ) +OPENSYNC_PLUGIN_INSTALL( example_external_plugin ) + +ADD_EXECUTABLE( example_external_demo external_demo.c ) +TARGET_LINK_LIBRARIES( example_external_demo ${OPENSYNC_LIBRARIES} ) + ### Format Plugin ######################## OPENSYNC_FORMAT_ADD( format_plugin format.c ) TARGET_LINK_LIBRARIES( format_plugin ${OPENSYNC_LIBRARIES} ) Added: trunk/docs/examples/plugins/src/external-demo ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/docs/examples/plugins/src/external-demo Fri Oct 30 22:30:07 2009 (r5895) @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<config version="1.0"> + <Resources> + <Resource> + <Enabled>1</Enabled> + <Formats> + <Format> + <Name>file</Name> + </Format> + </Formats> + <ObjType>data</ObjType> + <Url></Url> + </Resource> + </Resources> +</config> Added: trunk/docs/examples/plugins/src/external_demo.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/docs/examples/plugins/src/external_demo.c Fri Oct 30 22:30:07 2009 (r5895) @@ -0,0 +1,146 @@ +/* + * external_demo.c - example implementation of an userspace process + * which acts as external OpenSync plugin + * + * Copyright (C) 2009 Daniel Gollub <go...@b1...> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <opensync/opensync.h> +#include <opensync/opensync-client.h> +#include <opensync/opensync-data.h> +#include <opensync/opensync-format.h> +#include <opensync/opensync-plugin.h> +#include <opensync/opensync-helper.h> +#include <opensync/opensync-version.h> + +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 *initialize(OSyncPlugin *plugin, OSyncPluginInfo *info, OSyncError **error) +{ + OSyncList *sinks, *s; + + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, info, error); + + printf("[EXTERNAL-DEMO]: %s\n", __func__); + + sinks = osync_plugin_info_get_objtype_sinks(info); + for (s = sinks; s; s = s->next) { + OSyncObjTypeSink *sink = s->data; + + /* Here you register all your objtype sink functions ... */ + osync_objtype_sink_set_get_changes_func(sink, get_changes); + /* You can also add sink function for + * - connect() + * - disconnect() + * - commit() + * - sync_done() + * - ... + */ + } + + osync_trace(TRACE_EXIT, "%s: %p", __func__, NULL); + return (void *) NULL; + +error: + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); + return NULL; +} + +static void finalize(void *data) +{ + printf("[EXTERNAL-DEMO]: %s\n", __func__); +} + +static osync_bool discover(OSyncPluginInfo *info, void *data, OSyncError **error) +{ + + printf("[EXTERNAL-DEMO]: %s\n", __func__); + OSyncList *s, *sinks = osync_plugin_info_get_objtype_sinks(info); + for (s = sinks; s; s = s->next) { + OSyncObjTypeSink *sink = (OSyncObjTypeSink *) s->data; + osync_objtype_sink_set_available(sink, TRUE); + } + osync_list_free(sinks); + + OSyncVersion *version = osync_version_new(error); + osync_version_set_plugin(version, "external-demo"); + osync_plugin_info_set_version(info, version); + osync_version_unref(version); + + return TRUE; +} + +int main(int argc, char **argv) +{ + const char *pipe_path; + OSyncError *error = NULL; + OSyncClient *client = NULL; + OSyncPlugin *plugin = NULL; + + if (!argv[1]) { + fprintf(stderr, "pipe path is missing!\n"); + return 1; + } + + pipe_path = argv[1]; + + + /** Plugin **/ + plugin = osync_plugin_new(&error); + if (!plugin) + goto error; + + osync_plugin_set_initialize(plugin, initialize); + osync_plugin_set_finalize(plugin, finalize); + osync_plugin_set_discover(plugin, discover); + + + /** Client */ + client = osync_client_new(&error); + if (!client) + goto error; + + osync_client_set_pipe_path(client, pipe_path); + osync_client_set_plugin(client, plugin); + + + printf("[EXTERNAL-DEMO]: OSyncPlugin:%p OSyncClient:%p\n", __func__, plugin, client); + printf("[EXTERNAL-DEMO]: Starting (blocking) OSyncClient ...\n", __func__, plugin, client); + + if (!osync_client_run_and_block(client, &error)) + goto error; + + printf("[EXTERNAL-DEMO]: OSyncClient completed.", __func__, plugin, client); + + osync_client_unref(client); + + return 0; + +error: + fprintf(stderr, "[EXTERNAL-DEMO] Error: %s\n", osync_error_print(&error)); + osync_error_unref(&error); + return 1; +} + Copied and modified: trunk/docs/examples/plugins/src/external_plugin.c (from r5893, trunk/docs/examples/plugins/src/simple_plugin.c) ============================================================================== --- trunk/docs/examples/plugins/src/simple_plugin.c Fri Oct 23 20:12:54 2009 (r5893, copy source) +++ trunk/docs/examples/plugins/src/external_plugin.c Fri Oct 30 22:30:07 2009 (r5895) @@ -1,332 +1,26 @@ +/* + * + * !!! This is only a temporary solution and will be soon obsolete. !!! + * + * This plugin is just a stub to register an external plugin to the plugin-env + * In the future this will be done via configuration files. + * + */ + #include <opensync/opensync.h> -#include <opensync/opensync-data.h> -#include <opensync/opensync-format.h> #include <opensync/opensync-plugin.h> -#include <opensync/opensync-helper.h> -#include <opensync/opensync-version.h> - -#include <string.h> - -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) - - //cast void* userdata to the sink specific data type - - 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 get_changes(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, osync_bool slow_sync, void *userdata) -{ - osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, userdata, info, ctx); - - OSyncFormatEnv *formatenv = osync_plugin_info_get_format_env(info); - - OSyncError *error = NULL; - - /* - * Now you can get the changes. - * Loop over all changes you get and do the following: - */ - - do { - char *uid = osync_strdup("<some uid>"); - - //Now get the data of this change - char *data = NULL; - - - /* Determine the "Change Type" of this change (e.g. ADDED, MODIFIED, DELETED, ...) */ - OSyncChangeType changetype = OSYNC_CHANGE_TYPE_ADDED; - - //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_changetype(change, changetype); - - if (changetype == OSYNC_CHANGE_TYPE_UNMODIFIED) { - osync_free(uid); - osync_change_unref(change); - continue; - } - - 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(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); - - //Now we need to answer the call - osync_context_report_success(ctx); - osync_trace(TRACE_EXIT, "%s", __func__); -} - -static void commit_change(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, OSyncChange *change, void *userdata) -{ - - /* - * 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 - break; - case OSYNC_CHANGE_TYPE_MODIFIED: - //Modify the change - //Dont forget to answer the call on error - break; - default: - ; - } - - //Answer the call - osync_context_report_success(ctx); -} - -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 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 finalize(void *userdata) -{ - //Free all stuff that you have allocated here. -} - - -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 - */ - void *env = NULL; - if (!env) - goto error; - - 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); - 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); - */ - } - - osync_list_free(list); - - //Now your return your struct. - return (void *) env; - -error: - osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); - return NULL; -} - -/* Here we actually tell opensync which sinks are available. */ -static osync_bool discover(OSyncPluginInfo *info, void *userdata, OSyncError **error) -{ - osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, userdata, info, error); - - // Report avaliable sinks... - OSyncObjTypeSink *sink = osync_plugin_info_find_objtype(info, "<objtype e.g. note>"); - if (!sink) { - return FALSE; - } - osync_objtype_sink_set_available(sink, TRUE); - - OSyncVersion *version = osync_version_new(error); - osync_version_set_plugin(version, "<your plugin-name>"); - //osync_version_set_version(version, "version"); - //osync_version_set_modelversion(version, "version"); - //osync_version_set_firmwareversion(version, "firmwareversion"); - //osync_version_set_softwareversion(version, "softwareversion"); - //osync_version_set_hardwareversion(version, "hardwareversion"); - osync_plugin_info_set_version(info, version); - osync_version_unref(version); - - osync_trace(TRACE_EXIT, "%s", __func__); - return TRUE; -} - osync_bool get_sync_info(OSyncPluginEnv *env, OSyncError **error) { - //Now you can create a new plugin information and fill in the details - //Note that you can create several plugins here OSyncPlugin *plugin = osync_plugin_new(error); if (!plugin) goto error; //Tell opensync something about your plugin - osync_plugin_set_name(plugin, "short name, maybe < 15 chars"); + osync_plugin_set_name(plugin, "external-demo"); osync_plugin_set_longname(plugin, "long name. maybe < 50 chars"); osync_plugin_set_description(plugin, "A longer description. < 200 chars"); - - //Now set the function we made earlier - osync_plugin_set_initialize(plugin, initialize); - osync_plugin_set_finalize(plugin, finalize); - osync_plugin_set_discover(plugin, discover); + osync_plugin_set_start_type(plugin, OSYNC_START_TYPE_EXTERNAL); if (!osync_plugin_env_register_plugin(env, plugin, error)) goto error; @@ -343,3 +37,4 @@ { return 1; } + |