From: <svn...@op...> - 2009-03-13 09:26:03
|
Author: bellmich Date: Fri Mar 13 10:25:49 2009 New Revision: 5290 URL: http://www.opensync.org/changeset/5290 Log: fixed the management of connect and connect_done - connect must be managed on a per datastore base because of connect_done - alert_type mutex and cond were used in a wrong way (wrong locking) - handling of disconnect after connect and before connect_done - signal changes of alert type during connect - removed g_list_add (no longer used) - renamed connect_done to syncml_connect_done FIXME: If disconnect is called after connect_done because of an abort FIXME: then disconnect is not handled correctly. FIXME: The plugin hangs in this situation. Modified: plugins/syncml/src/syncml_callbacks.c plugins/syncml/src/syncml_common.c plugins/syncml/src/syncml_common.h plugins/syncml/src/syncml_ds_client.c plugins/syncml/src/syncml_ds_server.c Modified: plugins/syncml/src/syncml_callbacks.c ============================================================================== --- plugins/syncml/src/syncml_callbacks.c Thu Mar 12 20:59:40 2009 (r5289) +++ plugins/syncml/src/syncml_callbacks.c Fri Mar 13 10:25:49 2009 (r5290) @@ -1,7 +1,7 @@ /* * syncml plugin - A syncml plugin for OpenSync * Copyright (C) 2005 Armin Bauer <arm...@op...> - * Copyright (C) 2008 Michael Bell <mic...@op...> + * Copyright (C) 2008-2009 Michael Bell <mic...@op...> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -55,9 +55,6 @@ goto error; break; case SML_DATA_SYNC_EVENT_CONNECT: - if (env->connectCtx) - report_success_on_context(&(env->connectCtx)); - break; case SML_DATA_SYNC_EVENT_DISCONNECT: break; @@ -129,9 +126,6 @@ OSyncError *oserror = NULL; osync_error_set(&oserror, OSYNC_ERROR_GENERIC, smlErrorPrint(&locerror)); - if (env->connectCtx) - report_error_on_context(&(env->connectCtx), &oserror, FALSE); - if (env->disconnectCtx) report_error_on_context(&(env->disconnectCtx), &oserror, FALSE); @@ -142,6 +136,26 @@ if (database->syncModeCtx) report_error_on_context(&(database->syncModeCtx), &oserror, FALSE); + if (database->connectCtx && database->alert_type_mutex) { + /* there was an error during connect */ + g_mutex_free(database->alert_type_mutex); + database->alert_type_mutex = NULL; + } + + if (database->connectCtx) { + report_error_on_context(&(database->connectCtx), &oserror, FALSE); + } + + if (database->alert_type_mutex) { + /* there was an error after connect + * but before the connect_done is completed. + */ + g_mutex_lock(database->alert_type_mutex); + g_cond_wait(database->alert_type_cond, database->alert_type_mutex); + g_mutex_unlock(database->alert_type_mutex); + } + + if (database->getChangesCtx) report_error_on_context(&(database->getChangesCtx), &oserror, FALSE); @@ -164,7 +178,7 @@ void *userdata, SmlError **error) { - osync_trace(TRACE_ENTRY, "%s - %s: %d", __func__, source, recvType); + osync_trace(TRACE_ENTRY, "%s: %s => %d", __func__, source, recvType); SmlPluginEnv *env = userdata; SmlAlertType sentType; @@ -177,11 +191,44 @@ */ sentType = SML_ALERT_TWO_WAY; } else { + /* get the related datastore */ SmlDatabase *database = get_database_from_source(env, source, error); if (!database) goto error; + /* locate alert type of sink */ + if (osync_objtype_sink_get_slowsync(database->sink)) + sentType = SML_ALERT_SLOW_SYNC; + else + sentType = SML_ALERT_TWO_WAY; + + /* update alert type of sink if necessary */ + if (recvType == SML_ALERT_SLOW_SYNC && + recvType != sentType) + { + osync_trace(TRACE_INTERNAL, "%s: signal SLOW-SYNC", __func__); + osync_objtype_sink_set_slowsync(database->sink, TRUE); + } + + /* signal the connect event */ + g_mutex_lock(database->alert_type_mutex); + if (database->connectCtx) + report_success_on_context(&(database->connectCtx)); + + /* wait for the signal from the connect_done callback*/ + osync_trace(TRACE_INTERNAL, "%s: waiting for approved alert type", __func__); g_cond_wait(database->alert_type_cond, database->alert_type_mutex); + osync_trace(TRACE_INTERNAL, "%s: received approval for alert type", __func__); + g_mutex_unlock(database->alert_type_mutex); + g_mutex_free(database->alert_type_mutex); + database->alert_type_mutex = NULL; + + /* if there is a disconnect context then this is an abort */ + if (database->env->disconnectCtx) { + smlErrorSet(error, SML_ERROR_GENERIC, + "A disconnect is enforced while waiting for connect_done."); + goto error; + } /* locate alert type of sink */ if (osync_objtype_sink_get_slowsync(database->sink)) Modified: plugins/syncml/src/syncml_common.c ============================================================================== --- plugins/syncml/src/syncml_common.c Thu Mar 12 20:59:40 2009 (r5289) +++ plugins/syncml/src/syncml_common.c Fri Mar 13 10:25:49 2009 (r5290) @@ -1,6 +1,7 @@ /* * syncml plugin - A syncml plugin for OpenSync * Copyright (C) 2005 Armin Bauer <arm...@op...> + * Copyright (C) 2008-2009 Michael Bell <mic...@op...> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,26 +29,6 @@ #include <opensync/opensync-plugin.h> #include <libsyncml/data_sync_api/callbacks.h> -GList *g_list_add(GList *databases, void *database) -{ - osync_trace(TRACE_ENTRY, "%s", __func__); - - // if we find the item in the list - // then we only return and do nothing - - if (g_list_find(databases, database) != NULL) - { - osync_trace(TRACE_EXIT, "%s - the item is an element of the list", __func__); - return databases; - } - - // add the item to the list - - GList *result = g_list_append(databases, database); - osync_trace(TRACE_EXIT, "%s - add a new list item %p", __func__, database); - return result; -} - void syncml_free_database(SmlDatabase *database) { osync_trace(TRACE_ENTRY, "%s(%p)", __func__, database); @@ -63,11 +44,15 @@ database->objformat = NULL; } - if (database->alert_type_mutex) + if (database->alert_type_mutex) { g_mutex_free(database->alert_type_mutex); + database->alert_type_mutex = NULL; + } - if (database->alert_type_cond) + if (database->alert_type_cond) { g_cond_free(database->alert_type_cond); + database->alert_type_cond = NULL; + } if (database->sink) { osync_objtype_sink_unref(database->sink); @@ -108,6 +93,11 @@ osync_error_set(&error, OSYNC_ERROR_GENERIC, "%s - syncModeCtx context discovered on finalize", __func__); report_error_on_context(&(database->syncModeCtx), &error, TRUE); } + if (database->connectCtx) { + OSyncError *error = NULL; + osync_error_set(&error, OSYNC_ERROR_GENERIC, "%s - connectCtx context discovered on finalize", __func__); + report_error_on_context(&(database->connectCtx), &error, TRUE); + } if (database->getChangesCtx) { OSyncError *error = NULL; osync_error_set(&error, OSYNC_ERROR_GENERIC, "%s - getChangesCtx context discovered on finalize", __func__); @@ -193,7 +183,7 @@ return OSYNC_CHANGE_TYPE_UNKNOWN; } -void connect_done(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *data) +void syncml_connect_done(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *data) { osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx); @@ -221,12 +211,24 @@ SmlPluginEnv *env = (SmlPluginEnv *)data; g_assert(env); - if ((env->state1 >= SML_DATA_SYNC_EVENT_DISCONNECT && - (!env->dsObject2 || - env->state2 >= SML_DATA_SYNC_EVENT_DISCONNECT || - env->state2 < SML_DATA_SYNC_EVENT_CONNECT) - ) || - env->state1 < SML_DATA_SYNC_EVENT_CONNECT) + SmlBool waiting = FALSE; + if (env->databases && + ((SmlDatabase *)env->databases->data)->alert_type_mutex && + !((SmlDatabase *)env->databases->data)->connectCtx) { + /* the datastores are waiting for the approved alert types */ + waiting = TRUE; + } + + if (!waiting && + ( + (env->state1 >= SML_DATA_SYNC_EVENT_DISCONNECT && + (!env->dsObject2 || + env->state2 >= SML_DATA_SYNC_EVENT_DISCONNECT || + env->state2 < SML_DATA_SYNC_EVENT_CONNECT) + ) || + env->state1 < SML_DATA_SYNC_EVENT_CONNECT + ) + ) { /* The disconnect already happened or * the session never existed (connect error). */ @@ -234,6 +236,24 @@ } else { env->disconnectCtx = ctx; osync_context_ref(env->disconnectCtx); + + /* If the disconnect is part of an abort and + * there is a hanging alert type callback + * then the condition must be signaled to + * abort the connection. + */ + GList *list = env->databases; + for (; list; list = list->next) { + SmlDatabase *database = list->data; + if (database->alert_type_mutex) { + osync_trace(TRACE_INTERNAL, "%s: signal alert_type approval", __func__); + g_mutex_lock(database->alert_type_mutex); + g_cond_signal(database->alert_type_cond); + g_mutex_unlock(database->alert_type_mutex); + osync_trace(TRACE_INTERNAL, "%s: signalled alert_type approval", __func__); + } + } + } osync_trace(TRACE_EXIT, "%s", __func__); @@ -284,11 +304,6 @@ /* Signal forgotten contexts */ - if (env->connectCtx) { - OSyncError *oerror = NULL; - osync_error_set(&oerror, OSYNC_ERROR_GENERIC, "%s - detected forgotten connect context", __func__); - report_error_on_context(&(env->connectCtx), &oerror, TRUE); - } if (env->disconnectCtx) { OSyncError *oerror = NULL; osync_error_set(&oerror, OSYNC_ERROR_GENERIC, "%s - detected forgotten disconnect context", __func__); @@ -409,7 +424,8 @@ { osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx); - SmlPluginEnv *env = (SmlPluginEnv *)data; + SmlDatabase *database = (SmlDatabase *)data; + SmlPluginEnv *env = database->env; SmlError *error = NULL; OSyncError *oserror = NULL; @@ -418,13 +434,18 @@ * then the connect context is signalled. */ - env->connectCtx = ctx; - osync_context_ref(env->connectCtx); - - if (!smlDataSyncInit(env->dsObject1, &error)) - goto error; - if (!smlDataSyncRun(env->dsObject1, &error)) - goto error; + database->connectCtx = ctx; + osync_context_ref(database->connectCtx); + if (g_atomic_int_dec_and_test(&(env->toBeConnected))) { + /* all database received the connect callback */ + smlTrace(TRACE_INTERNAL, "%s: executing connect", __func__); + if (!smlDataSyncInit(env->dsObject1, &error)) + goto error; + if (!smlDataSyncRun(env->dsObject1, &error)) + goto error; + } else { + smlTrace(TRACE_INTERNAL, "%s: just another connect", __func__); + } osync_trace(TRACE_EXIT, "%s", __func__); return; @@ -432,7 +453,7 @@ osync_error_set(&oserror, OSYNC_ERROR_GENERIC, "%s", smlErrorPrint(&error)); smlErrorDeref(&error); osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(&oserror)); - report_error_on_context(&(env->connectCtx), &oserror, TRUE); + report_error_on_context(&(database->connectCtx), &oserror, TRUE); } osync_bool discover(const char *name, void *data, OSyncPluginInfo *info, OSyncError **error) @@ -746,7 +767,6 @@ /* prepare the function list for OpenSync */ OSyncObjTypeSinkFunctions main_functions; memset(&main_functions, 0, sizeof(main_functions)); - main_functions.connect = syncml_connect; main_functions.disconnect = disconnect; /* Register main sink for connect and disconnect functions */ @@ -791,6 +811,7 @@ if (sessionType == SML_SESSION_TYPE_CLIENT && !ds_client_init_databases(env, info, oerror)) goto error_free_env; + env->toBeConnected = g_list_length(env->databases); osync_trace(TRACE_EXIT, "%s: %p", __func__, env); return (void *)env; Modified: plugins/syncml/src/syncml_common.h ============================================================================== --- plugins/syncml/src/syncml_common.h Thu Mar 12 20:59:40 2009 (r5289) +++ plugins/syncml/src/syncml_common.h Fri Mar 13 10:25:49 2009 (r5290) @@ -1,6 +1,7 @@ /* * syncml plugin - A syncml plugin for OpenSync * Copyright (C) 2005 Armin Bauer <arm...@op...> + * Copyright (C) 2008-2009 Michael Bell <mic...@op...> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -97,7 +98,7 @@ /* opensync state management */ - OSyncContext *connectCtx; + int toBeConnected; OSyncContext *disconnectCtx; GList *databases; unsigned int gotDatabaseCommits; /* only for OMA DS server */ @@ -131,6 +132,7 @@ OSyncPluginSyncmlDatastoreCommand command; + OSyncContext *connectCtx; OSyncContext *syncModeCtx; OSyncContext *getChangesCtx; OSyncContext *commitCtx; @@ -157,7 +159,7 @@ OSyncPluginInfo *info, OSyncError **oerror); void syncml_connect(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *data); -void connect_done(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *data); +void syncml_connect_done(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *data); void sync_done(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *data); void disconnect(OSyncObjTypeSink *sink, OSyncPluginInfo *info, OSyncContext *ctx, void *data); @@ -172,11 +174,6 @@ OSyncPluginResource *res, OSyncError **error); -/* this is a helper function which adds an object to a GList */ -/* the function guarantees that an object exists only once in */ -/* this GList. No double entrees. */ -GList *g_list_add(GList *databases, void *database); - void finalize(void *data); void safe_cfree(char **address); Modified: plugins/syncml/src/syncml_ds_client.c ============================================================================== --- plugins/syncml/src/syncml_ds_client.c Thu Mar 12 20:59:40 2009 (r5289) +++ plugins/syncml/src/syncml_ds_client.c Fri Mar 13 10:25:49 2009 (r5290) @@ -1,3 +1,23 @@ +/* + * syncml plugin - A syncml plugin for OpenSync + * Copyright (C) 2008-2009 Michael Bell <mic...@op...> + * + * 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 "syncml_ds_client.h" #include "syncml_callbacks.h" #include "syncml_devinf.h" @@ -25,7 +45,8 @@ OSyncObjTypeSinkFunctions functions; memset(&functions, 0, sizeof(functions)); - functions.connect_done = connect_done; + functions.connect = syncml_connect; + functions.connect_done = syncml_connect_done; functions.get_changes = ds_client_get_changeinfo; functions.sync_done = sync_done; functions.batch_commit = ds_client_batch_commit; Modified: plugins/syncml/src/syncml_ds_server.c ============================================================================== --- plugins/syncml/src/syncml_ds_server.c Thu Mar 12 20:59:40 2009 (r5289) +++ plugins/syncml/src/syncml_ds_server.c Fri Mar 13 10:25:49 2009 (r5290) @@ -1,3 +1,23 @@ +/* + * syncml plugin - A syncml plugin for OpenSync + * Copyright (C) 2008-2009 Michael Bell <mic...@op...> + * + * 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 "syncml_ds_server.h" #include "syncml_callbacks.h" #include "syncml_devinf.h" @@ -22,7 +42,8 @@ OSyncObjTypeSinkFunctions functions; memset(&functions, 0, sizeof(functions)); - functions.connect_done = connect_done; + functions.connect = syncml_connect; + functions.connect_done = syncml_connect_done; functions.get_changes = ds_server_get_changeinfo; functions.sync_done = sync_done; functions.batch_commit = ds_server_batch_commit; |