diff options
Diffstat (limited to 'debian/opensync/opensync-0.22/osengine/osengine_engine.c')
-rw-r--r-- | debian/opensync/opensync-0.22/osengine/osengine_engine.c | 1233 |
1 files changed, 0 insertions, 1233 deletions
diff --git a/debian/opensync/opensync-0.22/osengine/osengine_engine.c b/debian/opensync/opensync-0.22/osengine/osengine_engine.c deleted file mode 100644 index c5a98f43..00000000 --- a/debian/opensync/opensync-0.22/osengine/osengine_engine.c +++ /dev/null @@ -1,1233 +0,0 @@ -/* - * libosengine - A synchronization engine for the opensync framework - * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org> - * - * 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 "engine.h" - -#include <errno.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include <glib.h> - -#include <opensync/opensync_support.h> -#include "opensync/opensync_message_internals.h" -#include "opensync/opensync_queue_internals.h" -#include "opensync/opensync_format_internals.h" - -#include "engine_internals.h" -#include <opensync/opensync_user_internals.h> - -OSyncMappingEntry *osengine_mappingtable_find_entry(OSyncMappingTable *table, const char *uid, const char *objtype, long long int memberid); -/** - * @defgroup OSEnginePrivate OpenSync Engine Private API - * @ingroup PrivateAPI - * @brief The internals of the multisync engine - * - */ - -/** - * @defgroup OSyncEnginePrivate OpenSync Engine Internals - * @ingroup OSEnginePrivate - * @brief The internals of the engine (communication part) - * - * This gives you an insight in the inner workings of the sync engine, - * especially the communication part. - * - * - */ -/*@{*/ - -void _new_change_receiver(OSyncEngine *engine, OSyncClient *client, OSyncChange *change) -{ - osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, engine, client, change); - - OSyncError *error = NULL; - OSyncChangeType change_type = osync_change_get_changetype(change); - OSyncFormatEnv *format_env = osync_group_get_format_env(engine->group); - OSyncObjType *objtype = osync_change_get_objtype(change); - const char* uid = osync_change_get_uid(change); - OSyncObjFormat *objformat = osync_change_get_objformat(change); - - osync_change_set_member(change, client->member); - - osync_trace(TRACE_INTERNAL, "Handling new change with uid %s, changetype %i, objtype %s and format %s from member %lli", uid, change_type, - objtype ? osync_objtype_get_name(objtype) : "None", osync_change_get_objformat(change) ? osync_objformat_get_name(osync_change_get_objformat(change)) : "None", - osync_member_get_id(client->member)); - - - /** - * first we need to detect the objtype because we use - * uid + objtype as identifier for an entry. - * Special case is file as objformat... we must not change - * the objtype with format file - **/ - if ( (change_type != CHANGE_DELETED) && - (osync_change_has_data(change))) { - osync_bool is_file_objformat = FALSE; - if(objformat) - is_file_objformat = - ((!strcmp(objformat->name, "file"))?(TRUE):(FALSE)); - if ( (!objtype) || (!objformat) || - (!strcmp(osync_objtype_get_name(objtype), "data")) || - (!strcmp(objformat->name, "plain"))) { - OSyncObjType *objtype_test = osync_change_detect_objtype_full(format_env, change, &error); - objtype = (objtype_test)?(objtype_test):(objtype); - } - if (objtype) { - osync_trace(TRACE_INTERNAL, "Detected the object to be of type %s", osync_objtype_get_name(objtype)); - - osync_change_set_objtype(change, objtype); - - /** - * do not use CHANGE_MODIFIED if slowsync or (change not - * exist before if not filesync) - **/ - if ( ( (osync_group_get_slow_sync(engine->group, - osync_objtype_get_name(objtype))) || - ( (!is_file_objformat) && - (!osengine_mappingtable_find_entry( - engine->maptable, uid, - osync_objtype_get_name(objtype), - osync_member_get_id(client->member))) ) - ) && (change_type == CHANGE_MODIFIED) ){ - osync_change_set_changetype(change, CHANGE_ADDED); - change_type = osync_change_get_changetype(change); - } - } - } else - if (change_type == CHANGE_DELETED){ - /** - * we need to handle the special delete case where objtype - * is data and no uid with objtype data exists from this - * member - **/ - if ( !objtype || - (( !strcmp(osync_objtype_get_name(objtype), "data") ) && - ( !osengine_mappingtable_find_entry( - engine->maptable, uid, - osync_objtype_get_name(objtype), - osync_member_get_id(client->member)) )) ){ - - OSyncMappingEntry *entry = - osengine_mappingtable_find_entry( - engine->maptable, uid, NULL, - osync_member_get_id(client->member) - ); - if (entry) { - osync_change_set_objtype(change, - osync_change_get_objtype( - entry->change)); - objtype=osync_change_get_objtype(change); - } else { - osync_error_set(&error, OSYNC_ERROR_GENERIC, - "Could not find one entry with UID=%s to delete.", uid); - goto error; - } - } - } else { - osync_trace(TRACE_INTERNAL, "Change has no data!"); - } - - osync_trace(TRACE_INTERNAL, "Handling new change with uid %s, changetype %i, data %p, size %i, objtype %s and format %s from member %lli", uid, change_type, osync_change_get_data(change), osync_change_get_datasize(change), objtype ? osync_objtype_get_name(objtype) : "None", osync_change_get_objformat(change) ? osync_objformat_get_name(osync_change_get_objformat(change)) : "None", osync_member_get_id(client->member)); - - if (!objtype){ - osync_error_set(&error, OSYNC_ERROR_GENERIC, - "ObjType not set for uid %s.", uid); - goto error; - } - - - OSyncMappingEntry *entry = osengine_mappingtable_store_change(engine->maptable, change); - change = entry->change; - if (!osync_change_save(change, TRUE, &error)) { - osync_error_duplicate(&engine->error, &error); - osync_status_update_change(engine, change, CHANGE_RECV_ERROR, &error); - osync_error_update(&engine->error, "Unable to receive one or more objects"); - osync_flag_unset(entry->fl_has_data); - goto error; - } - - osync_group_remove_changelog(engine->group, change, &error); - - //We convert to the common format here to make sure we always pass it - osync_change_convert_to_common(change, NULL); - - if (!entry->mapping) { - osync_flag_attach(entry->fl_mapped, engine->cmb_entries_mapped); - osync_flag_unset(entry->fl_mapped); - osync_debug("ENG", 3, "+It has no mapping"); - } else { - osync_debug("ENG", 3, "+It has mapping"); - osync_flag_set(entry->fl_mapped); - osync_flag_unset(entry->mapping->fl_solved); - osync_flag_unset(entry->mapping->fl_chkconflict); - osync_flag_unset(entry->mapping->fl_multiplied); - } - - if (osync_change_has_data(change)) { - osync_debug("ENG", 3, "+It has data"); - osync_flag_set(entry->fl_has_data); - osync_status_update_change(engine, change, CHANGE_RECEIVED, NULL); - } else { - osync_debug("ENG", 3, "+It has no data"); - osync_flag_unset(entry->fl_has_data); - osync_status_update_change(engine, change, CHANGE_RECEIVED_INFO, NULL); - } - - if (osync_change_get_changetype(change) == CHANGE_DELETED) - osync_flag_set(entry->fl_deleted); - - osync_flag_set(entry->fl_has_info); - osync_flag_unset(entry->fl_synced); - - osengine_mappingentry_decider(engine, entry); - - osync_trace(TRACE_EXIT, "%s", __func__); - return; - -error: - osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(&error)); - osync_error_free(&error); - return; -} - -OSyncClient *osengine_get_client(OSyncEngine *engine, long long int memberId) -{ - GList *c = NULL; - for (c = engine->clients; c; c = c->next) { - OSyncClient *client = c->data; - if (osync_member_get_id(client->member) == memberId) - return client; - } - return NULL; -} - - -void send_engine_changed(OSyncEngine *engine) -{ - if (!engine->is_initialized) - return; - - OSyncMessage *message = osync_message_new(OSYNC_MESSAGE_ENGINE_CHANGED, 0, NULL); - /*FIXME: Handle errors here */ - - osync_debug("ENG", 4, "Sending message %p:\"ENGINE_CHANGED\"", message); - osync_queue_send_message(engine->commands_to_self, NULL, message, NULL); -} - -void send_mapping_changed(OSyncEngine *engine, OSyncMapping *mapping) -{ - OSyncMessage *message = osync_message_new(OSYNC_MESSAGE_MAPPING_CHANGED, sizeof(long long), NULL); - osync_message_write_long_long_int(message, mapping->id); - /*FIXME: Handle errors here */ - - osync_queue_send_message(engine->commands_to_self, NULL, message, NULL); - /*FIXME: Handle errors here, too */ -} - -void send_mappingentry_changed(OSyncEngine *engine, OSyncMappingEntry *entry) -{ - OSyncMessage *message = osync_message_new(OSYNC_MESSAGE_MAPPINGENTRY_CHANGED, sizeof(long long)*2, NULL); - - /*FIXME: don't pass a pointer through the messaging system */ - long long ptr = (long long)(long)entry; - osync_message_write_long_long_int(message, ptr); - /*FIXME: Handle errors here */ - - osync_queue_send_message(engine->commands_to_self, NULL, message, NULL); - /*FIXME: Handle errors here, too */ -} - -/*! @brief The queue message handler of the engine - * - * @param sender The Client who sent this message - * @param message The message - * @param engine The engine - * - */ -static void engine_message_handler(OSyncMessage *message, OSyncEngine *engine) -{ - osync_trace(TRACE_ENTRY, "engine_message_handler(%p:%lli-%i, %p)", message, message->id1, message->id2, engine); - - OSyncChange *change = NULL; - - osync_trace(TRACE_INTERNAL, "engine received command %i", osync_message_get_command(message)); - - switch (osync_message_get_command(message)) { - case OSYNC_MESSAGE_SYNCHRONIZE: - osync_trace(TRACE_INTERNAL, "all deciders"); - osengine_client_all_deciders(engine); - break; - case OSYNC_MESSAGE_NEW_CHANGE: - osync_demarshal_change(message, osync_group_get_format_env(engine->group), &change); - - long long int member_id = 0; - osync_message_read_long_long_int(message, &member_id); - OSyncClient *sender = osengine_get_client(engine, member_id); - - _new_change_receiver(engine, sender, change); - break; - case OSYNC_MESSAGE_ENGINE_CHANGED: - osengine_client_all_deciders(engine); - osengine_mapping_all_deciders(engine); - GList *u; - for (u = engine->maptable->unmapped; u; u = u->next) { - OSyncMappingEntry *unmapped = u->data; - send_mappingentry_changed(engine, unmapped); - } - break; - case OSYNC_MESSAGE_MAPPING_CHANGED: - { - long long id; - osync_message_read_long_long_int(message, &id); - /*FIXME: check errors by read_long_long_int */ - OSyncMapping *mapping = osengine_mappingtable_mapping_from_id(engine->maptable, id); - - if (!g_list_find(engine->maptable->mappings, mapping)) { - osync_trace(TRACE_EXIT, "%s: Mapping %p is dead", __func__, mapping); - return; - } - - osengine_mapping_decider(engine, mapping); - } - break; - case OSYNC_MESSAGE_MAPPINGENTRY_CHANGED: - { - long long ptr; - osync_message_read_long_long_int(message, &ptr); - OSyncMappingEntry *entry = (OSyncMappingEntry*)(long)ptr; - - if (!g_list_find(engine->maptable->entries, entry) && !g_list_find(engine->maptable->unmapped, entry)) { - osync_trace(TRACE_EXIT, "%s: Entry %p is dead", __func__, entry); - return; - } - - osengine_mappingentry_decider(engine, entry); - } - break; - case OSYNC_MESSAGE_SYNC_ALERT: - if (engine->allow_sync_alert) - osync_flag_set(engine->fl_running); - else - osync_trace(TRACE_INTERNAL, "Sync Alert not allowed"); - break; - - default: - break; - } - - /*TODO: Implement handling of the messages listed below, on commented code */ - - /* - if (osync_message_is_signal (message, "CLIENT_CHANGED")) { - OSyncClient *client = osync_message_get_data(message, "client"); - - if (!g_list_find(engine->clients, client)) { - osync_trace(TRACE_EXIT, "%s: Client %p is dead", __func__, client); - return; - } - - osengine_client_decider(engine, client); - osync_trace(TRACE_EXIT, "engine_message_handler"); - return; - } - - if (osync_message_is_signal (message, "PLUGIN_MESSAGE")) { - char *name = osync_message_get_data(message, "name"); - void *data = osync_message_get_data(message, "data"); - engine->plgmsg_callback(engine, sender, name, data, engine->plgmsg_userdata); - osync_trace(TRACE_EXIT, "engine_message_handler"); - return; - } - - osync_debug("ENG", 0, "Unknown message \"%s\"", osync_message_get_msgname(message)); - osync_trace(TRACE_EXIT_ERROR, "engine_message_handler: Unknown message"); - g_assert_not_reached();*/ - osync_trace(TRACE_EXIT, "%s", __func__); -} - -static void trigger_clients_sent_changes(OSyncEngine *engine) -{ - osync_trace(TRACE_ENTRY, "%s(%p)", __func__, engine); - osync_status_update_engine(engine, ENG_ENDPHASE_READ, NULL); - - g_mutex_lock(engine->info_received_mutex); - g_cond_signal(engine->info_received); - g_mutex_unlock(engine->info_received_mutex); - - //Load the old mappings - osengine_mappingtable_inject_changes(engine->maptable); - - send_engine_changed(engine); - osync_trace(TRACE_EXIT, "%s", __func__); -} - -static void trigger_clients_read_all(OSyncEngine *engine) -{ - osync_trace(TRACE_ENTRY, "%s(%p)", __func__, engine); - - send_engine_changed(engine); - osync_trace(TRACE_EXIT, "%s", __func__); -} - -static void trigger_status_end_conflicts(OSyncEngine *engine) -{ - osync_trace(TRACE_ENTRY, "%s(%p)", __func__, engine); - osync_status_update_engine(engine, ENG_END_CONFLICTS, NULL); - - osync_trace(TRACE_EXIT, "%s", __func__); -} - -static void trigger_clients_connected(OSyncEngine *engine) -{ - osync_trace(TRACE_ENTRY, "%s(%p)", __func__, engine); - osync_status_update_engine(engine, ENG_ENDPHASE_CON, NULL); - osengine_client_all_deciders(engine); - - osync_trace(TRACE_EXIT, "%s", __func__); -} - -static void trigger_clients_comitted_all(OSyncEngine *engine) -{ - osync_trace(TRACE_ENTRY, "%s(%p)", __func__, engine); - osync_status_update_engine(engine, ENG_ENDPHASE_WRITE, NULL); - - osync_trace(TRACE_EXIT, "%s", __func__); -} - - -/*void send_engine_committed_all(OSyncEngine *engine) -{ - osync_trace(TRACE_ENTRY, "%s(%p)", __func__, engine); - - engine->committed_all_sent = TRUE; - - osync_trace(TRACE_INTERNAL, "++++ ENGINE COMMAND: Committed all ++++"); - - GList *c = NULL; - for (c = engine->clients; c; c = c->next) { - OSyncClient *client = c->data; - if (osync_flag_is_not_set(client->fl_committed_all)) - send_committed_all(client, engine); - } - - osync_trace(TRACE_EXIT, "%s", __func__); -} - -static void trigger_engine_committed_all(OSyncEngine *engine) -{ - osync_trace(TRACE_ENTRY, "%s(%p)", __func__, engine); - - if (osync_flag_is_not_set(engine->cmb_multiplied)) { - osync_trace(TRACE_EXIT, "%s: Not multiplied yet", __func__); - return; - } - - send_engine_committed_all(engine); - - osync_trace(TRACE_EXIT, "%s", __func__); -}*/ - -static gboolean startupfunc(gpointer data) -{ - OSyncEngine *engine = data; - osync_trace(TRACE_INTERNAL, "+++++++++ This is the engine of group \"%s\" +++++++++", osync_group_get_name(engine->group)); - - OSyncError *error = NULL; - if (!osengine_mappingtable_load(engine->maptable, &error)) { - osync_error_duplicate(&engine->error, &error); - osync_status_update_engine(engine, ENG_ERROR, &error); - osync_error_update(&engine->error, "Unable to connect one of the members"); - osync_flag_set(engine->fl_stop); - } - - g_mutex_lock(engine->started_mutex); - g_cond_signal(engine->started); - g_mutex_unlock(engine->started_mutex); - return FALSE; -} - -/*@}*/ - -/** - * @defgroup OSEnginePublic OpenSync Engine API - * @ingroup PublicAPI - * @brief The API of the syncengine available to everyone - * - * This gives you an insight in the public API of the opensync sync engine. - * - */ -/*@{*/ - -/*! @brief This will reset the engine to its initial state - * - * This function will reset the engine to its initial state. The engine - * must not be running at this point. - * - * @param engine A pointer to the engine you want to reset - * @param error A pointer to a error struct - * @returns TRUE if command was succcessfull, FALSE otherwise - * - */ -osync_bool osengine_reset(OSyncEngine *engine, OSyncError **error) -{ - //FIXME Check if engine is running - osync_trace(TRACE_ENTRY, "osengine_reset(%p, %p)", engine, error); - GList *c = NULL; - for (c = engine->clients; c; c = c->next) { - OSyncClient *client = c->data; - osync_client_reset(client); - } - - osync_flag_set_state(engine->fl_running, FALSE); - osync_flag_set_state(engine->fl_stop, FALSE); - osync_flag_set_state(engine->cmb_sent_changes, FALSE); - osync_flag_set_state(engine->cmb_entries_mapped, TRUE); - osync_flag_set_state(engine->cmb_synced, TRUE); - osync_flag_set_state(engine->cmb_chkconflict, TRUE); - osync_flag_set_state(engine->cmb_finished, FALSE); - osync_flag_set_state(engine->cmb_connected, FALSE); - osync_flag_set_state(engine->cmb_read_all, TRUE); - osync_flag_set_state(engine->cmb_committed_all, TRUE); - osync_flag_set_state(engine->cmb_committed_all_sent, FALSE); - - osync_status_update_engine(engine, ENG_ENDPHASE_DISCON, NULL); - - engine->committed_all_sent = FALSE; - - osengine_mappingtable_reset(engine->maptable); - - if (engine->error) { - //FIXME We might be leaking memory here - OSyncError *newerror = NULL; - osync_error_duplicate(&newerror, &engine->error); - osync_status_update_engine(engine, ENG_ERROR, &newerror); - osync_group_set_slow_sync(engine->group, "data", TRUE); - } else { - osync_status_update_engine(engine, ENG_SYNC_SUCCESSFULL, NULL); - osync_group_reset_slow_sync(engine->group, "data"); - } - - osync_trace(TRACE_INTERNAL, "engine error is %p", engine->error); - - g_mutex_lock(engine->syncing_mutex); - g_cond_signal(engine->syncing); - g_mutex_unlock(engine->syncing_mutex); - - osync_trace(TRACE_EXIT, "osengine_reset"); - return TRUE; -} - -/* Implementation of g_mkdir_with_parents() - * - * This function overwrite the contents of the 'dir' parameter - */ -static int __mkdir_with_parents(char *dir, int mode) -{ - if (g_file_test(dir, G_FILE_TEST_IS_DIR)) - return 0; - - char *slash = strrchr(dir, '/'); - if (slash && slash != dir) { - /* Create parent directory if needed */ - - /* This is a trick: I don't want to allocate a new string - * for the parent directory. So, just put a NUL char - * in the last slash, and restore it after creating the - * parent directory - */ - *slash = '\0'; - if (__mkdir_with_parents(dir, mode) < 0) - return -1; - *slash = '/'; - } - - if (mkdir(dir, mode) < 0) - return -1; - - return 0; -} - -static int mkdir_with_parents(const char *dir, int mode) -{ - int r; - char *mydir = strdup(dir); - if (!mydir) - return -1; - - r = __mkdir_with_parents(mydir, mode); - free(mydir); - return r; -} - -/*! @brief This will create a new engine for the given group - * - * This will create a new engine for the given group - * - * @param group A pointer to the group, for which you want to create a new engine - * @param error A pointer to a error struct - * @returns Pointer to a newly allocated OSyncEngine on success, NULL otherwise - * - */ -OSyncEngine *osengine_new(OSyncGroup *group, OSyncError **error) -{ - osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, group, error); - - g_assert(group); - OSyncEngine *engine = g_malloc0(sizeof(OSyncEngine)); - osync_group_set_data(group, engine); - - if (!g_thread_supported ()) - g_thread_init (NULL); - - engine->context = g_main_context_new(); - engine->syncloop = g_main_loop_new(engine->context, FALSE); - engine->group = group; - - OSyncUserInfo *user = osync_user_new(error); - if (!user) - goto error; - - char *enginesdir = g_strdup_printf("%s/engines", osync_user_get_confdir(user)); - char *path = g_strdup_printf("%s/enginepipe", enginesdir); - - if (mkdir_with_parents(enginesdir, 0755) < 0) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "Couldn't create engines directory: %s", strerror(errno)); - goto error_free_paths; - } - - engine->syncing_mutex = g_mutex_new(); - engine->info_received_mutex = g_mutex_new(); - engine->syncing = g_cond_new(); - engine->info_received = g_cond_new(); - engine->started_mutex = g_mutex_new(); - engine->started = g_cond_new(); - - //Set the default start flags - engine->fl_running = osync_flag_new(NULL); - osync_flag_set_pos_trigger(engine->fl_running, (OSyncFlagTriggerFunc)osengine_client_all_deciders, engine, NULL); - - engine->fl_sync = osync_flag_new(NULL); - engine->fl_stop = osync_flag_new(NULL); - osync_flag_set_pos_trigger(engine->fl_stop, (OSyncFlagTriggerFunc)osengine_client_all_deciders, engine, NULL); - - //The combined flags - engine->cmb_sent_changes = osync_comb_flag_new(FALSE, FALSE); - osync_flag_set_pos_trigger(engine->cmb_sent_changes, (OSyncFlagTriggerFunc)trigger_clients_sent_changes, engine, NULL); - - engine->cmb_read_all = osync_comb_flag_new(FALSE, TRUE); - osync_flag_set_pos_trigger(engine->cmb_read_all, (OSyncFlagTriggerFunc)trigger_clients_read_all, engine, NULL); - - engine->cmb_entries_mapped = osync_comb_flag_new(FALSE, FALSE); - osync_flag_set_pos_trigger(engine->cmb_entries_mapped, (OSyncFlagTriggerFunc)send_engine_changed, engine, NULL); - - - engine->cmb_synced = osync_comb_flag_new(FALSE, TRUE); - osync_flag_set_pos_trigger(engine->cmb_synced, (OSyncFlagTriggerFunc)send_engine_changed, engine, NULL); - - - engine->cmb_finished = osync_comb_flag_new(FALSE, TRUE); - osync_flag_set_pos_trigger(engine->cmb_finished, (OSyncFlagTriggerFunc)osengine_reset, engine, NULL); - - engine->cmb_connected = osync_comb_flag_new(FALSE, FALSE); - osync_flag_set_pos_trigger(engine->cmb_connected, (OSyncFlagTriggerFunc)trigger_clients_connected, engine, NULL); - - engine->cmb_chkconflict = osync_comb_flag_new(FALSE, TRUE); - osync_flag_set_pos_trigger(engine->cmb_chkconflict, (OSyncFlagTriggerFunc)trigger_status_end_conflicts, engine, NULL); - - engine->cmb_multiplied = osync_comb_flag_new(FALSE, TRUE); - - engine->cmb_committed_all = osync_comb_flag_new(FALSE, TRUE); - osync_flag_set_pos_trigger(engine->cmb_committed_all, (OSyncFlagTriggerFunc)send_engine_changed, engine, NULL); - - - engine->cmb_committed_all_sent = osync_comb_flag_new(FALSE, TRUE); - osync_flag_set_pos_trigger(engine->cmb_committed_all_sent, (OSyncFlagTriggerFunc)trigger_clients_comitted_all, engine, NULL); - - osync_flag_set(engine->fl_sync); - - int i; - for (i = 0; i < osync_group_num_members(group); i++) { - OSyncMember *member = osync_group_nth_member(group, i); - if (!osync_client_new(engine, member, error)) - goto error_free_paths; - } - - engine->maptable = osengine_mappingtable_new(engine); - - osync_trace(TRACE_EXIT, "osengine_new: %p", engine); - return engine; - -error_free_paths: - g_free(path); - g_free(enginesdir); -error: - osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); - return NULL; -} - -/*! @brief This will free a engine and all resources associated - * - * This will free a engine and all resources associated - * - * @param engine A pointer to the engine, which you want to free - * - */ -void osengine_free(OSyncEngine *engine) -{ - osync_trace(TRACE_ENTRY, "osengine_free(%p)", engine); - - GList *c = NULL; - for (c = engine->clients; c; c = c->next) { - OSyncClient *client = c->data; - osync_client_free(client); - } - - osengine_mappingtable_free(engine->maptable); - engine->maptable = NULL; - - osync_flag_free(engine->fl_running); - osync_flag_free(engine->fl_sync); - osync_flag_free(engine->fl_stop); - osync_flag_free(engine->cmb_sent_changes); - osync_flag_free(engine->cmb_entries_mapped); - osync_flag_free(engine->cmb_synced); - osync_flag_free(engine->cmb_chkconflict); - osync_flag_free(engine->cmb_finished); - osync_flag_free(engine->cmb_connected); - osync_flag_free(engine->cmb_read_all); - osync_flag_free(engine->cmb_multiplied); - osync_flag_free(engine->cmb_committed_all); - osync_flag_free(engine->cmb_committed_all_sent); - - g_list_free(engine->clients); - g_main_loop_unref(engine->syncloop); - - g_main_context_unref(engine->context); - - g_mutex_free(engine->syncing_mutex); - g_mutex_free(engine->info_received_mutex); - g_cond_free(engine->syncing); - g_cond_free(engine->info_received); - g_mutex_free(engine->started_mutex); - g_cond_free(engine->started); - - g_free(engine); - osync_trace(TRACE_EXIT, "osengine_free"); -} - -/*! @brief This will set the conflict handler for the given engine - * - * The conflict handler will be called everytime a conflict occurs - * - * @param engine A pointer to the engine, for which to set the callback - * @param function A pointer to a function which will receive the conflict - * @param user_data Pointer to some data that will get passed to the status function as the last argument - * - */ -void osengine_set_conflict_callback(OSyncEngine *engine, void (* function) (OSyncEngine *, OSyncMapping *, void *), void *user_data) -{ - engine->conflict_callback = function; - engine->conflict_userdata = user_data; -} - -/*! @brief This will set the change status handler for the given engine - * - * The change status handler will be called every time a new change is received, written etc - * - * @param engine A pointer to the engine, for which to set the callback - * @param function A pointer to a function which will receive the change status - * @param user_data Pointer to some data that will get passed to the status function as the last argument - * - */ -void osengine_set_changestatus_callback(OSyncEngine *engine, void (* function) (OSyncEngine *, OSyncChangeUpdate *, void *), void *user_data) -{ - engine->changestat_callback = function; - engine->changestat_userdata = user_data; -} - -/*! @brief This will set the mapping status handler for the given engine - * - * The mapping status handler will be called every time a mapping is updated - * - * @param engine A pointer to the engine, for which to set the callback - * @param function A pointer to a function which will receive the mapping status - * @param user_data Pointer to some data that will get passed to the status function as the last argument - * - */ -void osengine_set_mappingstatus_callback(OSyncEngine *engine, void (* function) (OSyncMappingUpdate *, void *), void *user_data) -{ - engine->mapstat_callback = function; - engine->mapstat_userdata = user_data; -} - -/*! @brief This will set the engine status handler for the given engine - * - * The engine status handler will be called every time the engine is updated (started, stoped etc) - * - * @param engine A pointer to the engine, for which to set the callback - * @param function A pointer to a function which will receive the engine status - * @param user_data Pointer to some data that will get passed to the status function as the last argument - * - */ -void osengine_set_enginestatus_callback(OSyncEngine *engine, void (* function) (OSyncEngine *, OSyncEngineUpdate *, void *), void *user_data) -{ - engine->engstat_callback = function; - engine->engstat_userdata = user_data; -} - -/*! @brief This will set the member status handler for the given engine - * - * The member status handler will be called every time a member is updated (connects, disconnects etc) - * - * @param engine A pointer to the engine, for which to set the callback - * @param function A pointer to a function which will receive the member status - * @param user_data Pointer to some data that will get passed to the status function as the last argument - * - */ -void osengine_set_memberstatus_callback(OSyncEngine *engine, void (* function) (OSyncMemberUpdate *, void *), void *user_data) -{ - engine->mebstat_callback = function; - engine->mebstat_userdata = user_data; -} - -/*! @brief This will set the callback handler for a custom message - * - * A custom message can be used to communicate with a plugin directly - * - * @param engine A pointer to the engine, for which to set the callback - * @param function A pointer to a function which will receive the member status - * @param user_data A pointer to some user data that the callback function will get passed - * - */ -void osengine_set_message_callback(OSyncEngine *engine, void *(* function) (OSyncEngine *, OSyncClient *, const char *, void *, void *), void *user_data) -{ - engine->plgmsg_callback = function; - engine->plgmsg_userdata = user_data; -} - -/*! @brief This will initialize a engine - * - * After initialization, the engine will be ready to sync. The threads for the engine, - * the members are started. If one of the members has a listening server, the server will be - * started and listening. - * - * @param engine A pointer to the engine, which will be initialized - * @param error A pointer to a error struct - * @returns TRUE on success, FALSE otherwise. Check the error on FALSE. - * - */ -osync_bool osengine_init(OSyncEngine *engine, OSyncError **error) -{ - osync_trace(TRACE_ENTRY, "osengine_init(%p, %p)", engine, error); - - if (engine->is_initialized) { - osync_error_set(error, OSYNC_ERROR_MISCONFIGURATION, "This engine was already initialized"); - osync_trace(TRACE_EXIT_ERROR, "osengine_init: %s", osync_error_print(error)); - return FALSE; - } - - switch (osync_group_lock(engine->group)) { - case OSYNC_LOCKED: - osync_error_set(error, OSYNC_ERROR_LOCKED, "Group is locked"); - osync_trace(TRACE_EXIT_ERROR, "osengine_init: %s", osync_error_print(error)); - return FALSE; - case OSYNC_LOCK_STALE: - osync_debug("ENG", 1, "Detected stale lock file. Slow-syncing"); - osync_status_update_engine(engine, ENG_PREV_UNCLEAN, NULL); - osync_group_set_slow_sync(engine->group, "data", TRUE); - break; - default: - break; - } - - osync_flag_set(engine->cmb_entries_mapped); - osync_flag_set(engine->cmb_synced); - engine->allow_sync_alert = TRUE; - - //OSyncMember *member = NULL; - OSyncGroup *group = engine->group; - - if (osync_group_num_members(group) < 2) { - //Not enough members! - osync_error_set(error, OSYNC_ERROR_MISCONFIGURATION, "You only configured %i members, but at least 2 are needed", osync_group_num_members(group)); - osync_group_unlock(engine->group, TRUE); - osync_trace(TRACE_EXIT_ERROR, "osengine_init: %s", osync_error_print(error)); - return FALSE; - } - - engine->is_initialized = TRUE; - - osync_trace(TRACE_INTERNAL, "Spawning clients"); - GList *c = NULL; - for (c = engine->clients; c; c = c->next) { - OSyncClient *client = c->data; - osync_queue_create(client->commands_from_osplugin, NULL); - - if (!osync_client_spawn(client, engine, error)) { - osync_group_unlock(engine->group, TRUE); - osync_trace(TRACE_EXIT_ERROR, "osengine_init: %s", osync_error_print(error)); - return FALSE; - } - - osync_queue_set_message_handler(client->commands_from_osplugin, (OSyncMessageHandler)engine_message_handler, engine); - if (!(engine->man_dispatch)) - osync_queue_setup_with_gmainloop(client->commands_from_osplugin, engine->context); - osync_trace(TRACE_INTERNAL, "opening client queue"); - if (!osync_queue_connect(client->commands_from_osplugin, OSYNC_QUEUE_RECEIVER, 0 )) { - osync_group_unlock(engine->group, TRUE); - osync_trace(TRACE_EXIT_ERROR, "osengine_init: %s", osync_error_print(error)); - return FALSE; - } - } - - osync_trace(TRACE_INTERNAL, "opening engine queue"); - if (!osync_queue_new_pipes(&engine->commands_from_self, &engine->commands_to_self, error)) { - osync_group_unlock(engine->group, TRUE); - osync_trace(TRACE_EXIT_ERROR, "osengine_init: %s", osync_error_print(error)); - return FALSE; - } - - if (!osync_queue_connect(engine->commands_from_self, OSYNC_QUEUE_RECEIVER, 0 )) { - osync_group_unlock(engine->group, TRUE); - osync_trace(TRACE_EXIT_ERROR, "osengine_init: %s", osync_error_print(error)); - return FALSE; - } - - if (!osync_queue_connect(engine->commands_to_self, OSYNC_QUEUE_SENDER, 0 )) { - osync_group_unlock(engine->group, TRUE); - osync_trace(TRACE_EXIT_ERROR, "osengine_init: %s", osync_error_print(error)); - return FALSE; - } - - osync_queue_set_message_handler(engine->commands_from_self, (OSyncMessageHandler)engine_message_handler, engine); - if (!(engine->man_dispatch)) - osync_queue_setup_with_gmainloop(engine->commands_from_self, engine->context); - - osync_trace(TRACE_INTERNAL, "initializing clients"); - for (c = engine->clients; c; c = c->next) { - OSyncClient *client = c->data; - if (!osync_client_init(client, engine, error)) { - osengine_finalize(engine); - osync_group_unlock(engine->group, TRUE); - osync_trace(TRACE_EXIT_ERROR, "osengine_init: %s", osync_error_print(error)); - return FALSE; - } - } - - osync_debug("ENG", 3, "Running the main loop"); - - //Now we can run the main loop - //We protect the startup by a g_cond - g_mutex_lock(engine->started_mutex); - GSource *idle = g_idle_source_new(); - g_source_set_priority(idle, G_PRIORITY_HIGH); - g_source_set_callback(idle, startupfunc, engine, NULL); - g_source_attach(idle, engine->context); - engine->thread = g_thread_create ((GThreadFunc)g_main_loop_run, engine->syncloop, TRUE, NULL); - g_cond_wait(engine->started, engine->started_mutex); - g_mutex_unlock(engine->started_mutex); - - osync_trace(TRACE_EXIT, "osengine_init"); - return TRUE; -} - -/*! @brief This will finalize a engine - * - * Finalizing a engine will stop all threads and listening server. - * The engine can be initialized again. - * - * @param engine A pointer to the engine, which will be finalized - * - */ -void osengine_finalize(OSyncEngine *engine) -{ - //FIXME check if engine is running - osync_trace(TRACE_ENTRY, "osengine_finalize(%p)", engine); - - if (!engine->is_initialized) { - osync_trace(TRACE_EXIT_ERROR, "osengine_finalize: Not initialized"); - return; - } - - g_assert(engine); - osync_debug("ENG", 3, "finalizing engine %p", engine); - - if (engine->thread) { - g_main_loop_quit(engine->syncloop); - g_thread_join(engine->thread); - } - - GList *c = NULL; - for (c = engine->clients; c; c = c->next) { - OSyncClient *client = c->data; - osync_queue_disconnect(client->commands_from_osplugin, NULL); - osync_client_finalize(client, NULL); - } - - osync_queue_disconnect(engine->commands_from_self, NULL); - osync_queue_disconnect(engine->commands_to_self, NULL); - - osync_queue_free(engine->commands_from_self); - engine->commands_from_self = NULL; - osync_queue_free(engine->commands_to_self); - engine->commands_to_self = NULL; - - osengine_mappingtable_close(engine->maptable); - - if (engine->error) { - /* If the error occured during connect, we - * dont want to trigger a slow-sync the next - * time. In the case the we have a slow-sync - * right in the beginning, we also dont remove - * the lockfile to trigger a slow-sync again - * next time */ - if (!osync_flag_is_set(engine->cmb_connected) && !engine->slowsync) - osync_group_unlock(engine->group, TRUE); - else - osync_group_unlock(engine->group, FALSE); - } else - osync_group_unlock(engine->group, TRUE); - - engine->is_initialized = FALSE; - osync_trace(TRACE_EXIT, "osengine_finalize"); -} - -/*! @brief Starts to synchronize the given OSyncEngine - * - * This function synchronizes a given engine. The Engine has to be created - * from a OSyncGroup before by using osengine_new(). This function will not block - * - * @param engine A pointer to the engine, which will be used to sync - * @param error A pointer to a error struct - * @returns TRUE on success, FALSE otherwise. Check the error on FALSE. Note that this just says if the sync has been started successfully, not if the sync itself was successfull - * - */ -osync_bool osengine_synchronize(OSyncEngine *engine, OSyncError **error) -{ - osync_trace(TRACE_INTERNAL, "synchronize now"); - osync_trace(TRACE_ENTRY, "%s(%p)", __func__, engine); - g_assert(engine); - - if (!engine->is_initialized) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "osengine_synchronize: Not initialized"); - goto error; - } - - /* We now remember if slow-sync is set right from the start. - * If it is, we dont remove the lock file in the case of - * a error during connect. */ - if (osync_group_get_slow_sync(engine->group, "data")) { - engine->slowsync = TRUE; - } else { - engine->slowsync = FALSE; - } - - engine->wasted = 0; - engine->alldeciders = 0; - - osync_flag_set(engine->fl_running); - - OSyncMessage *message = osync_message_new(OSYNC_MESSAGE_SYNCHRONIZE, 0, error); - if (!message) - goto error; - - if (!osync_queue_send_message(engine->commands_to_self, NULL, message, error)) - goto error_free_message; - - osync_message_unref(message); - - osync_trace(TRACE_EXIT, "%s", __func__); - return TRUE; - -error_free_message: - osync_message_unref(message); -error: - osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); - return FALSE; -} - -/*! @brief Sets a flag on the engine that the engine should only request the info about sync objects - * - * This can be used to see only what has changed. The engine will not request the data itself from - * the members. Note that some members might not support this behaviour and might send the data anyways. - * - * @param engine A pointer to the engine, for which to set the flag - */ -void osengine_flag_only_info(OSyncEngine *engine) -{ - osync_flag_unset(engine->fl_sync); -} - -/*! @brief Sets a flag on the engine that the engine should do single stepping (For debugging) - * - * This flag can be used to set single stepping on the engine. The engine will pause after each iteration. - * Use osengine_one_iteration to initialize the next iteration. This is only for debugging purposes. - * - * @param engine A pointer to the engine, for which to set the flag - */ -void osengine_flag_manual(OSyncEngine *engine) -{ - if (engine->syncloop) { - g_warning("Unable to flag manual since engine is already initialized\n"); - } - engine->man_dispatch = TRUE; -} - -/*! @brief This will pause the engine - * - * This flag can be used to temporarily suspend the engine - * - * @param engine A pointer to the engine, for which to set the flag - */ -void osengine_pause(OSyncEngine *engine) -{ - osync_flag_unset(engine->fl_running); -} - -/*! @brief Sets a flag on the engine that the engine should do single stepping (For debugging) - * - * This flag can be used to set single stepping on the engine. The engine will pause after each iteration. - * Use osengine_one_iteration to initialize the next iteration. This is only for debugging purposes. - * - * @param engine A pointer to the engine, for which to set the flag - */ -void osengine_abort(OSyncEngine *engine) -{ - osync_flag_set(engine->fl_stop); -} - -/*! @brief Allows that the engine can be started by a member - * - * Allow the engine to by started by a member by sending a sync alert. - * - * @param engine The engine - */ -void osengine_allow_sync_alert(OSyncEngine *engine) -{ - engine->allow_sync_alert = TRUE; -} - -/*! @brief Do not allow that the engine can be started by a member - * - * Do not allow the engine to by started by a member by sending a sync alert. - * - * @param engine The engine - */ -void osengine_deny_sync_alert(OSyncEngine *engine) -{ - engine->allow_sync_alert = FALSE; -} - -/*! @brief This function will synchronize once and block until the sync has finished - * - * This can be used to sync a group and wait for the synchronization end. DO NOT USE - * osengine_wait_sync_end for this as this might introduce a race condition. - * - * @param engine A pointer to the engine, which to sync and wait for the sync end - * @param error A pointer to a error struct - * @returns TRUE on success, FALSE otherwise. - * - */ -osync_bool osengine_sync_and_block(OSyncEngine *engine, OSyncError **error) -{ - osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, engine, error); - - g_mutex_lock(engine->syncing_mutex); - - if (!osengine_synchronize(engine, error)) { - g_mutex_unlock(engine->syncing_mutex); - goto error; - } - - g_cond_wait(engine->syncing, engine->syncing_mutex); - g_mutex_unlock(engine->syncing_mutex); - - if (engine->error) { - osync_error_duplicate(error, &(engine->error)); - goto error; - } - - osync_trace(TRACE_EXIT, "%s", __func__); - return TRUE; - -error: - osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); - return FALSE; -} - -/*! @brief This function will block until a synchronization has ended - * - * This can be used to wait until the synchronization has ended. Note that this function will always - * block until 1 sync has ended. It can be used before the sync has started, to wait for one auto-sync - * to end - * - * @param engine A pointer to the engine, for which to wait for the sync end - * @param error Return location for the error if the sync was not successfull - * @returns TRUE on success, FALSE otherwise. - */ -osync_bool osengine_wait_sync_end(OSyncEngine *engine, OSyncError **error) -{ - g_mutex_lock(engine->syncing_mutex); - g_cond_wait(engine->syncing, engine->syncing_mutex); - g_mutex_unlock(engine->syncing_mutex); - - if (engine->error) { - osync_error_duplicate(error, &(engine->error)); - return FALSE; - } - return TRUE; -} - -/*! @brief This function will block until all change object information has been received - * - * This will block until the information and not the data has been received. - * - * @param engine A pointer to the engine, for which to wait for the info - */ -void osengine_wait_info_end(OSyncEngine *engine) -{ - g_mutex_lock(engine->info_received_mutex); - g_cond_wait(engine->info_received, engine->info_received_mutex); - g_mutex_unlock(engine->info_received_mutex); -} - -/*! @brief Does one iteration of the engine (For debugging) - * - * @param engine The engine to iterate - */ -void osengine_one_iteration(OSyncEngine *engine) -{ - /*TODO: Reimplement support to stepping mode on engine */ - abort();//osync_queue_dispatch(engine->incoming); -} - -/*! @brief Searches for a mapping by its id - * - * @param engine The engine - * @param id The id of the mapping - * @returns The mapping or NULL if not found - */ -OSyncMapping *osengine_mapping_from_id(OSyncEngine *engine, long long int id) -{ - return osengine_mappingtable_mapping_from_id(engine->maptable, id); -} - -/** @}*/ |